Merge branch 'telemini' into telebt
authorKeith Packard <keithp@keithp.com>
Tue, 19 Apr 2011 21:06:39 +0000 (14:06 -0700)
committerKeith Packard <keithp@keithp.com>
Tue, 19 Apr 2011 21:06:39 +0000 (14:06 -0700)
41 files changed:
altosui/Altos.java
altosui/AltosBTDevice.java [new file with mode: 0644]
altosui/AltosBTDeviceIterator.java [new file with mode: 0644]
altosui/AltosBTKnown.java [new file with mode: 0644]
altosui/AltosBTManage.java [new file with mode: 0644]
altosui/AltosConfig.java
altosui/AltosConfigureUI.java
altosui/AltosDevice.java
altosui/AltosDeviceDialog.java
altosui/AltosEepromDownload.java
altosui/AltosEepromManage.java
altosui/AltosFlashUI.java
altosui/AltosFlightUI.java
altosui/AltosIgnite.java
altosui/AltosIgniteUI.java
altosui/AltosPreferences.java
altosui/AltosSerial.java
altosui/AltosSerialInUseException.java
altosui/AltosSiteMap.java
altosui/AltosUI.java
altosui/AltosUSBDevice.java [new file with mode: 0644]
altosui/Makefile.am
altosui/libaltos/Makefile.am
altosui/libaltos/cjnitest.c
altosui/libaltos/libaltos.c
altosui/libaltos/libaltos.h
src/Makefile
src/Makefile.proto
src/ao.h
src/ao_btm.c [new file with mode: 0644]
src/ao_cmd.c
src/ao_packet_master.c
src/ao_pins.h
src/ao_serial.c
src/ao_stdio.c
src/ao_telebt.c [new file with mode: 0644]
src/ao_usb.c
src/cc1111.h
src/telebt-v0.0/.gitignore [new file with mode: 0644]
src/telebt-v0.0/.sdcdbrc [new file with mode: 0644]
src/telebt-v0.0/Makefile.defs [new file with mode: 0644]

index 54aced3222fa27571cc02acefebd826990bae7e3..6a2d9b9b202ff2ce0dddff09526316da14ef3616 100644 (file)
@@ -21,6 +21,8 @@ import java.awt.*;
 import java.util.*;
 import java.text.*;
 
+import libaltosJNI.*;
+
 public class Altos {
        /* EEProm command letters */
        static final int AO_LOG_FLIGHT = 'F';
@@ -222,4 +224,91 @@ public class Altos {
                        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();
 }
diff --git a/altosui/AltosBTDevice.java b/altosui/AltosBTDevice.java
new file mode 100644 (file)
index 0000000..c2721b2
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * 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
diff --git a/altosui/AltosBTDeviceIterator.java b/altosui/AltosBTDeviceIterator.java
new file mode 100644 (file)
index 0000000..7c36070
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * 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);
+       }
+}
diff --git a/altosui/AltosBTKnown.java b/altosui/AltosBTKnown.java
new file mode 100644 (file)
index 0000000..9583063
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * 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
diff --git a/altosui/AltosBTManage.java b/altosui/AltosBTManage.java
new file mode 100644 (file)
index 0000000..98a8b75
--- /dev/null
@@ -0,0 +1,344 @@
+/*
+ * 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);
+                       }
+               });
+       }
+}
index f45e20408c7501b604f0b6d67e829ea66772b9c6..c5de83f20608cea55c17a6eb78b1d5cab3090470 100644 (file)
@@ -344,11 +344,11 @@ public class AltosConfig implements ActionListener {
                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();
index 9a292c915b760fd51fda9b2a392665492b0363ea..0f5e4a3bd3a7335fdcc1fc8da9e54b8c7beb2de0 100644 (file)
@@ -49,6 +49,8 @@ public class AltosConfigureUI
 
        JRadioButton    serial_debug;
 
+       JButton         manage_bluetooth;
+
        /* DocumentListener interface methods */
        public void changedUpdate(DocumentEvent e) {
                AltosPreferences.set_callsign(callsign_value.getText());
@@ -199,6 +201,19 @@ public class AltosConfigureUI
                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() {
@@ -207,7 +222,7 @@ public class AltosConfigureUI
                                }
                        });
                c.gridx = 0;
