import java.util.*;
import java.text.*;
+import libaltosJNI.*;
+
public class Altos {
/* EEProm command letters */
static final int AO_LOG_FLIGHT = 'F';
input = input.substring(0,dot);
return input.concat(extension);
}
+
+ static public boolean initialized = false;
+ static public boolean loaded_library = false;
+
+ public static boolean load_library() {
+ if (!initialized) {
+ try {
+ System.loadLibrary("altos");
+ libaltos.altos_init();
+ loaded_library = true;
+ } catch (UnsatisfiedLinkError e) {
+ loaded_library = false;
+ }
+ initialized = true;
+ }
+ return loaded_library;
+ }
+
+ static int usb_vendor_altusmetrum() {
+ if (load_library())
+ return libaltosConstants.USB_VENDOR_ALTUSMETRUM;
+ return 0x000a;
+ }
+
+ static int usb_product_altusmetrum() {
+ if (load_library())
+ return libaltosConstants.USB_PRODUCT_ALTUSMETRUM;
+ return 0x000a;
+ }
+
+ static int usb_product_altusmetrum_min() {
+ if (load_library())
+ return libaltosConstants.USB_PRODUCT_ALTUSMETRUM_MIN;
+ return 0x000a;
+ }
+
+ static int usb_product_altusmetrum_max() {
+ if (load_library())
+ return libaltosConstants.USB_PRODUCT_ALTUSMETRUM_MAX;
+ return 0x000d;
+ }
+
+ static int usb_product_telemetrum() {
+ if (load_library())
+ return libaltosConstants.USB_PRODUCT_TELEMETRUM;
+ return 0x000b;
+ }
+
+ static int usb_product_teledongle() {
+ if (load_library())
+ return libaltosConstants.USB_PRODUCT_TELEDONGLE;
+ return 0x000c;
+ }
+
+ static int usb_product_teleterra() {
+ if (load_library())
+ return libaltosConstants.USB_PRODUCT_TELETERRA;
+ return 0x000d;
+ }
+
+ static int usb_product_telebt() {
+ if (load_library())
+ return libaltosConstants.USB_PRODUCT_TELEBT;
+ return 0x000e;
+ }
+
+ public final static int vendor_altusmetrum = usb_vendor_altusmetrum();
+ public final static int product_altusmetrum = usb_product_altusmetrum();
+ public final static int product_telemetrum = usb_product_telemetrum();
+ public final static int product_teledongle = usb_product_teledongle();
+ public final static int product_teleterra = usb_product_teleterra();
+ public final static int product_telebt = usb_product_telebt();
+ public final static int product_altusmetrum_min = usb_product_altusmetrum_min();
+ public final static int product_altusmetrum_max = usb_product_altusmetrum_max();
+
+ public final static int product_any = 0x10000;
+ public final static int product_basestation = 0x10000 + 1;
+
+ static String bt_product_telebt() {
+ if (load_library())
+ return libaltosConstants.BLUETOOTH_PRODUCT_TELEBT;
+ return "TeleBT";
+ }
+
+ public final static String bt_product_telebt = bt_product_telebt();
+
+ public static AltosBTKnown bt_known = new AltosBTKnown();
}
--- /dev/null
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * 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.util.*;
+import libaltosJNI.*;
+
+public class AltosBTDevice extends altos_bt_device implements AltosDevice {
+
+ public String getProductName() {
+ String name = getName();
+ if (name == null)
+ return "Altus Metrum";
+ int dash = name.lastIndexOf("-");
+ if (dash < 0)
+ return name;
+ return name.substring(0,dash);
+ }
+
+ public int getProduct() {
+ if (Altos.bt_product_telebt.equals(getProductName()))
+ return Altos.product_telebt;
+ return 0;
+ }
+
+ public String getPath() {
+ return getAddr();
+ }
+
+ public int getSerial() {
+ String name = getName();
+ if (name == null)
+ return 0;
+ int dash = name.lastIndexOf("-");
+ if (dash < 0 || dash >= name.length())
+ return 0;
+ String sn = name.substring(dash + 1, name.length());
+ try {
+ return Integer.parseInt(sn);
+ } catch (NumberFormatException ne) {
+ return 0;
+ }
+ }
+
+ public String toString() {
+ String name = getName();
+ if (name == null)
+ name = "Altus Metrum";
+ return String.format("%-20.20s %4d %s",
+ getProductName(), getSerial(), getAddr());
+ }
+
+ public String toShortString() {
+ String name = getName();
+ if (name == null)
+ name = "Altus Metrum";
+ return String.format("%s %d %s",
+ getProduct(), getSerial(), getAddr());
+
+ }
+
+ public SWIGTYPE_p_altos_file open() {
+ return libaltos.altos_bt_open(this);
+ }
+
+ private boolean isAltusMetrum() {
+ if (getName().startsWith(Altos.bt_product_telebt))
+ return true;
+ return false;
+ }
+
+ public boolean matchProduct(int want_product) {
+
+ System.out.printf("matchProduct %s %d\n", toString(), want_product);
+// if (!isAltusMetrum())
+// return false;
+
+ if (want_product == Altos.product_any)
+ return true;
+
+ if (want_product == Altos.product_basestation)
+ return matchProduct(Altos.product_telebt);
+
+ if (want_product == getProduct())
+ return true;
+
+ return false;
+ }
+
+ public boolean equals(Object o) {
+ if (!(o instanceof AltosBTDevice))
+ return false;
+ AltosBTDevice other = (AltosBTDevice) o;
+ System.out.printf("AltosBTDevice equals %s == %s\n", toString(), other.toString());
+ return getName().equals(other.getName()) && getAddr().equals(other.getAddr());
+ }
+
+ public int hashCode() {
+ return getName().hashCode() ^ getAddr().hashCode();
+ }
+
+ public AltosBTDevice(String name, String addr) {
+ libaltos.altos_bt_fill_in(name, addr,this);
+ }
+
+ public AltosBTDevice() {
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * 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.util.*;
+import libaltosJNI.*;
+
+public class AltosBTDeviceIterator implements Iterator<AltosBTDevice> {
+ AltosBTDevice current;
+ boolean done;
+ SWIGTYPE_p_altos_bt_list list;
+
+ public boolean hasNext() {
+ System.out.printf ("BT has next?\n");
+ if (list == null)
+ return false;
+ if (current != null)
+ return true;
+ if (done)
+ return false;
+ current = new AltosBTDevice();
+ while (libaltos.altos_bt_list_next(list, current) != 0) {
+ System.out.printf("Got BT device %s\n", current.toString());
+// if (current.matchProduct(product))
+ return true;
+ }
+ current = null;
+ done = true;
+ return false;
+ }
+
+ public AltosBTDevice next() {
+ if (hasNext()) {
+ AltosBTDevice next = current;
+ current = null;
+ return next;
+ }
+ return null;
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ public AltosBTDeviceIterator(int inquiry_time) {
+ done = false;
+ current = null;
+ list = libaltos.altos_bt_list_start(inquiry_time);
+ }
+}
--- /dev/null
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * 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.util.*;
+import libaltosJNI.*;
+import java.util.prefs.*;
+
+public class AltosBTKnown implements Iterable<AltosBTDevice> {
+ LinkedList<AltosBTDevice> devices = new LinkedList<AltosBTDevice>();
+ Preferences bt_pref = AltosPreferences.bt_devices();
+
+ private String get_address(String name) {
+ return bt_pref.get(name, "");
+ }
+
+ private void set_address(String name, String addr) {
+ bt_pref.put(name, addr);
+ System.out.printf("saving known %s %s\n", name, addr);
+ }
+
+ private void remove(String name) {
+ bt_pref.remove(name);
+ }
+
+ private void load() {
+ try {
+ String[] names = bt_pref.keys();
+ for (int i = 0; i < names.length; i++) {
+ String name = names[i];
+ String addr = get_address(name);
+ System.out.printf("Known device %s %s\n", name, addr);
+ devices.add(new AltosBTDevice(name, addr));
+ }
+ } catch (BackingStoreException be) {
+ } catch (IllegalStateException ie) {
+ }
+ }
+
+ public Iterator<AltosBTDevice> iterator() {
+ return devices.iterator();
+ }
+
+ private void flush() {
+ AltosPreferences.flush_preferences();
+ }
+
+ public void set(Iterable<AltosBTDevice> new_devices) {
+ for (AltosBTDevice old : devices) {
+ boolean found = false;
+ for (AltosBTDevice new_device : new_devices) {
+ if (new_device.equals(old)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ remove(old.getName());
+ }
+ devices = new LinkedList<AltosBTDevice>();
+ for (AltosBTDevice new_device : new_devices) {
+ devices.add(new_device);
+ set_address(new_device.getName(), new_device.getAddr());
+ }
+ flush();
+ }
+
+ public List<AltosDevice> list(int product) {
+ LinkedList<AltosDevice> list = new LinkedList<AltosDevice>();
+ for (AltosBTDevice device : devices) {
+ if (device.matchProduct(product))
+ list.add(device);
+ }
+ return list;
+ }
+
+ public AltosBTKnown() {
+ devices = new LinkedList<AltosBTDevice>();
+ bt_pref = AltosPreferences.bt_devices();
+ load();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * 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 javax.swing.event.*;
+import javax.swing.plaf.basic.*;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.util.prefs.*;
+import java.util.concurrent.*;
+
+import libaltosJNI.*;
+
+public class AltosBTManage extends JDialog implements ActionListener, Iterable<AltosBTDevice> {
+ LinkedBlockingQueue<AltosBTDevice> found_devices;
+ Frame frame;
+ LinkedList<ActionListener> listeners;
+ AltosBTKnown bt_known;
+
+ class DeviceList extends JList implements Iterable<AltosBTDevice> {
+ LinkedList<AltosBTDevice> devices;
+ DefaultListModel list_model;
+
+ public void add (AltosBTDevice device) {
+ if (!devices.contains(device)) {
+ devices.add(device);
+ list_model.addElement(device);
+ }
+ }
+
+ public void remove (AltosBTDevice device) {
+ if (devices.contains(device)) {
+ devices.remove(device);
+ list_model.removeElement(device);
+ }
+ }
+
+ public boolean contains(AltosBTDevice device) {
+ return devices.contains(device);
+ }
+
+ //Subclass JList to workaround bug 4832765, which can cause the
+ //scroll pane to not let the user easily scroll up to the beginning
+ //of the list. An alternative would be to set the unitIncrement
+ //of the JScrollBar to a fixed value. You wouldn't get the nice
+ //aligned scrolling, but it should work.
+ public int getScrollableUnitIncrement(Rectangle visibleRect,
+ int orientation,
+ int direction) {
+ int row;
+ if (orientation == SwingConstants.VERTICAL &&
+ direction < 0 && (row = getFirstVisibleIndex()) != -1) {
+ Rectangle r = getCellBounds(row, row);
+ if ((r.y == visibleRect.y) && (row != 0)) {
+ Point loc = r.getLocation();
+ loc.y--;
+ int prevIndex = locationToIndex(loc);
+ Rectangle prevR = getCellBounds(prevIndex, prevIndex);
+
+ if (prevR == null || prevR.y >= r.y) {
+ return 0;
+ }
+ return prevR.height;
+ }
+ }
+ return super.getScrollableUnitIncrement(
+ visibleRect, orientation, direction);
+ }
+
+ public Iterator<AltosBTDevice> iterator() {
+ return devices.iterator();
+ }
+
+ public java.util.List<AltosBTDevice> selected_list() {
+ java.util.LinkedList<AltosBTDevice> l = new java.util.LinkedList<AltosBTDevice>();
+ Object[] a = getSelectedValues();
+ for (int i = 0; i < a.length; i++)
+ l.add((AltosBTDevice)a[i]);
+ return l;
+ }
+
+ public DeviceList() {
+ devices = new LinkedList<AltosBTDevice>();
+ list_model = new DefaultListModel();
+ setModel(list_model);
+ setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
+ setLayoutOrientation(JList.HORIZONTAL_WRAP);
+ setVisibleRowCount(-1);
+ }
+ }
+
+ DeviceList visible_devices;
+
+ DeviceList known_devices;
+ Thread bt_thread;
+
+ public Iterator<AltosBTDevice> iterator() {
+ return known_devices.iterator();
+ }
+
+ public void commit() {
+ bt_known.set(this);
+ }
+
+ public void add_known() {
+ for (AltosBTDevice device : visible_devices.selected_list()) {
+ System.out.printf("Add known %s\n", device.toString());
+ known_devices.add(device);
+ visible_devices.remove(device);
+ }
+ }
+
+ public void remove_known() {
+ for (AltosBTDevice device : known_devices.selected_list()) {
+ System.out.printf("Remove known %s\n", device.toString());
+ known_devices.remove(device);
+ visible_devices.add(device);
+ }
+ }
+
+ public void addActionListener(ActionListener l) {
+ listeners.add(l);
+ }
+
+ private void forwardAction(ActionEvent e) {
+ for (ActionListener l : listeners)
+ l.actionPerformed(e);
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ String command = e.getActionCommand();
+ System.out.printf("manage command %s\n", command);
+ if ("ok".equals(command)) {
+ bt_thread.interrupt();
+ commit();
+ setVisible(false);
+ forwardAction(e);
+ } else if ("cancel".equals(command)) {
+ bt_thread.interrupt();
+ setVisible(false);
+ forwardAction(e);
+ } else if ("select".equals(command)) {
+ add_known();
+ } else if ("deselect".equals(command)) {
+ remove_known();
+ }
+ }
+
+ public void got_visible_device() {
+ while (!found_devices.isEmpty()) {
+ AltosBTDevice device = found_devices.remove();
+ if (!known_devices.contains(device))
+ visible_devices.add(device);
+ }
+ }
+
+ class BTGetVisibleDevices implements Runnable {
+ public void run () {
+ for (;;)
+ for (int time = 1; time <= 8; time <<= 1) {
+ AltosBTDeviceIterator i = new AltosBTDeviceIterator(time);
+ AltosBTDevice device;
+
+ if (Thread.interrupted())
+ return;
+ try {
+ while ((device = i.next()) != null) {
+ Runnable r;
+
+ if (Thread.interrupted())
+ return;
+ found_devices.add(device);
+ r = new Runnable() {
+ public void run() {
+ got_visible_device();
+ }
+ };
+ SwingUtilities.invokeLater(r);
+ }
+ } catch (Exception e) {
+ System.out.printf("uh-oh, exception %s\n", e.toString());
+ }
+ }
+ }
+ }
+
+ public static void show(Component frameComp, AltosBTKnown known) {
+ Frame frame = JOptionPane.getFrameForComponent(frameComp);
+ AltosBTManage dialog;
+
+ dialog = new AltosBTManage(frame, known);
+ dialog.setVisible(true);
+ }
+
+ public AltosBTManage(Frame in_frame, AltosBTKnown in_known) {
+ super(in_frame, "Manage Bluetooth Devices", true);
+
+ frame = in_frame;
+ bt_known = in_known;
+ BTGetVisibleDevices get_visible_devices = new BTGetVisibleDevices();
+ bt_thread = new Thread(get_visible_devices);
+ bt_thread.start();
+
+ listeners = new LinkedList<ActionListener>();
+
+ found_devices = new LinkedBlockingQueue<AltosBTDevice>();
+
+ Container pane = getContentPane();
+ pane.setLayout(new GridBagLayout());
+
+ GridBagConstraints c = new GridBagConstraints();
+ c.insets = new Insets(4,4,4,4);
+
+ /*
+ * Known devices label and list
+ */
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.WEST;
+ c.gridx = 0;
+ c.gridy = 0;
+ c.gridwidth = 1;
+ c.gridheight = 1;
+ pane.add(new JLabel("Known Devices"), c);
+
+ known_devices = new DeviceList();
+ for (AltosBTDevice device : bt_known)
+ known_devices.add(device);
+
+ JScrollPane known_list_scroller = new JScrollPane(known_devices);
+ known_list_scroller.setPreferredSize(new Dimension(400, 80));
+ known_list_scroller.setAlignmentX(LEFT_ALIGNMENT);
+ c.fill = GridBagConstraints.BOTH;
+ c.anchor = GridBagConstraints.WEST;
+ c.gridx = 0;
+ c.gridy = 1;
+ c.gridwidth = 1;
+ c.gridheight = 2;
+ pane.add(known_list_scroller, c);
+
+ /*
+ * Visible devices label and list
+ */
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.WEST;
+ c.gridx = 2;
+ c.gridy = 0;
+ c.gridwidth = 1;
+ c.gridheight = 1;
+ pane.add(new JLabel("Visible Devices"), c);
+
+ visible_devices = new DeviceList();
+ JScrollPane visible_list_scroller = new JScrollPane(visible_devices);
+ visible_list_scroller.setPreferredSize(new Dimension(400, 80));
+ visible_list_scroller.setAlignmentX(LEFT_ALIGNMENT);
+ c.fill = GridBagConstraints.BOTH;
+ c.anchor = GridBagConstraints.WEST;
+ c.gridx = 2;
+ c.gridy = 1;
+ c.gridheight = 2;
+ c.gridwidth = 1;
+ pane.add(visible_list_scroller, c);
+
+ /*
+ * Arrows between the two lists
+ */
+ BasicArrowButton select_arrow = new BasicArrowButton(SwingConstants.WEST);
+ select_arrow.setActionCommand("select");
+ select_arrow.addActionListener(this);
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.SOUTH;
+ c.gridx = 1;
+ c.gridy = 1;
+ c.gridheight = 1;
+ c.gridwidth = 1;
+ pane.add(select_arrow, c);
+
+ BasicArrowButton deselect_arrow = new BasicArrowButton(SwingConstants.EAST);
+ deselect_arrow.setActionCommand("deselect");
+ deselect_arrow.addActionListener(this);
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.NORTH;
+ c.gridx = 1;
+ c.gridy = 2;
+ c.gridheight = 1;
+ c.gridwidth = 1;
+ pane.add(deselect_arrow, c);
+
+ JButton cancel_button = new JButton("Cancel");
+ cancel_button.setActionCommand("cancel");
+ cancel_button.addActionListener(this);
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.CENTER;
+ c.gridx = 0;
+ c.gridy = 3;
+ c.gridheight = 1;
+ c.gridwidth = 1;
+ pane.add(cancel_button, c);
+
+ JButton ok_button = new JButton("OK");
+ ok_button.setActionCommand("ok");
+ ok_button.addActionListener(this);
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.CENTER;
+ c.gridx = 2;
+ c.gridy = 3;
+ c.gridheight = 1;
+ c.gridwidth = 1;
+ pane.add(ok_button, c);
+
+ getRootPane().setDefaultButton(ok_button);
+
+ pack();
+ setLocationRelativeTo(frame);
+ setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
+ addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowClosing(WindowEvent e) {
+ bt_thread.interrupt();
+ setVisible(false);
+ }
+ });
+ }
+}
version = new string_ref("unknown");
product = new string_ref("unknown");
- device = AltosDeviceDialog.show(owner, AltosDevice.product_any);
+ device = AltosDeviceDialog.show(owner, Altos.product_any);
if (device != null) {
try {
serial_line = new AltosSerial(device);
- if (!device.matchProduct(AltosDevice.product_telemetrum))
+ if (!device.matchProduct(Altos.product_telemetrum))
remote = true;
try {
init_ui();
JRadioButton serial_debug;
+ JButton manage_bluetooth;
+
/* DocumentListener interface methods */
public void changedUpdate(DocumentEvent e) {
AltosPreferences.set_callsign(callsign_value.getText());
c.anchor = GridBagConstraints.WEST;
pane.add(serial_debug, c);
+ manage_bluetooth = new JButton("Manage Bluetooth");
+ manage_bluetooth.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ AltosBTManage.show(owner, Altos.bt_known);
+ }
+ });
+ c.gridx = 1;
+ c.gridy = 6;
+ c.gridwidth = 3;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.WEST;
+ pane.add(manage_bluetooth, c);
+
/* And a close button at the bottom */
close = new JButton("Close");
close.addActionListener(new ActionListener() {
}
});
c.gridx = 0;
- c.gridy = 6;
+ c.gridy = 7;
c.gridwidth = 3;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.CENTER;
/*
- * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
*
* 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
import java.util.*;
import libaltosJNI.*;
-public class AltosDevice extends altos_device {
-
- static public boolean initialized = false;
- static public boolean loaded_library = false;
-
- public static boolean load_library() {
- if (!initialized) {
- try {
- System.loadLibrary("altos");
- libaltos.altos_init();
- loaded_library = true;
- } catch (UnsatisfiedLinkError e) {
- loaded_library = false;
- }
- initialized = true;
- }
- return loaded_library;
- }
-
- static int usb_vendor_altusmetrum() {
- if (load_library())
- return libaltosConstants.USB_VENDOR_ALTUSMETRUM;
- return 0x000a;
- }
-
- static int usb_product_altusmetrum() {
- if (load_library())
- return libaltosConstants.USB_PRODUCT_ALTUSMETRUM;
- return 0x000a;
- }
-
- static int usb_product_altusmetrum_min() {
- if (load_library())
- return libaltosConstants.USB_PRODUCT_ALTUSMETRUM_MIN;
- return 0x000a;
- }
-
- static int usb_product_altusmetrum_max() {
- if (load_library())
- return libaltosConstants.USB_PRODUCT_ALTUSMETRUM_MAX;
- return 0x000d;
- }
-
- static int usb_product_telemetrum() {
- if (load_library())
- return libaltosConstants.USB_PRODUCT_TELEMETRUM;
- return 0x000b;
- }
-
- static int usb_product_teledongle() {
- if (load_library())
- return libaltosConstants.USB_PRODUCT_TELEDONGLE;
- return 0x000c;
- }
-
- static int usb_product_teleterra() {
- if (load_library())
- return libaltosConstants.USB_PRODUCT_TELETERRA;
- return 0x000d;
- }
-
- public final static int vendor_altusmetrum = usb_vendor_altusmetrum();
- public final static int product_altusmetrum = usb_product_altusmetrum();
- public final static int product_telemetrum = usb_product_telemetrum();
- public final static int product_teledongle = usb_product_teledongle();
- public final static int product_teleterra = usb_product_teleterra();
- public final static int product_altusmetrum_min = usb_product_altusmetrum_min();
- public final static int product_altusmetrum_max = usb_product_altusmetrum_max();
-
-
- public final static int product_any = 0x10000;
- public final static int product_basestation = 0x10000 + 1;
-
- public String toString() {
- String name = getName();
- if (name == null)
- name = "Altus Metrum";
- return String.format("%-20.20s %4d %s",
- getName(), getSerial(), getPath());
- }
-
- public String toShortString() {
- String name = getName();
- if (name == null)
- name = "Altus Metrum";
- return String.format("%s %d %s",
- name, getSerial(), getPath());
-
- }
-
- public boolean isAltusMetrum() {
- if (getVendor() != vendor_altusmetrum)
- return false;
- if (getProduct() < product_altusmetrum_min)
- return false;
- if (getProduct() > product_altusmetrum_max)
- return false;
- return true;
- }
-
- public boolean matchProduct(int want_product) {
-
- if (!isAltusMetrum())
- return false;
-
- if (want_product == product_any)
- return true;
-
- if (want_product == product_basestation)
- return matchProduct(product_teledongle) || matchProduct(product_teleterra);
-
- int have_product = getProduct();
-
- if (have_product == product_altusmetrum) /* old devices match any request */
- return true;
-
- if (want_product == have_product)
- return true;
-
- return false;
- }
-
- static AltosDevice[] list(int product) {
- if (!load_library())
- return null;
-
- SWIGTYPE_p_altos_list list = libaltos.altos_list_start();
-
- ArrayList<AltosDevice> device_list = new ArrayList<AltosDevice>();
- if (list != null) {
- SWIGTYPE_p_altos_file file;
-
- for (;;) {
- AltosDevice device = new AltosDevice();
- if (libaltos.altos_list_next(list, device) == 0)
- break;
- if (device.matchProduct(product))
- device_list.add(device);
- }
- libaltos.altos_list_finish(list);
- }
-
- AltosDevice[] devices = new AltosDevice[device_list.size()];
- for (int i = 0; i < device_list.size(); i++)
- devices[i] = device_list.get(i);
- return devices;
- }
-}
\ No newline at end of file
+public interface AltosDevice {
+ public abstract String toString();
+ public abstract String toShortString();
+ public abstract int getSerial();
+ public abstract String getPath();
+ public abstract boolean matchProduct(int product);
+ public SWIGTYPE_p_altos_file open();
+}
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
-import libaltosJNI.libaltos;
-import libaltosJNI.altos_device;
-import libaltosJNI.SWIGTYPE_p_altos_file;
-import libaltosJNI.SWIGTYPE_p_altos_list;
+import libaltosJNI.*;
public class AltosDeviceDialog extends JDialog implements ActionListener {
- private static AltosDeviceDialog dialog;
- private static AltosDevice value = null;
- private JList list;
+ private AltosDevice value;
+ private JList list;
+ private JButton cancel_button;
+ private JButton select_button;
+ private JButton manage_bluetooth_button;
+ private Frame frame;
+ private int product;
- public static AltosDevice show (Component frameComp, int product) {
+ private AltosDevice getValue() {
+ return value;
+ }
- Frame frame = JOptionPane.getFrameForComponent(frameComp);
- AltosDevice[] devices;
- devices = AltosDevice.list(product);
-
- if (devices != null && devices.length > 0) {
- value = null;
- dialog = new AltosDeviceDialog(frame, frameComp,
- devices,
- devices[0]);
-
- dialog.setVisible(true);
- return value;
- } else {
- /* check for missing altos JNI library, which
- * will put up its own error dialog
- */
- if (AltosUI.load_library(frame)) {
- JOptionPane.showMessageDialog(frame,
- "No AltOS devices available",
- "No AltOS devices",
- JOptionPane.ERROR_MESSAGE);
- }
- return null;
- }
+ private AltosDevice[] devices() {
+ java.util.List<AltosDevice> usb_devices = AltosUSBDevice.list(product);
+ java.util.List<AltosDevice> bt_devices = Altos.bt_known.list(product);
+ AltosDevice[] devices = new AltosDevice[usb_devices.size() + bt_devices.size()];
+
+ for (int i = 0; i < usb_devices.size(); i++)
+ devices[i] = usb_devices.get(i);
+ int off = usb_devices.size();
+ for (int j = 0; j < bt_devices.size(); j++)
+ devices[off + j] = bt_devices.get(j);
+ return devices;
}
- private AltosDeviceDialog (Frame frame, Component location,
- AltosDevice[] devices,
- AltosDevice initial) {
- super(frame, "Device Selection", true);
+ private void update_devices() {
+ AltosDevice[] devices = devices();
+ list.setListData(devices);
+ select_button.setEnabled(devices.length > 0);
+ }
+ private AltosDeviceDialog (Frame in_frame, Component location, int in_product) {
+ super(in_frame, "Device Selection", true);
+
+ product = in_product;
+ frame = in_frame;
value = null;
- JButton cancelButton = new JButton("Cancel");
- cancelButton.addActionListener(this);
+ AltosDevice[] devices = devices();
+
+ cancel_button = new JButton("Cancel");
+ cancel_button.setActionCommand("cancel");
+ cancel_button.addActionListener(this);
+
+ manage_bluetooth_button = new JButton("Manage Bluetooth");
+ manage_bluetooth_button.setActionCommand("manage");
+ manage_bluetooth_button.addActionListener(this);
- final JButton selectButton = new JButton("Select");
- selectButton.setActionCommand("select");
- selectButton.addActionListener(this);
- getRootPane().setDefaultButton(selectButton);
+ select_button = new JButton("Select");
+ select_button.setActionCommand("select");
+ select_button.addActionListener(this);
+ if (devices.length == 0)
+ select_button.setEnabled(false);
+ getRootPane().setDefaultButton(select_button);
list = new JList(devices) {
//Subclass JList to workaround bug 4832765, which can cause the
list.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
- selectButton.doClick(); //emulate button click
+ select_button.doClick(); //emulate button click
}
}
});
buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS));
buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
buttonPane.add(Box.createHorizontalGlue());
- buttonPane.add(cancelButton);
+ buttonPane.add(cancel_button);
buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
- buttonPane.add(selectButton);
+ buttonPane.add(manage_bluetooth_button);
+ buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
+ buttonPane.add(select_button);
//Put everything together, using the content pane's BorderLayout.
Container contentPane = getContentPane();
contentPane.add(buttonPane, BorderLayout.PAGE_END);
//Initialize values.
- list.setSelectedValue(initial, true);
+ if (devices != null && devices.length != 0)
+ list.setSelectedValue(devices[0], true);
pack();
setLocationRelativeTo(location);
}
//Handle clicks on the Set and Cancel buttons.
public void actionPerformed(ActionEvent e) {
if ("select".equals(e.getActionCommand()))
- AltosDeviceDialog.value = (AltosDevice)(list.getSelectedValue());
- AltosDeviceDialog.dialog.setVisible(false);
+ value = (AltosDevice)(list.getSelectedValue());
+ if ("manage".equals(e.getActionCommand())) {
+ AltosBTManage.show(frame, Altos.bt_known);
+ update_devices();
+ return;
+ }
+ setVisible(false);
}
+ public static AltosDevice show (Component frameComp, int product) {
+
+ Frame frame = JOptionPane.getFrameForComponent(frameComp);
+ AltosDeviceDialog dialog;
+
+ dialog = new AltosDeviceDialog(frame, frameComp, product);
+ dialog.setVisible(true);
+ return dialog.getValue();
+ }
}
r = new AltosEepromRecord(Altos.AO_LOG_STATE, tiny_tick, state, 0);
if (state == Altos.ao_flight_landed)
done = true;
+ state = s;
any_valid = true;
} else {
if (v != 0xffff)
boolean running = false;
frame = given_frame;
- device = AltosDeviceDialog.show(frame, AltosDevice.product_any);
+ device = AltosDeviceDialog.show(frame, Altos.product_any);
remote = false;
any_download = false;
if (device != null) {
try {
serial_line = new AltosSerial(device);
- if (!device.matchProduct(AltosDevice.product_telemetrum))
+ if (!device.matchProduct(Altos.product_telemetrum))
remote = true;
serial_line.set_frame(frame);
build_dialog();
- debug_dongle = AltosDeviceDialog.show(frame, AltosDevice.product_any);
+ debug_dongle = AltosDeviceDialog.show(frame, Altos.product_any);
if (debug_dongle == null)
return;
JComboBox telemetries;
public AltosFlightUI(AltosVoice in_voice, AltosFlightReader in_reader, final int serial) {
- AltosPreferences.init(this);
+ AltosPreferences.set_component(this);
voice = in_voice;
reader = in_reader;
serial = new AltosSerial(device);
remote = false;
- if (!device.matchProduct(AltosDevice.product_telemetrum))
+ if (!device.matchProduct(Altos.product_telemetrum))
remote = true;
}
}
\ No newline at end of file
private boolean open() {
command_queue = new LinkedBlockingQueue<String>();
- device = AltosDeviceDialog.show(owner, AltosDevice.product_any);
+ device = AltosDeviceDialog.show(owner, Altos.product_any);
if (device != null) {
try {
AltosIgnite ignite = new AltosIgnite(device);
/* Serial debug */
static boolean serial_debug;
- public static void init(Component ui) {
+ public static void init() {
preferences = Preferences.userRoot().node("/org/altusmetrum/altosui");
- component = ui;
-
/* Initialize logdir from preferences */
String logdir_string = preferences.get(logdirPreference, null);
if (logdir_string != null)
AltosSerial.set_debug(serial_debug);
}
+ static { init(); }
+
+ static void set_component(Component in_component) {
+ component = in_component;
+ }
+
static void flush_preferences() {
try {
preferences.flush();
} catch (BackingStoreException ee) {
- JOptionPane.showMessageDialog(component,
- preferences.absolutePath(),
- "Cannot save prefernces",
- JOptionPane.ERROR_MESSAGE);
+ if (component != null)
+ JOptionPane.showMessageDialog(component,
+ preferences.absolutePath(),
+ "Cannot save prefernces",
+ JOptionPane.ERROR_MESSAGE);
+ else
+ System.err.printf("Cannot save preferences\n");
}
}
public static boolean serial_debug() {
return serial_debug;
}
+
+ public static Preferences bt_devices() {
+ return preferences.node("bt_devices");
+ }
}
throw new AltosSerialInUseException(device);
devices_opened.add(device.getPath());
}
- altos = libaltos.altos_open(device);
+ altos = device.open();
if (altos == null) {
close();
throw new FileNotFoundException(device.toShortString());
package altosui;
-import libaltosJNI.*;
-
public class AltosSerialInUseException extends Exception {
- public altos_device device;
+ public AltosDevice device;
- public AltosSerialInUseException (altos_device in_device) {
+ public AltosSerialInUseException (AltosDevice in_device) {
device = in_device;
}
}
}
public static void prefetchMaps(double lat, double lng, int w, int h) {
- AltosPreferences.init(null);
-
AltosSiteMap asm = new AltosSiteMap(true);
asm.centre = asm.getBaseLocation(lat, lng);
public AltosVoice voice = new AltosVoice();
public static boolean load_library(Frame frame) {
- if (!AltosDevice.load_library()) {
+ if (!Altos.load_library()) {
JOptionPane.showMessageDialog(frame,
String.format("No AltOS library in \"%s\"",
System.getProperty("java.library.path","<undefined>")),
if (imgURL != null)
setIconImage(new ImageIcon(imgURL).getImage());
- AltosPreferences.init(this);
+ AltosPreferences.set_component(this);
pane = getContentPane();
gridbag = new GridBagLayout();
private void ConnectToDevice() {
AltosDevice device = AltosDeviceDialog.show(AltosUI.this,
- AltosDevice.product_basestation);
+ Altos.product_basestation);
if (device != null)
telemetry_window(device);
AltosUI altosui = new AltosUI();
altosui.setVisible(true);
- AltosDevice[] devices = AltosDevice.list(AltosDevice.product_basestation);
- for (int i = 0; i < devices.length; i++)
- altosui.telemetry_window(devices[i]);
+ java.util.List<AltosDevice> devices = AltosUSBDevice.list(Altos.product_basestation);
+ for (AltosDevice device : devices)
+ altosui.telemetry_window(device);
}
}
}
--- /dev/null
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * 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.util.*;
+import libaltosJNI.*;
+
+public class AltosUSBDevice extends altos_device implements AltosDevice {
+
+ public String toString() {
+ String name = getName();
+ if (name == null)
+ name = "Altus Metrum";
+ return String.format("%-20.20s %4d %s",
+ name, getSerial(), getPath());
+ }
+
+ public String toShortString() {
+ String name = getName();
+ if (name == null)
+ name = "Altus Metrum";
+ return String.format("%s %d %s",
+ name, getSerial(), getPath());
+
+ }
+
+ public SWIGTYPE_p_altos_file open() {
+ return libaltos.altos_open(this);
+ }
+
+ private boolean isAltusMetrum() {
+ if (getVendor() != Altos.vendor_altusmetrum)
+ return false;
+ if (getProduct() < Altos.product_altusmetrum_min)
+ return false;
+ if (getProduct() > Altos.product_altusmetrum_max)
+ return false;
+ return true;
+ }
+
+ public boolean matchProduct(int want_product) {
+
+ if (!isAltusMetrum())
+ return false;
+
+ if (want_product == Altos.product_any)
+ return true;
+
+ if (want_product == Altos.product_basestation)
+ return matchProduct(Altos.product_teledongle) ||
+ matchProduct(Altos.product_teleterra) ||
+ matchProduct(Altos.product_telebt);
+
+ int have_product = getProduct();
+
+ if (have_product == Altos.product_altusmetrum) /* old devices match any request */
+ return true;
+
+ if (want_product == have_product)
+ return true;
+
+ return false;
+ }
+
+ static java.util.List<AltosDevice> list(int product) {
+ if (!Altos.load_library())
+ return null;
+
+ SWIGTYPE_p_altos_list list = libaltos.altos_list_start();
+
+ ArrayList<AltosDevice> device_list = new ArrayList<AltosDevice>();
+ if (list != null) {
+ for (;;) {
+ AltosUSBDevice device = new AltosUSBDevice();
+ if (libaltos.altos_list_next(list, device) == 0)
+ break;
+ if (device.matchProduct(product))
+ device_list.add(device);
+ }
+ libaltos.altos_list_finish(list);
+ }
+
+ return device_list;
+ }
+}
\ No newline at end of file
AltosDescent.java \
AltosDeviceDialog.java \
AltosDevice.java \
+ AltosUSBDevice.java \
+ AltosBTDevice.java \
+ AltosBTDeviceIterator.java \
+ AltosBTManage.java \
+ AltosBTKnown.java \
AltosDisplayThread.java \
AltosEepromChunk.java \
AltosEepromDelete.java \
cjnitest_LDADD=libaltos.la
-LIBS=
+LIBS=-lbluetooth
HFILES=libaltos.h
{
struct altos_device device;
struct altos_list *list;
+ struct altos_bt_device bt_device;
+ struct altos_bt_list *bt_list;
altos_init();
list = altos_list_start();
altos_close(file);
}
altos_list_finish(list);
+ bt_list = altos_bt_list_start(8);
+ while (altos_bt_list_next(bt_list, &bt_device)) {
+ printf ("%s %s\n", bt_device.name, bt_device.addr);
+ if (strncmp(bt_device.name, "TeleBT", 6) == 0) {
+ struct altos_file *file;
+
+ int c;
+ file = altos_bt_open(&bt_device);
+ if (!file) {
+ printf("altos_bt_open failed\n");
+ continue;
+ }
+ altos_puts(file,"v\nc s\n");
+ altos_flush(file);
+ while ((c = altos_getchar(file, 100)) >= 0) {
+ putchar(c);
+ }
+ if (c != LIBALTOS_TIMEOUT)
+ printf("getchar returns %d\n", c);
+ altos_close(file);
+ }
+ }
+ altos_bt_list_finish(bt_list);
altos_fini();
+ return 0;
}
#define altos_strndup strndup
#endif
+#ifdef POSIX_TTY
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <errno.h>
+
+#define USB_BUF_SIZE 64
+
+struct altos_file {
+ int fd;
+#ifdef USE_POLL
+ int pipe[2];
+#else
+ int out_fd;
+#endif
+ unsigned char out_data[USB_BUF_SIZE];
+ int out_used;
+ unsigned char in_data[USB_BUF_SIZE];
+ int in_used;
+ int in_read;
+};
+
+PUBLIC struct altos_file *
+altos_open(struct altos_device *device)
+{
+ struct altos_file *file = calloc (sizeof (struct altos_file), 1);
+ int ret;
+ struct termios term;
+
+ if (!file)
+ return NULL;
+
+ file->fd = open(device->path, O_RDWR | O_NOCTTY);
+ if (file->fd < 0) {
+ perror(device->path);
+ free(file);
+ return NULL;
+ }
+#ifdef USE_POLL
+ pipe(file->pipe);
+#else
+ file->out_fd = open(device->path, O_RDWR | O_NOCTTY);
+ if (file->out_fd < 0) {
+ perror(device->path);
+ close(file->fd);
+ free(file);
+ return NULL;
+ }
+#endif
+ ret = tcgetattr(file->fd, &term);
+ if (ret < 0) {
+ perror("tcgetattr");
+ close(file->fd);
+#ifndef USE_POLL
+ close(file->out_fd);
+#endif
+ free(file);
+ return NULL;
+ }
+ cfmakeraw(&term);
+#ifdef USE_POLL
+ term.c_cc[VMIN] = 1;
+ term.c_cc[VTIME] = 0;
+#else
+ term.c_cc[VMIN] = 0;
+ term.c_cc[VTIME] = 1;
+#endif
+ ret = tcsetattr(file->fd, TCSAFLUSH, &term);
+ if (ret < 0) {
+ perror("tcsetattr");
+ close(file->fd);
+#ifndef USE_POLL
+ close(file->out_fd);
+#endif
+ free(file);
+ return NULL;
+ }
+ return file;
+}
+
+PUBLIC void
+altos_close(struct altos_file *file)
+{
+ if (file->fd != -1) {
+ int fd = file->fd;
+ file->fd = -1;
+#ifdef USE_POLL
+ write(file->pipe[1], "\r", 1);
+#else
+ close(file->out_fd);
+ file->out_fd = -1;
+#endif
+ close(fd);
+ }
+}
+
+PUBLIC void
+altos_free(struct altos_file *file)
+{
+ altos_close(file);
+ free(file);
+}
+
+PUBLIC int
+altos_flush(struct altos_file *file)
+{
+ if (file->out_used && 0) {
+ printf ("flush \"");
+ fwrite(file->out_data, 1, file->out_used, stdout);
+ printf ("\"\n");
+ }
+ while (file->out_used) {
+ int ret;
+
+ if (file->fd < 0)
+ return -EBADF;
+#ifdef USE_POLL
+ ret = write (file->fd, file->out_data, file->out_used);
+#else
+ ret = write (file->out_fd, file->out_data, file->out_used);
+#endif
+ if (ret < 0)
+ return -errno;
+ if (ret) {
+ memmove(file->out_data, file->out_data + ret,
+ file->out_used - ret);
+ file->out_used -= ret;
+ }
+ }
+ return 0;
+}
+
+PUBLIC int
+altos_putchar(struct altos_file *file, char c)
+{
+ int ret;
+
+ if (file->out_used == USB_BUF_SIZE) {
+ ret = altos_flush(file);
+ if (ret) {
+ return ret;
+ }
+ }
+ file->out_data[file->out_used++] = c;
+ ret = 0;
+ if (file->out_used == USB_BUF_SIZE)
+ ret = altos_flush(file);
+ return 0;
+}
+
+#ifdef USE_POLL
+#include <poll.h>
+#endif
+
+static int
+altos_fill(struct altos_file *file, int timeout)
+{
+ int ret;
+#ifdef USE_POLL
+ struct pollfd fd[2];
+#endif
+
+ if (timeout == 0)
+ timeout = -1;
+ while (file->in_read == file->in_used) {
+ if (file->fd < 0)
+ return LIBALTOS_ERROR;
+#ifdef USE_POLL
+ fd[0].fd = file->fd;
+ fd[0].events = POLLIN|POLLERR|POLLHUP|POLLNVAL;
+ fd[1].fd = file->pipe[0];
+ fd[1].events = POLLIN;
+ ret = poll(fd, 2, timeout);
+ if (ret < 0) {
+ perror("altos_getchar");
+ return LIBALTOS_ERROR;
+ }
+ if (ret == 0)
+ return LIBALTOS_TIMEOUT;
+
+ if (fd[0].revents & (POLLHUP|POLLERR|POLLNVAL))
+ return LIBALTOS_ERROR;
+ if (fd[0].revents & POLLIN)
+#endif
+ {
+ ret = read(file->fd, file->in_data, USB_BUF_SIZE);
+ if (ret < 0) {
+ perror("altos_getchar");
+ return LIBALTOS_ERROR;
+ }
+ file->in_read = 0;
+ file->in_used = ret;
+#ifndef USE_POLL
+ if (ret == 0 && timeout > 0)
+ return LIBALTOS_TIMEOUT;
+#endif
+ }
+ }
+ if (file->in_used && 0) {
+ printf ("fill \"");
+ fwrite(file->in_data, 1, file->in_used, stdout);
+ printf ("\"\n");
+ }
+ return 0;
+}
+
+PUBLIC int
+altos_getchar(struct altos_file *file, int timeout)
+{
+ int ret;
+ while (file->in_read == file->in_used) {
+ if (file->fd < 0)
+ return LIBALTOS_ERROR;
+ ret = altos_fill(file, timeout);
+ if (ret)
+ return ret;
+ }
+ return file->in_data[file->in_read++];
+}
+
+#endif /* POSIX_TTY */
+
/*
* Scan for Altus Metrum devices by looking through /sys
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_lib.h>
+#include <bluetooth/rfcomm.h>
static char *
cc_fullname (char *dir, char *file)
free(usbdevs);
}
+struct altos_bt_list {
+ inquiry_info *ii;
+ int sock;
+ int dev_id;
+ int rsp;
+ int num_rsp;
+};
+
+#define INQUIRY_MAX_RSP 255
+
+struct altos_bt_list *
+altos_bt_list_start(int inquiry_time)
+{
+ struct altos_bt_list *bt_list;
+
+ bt_list = calloc(1, sizeof (struct altos_bt_list));
+ if (!bt_list)
+ goto no_bt_list;
+
+ bt_list->ii = calloc(INQUIRY_MAX_RSP, sizeof (inquiry_info));
+ if (!bt_list->ii)
+ goto no_ii;
+ bt_list->dev_id = hci_get_route(NULL);
+ if (bt_list->dev_id < 0)
+ goto no_dev_id;
+
+ bt_list->sock = hci_open_dev(bt_list->dev_id);
+ if (bt_list->sock < 0)
+ goto no_sock;
+
+ bt_list->num_rsp = hci_inquiry(bt_list->dev_id,
+ inquiry_time,
+ INQUIRY_MAX_RSP,
+ NULL,
+ &bt_list->ii,
+ IREQ_CACHE_FLUSH);
+ if (bt_list->num_rsp < 0)
+ goto no_rsp;
+
+ bt_list->rsp = 0;
+ return bt_list;
+
+no_rsp:
+ close(bt_list->sock);
+no_sock:
+no_dev_id:
+ free(bt_list->ii);
+no_ii:
+ free(bt_list);
+no_bt_list:
+ return NULL;
+}
+
+int
+altos_bt_list_next(struct altos_bt_list *bt_list,
+ struct altos_bt_device *device)
+{
+ inquiry_info *ii;
+
+ if (bt_list->rsp >= bt_list->num_rsp)
+ return 0;
+
+ ii = &bt_list->ii[bt_list->rsp];
+ ba2str(&ii->bdaddr, device->addr);
+ memset(&device->name, '\0', sizeof (device->name));
+ if (hci_read_remote_name(bt_list->sock, &ii->bdaddr,
+ sizeof (device->name),
+ device->name, 0) < 0) {
+ strcpy(device->name, "[unknown]");
+ }
+ bt_list->rsp++;
+ return 1;
+}
+
+void
+altos_bt_list_finish(struct altos_bt_list *bt_list)
+{
+ close(bt_list->sock);
+ free(bt_list->ii);
+ free(bt_list);
+}
+
+void
+altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device)
+{
+ strncpy(device->name, name, sizeof (device->name));
+ device->name[sizeof(device->name)-1] = '\0';
+ strncpy(device->addr, addr, sizeof (device->addr));
+ device->addr[sizeof(device->addr)-1] = '\0';
+}
+
+struct altos_file *
+altos_bt_open(struct altos_bt_device *device)
+{
+ struct sockaddr_rc addr = { 0 };
+ int s, status;
+ struct altos_file *file;
+
+ file = calloc(1, sizeof (struct altos_file));
+ if (!file)
+ goto no_file;
+ file->fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
+ if (file->fd < 0)
+ goto no_sock;
+
+ addr.rc_family = AF_BLUETOOTH;
+ addr.rc_channel = 1;
+ str2ba(device->addr, &addr.rc_bdaddr);
+
+ status = connect(file->fd,
+ (struct sockaddr *)&addr,
+ sizeof(addr));
+ if (status < 0) {
+ perror("connect");
+ goto no_link;
+ }
+ sleep(2);
+
+#ifdef USE_POLL
+ pipe(file->pipe);
+#else
+ file->out_fd = dup(file->fd);
+#endif
+ return file;
+no_link:
+ close(s);
+no_sock:
+ free(file);
+no_file:
+ return NULL;
+}
+
#endif
#ifdef DARWIN
}
struct altos_list *
-altos_list_start(void)
+altos_list_start(int time)
{
struct altos_list *list = calloc (sizeof (struct altos_list), 1);
CFMutableDictionaryRef matching_dictionary = IOServiceMatching("IOUSBDevice");
#endif
-#ifdef POSIX_TTY
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <termios.h>
-#include <errno.h>
-
-#define USB_BUF_SIZE 64
-
-struct altos_file {
- int fd;
-#ifdef USE_POLL
- int pipe[2];
-#else
- int out_fd;
-#endif
- unsigned char out_data[USB_BUF_SIZE];
- int out_used;
- unsigned char in_data[USB_BUF_SIZE];
- int in_used;
- int in_read;
-};
-
-PUBLIC struct altos_file *
-altos_open(struct altos_device *device)
-{
- struct altos_file *file = calloc (sizeof (struct altos_file), 1);
- int ret;
- struct termios term;
-
- if (!file)
- return NULL;
-
- file->fd = open(device->path, O_RDWR | O_NOCTTY);
- if (file->fd < 0) {
- perror(device->path);
- free(file);
- return NULL;
- }
-#ifdef USE_POLL
- pipe(file->pipe);
-#else
- file->out_fd = open(device->path, O_RDWR | O_NOCTTY);
- if (file->out_fd < 0) {
- perror(device->path);
- close(file->fd);
- free(file);
- return NULL;
- }
-#endif
- ret = tcgetattr(file->fd, &term);
- if (ret < 0) {
- perror("tcgetattr");
- close(file->fd);
-#ifndef USE_POLL
- close(file->out_fd);
-#endif
- free(file);
- return NULL;
- }
- cfmakeraw(&term);
-#ifdef USE_POLL
- term.c_cc[VMIN] = 1;
- term.c_cc[VTIME] = 0;
-#else
- term.c_cc[VMIN] = 0;
- term.c_cc[VTIME] = 1;
-#endif
- ret = tcsetattr(file->fd, TCSAFLUSH, &term);
- if (ret < 0) {
- perror("tcsetattr");
- close(file->fd);
-#ifndef USE_POLL
- close(file->out_fd);
-#endif
- free(file);
- return NULL;
- }
- return file;
-}
-
-PUBLIC void
-altos_close(struct altos_file *file)
-{
- if (file->fd != -1) {
- int fd = file->fd;
- file->fd = -1;
-#ifdef USE_POLL
- write(file->pipe[1], "\r", 1);
-#else
- close(file->out_fd);
- file->out_fd = -1;
-#endif
- close(fd);
- }
-}
-
-PUBLIC void
-altos_free(struct altos_file *file)
-{
- altos_close(file);
- free(file);
-}
-
-PUBLIC int
-altos_flush(struct altos_file *file)
-{
- if (file->out_used && 0) {
- printf ("flush \"");
- fwrite(file->out_data, 1, file->out_used, stdout);
- printf ("\"\n");
- }
- while (file->out_used) {
- int ret;
-
- if (file->fd < 0)
- return -EBADF;
-#ifdef USE_POLL
- ret = write (file->fd, file->out_data, file->out_used);
-#else
- ret = write (file->out_fd, file->out_data, file->out_used);
-#endif
- if (ret < 0)
- return -errno;
- if (ret) {
- memmove(file->out_data, file->out_data + ret,
- file->out_used - ret);
- file->out_used -= ret;
- }
- }
- return 0;
-}
-
-PUBLIC int
-altos_putchar(struct altos_file *file, char c)
-{
- int ret;
-
- if (file->out_used == USB_BUF_SIZE) {
- ret = altos_flush(file);
- if (ret) {
- return ret;
- }
- }
- file->out_data[file->out_used++] = c;
- ret = 0;
- if (file->out_used == USB_BUF_SIZE)
- ret = altos_flush(file);
- return 0;
-}
-
-#ifdef USE_POLL
-#include <poll.h>
-#endif
-
-static int
-altos_fill(struct altos_file *file, int timeout)
-{
- int ret;
-#ifdef USE_POLL
- struct pollfd fd[2];
-#endif
-
- if (timeout == 0)
- timeout = -1;
- while (file->in_read == file->in_used) {
- if (file->fd < 0)
- return LIBALTOS_ERROR;
-#ifdef USE_POLL
- fd[0].fd = file->fd;
- fd[0].events = POLLIN|POLLERR|POLLHUP|POLLNVAL;
- fd[1].fd = file->pipe[0];
- fd[1].events = POLLIN;
- ret = poll(fd, 2, timeout);
- if (ret < 0) {
- perror("altos_getchar");
- return LIBALTOS_ERROR;
- }
- if (ret == 0)
- return LIBALTOS_TIMEOUT;
-
- if (fd[0].revents & (POLLHUP|POLLERR|POLLNVAL))
- return LIBALTOS_ERROR;
- if (fd[0].revents & POLLIN)
-#endif
- {
- ret = read(file->fd, file->in_data, USB_BUF_SIZE);
- if (ret < 0) {
- perror("altos_getchar");
- return LIBALTOS_ERROR;
- }
- file->in_read = 0;
- file->in_used = ret;
-#ifndef USE_POLL
- if (ret == 0 && timeout > 0)
- return LIBALTOS_TIMEOUT;
-#endif
- }
- }
- if (file->in_used && 0) {
- printf ("fill \"");
- fwrite(file->in_data, 1, file->in_used, stdout);
- printf ("\"\n");
- }
- return 0;
-}
-
-PUBLIC int
-altos_getchar(struct altos_file *file, int timeout)
-{
- int ret;
- while (file->in_read == file->in_used) {
- if (file->fd < 0)
- return LIBALTOS_ERROR;
- ret = altos_fill(file, timeout);
- if (ret)
- return ret;
- }
- return file->in_data[file->in_read++];
-}
-
-#endif /* POSIX_TTY */
#ifdef WINDOWS
#define USB_PRODUCT_TELEMETRUM 0x000b
#define USB_PRODUCT_TELEDONGLE 0x000c
#define USB_PRODUCT_TELETERRA 0x000d
+#define USB_PRODUCT_TELEBT 0x000e
#define USB_PRODUCT_ALTUSMETRUM_MIN 0x000a
#define USB_PRODUCT_ALTUSMETRUM_MAX 0x0013
//%mutable;
};
+#define BLUETOOTH_PRODUCT_TELEBT "TeleBT"
+
+struct altos_bt_device {
+ //%immutable;
+ char name[256];
+ char addr[20];
+ //%mutable;
+};
+
#define LIBALTOS_SUCCESS 0
#define LIBALTOS_ERROR -1
#define LIBALTOS_TIMEOUT -2
PUBLIC int
altos_getchar(struct altos_file *file, int timeout);
+PUBLIC struct altos_bt_list *
+altos_bt_list_start(int inquiry_time);
+
+PUBLIC int
+altos_bt_list_next(struct altos_bt_list *list, struct altos_bt_device *device);
+
+PUBLIC void
+altos_bt_list_finish(struct altos_bt_list *list);
+
+PUBLIC void
+altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device);
+
+PUBLIC struct altos_file *
+altos_bt_open(struct altos_bt_device *device);
+
#endif /* _LIBALTOS_H_ */
telemetrum-v1.1 telemetrum-v1.0 \
teledongle-v0.2 teledongle-v0.1 \
telemini-v0.1 telenano-v0.1 \
+ telebt-v0.0 \
telemetrum-v0.1-sky telemetrum-v0.1-sirf \
tidongle test
#
SIRF_DRIVER_SRC = \
ao_gps_sirf.c
+
#
# Skytraq driver source
#
SKY_DRIVER_SRC = \
ao_gps_skytraq.c
+
+#
+# BTM-182 driver source
+#
+BTM_DRIVER_SRC = \
+ ao_btm.c
+
#
# Tasks run on TeleMetrum
#
$(TNANO_TASK_SRC) \
$(TNANO_MAIN_SRC)
+#
+# Sources for TeleDongle
+#
+
+TBT_MAIN_SRC = \
+ ao_telebt.c
+
+TBT_BASE_SRC = \
+ $(ALTOS_SRC) \
+ $(ALTOS_DRIVER_SRC) \
+ $(TELE_RECEIVER_SRC) \
+ $(TELE_COMMON_SRC) \
+ $(SERIAL_DRIVER_SRC) \
+ $(USB_DRIVER_SRC) \
+ $(BTM_DRIVER_SRC) \
+ $(DBG_SRC) \
+ $(TBT_MAIN_SRC)
+
#
# TI Dongle sources
#
#define AO_PANIC_REBOOT 8 /* Reboot failed */
#define AO_PANIC_FLASH 9 /* Invalid flash part (or wrong blocksize) */
#define AO_PANIC_USB 10 /* Trying to send USB packet while busy */
+#define AO_PANIC_BT 11 /* Communications with bluetooth device failed */
/* Stop the operating system, beeping and blinking the reason */
void
void
ao_cmd_init(void);
+#if HAS_CMD_FILTER
+/*
+ * Provided by an external module to filter raw command lines
+ */
+uint8_t
+ao_cmd_filter(void);
+#endif
+
/*
* ao_dma.c
*/
#endif
#if HAS_SERIAL_1
+#ifndef USE_SERIAL_STDIN
+#error Please define USE_SERIAL_STDIN
+#endif
+
void
ao_serial_rx1_isr(void) __interrupt 3;
char
ao_serial_getchar(void) __critical;
+#if USE_SERIAL_STDIN
+char
+ao_serial_pollchar(void) __critical;
+
+void
+ao_serial_set_stdin(uint8_t stdin);
+#endif
+
void
ao_serial_putchar(char c) __critical;
+void
+ao_serial_drain(void) __critical;
+
#define AO_SERIAL_SPEED_4800 0
#define AO_SERIAL_SPEED_9600 1
-#define AO_SERIAL_SPEED_57600 2
+#define AO_SERIAL_SPEED_19200 2
+#define AO_SERIAL_SPEED_57600 3
void
ao_serial_set_speed(uint8_t speed);
char (*pollchar)(void);
void (*putchar)(char c) __reentrant;
void (*flush)(void);
+ uint8_t echo;
};
+extern __xdata struct ao_stdio ao_stdios[];
+extern __data int8_t ao_cur_stdio;
+extern __data int8_t ao_num_stdios;
+
void
flush(void);
extern __xdata uint8_t ao_stdin_ready;
-void
+uint8_t
+ao_echo(void);
+
+int8_t
ao_add_stdio(char (*pollchar)(void),
void (*putchar)(char) __reentrant,
void (*flush)(void)) __reentrant;
void
ao_packet_slave_init(uint8_t enable);
+/* ao_btm.c */
+
+/* Shared by USB, so the USB code calls this function */
+void
+ao_btm_isr(void);
+
+void
+ao_btm_init(void);
+
#endif /* _AO_H_ */
--- /dev/null
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * 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.
+ */
+
+#include "ao.h"
+
+int8_t ao_btm_stdio;
+__xdata uint8_t ao_btm_connected;
+
+#define AO_BTM_MAX_REPLY 16
+__xdata char ao_btm_reply[AO_BTM_MAX_REPLY];
+
+extern volatile __xdata struct ao_fifo ao_usart1_rx_fifo;
+
+/*
+ * Read a line of data from the serial port, truncating
+ * it after a few characters.
+ */
+
+uint8_t
+ao_btm_get_line(void)
+{
+ uint8_t ao_btm_reply_len = 0;
+ char c;
+
+ for (;;) {
+
+ while ((c = ao_serial_pollchar()) != AO_READ_AGAIN) {
+ if (ao_btm_reply_len < sizeof (ao_btm_reply))
+ ao_btm_reply[ao_btm_reply_len++] = c;
+ if (c == '\r' || c == '\n')
+ goto done;
+ }
+ for (c = 0; c < 10; c++) {
+ ao_delay(AO_MS_TO_TICKS(10));
+ if (!ao_fifo_empty(ao_usart1_rx_fifo))
+ break;
+ }
+ if (c == 10)
+ goto done;
+ }
+done:
+ for (c = ao_btm_reply_len; c < sizeof (ao_btm_reply);)
+ ao_btm_reply[c++] = '\0';
+ return ao_btm_reply_len;
+}
+
+/*
+ * Drain the serial port completely
+ */
+void
+ao_btm_drain()
+{
+ while (ao_btm_get_line())
+ ;
+}
+
+/*
+ * Set the stdio echo for the bluetooth link
+ */
+void
+ao_btm_echo(uint8_t echo)
+{
+ ao_stdios[ao_btm_stdio].echo = echo;
+}
+
+/*
+ * Delay between command charaters; the BT module
+ * can't keep up with 57600 baud
+ */
+
+void
+ao_btm_putchar(char c)
+{
+ ao_serial_putchar(c);
+ ao_delay(1);
+}
+
+/*
+ * Wait for the bluetooth device to return
+ * status from the previously executed command
+ */
+uint8_t
+ao_btm_wait_reply(void)
+{
+ for (;;) {
+ ao_btm_get_line();
+ if (!strncmp(ao_btm_reply, "OK", 2))
+ return 1;
+ if (!strncmp(ao_btm_reply, "ERROR", 5))
+ return -1;
+ if (ao_btm_reply[0] == '\0')
+ return 0;
+ }
+}
+
+void
+ao_btm_string(__code char *cmd)
+{
+ char c;
+
+ while (c = *cmd++)
+ ao_btm_putchar(c);
+}
+
+uint8_t
+ao_btm_cmd(__code char *cmd)
+{
+ ao_btm_drain();
+ ao_btm_string(cmd);
+ return ao_btm_wait_reply();
+}
+
+uint8_t
+ao_btm_set_name(void)
+{
+ char sn[8];
+ char *s = sn + 8;
+ char c;
+ int n;
+ ao_btm_string("ATN=TeleBT-");
+ *--s = '\0';
+ *--s = '\r';
+ n = ao_serial_number;
+ do {
+ *--s = '0' + n % 10;
+ } while (n /= 10);
+ while ((c = *s++))
+ ao_btm_putchar(c);
+ return ao_btm_wait_reply();
+}
+
+uint8_t
+ao_btm_try_speed(uint8_t speed)
+{
+ ao_serial_set_speed(speed);
+ ao_btm_drain();
+ (void) ao_btm_cmd("\rATE0\rATQ0\r");
+ if (ao_btm_cmd("AT\r") == 1)
+ return 1;
+ return 0;
+}
+
+/*
+ * A thread to initialize the bluetooth device and
+ * hang around to blink the LED when connected
+ */
+void
+ao_btm(void)
+{
+ /*
+ * Wait for the bluetooth device to boot
+ */
+ ao_delay(AO_SEC_TO_TICKS(3));
+
+ /*
+ * The first time we connect, the BTM-180 comes up at 19200 baud.
+ * After that, it will remember and come up at 57600 baud. So, see
+ * if it is already running at 57600 baud, and if that doesn't work
+ * then tell it to switch to 57600 from 19200 baud.
+ */
+ while (!ao_btm_try_speed(AO_SERIAL_SPEED_57600)) {
+ ao_delay(AO_SEC_TO_TICKS(1));
+ if (ao_btm_try_speed(AO_SERIAL_SPEED_19200))
+ ao_btm_cmd("ATL4\r");
+ ao_delay(AO_SEC_TO_TICKS(1));
+ }
+
+ /* Disable echo */
+ ao_btm_cmd("ATE0\r");
+
+ /* Enable flow control */
+ ao_btm_cmd("ATC1\r");
+
+ /* Set the reported name to something we can find on the host */
+ ao_btm_set_name();
+
+ /* Turn off status reporting */
+ ao_btm_cmd("ATQ1\r");
+
+ ao_btm_stdio = ao_add_stdio(ao_serial_pollchar,
+ ao_serial_putchar,
+ NULL);
+ ao_btm_echo(0);
+
+ for (;;) {
+ while (!ao_btm_connected)
+ ao_sleep(&ao_btm_connected);
+ while (ao_btm_connected) {
+ ao_led_for(AO_LED_GREEN, AO_MS_TO_TICKS(20));
+ ao_delay(AO_SEC_TO_TICKS(3));
+ }
+ }
+}
+
+__xdata struct ao_task ao_btm_task;
+
+void
+ao_btm_check_link() __critical
+{
+ if (P2_1) {
+ ao_btm_connected = 0;
+ PICTL |= PICTL_P2ICON;
+ } else {
+ ao_btm_connected = 1;
+ PICTL &= ~PICTL_P2ICON;
+ }
+}
+
+void
+ao_btm_isr(void)
+{
+ if (P2IFG & (1 << 1)) {
+ ao_btm_check_link();
+ ao_wakeup(&ao_btm_connected);
+ }
+ P2IFG = 0;
+}
+
+void
+ao_btm_init (void)
+{
+ ao_serial_init();
+ ao_serial_set_speed(AO_SERIAL_SPEED_19200);
+
+ /*
+ * Configure link status line
+ */
+
+ /* Set P2_1 to input, pull-down */
+ P2DIR &= ~(1 << 1);
+ P2INP |= P2INP_MDP2_1_TRISTATE;
+
+ /* Enable P2 interrupts */
+ IEN2 |= IEN2_P2IE;
+ ao_btm_check_link();
+ PICTL |= PICTL_P2IEN;
+
+ ao_add_task(&ao_btm_task, ao_btm, "bt");
+}
__xdata uint32_t ao_cmd_lex_u32;
__xdata char ao_cmd_lex_c;
__xdata enum ao_cmd_status ao_cmd_status;
-static __xdata uint8_t lex_echo;
#define CMD_LEN 32
readline(void)
{
__xdata char c;
- if (lex_echo)
+ if (ao_echo())
put_string("> ");
cmd_len = 0;
for (;;) {
/* backspace/delete */
if (c == '\010' || c == '\177') {
if (cmd_len != 0) {
- if (lex_echo)
+ if (ao_echo())
put_string("\010 \010");
--cmd_len;
}
/* ^U */
if (c == '\025') {
while (cmd_len != 0) {
- if (lex_echo)
+ if (ao_echo())
put_string("\010 \010");
--cmd_len;
}
c = '\n';
if (c == '\n') {
- if (lex_echo)
+ if (ao_echo())
putchar('\n');
break;
}
if (cmd_len >= CMD_LEN - 2) {
- if (lex_echo)
+ if (ao_echo())
putchar('\007');
continue;
}
cmd_line[cmd_len++] = c;
- if (lex_echo)
+ if (ao_echo())
putchar(c);
}
cmd_line[cmd_len++] = '\n';
echo(void)
{
ao_cmd_hex();
- lex_echo = ao_cmd_lex_i != 0;
+ if (ao_cmd_status == ao_cmd_success)
+ ao_stdios[ao_cur_stdio].echo = ao_cmd_lex_i != 0;
}
static void
__code struct ao_cmds * __xdata cs;
void (*__xdata func)(void);
- lex_echo = 1;
for (;;) {
readline();
ao_cmd_lex();
break;
if (ao_packet_master_sleeping)
ao_wakeup(&ao_packet_master_sleeping);
- ao_usb_flush();
+ flush();
ao_sleep(&ao_stdin_ready);
}
return c;
while (ao_packet_enable) {
c = ao_packet_getchar();
if (c != AO_READ_AGAIN)
- ao_usb_putchar(c);
+ putchar(c);
}
ao_exit();
}
ao_set_monitor(0);
ao_add_task(&ao_packet_task, ao_packet_master, "master");
ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo");
- while ((c = ao_usb_getchar()) != '~') {
+ while ((c = getchar()) != '~') {
if (c == '\r') c = '\n';
ao_packet_putchar(c);
}
#define HAS_GPS 1
#define HAS_SERIAL_1 1
#define HAS_ADC 1
+ #define USE_SERIAL_STDIN 0
#define HAS_EEPROM 1
#define USE_INTERNAL_FLASH 0
#define HAS_DBG 1
#define HAS_BEEP 1
#define HAS_GPS 1
#define HAS_SERIAL_1 1
+ #define USE_SERIAL_STDIN 0
#define HAS_ADC 1
#define HAS_EEPROM 1
#define USE_INTERNAL_FLASH 0
#define HAS_USB 1
#define HAS_BEEP 0
#define HAS_SERIAL_1 0
+ #define USE_SERIAL_STDIN 0
#define HAS_ADC 0
#define HAS_DBG 1
#define HAS_EEPROM 0
#define HAS_BEEP 0
#define HAS_GPS 0
#define HAS_SERIAL_1 0
+ #define USE_SERIAL_STDIN 0
#define HAS_ADC 1
#define HAS_EEPROM 1
#define USE_INTERNAL_FLASH 1
#define HAS_BEEP 0
#define HAS_GPS 0
#define HAS_SERIAL_1 0
+ #define USE_SERIAL_STDIN 0
#define HAS_ADC 1
#define HAS_EEPROM 1
#define USE_INTERNAL_FLASH 1
#define HAS_BEEP 1
#define HAS_GPS 1
#define HAS_SERIAL_1 1
+ #define USE_SERIAL_STDIN 0
#define HAS_ADC 1
#define HAS_DBG 0
#define HAS_EEPROM 1
#define HAS_USB 1
#define HAS_BEEP 0
#define HAS_SERIAL_1 0
+ #define USE_SERIAL_STDIN 0
#define HAS_ADC 0
#define HAS_DBG 0
#define HAS_EEPROM 0
#define HAS_USB 1
#define HAS_BEEP 0
#define HAS_SERIAL_1 0
+ #define USE_SERIAL_STDIN 0
#define HAS_ADC 0
#define HAS_DBG 1
#define HAS_EEPROM 0
#define HAS_IGNITE 0
#endif
+#if defined(TELEBT_V_0_0)
+ #define HAS_FLIGHT 0
+ #define HAS_USB 1
+ #define HAS_BEEP 0
+ #define HAS_SERIAL_1 1
+ #define USE_SERIAL_STDIN 1
+ #define HAS_ADC 0
+ #define HAS_DBG 1
+ #define HAS_EEPROM 0
+ #define HAS_BTM 1
+ #define DBG_ON_P1 0
+ #define DBG_ON_P0 1
+ #define IGNITE_ON_P2 0
+ #define IGNITE_ON_P0 0
+ #define PACKET_HAS_MASTER 1
+ #define PACKET_HAS_SLAVE 0
+ #define AO_LED_RED 2
+ #define AO_LED_GREEN 1
+ #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN)
+ #define SPI_CS_ON_P1 1
+ #define SPI_CS_ON_P0 0
+ #define HAS_IGNITE 0
+#endif
+
#if DBG_ON_P1
#define DBG_CLOCK (1 << 4) /* mi0 */
#error Please define HAS_SERIAL_1
#endif
+#ifndef USE_SERIAL_STDIN
+#error Please define USE_SERIAL_STDIN
+#endif
+
#ifndef HAS_ADC
#error Please define HAS_ADC
#endif
if (!ao_fifo_full(ao_usart1_rx_fifo))
ao_fifo_insert(ao_usart1_rx_fifo, U1DBUF);
ao_wakeup(&ao_usart1_rx_fifo);
+#if USE_SERIAL_STDIN
+ ao_wakeup(&ao_stdin_ready);
+#endif
}
static __xdata uint8_t ao_serial_tx1_started;
ao_wakeup(&ao_usart1_tx_fifo);
}
-static __pdata serial_echo;
-
char
ao_serial_getchar(void) __critical
{
while (ao_fifo_empty(ao_usart1_rx_fifo))
ao_sleep(&ao_usart1_rx_fifo);
ao_fifo_remove(ao_usart1_rx_fifo, c);
- if (serial_echo) {
- printf("%02x ", ((int) c) & 0xff);
- if (c >= ' ')
- putchar(c);
- putchar('\n');
- flush();
- }
return c;
}
+#if USE_SERIAL_STDIN
+char
+ao_serial_pollchar(void) __critical
+{
+ char c;
+ if (ao_fifo_empty(ao_usart1_rx_fifo))
+ return AO_READ_AGAIN;
+ ao_fifo_remove(ao_usart1_rx_fifo,c);
+ return c;
+}
+#endif
+
void
ao_serial_putchar(char c) __critical
{
ao_serial_tx1_start();
}
-static void
+void
ao_serial_drain(void) __critical
{
while (!ao_fifo_empty(ao_usart1_tx_fifo))
ao_sleep(&ao_usart1_tx_fifo);
}
-static void
-monitor_serial(void)
-{
- ao_cmd_hex();
- serial_echo = ao_cmd_lex_i != 0;
-}
-
-__code struct ao_cmds ao_serial_cmds[] = {
- { monitor_serial, "M <enable>\0Monitor serial data" },
- { 0, NULL },
-};
-
static const struct {
uint8_t baud;
uint8_t gcr;
/* .baud = */ 163,
/* .gcr = */ (8 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
},
+ /* [AO_SERIAL_SPEED_19200] = */ {
+ /* .baud = */ 163,
+ /* .gcr = */ (9 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
+ },
/* [AO_SERIAL_SPEED_57600] = */ {
/* .baud = */ 59,
/* .gcr = */ (11 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
ao_serial_drain();
if (speed > AO_SERIAL_SPEED_57600)
return;
+ U1UCR |= UxUCR_FLUSH;
U1BAUD = ao_serial_speeds[speed].baud;
U1GCR = ao_serial_speeds[speed].gcr;
}
/* Set up the USART pin assignment */
PERCFG = (PERCFG & ~PERCFG_U1CFG_ALT_MASK) | PERCFG_U1CFG_ALT_2;
- /* ee has already set the P2SEL bits */
+ P2SEL = (P2SEL & ~(P2SEL_PRI3P1_MASK | P2SEL_PRI2P1_MASK)) |
+ (P2SEL_PRI3P1_USART1 | P2SEL_PRI2P1_USART1);
/* Make the USART pins be controlled by the USART */
P1SEL |= (1 << 6) | (1 << 7);
/* Reasonable serial parameters */
U1UCR = (UxUCR_FLUSH |
UxUCR_FLOW_DISABLE |
- UxUCR_D9_ODD_PARITY |
+ UxUCR_D9_EVEN_PARITY |
UxUCR_BIT9_8_BITS |
UxUCR_PARITY_DISABLE |
UxUCR_SPB_1_STOP_BIT |
IEN0 |= IEN0_URX1IE;
IEN2 |= IEN2_UTX1IE;
-
- ao_cmd_register(&ao_serial_cmds[0]);
}
* Basic I/O functions to support SDCC stdio package
*/
-#define AO_NUM_STDIOS 2
+#define AO_NUM_STDIOS (HAS_USB + PACKET_HAS_SLAVE + USE_SERIAL_STDIN)
-static __xdata struct ao_stdio stdios[AO_NUM_STDIOS];
-static __data int8_t ao_cur_stdio;
-static __data int8_t ao_num_stdios;
+__xdata struct ao_stdio ao_stdios[AO_NUM_STDIOS];
+__data int8_t ao_cur_stdio;
+__data int8_t ao_num_stdios;
void
putchar(char c)
{
if (c == '\n')
- (*stdios[ao_cur_stdio].putchar)('\r');
- (*stdios[ao_cur_stdio].putchar)(c);
+ (*ao_stdios[ao_cur_stdio].putchar)('\r');
+ (*ao_stdios[ao_cur_stdio].putchar)(c);
}
void
flush(void)
{
- if (stdios[ao_cur_stdio].flush)
- stdios[ao_cur_stdio].flush();
+ if (ao_stdios[ao_cur_stdio].flush)
+ ao_stdios[ao_cur_stdio].flush();
}
__xdata uint8_t ao_stdin_ready;
int8_t stdio = ao_cur_stdio;
for (;;) {
- c = stdios[stdio].pollchar();
+ c = ao_stdios[stdio].pollchar();
if (c != AO_READ_AGAIN)
break;
if (++stdio == ao_num_stdios)
return c;
}
-void
+uint8_t
+ao_echo(void)
+{
+ return ao_stdios[ao_cur_stdio].echo;
+}
+
+int8_t
ao_add_stdio(char (*pollchar)(void),
void (*putchar)(char),
void (*flush)(void)) __reentrant
{
if (ao_num_stdios == AO_NUM_STDIOS)
ao_panic(AO_PANIC_STDIO);
- stdios[ao_num_stdios].pollchar = pollchar;
- stdios[ao_num_stdios].putchar = putchar;
- stdios[ao_num_stdios].flush = flush;
- ao_num_stdios++;
+ ao_stdios[ao_num_stdios].pollchar = pollchar;
+ ao_stdios[ao_num_stdios].putchar = putchar;
+ ao_stdios[ao_num_stdios].flush = flush;
+ ao_stdios[ao_num_stdios].echo = 1;
+ return ao_num_stdios++;
}
--- /dev/null
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * 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.
+ */
+
+#include "ao.h"
+
+void
+main(void)
+{
+ ao_clock_init();
+
+ /* Turn on the LED until the system is stable */
+ ao_led_init(LEDS_AVAILABLE);
+ ao_led_on(AO_LED_RED);
+ ao_timer_init();
+ ao_cmd_init();
+ ao_usb_init();
+ ao_monitor_init(AO_LED_GREEN, TRUE);
+ ao_rssi_init(AO_LED_RED);
+ ao_radio_init();
+ ao_packet_master_init();
+ ao_btm_init();
+#if HAS_DBG
+ ao_dbg_init();
+#endif
+ ao_config_init();
+ ao_start_scheduler();
+}
ao_usb_isr(void) __interrupt 6
{
USBIF = 0;
+ IRCON2 &= ~IRCON2_USBIF;
ao_usb_iif |= USBIIF;
if (ao_usb_iif & 1)
ao_wakeup(&ao_usb_task);
if (USBCIF & USBCIF_RSTIF)
ao_usb_set_interrupts();
+#if HAS_BTM
+ ao_btm_isr();
+#endif
}
struct ao_usb_setup {
#define P2SEL_PRI3P1_MASK (1 << 6)
#define P2SEL_PRI2P1_USART1 (0 << 5)
#define P2SEL_PRI2P1_TIMER3 (1 << 5)
+#define P2SEL_PRI2P1_MASK (1 << 5)
#define P2SEL_PRI1P1_TIMER1 (0 << 4)
#define P2SEL_PRI1P1_TIMER4 (1 << 4)
+#define P2SEL_PRI1P1_MASK (1 << 4)
#define P2SEL_PRI0P1_USART0 (0 << 3)
#define P2SEL_PRI0P1_TIMER1 (1 << 3)
+#define P2SEL_PRI0P1_MASK (1 << 3)
#define P2SEL_SELP2_4_GPIO (0 << 2)
#define P2SEL_SELP2_4_PERIPHERAL (1 << 2)
+#define P2SEL_SELP2_4_MASK (1 << 2)
#define P2SEL_SELP2_3_GPIO (0 << 1)
#define P2SEL_SELP2_3_PERIPHERAL (1 << 1)
+#define P2SEL_SELP2_3_MASK (1 << 1)
#define P2SEL_SELP2_0_GPIO (0 << 0)
#define P2SEL_SELP2_0_PERIPHERAL (1 << 0)
#define P2SEL_SELP2_0_MASK (1 << 0)
#define P0IFG_USB_RESUME (1 << 7)
+sfr at 0x8C PICTL;
+#define PICTL_P2IEN (1 << 5)
+#define PICTL_P0IENH (1 << 4)
+#define PICTL_P0IENL (1 << 3)
+#define PICTL_P2ICON (1 << 2)
+#define PICTL_P1ICON (1 << 1)
+#define PICTL_P0ICON (1 << 0)
+
/* GPIO pins */
sfr at 0x80 P0;
--- /dev/null
+telebt-*
+ao_product.h
--- /dev/null
+--directory=..
--- /dev/null
+PROG = telebt-v0.0-$(VERSION).ihx
+
+SRC = \
+ $(TBT_BASE_SRC)
+
+PRODUCT=TeleBT-v0.0
+PRODUCT_DEF=-DTELEBT_V_0_0
+IDPRODUCT=0x000e