-               c.gridy = 6;
+               c.gridy = 7;
                c.gridwidth = 3;
                c.fill = GridBagConstraints.NONE;
                c.anchor = GridBagConstraints.CENTER;
index f0fda57bc0b825c71d4af0dfa08180e4b3d4899e..3357c550fa632ab66c8f73773ae15849b3605c77 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -20,151 +20,11 @@ import java.lang.*;
 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();
+}
index 2966ad1e52bd44a6855d07e47fe3c68bad6bd9b1..e17504e2475580c4c75364ab060391cc1357a425 100644 (file)
@@ -22,59 +22,64 @@ import java.util.*;
 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
@@ -112,7 +117,7 @@ public class AltosDeviceDialog extends JDialog implements ActionListener {
                list.addMouseListener(new MouseAdapter() {
                                 public void mouseClicked(MouseEvent e) {
                                         if (e.getClickCount() == 2) {
-                                                selectButton.doClick(); //emulate button click
+                                                select_button.doClick(); //emulate button click
                                         }
                                 }
                        });
@@ -139,9 +144,11 @@ public class AltosDeviceDialog extends JDialog implements ActionListener {
                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();
@@ -149,7 +156,8 @@ public class AltosDeviceDialog extends JDialog implements ActionListener {
                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);
        }
@@ -157,8 +165,22 @@ public class AltosDeviceDialog extends JDialog implements ActionListener {
        //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();
+       }
 }
index 3dd5b12f4794d15dacd38e59274757d27807226e..82f01ef52ea360dc53dc59ecda51203777c5067a 100644 (file)
@@ -159,6 +159,7 @@ public class AltosEepromDownload implements Runnable {
                                        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)
index b46364dbaacdd7efc8c6a13703407f8433ed9405..cd2b74fef448d6816ac25e23f5208ffa2367eb76 100644 (file)
@@ -197,7 +197,7 @@ public class AltosEepromManage implements ActionListener {
                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;
@@ -206,7 +206,7 @@ public class AltosEepromManage implements ActionListener {
                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);
index 0302ccd38d9231fd25e8166d2547422efe5c1d01..ad7aeac844feb6eecb166fe6b0ae56d88f03322c 100644 (file)
@@ -151,7 +151,7 @@ public class AltosFlashUI
 
                build_dialog();
 
-               debug_dongle = AltosDeviceDialog.show(frame, AltosDevice.product_any);
+               debug_dongle = AltosDeviceDialog.show(frame, Altos.product_any);
 
                if (debug_dongle == null)
                        return;
index 66dcdad57863f8942a49d2fc3d87ea3834ab5d48..eb6c6d9d82d1edc5f3500dcc142f3769dfc6d39d 100644 (file)
@@ -122,7 +122,7 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay {
        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;
index 1171d2edd4510aeeea6f846aeb79ef1d341a97de..7a06c63d41244a7a53d2581c15d17907f93b1400 100644 (file)
@@ -172,7 +172,7 @@ public class AltosIgnite {
                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
index 000adc980d76144b615bcebad943426e274d98d7..ad5b7cfb192f99ed0e6b5affdba51a90cd477eb6 100644 (file)
@@ -275,7 +275,7 @@ public class AltosIgniteUI
        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);
index 5f82765569dae85f0a69211c41bc0d1ed04b119f..b1192be110e1f3573e2626939f73e238c68a3fda 100644 (file)
@@ -79,11 +79,9 @@ class AltosPreferences {
        /* 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)
@@ -116,14 +114,23 @@ class AltosPreferences {
                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");
                }
        }
 
@@ -262,4 +269,8 @@ class AltosPreferences {
        public static boolean serial_debug() {
                return serial_debug;
        }
+
+       public static Preferences bt_devices() {
+               return preferences.node("bt_devices");
+       }
 }
index 111bd77170fc5514107c4ef75f0ca050a84c4a9a..6c80b66fbd46ec6d7401ac52162a2332bcb9a7a5 100644 (file)
@@ -304,7 +304,7 @@ 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) {
                        close();
                        throw new FileNotFoundException(device.toShortString());
index 4b108c7c5ee566325884e6c015c55e2e698f9358..7380f331b2d561b46b39943554735461af57acc0 100644 (file)
 
 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;
        }
 }
index f4b6b7e0a52350bf3c66d32d92807ecb61535931..7575c10e62d3b95cfa23ca2c7d938485573d79af 100644 (file)
@@ -164,8 +164,6 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay {
        }
 
        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);
 
index 4d17b0d24d68e961ffe963e922634849d9ee3056..7955c1c20660a5348537a9a5450cdacf5b7434b0 100644 (file)
@@ -34,7 +34,7 @@ public class AltosUI extends JFrame {
        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>")),
@@ -99,7 +99,7 @@ public class AltosUI extends JFrame {
                if (imgURL != null)
                        setIconImage(new ImageIcon(imgURL).getImage());
 
-               AltosPreferences.init(this);
+               AltosPreferences.set_component(this);
 
                pane = getContentPane();
                gridbag = new GridBagLayout();
@@ -199,7 +199,7 @@ public class AltosUI extends JFrame {
 
        private void ConnectToDevice() {
                AltosDevice     device = AltosDeviceDialog.show(AltosUI.this,
-                                                               AltosDevice.product_basestation);
+                                                               Altos.product_basestation);
 
                if (device != null)
                        telemetry_window(device);
@@ -397,9 +397,9 @@ public class AltosUI extends JFrame {
                        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);
                }
        }
 }
diff --git a/altosui/AltosUSBDevice.java b/altosui/AltosUSBDevice.java
new file mode 100644 (file)
index 0000000..dc746a6
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * 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
index 01fe50c8560924d0efab5546892351c15a64b02f..f4d84ad29648ee93fa98b030614106049ffa51aa 100644 (file)
@@ -26,6 +26,11 @@ altosui_JAVA = \
        AltosDescent.java \
        AltosDeviceDialog.java \
        AltosDevice.java \
+       AltosUSBDevice.java \
+       AltosBTDevice.java \
+       AltosBTDeviceIterator.java \
+       AltosBTManage.java \
+       AltosBTKnown.java \
        AltosDisplayThread.java \
        AltosEepromChunk.java \
        AltosEepromDelete.java \
index 388d21046dc1c655fb66d20ebd89789fccb832ed..3f5f3ee2f07d32559e2e7de2a700741fbc69e086 100644 (file)
@@ -16,7 +16,7 @@ noinst_PROGRAMS=cjnitest
 
 cjnitest_LDADD=libaltos.la
 
-LIBS=
+LIBS=-lbluetooth
 
 HFILES=libaltos.h
 
index c6d6e069c1f188cd56666292236e5c1f083c7dbb..88e40d739bc0e469af9e3680186df4ce846a6118 100644 (file)
@@ -14,6 +14,8 @@ main ()
 {
        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();
@@ -39,5 +41,29 @@ main ()
                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;
 }
index 465f0ac89475c03d61b1b89067a7b4b05ef67e4a..c5bcf90070682a6f1974300ef916eeef941fc508 100644 (file)
@@ -56,6 +56,230 @@ altos_strndup (const char *s, size_t n)
 #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
  */
@@ -68,6 +292,10 @@ altos_strndup (const char *s, size_t n)
 #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)
@@ -354,6 +582,138 @@ altos_list_finish(struct altos_list *usbdevs)
        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
@@ -417,7 +777,7 @@ get_number(io_object_t object, CFStringRef entry, int *result)
 }
 
 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");
@@ -468,229 +828,6 @@ altos_list_finish(struct altos_list *list)
 
 #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
 
index 6e94899e8a1ec37e54319ccfa0c363c9dca3b0e2..f710919c510ade1ba1fb96c026c45b9f6cee15fb 100644 (file)
@@ -40,6 +40,7 @@
 #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
 
@@ -57,6 +58,15 @@ struct altos_device {
        //%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
@@ -99,4 +109,19 @@ altos_flush(struct altos_file *file);
 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_ */
index a5dec57b2144efc8d5fd7074444095daa13a02f9..d83ec668b8e3a9a8a4fd6d9629100e15842fc18d 100644 (file)
@@ -10,6 +10,7 @@ SUBDIRS=\
        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
 
index 5aad445fa44c3aaff4efc9ad5c89b71bc02712b7..ca68edbcba016322c3f80db92f8ac8fbe489c32f 100644 (file)
@@ -136,12 +136,20 @@ M25_DRIVER_SRC = \
 #
 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
 #
@@ -229,6 +237,24 @@ TNANO_BASE_SRC = \
        $(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
 #
index 89109fd964449926bb4141020f61aa90c0982df1..226f9a2248dd0425ebed6bf27593d245ce796384 100644 (file)
--- a/src/ao.h
+++ b/src/ao.h
@@ -107,6 +107,7 @@ ao_start_scheduler(void);
 #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
@@ -403,6 +404,14 @@ ao_cmd_register(__code struct ao_cmds *cmds);
 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
  */
@@ -903,6 +912,10 @@ ao_dbg_init(void);
 #endif
 
 #if HAS_SERIAL_1
+#ifndef USE_SERIAL_STDIN
+#error Please define USE_SERIAL_STDIN
+#endif
+
 void
 ao_serial_rx1_isr(void) __interrupt 3;
 
@@ -912,12 +925,24 @@ ao_serial_tx1_isr(void) __interrupt 14;
 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);
@@ -1154,14 +1179,22 @@ struct ao_stdio {
        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;
@@ -1332,4 +1365,13 @@ ao_packet_slave_stop(void);
 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_ */
diff --git a/src/ao_btm.c b/src/ao_btm.c
new file mode 100644 (file)
index 0000000..db0ff6b
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ * 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");
+}
index 6007773c96cdaba0a8eb6ca63ea4c83580bc7b9f..23346c3d53c918ea9ae906005e6eb4b9bd03ac20 100644 (file)
@@ -21,7 +21,6 @@ __xdata uint16_t ao_cmd_lex_i;
 __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
 
@@ -41,7 +40,7 @@ static void
 readline(void)
 {
        __xdata char c;
-       if (lex_echo)
+       if (ao_echo())
                put_string("> ");
        cmd_len = 0;
        for (;;) {
@@ -50,7 +49,7 @@ readline(void)
                /* backspace/delete */
                if (c == '\010' || c == '\177') {
                        if (cmd_len != 0) {
-                               if (lex_echo)
+                               if (ao_echo())
                                        put_string("\010 \010");
                                --cmd_len;
                        }
@@ -60,7 +59,7 @@ readline(void)
                /* ^U */
                if (c == '\025') {
                        while (cmd_len != 0) {
-                               if (lex_echo)
+                               if (ao_echo())
                                        put_string("\010 \010");
                                --cmd_len;
                        }
@@ -72,18 +71,18 @@ readline(void)
                        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';
@@ -198,7 +197,8 @@ static void
 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
@@ -272,7 +272,6 @@ ao_cmd(void)
        __code struct ao_cmds * __xdata cs;
        void (*__xdata func)(void);
 
-       lex_echo = 1;
        for (;;) {
                readline();
                ao_cmd_lex();
index 069bc5df4044f9fadb2c1e6e1f6e0a1a2894b0aa..e721ffba39c948a0d17a5fc35cf45ccfec664eea 100644 (file)
@@ -26,7 +26,7 @@ ao_packet_getchar(void) __critical
                        break;
                if (ao_packet_master_sleeping)
                        ao_wakeup(&ao_packet_master_sleeping);
-               ao_usb_flush();
+               flush();
                ao_sleep(&ao_stdin_ready);
        }
        return c;
@@ -39,7 +39,7 @@ ao_packet_echo(void) __reentrant
        while (ao_packet_enable) {
                c = ao_packet_getchar();
                if (c != AO_READ_AGAIN)
-                       ao_usb_putchar(c);
+                       putchar(c);
        }
        ao_exit();
 }
@@ -112,7 +112,7 @@ ao_packet_forward(void) __reentrant
        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);
        }
index 2161c5d2de5b30a229d41c4659a9854f293cae27..324d78273daaca46c9900446ade5299a1a5d2ed8 100644 (file)
@@ -25,6 +25,7 @@
        #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
@@ -49,6 +50,7 @@
        #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
@@ -77,6 +79,7 @@
        #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
index dd383fca18ff141a5ffd7c0af0f923f746437eca..9c0b798daf674cfcd894fe07db4eefa4c7cab236 100644 (file)
@@ -26,6 +26,9 @@ ao_serial_rx1_isr(void) __interrupt 3
        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;
@@ -50,8 +53,6 @@ ao_serial_tx1_isr(void) __interrupt 14
        ao_wakeup(&ao_usart1_tx_fifo);
 }
 
-static __pdata serial_echo;
-
 char
 ao_serial_getchar(void) __critical
 {
@@ -59,16 +60,21 @@ 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
 {
@@ -78,25 +84,13 @@ 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;
@@ -109,6 +103,10 @@ static const struct {
                /* .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
@@ -121,6 +119,7 @@ ao_serial_set_speed(uint8_t speed)
        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;
 }
@@ -131,7 +130,8 @@ ao_serial_init(void)
        /* 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);
@@ -145,7 +145,7 @@ ao_serial_init(void)
        /* 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 |
@@ -154,6 +154,4 @@ ao_serial_init(void)
 
        IEN0 |= IEN0_URX1IE;
        IEN2 |= IEN2_UTX1IE;
-
-       ao_cmd_register(&ao_serial_cmds[0]);
 }
index 6e1f5effde50409d1f89967381a9d5054ce8a05a..6b8908329aa1e8838eecdc62333720f8ffa2608a 100644 (file)
  * 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;
@@ -51,7 +51,7 @@ getchar(void) __reentrant __critical
        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)
@@ -63,15 +63,22 @@ getchar(void) __reentrant __critical
        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++;
 }
diff --git a/src/ao_telebt.c b/src/ao_telebt.c
new file mode 100644 (file)
index 0000000..295f0ce
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * 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();
+}
index b4e3f1fe6aa3364bd7925458d6e58af28f4922e8..ece6756a030c05bd104e1507a78879bafd54acac 100644 (file)
@@ -46,6 +46,7 @@ void
 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);
@@ -57,6 +58,9 @@ ao_usb_isr(void) __interrupt 6
 
        if (USBCIF & USBCIF_RSTIF)
                ao_usb_set_interrupts();
+#if HAS_BTM
+       ao_btm_isr();
+#endif
 }
 
 struct ao_usb_setup {
index effb1a68657820eed7991fc37c4377f1b4a13257..a07490e52bc2ffa697cb2580e4506e1713735db0 100644 (file)
@@ -565,14 +565,19 @@ sfr at 0xF5 P2SEL;
 #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)
@@ -657,6 +662,14 @@ sfr at 0x8B P2IFG;
 
 #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;
 
diff --git a/src/telebt-v0.0/.gitignore b/src/telebt-v0.0/.gitignore
new file mode 100644 (file)
index 0000000..1acfbfc
--- /dev/null
@@ -0,0 +1,2 @@
+telebt-*
+ao_product.h
diff --git a/src/telebt-v0.0/.sdcdbrc b/src/telebt-v0.0/.sdcdbrc
new file mode 100644 (file)
index 0000000..710b4a2
--- /dev/null
@@ -0,0 +1 @@
+--directory=..
diff --git a/src/telebt-v0.0/Makefile.defs b/src/telebt-v0.0/Makefile.defs
new file mode 100644 (file)
index 0000000..f0bb5e0
--- /dev/null
@@ -0,0 +1,8 @@
+PROG = telebt-v0.0-$(VERSION).ihx
+
+SRC = \
+       $(TBT_BASE_SRC)
+
+PRODUCT=TeleBT-v0.0
+PRODUCT_DEF=-DTELEBT_V_0_0
+IDPRODUCT=0x000e