public final static String bt_product_telebt = bt_product_telebt();
-// public static AltosBTKnown bt_known = new AltosBTKnown();
+ public static AltosBTKnown bt_known = new AltosBTKnown();
}
return getAddr();
}
+ public String getErrorString() {
+ altos_error error = new altos_error();
+
+ libaltos.altos_get_last_error(error);
+ return String.format("%s (%d)", error.getString(), error.getCode());
+ }
+
public int getSerial() {
String name = getName();
if (name == null)
writer.close();
} catch (FileNotFoundException ee) {
JOptionPane.showMessageDialog(frame,
- file.getName(),
+ ee.getMessage(),
"Cannot open file",
JOptionPane.ERROR_MESSAGE);
}
}
} catch (FileNotFoundException ee) {
JOptionPane.showMessageDialog(owner,
- String.format("Cannot open device \"%s\"",
- device.toShortString()),
+ ee.getMessage(),
"Cannot open target device",
JOptionPane.ERROR_MESSAGE);
} catch (AltosSerialInUseException si) {
JRadioButton serial_debug;
-// BLUETOOTH
-// JButton manage_bluetooth;
+ JButton manage_bluetooth;
JButton manage_frequencies;
final static String[] font_size_names = { "Small", "Medium", "Large" };
c.anchor = GridBagConstraints.WEST;
pane.add(serial_debug, c);
-// BLUETOOTH
-// manage_bluetooth = new JButton("Manage Bluetooth");
-// manage_bluetooth.addActionListener(new ActionListener() {
-// public void actionPerformed(ActionEvent e) {
-// AltosBTManage.show(owner, Altos.bt_known);
-// }
-// });
-// c.gridx = 0;
-// c.gridy = row++;
-// c.gridwidth = 2;
-// c.fill = GridBagConstraints.NONE;
-// c.anchor = GridBagConstraints.WEST;
-// pane.add(manage_bluetooth, 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 = 0;
+ c.gridy = row;
+ c.gridwidth = 2;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.WEST;
+ pane.add(manage_bluetooth, c);
manage_frequencies = new JButton("Manage Frequencies");
manage_frequencies.addActionListener(new ActionListener() {
}
});
manage_frequencies.setToolTipText("Configure which values are shown in frequency menus");
-// BLUETOOTH
-// c.gridx = 2;
- c.gridx = 1;
+ c.gridx = 2;
+ c.gridx = 2;
c.gridy = row++;
c.gridwidth = 2;
c.fill = GridBagConstraints.NONE;
}
} catch (FileNotFoundException fe) {
JOptionPane.showMessageDialog(frame,
- filename,
+ fe.getMessage(),
"Cannot open file",
JOptionPane.ERROR_MESSAGE);
}
public abstract int getSerial();
public abstract String getPath();
public abstract boolean matchProduct(int product);
+ public abstract String getErrorString();
public SWIGTYPE_p_altos_file open();
}
private JList list;
private JButton cancel_button;
private JButton select_button;
-// BLUETOOTH
-// private JButton manage_bluetooth_button;
+ private JButton manage_bluetooth_button;
private Frame frame;
private int product;
private AltosDevice[] devices() {
java.util.List<AltosDevice> usb_devices = AltosUSBDevice.list(product);
int num_devices = usb_devices.size();
-// BLUETOOTH
-// java.util.List<AltosDevice> bt_devices = Altos.bt_known.list(product);
-// num_devices += bt_devices.size();
+ java.util.List<AltosDevice> bt_devices = Altos.bt_known.list(product);
+ num_devices += bt_devices.size();
AltosDevice[] devices = new AltosDevice[num_devices];
for (int i = 0; i < usb_devices.size(); i++)
devices[i] = usb_devices.get(i);
-// BLUETOOTH
-// int off = usb_devices.size();
-// for (int j = 0; j < bt_devices.size(); j++)
-// devices[off + j] = bt_devices.get(j);
+ int off = usb_devices.size();
+ for (int j = 0; j < bt_devices.size(); j++)
+ devices[off + j] = bt_devices.get(j);
return devices;
}
cancel_button.setActionCommand("cancel");
cancel_button.addActionListener(this);
-// BLUETOOTH
-// manage_bluetooth_button = new JButton("Manage Bluetooth");
-// manage_bluetooth_button.setActionCommand("manage");
-// manage_bluetooth_button.addActionListener(this);
+ manage_bluetooth_button = new JButton("Manage Bluetooth");
+ manage_bluetooth_button.setActionCommand("manage");
+ manage_bluetooth_button.addActionListener(this);
select_button = new JButton("Select");
select_button.setActionCommand("select");
buttonPane.add(Box.createHorizontalGlue());
buttonPane.add(cancel_button);
buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
-// BLUETOOTH
-// buttonPane.add(manage_bluetooth_button);
+ buttonPane.add(manage_bluetooth_button);
buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
buttonPane.add(select_button);
public void actionPerformed(ActionEvent e) {
if ("select".equals(e.getActionCommand()))
value = (AltosDevice)(list.getSelectedValue());
-// BLUETOOTH
-// if ("manage".equals(e.getActionCommand())) {
-// AltosBTManage.show(frame, Altos.bt_known);
-// update_devices();
-// return;
-// }
+ if ("manage".equals(e.getActionCommand())) {
+ AltosBTManage.show(frame, Altos.bt_known);
+ update_devices();
+ return;
+ }
setVisible(false);
}
done = true;
}
+ void CaptureTelemetry(AltosEepromChunk eechunk) throws IOException {
+
+ }
+
void CaptureLog(AltosEepromLog log) throws IOException, InterruptedException, TimeoutException {
int block, state_block = 0;
int log_format = flights.config_data.log_format;
extension = "eeprom";
CaptureTiny(eechunk);
break;
-// case Altos.AO_LOG_FORMAT_TELEMETRY:
-// extension = "telem";
-// CaptureTelemetry(eechunk);
-// break;
+ case Altos.AO_LOG_FORMAT_TELEMETRY:
+ extension = "telem";
+ CaptureTelemetry(eechunk);
+ break;
case Altos.AO_LOG_FORMAT_TELESCIENCE:
extension = "science";
CaptureTeleScience(eechunk);
t.start();
} catch (FileNotFoundException ee) {
JOptionPane.showMessageDialog(frame,
- String.format("Cannot open device \"%s\"",
- device.toShortString()),
+ ee.getMessage(),
"Cannot open target device",
JOptionPane.ERROR_MESSAGE);
} catch (AltosSerialInUseException si) {
void exception (Exception e) {
if (e instanceof FileNotFoundException) {
JOptionPane.showMessageDialog(frame,
- "Cannot open image",
- file.toString(),
+ ((FileNotFoundException) e).getMessage(),
+ "Cannot open file",
JOptionPane.ERROR_MESSAGE);
} else if (e instanceof AltosSerialInUseException) {
JOptionPane.showMessageDialog(frame,
void ignite_exception(Exception e) {
if (e instanceof FileNotFoundException) {
JOptionPane.showMessageDialog(owner,
- String.format("Cannot open device \"%s\"",
- device.toShortString()),
+ ((FileNotFoundException) e).getMessage(),
"Cannot open target device",
JOptionPane.ERROR_MESSAGE);
} else if (e instanceof AltosSerialInUseException) {
FileInputStream in = new FileInputStream(file);
records = new AltosTelemetryIterable(in);
} else {
- throw new FileNotFoundException();
+ throw new FileNotFoundException(filename);
}
try {
new AltosGraphUI(records, filename);
}
} catch (FileNotFoundException fe) {
JOptionPane.showMessageDialog(null,
- filename,
+ fe.getMessage(),
"Cannot open file",
JOptionPane.ERROR_MESSAGE);
}
--- /dev/null
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package altosui;
+
+import java.io.*;
+import java.util.concurrent.*;
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import javax.swing.table.*;
+import javax.swing.event.*;
+
+public class AltosLaunch {
+ AltosDevice device;
+ AltosSerial serial;
+ boolean serial_started;
+ int launcher_serial;
+ int launcher_channel;
+ int rssi;
+
+ final static int Unknown = -1;
+ final static int Good = 0;
+ final static int Bad = 1;
+
+ int armed;
+ int igniter;
+
+ private void start_serial() throws InterruptedException {
+ serial_started = true;
+ }
+
+ private void stop_serial() throws InterruptedException {
+ if (!serial_started)
+ return;
+ serial_started = false;
+ if (serial == null)
+ return;
+ }
+
+ class string_ref {
+ String value;
+
+ public String get() {
+ return value;
+ }
+ public void set(String i) {
+ value = i;
+ }
+ public string_ref() {
+ value = null;
+ }
+ }
+
+ private boolean get_string(String line, String label, string_ref s) {
+ if (line.startsWith(label)) {
+ String quoted = line.substring(label.length()).trim();
+
+ if (quoted.startsWith("\""))
+ quoted = quoted.substring(1);
+ if (quoted.endsWith("\""))
+ quoted = quoted.substring(0,quoted.length()-1);
+ s.set(quoted);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public boolean status() throws InterruptedException, TimeoutException {
+ boolean ok = false;
+ if (serial == null)
+ return false;
+ string_ref status_name = new string_ref();
+ start_serial();
+ serial.printf("l %d %d\n", launcher_serial, launcher_channel);
+ for (;;) {
+ String line = serial.get_reply(20000);
+ if (line == null)
+ throw new TimeoutException();
+ if (get_string(line, "Rssi: ", status_name)) {
+ try {
+ rssi = Altos.fromdec(status_name.get());
+ } catch (NumberFormatException ne) {
+ }
+ break;
+ } else if (get_string(line, "Armed: ", status_name)) {
+ armed = Good;
+ String status = status_name.get();
+ if (status.startsWith("igniter good"))
+ igniter = Good;
+ else if (status.startsWith("igniter bad"))
+ igniter = Bad;
+ else
+ igniter = Unknown;
+ ok = true;
+ } else if (get_string(line, "Disarmed: ", status_name)) {
+ armed = Bad;
+ if (status_name.get().startsWith("igniter good"))
+ igniter = Good;
+ else if (status_name.get().startsWith("igniter bad"))
+ igniter = Bad;
+ else
+ igniter = Unknown;
+ ok = true;
+ } else if (get_string(line, "Error ", status_name)) {
+ armed = Unknown;
+ igniter = Unknown;
+ ok = false;
+ break;
+ }
+ }
+ stop_serial();
+ if (!ok) {
+ armed = Unknown;
+ igniter = Unknown;
+ }
+ return ok;
+ }
+
+ public static String status_string(int status) {
+ switch (status) {
+ case Good:
+ return "good";
+ case Bad:
+ return "open";
+ }
+ return "unknown";
+ }
+
+ public void arm() {
+ if (serial == null)
+ return;
+ try {
+ start_serial();
+ serial.printf("a %d %d\n", launcher_serial, launcher_channel);
+ serial.flush_output();
+ } catch (InterruptedException ie) {
+ } finally {
+ try {
+ stop_serial();
+ } catch (InterruptedException ie) {
+ }
+ }
+ }
+
+ public void fire() {
+ if (serial == null)
+ return;
+ try {
+ start_serial();
+ serial.printf("i %d %d\n", launcher_serial, launcher_channel);
+ serial.flush_output();
+ } catch (InterruptedException ie) {
+ } finally {
+ try {
+ stop_serial();
+ } catch (InterruptedException ie) {
+ }
+ }
+ }
+
+ public void close() {
+ try {
+ stop_serial();
+ } catch (InterruptedException ie) {
+ }
+ serial.close();
+ serial = null;
+ }
+
+ public void set_frame(Frame frame) {
+ serial.set_frame(frame);
+ }
+
+ public void set_remote(int in_serial, int in_channel) {
+ launcher_serial = in_serial;
+ launcher_channel = in_channel;
+ }
+
+ public AltosLaunch(AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException {
+
+ device = in_device;
+ serial = new AltosSerial(device);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package altosui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import javax.swing.table.*;
+import javax.swing.event.*;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.util.prefs.*;
+import java.util.concurrent.*;
+
+class FireButton extends JButton {
+ protected void processMouseEvent(MouseEvent e) {
+ super.processMouseEvent(e);
+ switch (e.getID()) {
+ case MouseEvent.MOUSE_PRESSED:
+ if (actionListener != null)
+ actionListener.actionPerformed(new ActionEvent(this, e.getID(), "fire_down"));
+ break;
+ case MouseEvent.MOUSE_RELEASED:
+ if (actionListener != null)
+ actionListener.actionPerformed(new ActionEvent(this, e.getID(), "fire_up"));
+ break;
+ }
+ }
+
+ public FireButton(String s) {
+ super(s);
+ }
+}
+
+public class AltosLaunchUI
+ extends JDialog
+ implements ActionListener
+{
+ AltosDevice device;
+ JFrame owner;
+ JLabel label;
+
+ int radio_channel;
+ JLabel radio_channel_label;
+ JTextField radio_channel_text;
+
+ int launcher_serial;
+ JLabel launcher_serial_label;
+ JTextField launcher_serial_text;
+
+ int launcher_channel;
+ JLabel launcher_channel_label;
+ JTextField launcher_channel_text;
+
+ JLabel armed_label;
+ JLabel armed_status_label;
+ JLabel igniter;
+ JLabel igniter_status_label;
+ JToggleButton arm;
+ FireButton fire;
+ javax.swing.Timer arm_timer;
+ javax.swing.Timer fire_timer;
+
+ boolean firing;
+ boolean armed;
+ int armed_status;
+ int igniter_status;
+ int rssi;
+
+ final static int arm_timeout = 1 * 1000;
+ final static int fire_timeout = 250;
+
+ int armed_count;
+
+ LinkedBlockingQueue<String> command_queue;
+
+ class LaunchHandler implements Runnable {
+ AltosLaunch launch;
+ JFrame owner;
+
+ void send_exception(Exception e) {
+ final Exception f_e = e;
+ Runnable r = new Runnable() {
+ public void run() {
+ launch_exception(f_e);
+ }
+ };
+ SwingUtilities.invokeLater(r);
+ }
+
+ public void run () {
+ try {
+ launch = new AltosLaunch(device);
+ } catch (Exception e) {
+ send_exception(e);
+ return;
+ }
+ launch.set_frame(owner);
+ launch.set_remote(launcher_serial, launcher_channel);
+
+ for (;;) {
+ Runnable r;
+
+ try {
+ String command = command_queue.take();
+ String reply = null;
+
+ if (command.equals("get_status")) {
+ launch.status();
+ reply = "status";
+ armed_status = launch.armed;
+ igniter_status = launch.igniter;
+ rssi = launch.rssi;
+ } else if (command.equals("set_remote")) {
+ launch.set_remote(launcher_serial, launcher_channel);
+ reply = "remote set";
+ } else if (command.equals("arm")) {
+ launch.arm();
+ reply = "armed";
+ } else if (command.equals("fire")) {
+ launch.fire();
+ reply = "fired";
+ } else if (command.equals("quit")) {
+ launch.close();
+ break;
+ } else {
+ throw new ParseException(String.format("invalid command %s", command), 0);
+ }
+ final String f_reply = reply;
+ r = new Runnable() {
+ public void run() {
+ launch_reply(f_reply);
+ }
+ };
+ SwingUtilities.invokeLater(r);
+ } catch (Exception e) {
+ send_exception(e);
+ }
+ }
+ }
+
+ public LaunchHandler(JFrame in_owner) {
+ owner = in_owner;
+ }
+ }
+
+ void launch_exception(Exception e) {
+ if (e instanceof FileNotFoundException) {
+ JOptionPane.showMessageDialog(owner,
+ ((FileNotFoundException) e).getMessage(),
+ "Cannot open target device",
+ JOptionPane.ERROR_MESSAGE);
+ } else if (e instanceof AltosSerialInUseException) {
+ JOptionPane.showMessageDialog(owner,
+ String.format("Device \"%s\" already in use",
+ device.toShortString()),
+ "Device in use",
+ JOptionPane.ERROR_MESSAGE);
+ } else if (e instanceof IOException) {
+ IOException ee = (IOException) e;
+ JOptionPane.showMessageDialog(owner,
+ device.toShortString(),
+ ee.getLocalizedMessage(),
+ JOptionPane.ERROR_MESSAGE);
+ } else {
+ JOptionPane.showMessageDialog(owner,
+ String.format("Connection to \"%s\" failed",
+ device.toShortString()),
+ "Connection Failed",
+ JOptionPane.ERROR_MESSAGE);
+ }
+ close();
+ }
+
+ void launch_reply(String reply) {
+ if (reply == null)
+ return;
+ if (reply.equals("remote set"))
+ poll_launch_status();
+ if (reply.equals("status")) {
+ set_launch_status();
+ }
+ }
+
+ void set_arm_text() {
+ if (arm.isSelected())
+ arm.setText(String.format("%d", armed_count));
+ else
+ arm.setText("Arm");
+ }
+
+ void start_arm_timer() {
+ armed_count = 30;
+ set_arm_text();
+ }
+
+ void stop_arm_timer() {
+ armed_count = 0;
+ armed = false;
+ arm.setSelected(false);
+ fire.setEnabled(false);
+ set_arm_text();
+ }
+
+ void cancel () {
+ fire.setEnabled(false);
+ firing = false;
+ stop_arm_timer();
+ }
+
+ void send_command(String command) {
+ try {
+ command_queue.put(command);
+ } catch (Exception ex) {
+ launch_exception(ex);
+ }
+ }
+
+ boolean getting_status = false;
+
+ void set_launch_status() {
+ getting_status = false;
+ armed_status_label.setText(String.format("\"%s\"", AltosLaunch.status_string(armed_status)));
+ igniter_status_label.setText(String.format("\"%s\"", AltosLaunch.status_string(igniter_status)));
+ }
+
+ void poll_launch_status() {
+ if (!getting_status && !firing && !armed) {
+ getting_status = true;
+ send_command("get_status");
+ }
+ }
+
+ void fired() {
+ firing = false;
+ cancel();
+ }
+
+ void close() {
+ send_command("quit");
+ arm_timer.stop();
+ setVisible(false);
+ dispose();
+ }
+
+ void tick_arm_timer() {
+ if (armed_count > 0) {
+ --armed_count;
+ if (armed_count <= 0) {
+ armed_count = 0;
+ cancel();
+ } else {
+ if (!firing) {
+ send_command("arm");
+ set_arm_text();
+ }
+ }
+ }
+ poll_launch_status();
+ }
+
+ void arm() {
+ if (arm.isSelected()) {
+ fire.setEnabled(true);
+ start_arm_timer();
+ if (!firing)
+ send_command("arm");
+ armed = true;
+ } else
+ cancel();
+ }
+
+ void fire_more() {
+ if (firing)
+ send_command("fire");
+ }
+
+ void fire_down() {
+ if (arm.isEnabled() && arm.isSelected() && armed_count > 0) {
+ firing = true;
+ fire_more();
+ fire_timer.restart();
+ }
+ }
+
+ void fire_up() {
+ firing = false;
+ fire_timer.stop();
+ }
+
+ void set_radio() {
+ try {
+ radio_channel = Integer.parseInt(radio_channel_text.getText());
+ } catch (NumberFormatException ne) {
+ radio_channel_text.setText(String.format("%d", radio_channel));
+ }
+ }
+
+ void set_serial() {
+ try {
+ launcher_serial = Integer.parseInt(launcher_serial_text.getText());
+ AltosPreferences.set_launcher_serial(launcher_serial);
+ send_command("set_remote");
+ } catch (NumberFormatException ne) {
+ launcher_serial_text.setText(String.format("%d", launcher_serial));
+ }
+ }
+
+ void set_channel() {
+ try {
+ launcher_channel = Integer.parseInt(launcher_channel_text.getText());
+ AltosPreferences.set_launcher_serial(launcher_channel);
+ send_command("set_remote");
+ } catch (NumberFormatException ne) {
+ launcher_channel_text.setText(String.format("%d", launcher_channel));
+ }
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ String cmd = e.getActionCommand();
+ System.out.printf("cmd %s\n", cmd);
+ if (cmd.equals("armed") || cmd.equals("igniter")) {
+ stop_arm_timer();
+ }
+
+ if (cmd.equals("arm"))
+ arm();
+ if (cmd.equals("tick_arm"))
+ tick_arm_timer();
+ if (cmd.equals("close"))
+ close();
+ if (cmd.equals("fire_down"))
+ fire_down();
+ if (cmd.equals("fire_up"))
+ fire_up();
+ if (cmd.equals("tick_fire"))
+ fire_more();
+ if (cmd.equals("new_serial"))
+ set_serial();
+ if (cmd.equals("new_channel"))
+ set_channel();
+ }
+
+ /* A window listener to catch closing events and tell the config code */
+ class ConfigListener extends WindowAdapter {
+ AltosLaunchUI ui;
+
+ public ConfigListener(AltosLaunchUI this_ui) {
+ ui = this_ui;
+ }
+
+ public void windowClosing(WindowEvent e) {
+ ui.actionPerformed(new ActionEvent(e.getSource(),
+ ActionEvent.ACTION_PERFORMED,
+ "close"));
+ }
+ }
+
+ private boolean open() {
+ command_queue = new LinkedBlockingQueue<String>();
+
+ device = AltosDeviceDialog.show(owner, Altos.product_any);
+ if (device != null) {
+ LaunchHandler handler = new LaunchHandler(owner);
+ Thread t = new Thread(handler);
+ t.start();
+ return true;
+ }
+ return false;
+ }
+
+ public AltosLaunchUI(JFrame in_owner) {
+
+ launcher_channel = AltosPreferences.launcher_channel();
+ launcher_serial = AltosPreferences.launcher_serial();
+ owner = in_owner;
+ armed_status = AltosLaunch.Unknown;
+ igniter_status = AltosLaunch.Unknown;
+
+ if (!open())
+ return;
+
+ Container pane = getContentPane();
+ GridBagConstraints c = new GridBagConstraints();
+ Insets i = new Insets(4,4,4,4);
+
+ arm_timer = new javax.swing.Timer(arm_timeout, this);
+ arm_timer.setActionCommand("tick_arm");
+ arm_timer.restart();
+
+ fire_timer = new javax.swing.Timer(fire_timeout, this);
+ fire_timer.setActionCommand("tick_fire");
+
+ owner = in_owner;
+
+ pane.setLayout(new GridBagLayout());
+
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.CENTER;
+ c.insets = i;
+ c.weightx = 1;
+ c.weighty = 1;
+
+ c.gridx = 0;
+ c.gridy = 0;
+ c.gridwidth = 2;
+ c.anchor = GridBagConstraints.CENTER;
+ label = new JLabel ("Launch Controller");
+ pane.add(label, c);
+
+ c.gridx = 0;
+ c.gridy = 1;
+ c.gridwidth = 1;
+ c.anchor = GridBagConstraints.WEST;
+ launcher_serial_label = new JLabel("Launcher Serial");
+ pane.add(launcher_serial_label, c);
+
+ c.gridx = 1;
+ c.gridy = 1;
+ c.gridwidth = 1;
+ c.anchor = GridBagConstraints.WEST;
+ launcher_serial_text = new JTextField(7);
+ launcher_serial_text.setText(String.format("%d", launcher_serial));
+ launcher_serial_text.setActionCommand("new_serial");
+ launcher_serial_text.addActionListener(this);
+ pane.add(launcher_serial_text, c);
+
+ c.gridx = 0;
+ c.gridy = 2;
+ c.gridwidth = 1;
+ c.anchor = GridBagConstraints.WEST;
+ launcher_channel_label = new JLabel("Launcher Channel");
+ pane.add(launcher_channel_label, c);
+
+ c.gridx = 1;
+ c.gridy = 2;
+ c.gridwidth = 1;
+ c.anchor = GridBagConstraints.WEST;
+ launcher_channel_text = new JTextField(7);
+ launcher_channel_text.setText(String.format("%d", launcher_channel));
+ launcher_channel_text.setActionCommand("new_channel");
+ launcher_channel_text.addActionListener(this);
+ pane.add(launcher_channel_text, c);
+
+ c.gridx = 0;
+ c.gridy = 3;
+ c.gridwidth = 1;
+ c.anchor = GridBagConstraints.WEST;
+ armed_label = new JLabel ("Armed");
+ pane.add(armed_label, c);
+
+ c.gridx = 1;
+ c.gridy = 3;
+ c.gridwidth = 1;
+ c.anchor = GridBagConstraints.WEST;
+ armed_status_label = new JLabel();
+ pane.add(armed_status_label, c);
+
+ c.gridx = 0;
+ c.gridy = 4;
+ c.gridwidth = 1;
+ c.anchor = GridBagConstraints.WEST;
+ igniter = new JLabel ("Igniter");
+ pane.add(igniter, c);
+
+ c.gridx = 1;
+ c.gridy = 4;
+ c.gridwidth = 1;
+ c.anchor = GridBagConstraints.WEST;
+ igniter_status_label = new JLabel();
+ pane.add(igniter_status_label, c);
+
+ c.gridx = 0;
+ c.gridy = 5;
+ c.gridwidth = 1;
+ c.anchor = GridBagConstraints.CENTER;
+ arm = new JToggleButton ("Arm");
+ pane.add(arm, c);
+ arm.addActionListener(this);
+ arm.setActionCommand("arm");
+ arm.setEnabled(true);
+
+ c.gridx = 1;
+ c.gridy = 5;
+ c.gridwidth = 1;
+ c.anchor = GridBagConstraints.CENTER;
+ fire = new FireButton ("Fire");
+ fire.setEnabled(false);
+ pane.add(fire, c);
+ fire.addActionListener(this);
+ fire.setActionCommand("fire");
+
+ pack();
+ setLocationRelativeTo(owner);
+
+ addWindowListener(new ConfigListener(this));
+
+ setVisible(true);
+ }
+}
\ No newline at end of file
/* font size preferences name */
final static String fontSizePreference = "FONT-SIZE";
+ /* Launcher serial preference name */
+ final static String launcherSerialPreference = "LAUNCHER-SERIAL";
+
+ /* Launcher channel prefernce name */
+ final static String launcherChannelPreference = "LAUNCHER-CHANNEL";
+
/* Default logdir is ~/TeleMetrum */
final static String logdirName = "TeleMetrum";
node.put(String.format(description_format, i), frequencies[i].description);
}
}
+ static int launcher_serial;
+
+ static int launcher_channel;
public static void init() {
preferences = Preferences.userRoot().node("/org/altusmetrum/altosui");
font_size = preferences.getInt(fontSizePreference, Altos.font_size_medium);
Altos.set_fonts(font_size);
+ launcher_serial = preferences.getInt(launcherSerialPreference, 0);
+
+ launcher_channel = preferences.getInt(launcherChannelPreference, 0);
+
String firmwaredir_string = preferences.get(firmwaredirPreference, null);
if (firmwaredir_string != null)
firmwaredir = new File(firmwaredir_string);
return serial_debug;
}
+ public static void set_launcher_serial(int new_launcher_serial) {
+ launcher_serial = new_launcher_serial;
+ System.out.printf("set launcher serial to %d\n", new_launcher_serial);
+ synchronized (preferences) {
+ preferences.putInt(launcherSerialPreference, launcher_serial);
+ flush_preferences();
+ }
+ }
+
+ public static int launcher_serial() {
+ return launcher_serial;
+ }
+
+ public static void set_launcher_channel(int new_launcher_channel) {
+ launcher_channel = new_launcher_channel;
+ System.out.printf("set launcher channel to %d\n", new_launcher_channel);
+ synchronized (preferences) {
+ preferences.putInt(launcherChannelPreference, launcher_channel);
+ flush_preferences();
+ }
+ }
+
+ public static int launcher_channel() {
+ return launcher_channel;
+ }
+
public static Preferences bt_devices() {
return preferences.node("bt_devices");
}
void scan_exception(Exception e) {
if (e instanceof FileNotFoundException) {
JOptionPane.showMessageDialog(owner,
- String.format("Cannot open device \"%s\"",
- device.toShortString()),
+ ((FileNotFoundException) e).getMessage(),
"Cannot open target device",
JOptionPane.ERROR_MESSAGE);
} else if (e instanceof AltosSerialInUseException) {
return true;
} catch (FileNotFoundException ee) {
JOptionPane.showMessageDialog(owner,
- String.format("Cannot open device \"%s\"",
- device.toShortString()),
+ ee.getMessage(),
"Cannot open target device",
JOptionPane.ERROR_MESSAGE);
} catch (AltosSerialInUseException si) {
}
altos = device.open();
if (altos == null) {
+ final String message = device.getErrorString();
close();
- throw new FileNotFoundException(device.toShortString());
+ throw new FileNotFoundException(String.format("%s (%s)",
+ device.toShortString(), message));
}
if (debug)
System.out.printf("Open %s\n", device.getPath());
new AltosFlightUI(voice, reader, device.getSerial());
} catch (FileNotFoundException ee) {
JOptionPane.showMessageDialog(AltosUI.this,
- String.format("Cannot open device \"%s\"",
- device.toShortString()),
+ ee.getMessage(),
"Cannot open target device",
JOptionPane.ERROR_MESSAGE);
} catch (AltosSerialInUseException si) {
});
b.setToolTipText("Check flight readiness of altimeter in idle mode");
+ b = addButton(3, 2, "Launch Controller");
+ b.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ LaunchController();
+ }
+ });
+
setTitle("AltOS");
pane.doLayout();
new AltosSiteMapPreload(AltosUI.this);
}
+ void LaunchController() {
+ new AltosLaunchUI(AltosUI.this);
+ }
+
/*
* Replay a flight from telemetry data
*/
else
return new AltosTelemetryIterable(in);
} catch (FileNotFoundException fe) {
- System.out.printf("Cannot open '%s'\n", filename);
+ System.out.printf("%s\n", fe.getMessage());
return null;
}
}
try {
return new AltosCSV(file);
} catch (FileNotFoundException fe) {
- System.out.printf("Cannot open '%s'\n", filename);
+ System.out.printf("%s\n", fe.getMessage());
return null;
}
}
try {
return new AltosKML(file);
} catch (FileNotFoundException fe) {
- System.out.printf("Cannot open '%s'\n", filename);
+ System.out.printf("%s\n", fe.getMessage());
return null;
}
}
}
+ public String getErrorString() {
+ altos_error error = new altos_error();
+
+ libaltos.altos_get_last_error(error);
+ return String.format("%s (%d)", error.getString(), error.getCode());
+ }
+
public SWIGTYPE_p_altos_file open() {
return libaltos.altos_open(this);
}
AltosIdleMonitorUI.java \
AltosIgnite.java \
AltosIgniteUI.java \
+ AltosLaunch.java \
+ AltosLaunchUI.java \
AltosInfoTable.java \
AltosKML.java \
AltosLanded.java \
AltosGraphUI.java \
AltosDataChooser.java \
AltosVersion.java \
- AltosVoice.java
+ AltosVoice.java \
+ $(altosui_BT)
JFREECHART_CLASS= \
jfreechart.jar
{
}
+static struct altos_error last_error;
+
+static void
+altos_set_last_error(int code, char *string)
+{
+ last_error.code = code;
+ strncpy(last_error.string, string, sizeof (last_error.string) -1);
+ last_error.string[sizeof(last_error.string)-1] = '\0';
+}
+
+PUBLIC void
+altos_get_last_error(struct altos_error *error)
+{
+ *error = last_error;
+}
+
#ifdef DARWIN
#undef USE_POLL
int in_read;
};
+static void
+altos_set_last_posix_error(void)
+{
+ altos_set_last_error(errno, strerror(errno));
+}
+
PUBLIC struct altos_file *
altos_open(struct altos_device *device)
{
int ret;
struct termios term;
- if (!file)
+ if (!file) {
+ altos_set_last_posix_error();
return NULL;
+ }
+
+// altos_set_last_error(12, "yeah yeah, failed again");
+// free(file);
+// return NULL;
file->fd = open(device->path, O_RDWR | O_NOCTTY);
if (file->fd < 0) {
- perror(device->path);
+ altos_set_last_posix_error();
free(file);
return NULL;
}
#else
file->out_fd = open(device->path, O_RDWR | O_NOCTTY);
if (file->out_fd < 0) {
- perror(device->path);
+ altos_set_last_posix_error();
close(file->fd);
free(file);
return NULL;
#endif
ret = tcgetattr(file->fd, &term);
if (ret < 0) {
- perror("tcgetattr");
+ altos_set_last_posix_error();
close(file->fd);
#ifndef USE_POLL
close(file->out_fd);
#endif
ret = tcsetattr(file->fd, TCSAFLUSH, &term);
if (ret < 0) {
- perror("tcsetattr");
+ altos_set_last_posix_error();
close(file->fd);
#ifndef USE_POLL
close(file->out_fd);
#else
ret = write (file->out_fd, file->out_data, file->out_used);
#endif
- if (ret < 0)
+ if (ret < 0) {
+ altos_set_last_posix_error();
return -errno;
+ }
if (ret) {
memmove(file->out_data, file->out_data + ret,
file->out_used - ret);
fd[1].events = POLLIN;
ret = poll(fd, 2, timeout);
if (ret < 0) {
- perror("altos_getchar");
+ altos_set_last_posix_error();
return LIBALTOS_ERROR;
}
if (ret == 0)
{
ret = read(file->fd, file->in_data, USB_BUF_SIZE);
if (ret < 0) {
- perror("altos_getchar");
+ altos_set_last_posix_error();
return LIBALTOS_ERROR;
}
file->in_read = 0;
free(usbdevs);
}
-#if HAS_BLUETOOTH
struct altos_bt_list {
inquiry_info *ii;
int sock;
if (!file)
goto no_file;
file->fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
- if (file->fd < 0)
+ if (file->fd < 0) {
+ altos_set_last_posix_error();
goto no_sock;
+ }
addr.rc_family = AF_BLUETOOTH;
addr.rc_channel = 1;
(struct sockaddr *)&addr,
sizeof(addr));
if (status < 0) {
- perror("connect");
+ altos_set_last_posix_error();
goto no_link;
}
sleep(1);
no_file:
return NULL;
}
-#endif /* HAS_BLUETOOTH */
#endif
free(list);
}
+struct altos_bt_list {
+ 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)
+{
+ return NULL;
+}
+
+int
+altos_bt_list_next(struct altos_bt_list *bt_list,
+ struct altos_bt_device *device)
+{
+ return 0;
+}
+
+void
+altos_bt_list_finish(struct altos_bt_list *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)
+{
+ return NULL;
+}
+
#endif
OVERLAPPED ov_write;
};
+static void
+altos_set_last_windows_error(void)
+{
+ DWORD error = GetLastError();
+ TCHAR message[1024];
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
+ 0,
+ error,
+ 0,
+ message,
+ sizeof (message) / sizeof (TCHAR),
+ NULL);
+ altos_set_last_error(error, message);
+}
+
PUBLIC struct altos_list *
altos_list_start(void)
{
list->dev_info = SetupDiGetClassDevs(NULL, "USB", NULL,
DIGCF_ALLCLASSES|DIGCF_PRESENT);
if (list->dev_info == INVALID_HANDLE_VALUE) {
- printf("SetupDiGetClassDevs failed %ld\n", GetLastError());
+ altos_set_last_windows_error();
free(list);
return NULL;
}
DICS_FLAG_GLOBAL, 0, DIREG_DEV,
KEY_READ);
if (dev_key == INVALID_HANDLE_VALUE) {
+ altos_set_last_windows_error();
printf("cannot open device registry key\n");
continue;
}
result = RegQueryValueEx(dev_key, "SymbolicName", NULL, NULL,
symbolic, &symbolic_len);
if (result != 0) {
+ altos_set_last_windows_error();
printf("cannot find SymbolicName value\n");
RegCloseKey(dev_key);
continue;
port, &port_len);
RegCloseKey(dev_key);
if (result != 0) {
+ altos_set_last_windows_error();
printf("failed to get PortName\n");
continue;
}
sizeof(friendlyname),
&friendlyname_len))
{
+ altos_set_last_windows_error();
printf("Failed to get friendlyname\n");
continue;
}
return 1;
}
result = GetLastError();
- if (result != ERROR_NO_MORE_ITEMS)
+ if (result != ERROR_NO_MORE_ITEMS) {
+ altos_set_last_windows_error();
printf ("SetupDiEnumDeviceInfo failed error %d\n", (int) result);
+ }
return 0;
}
return LIBALTOS_SUCCESS;
if (!ReadFile(file->handle, file->in_data, USB_BUF_SIZE, &got, &file->ov_read)) {
- if (GetLastError() != ERROR_IO_PENDING)
+ if (GetLastError() != ERROR_IO_PENDING) {
+ altos_set_last_windows_error();
return LIBALTOS_ERROR;
+ }
file->pend_read = TRUE;
} else {
file->pend_read = FALSE;
ret = WaitForSingleObject(file->ov_read.hEvent, timeout);
switch (ret) {
case WAIT_OBJECT_0:
- if (!GetOverlappedResult(file->handle, &file->ov_read, &got, FALSE))
+ if (!GetOverlappedResult(file->handle, &file->ov_read, &got, FALSE)) {
+ altos_set_last_windows_error();
return LIBALTOS_ERROR;
+ }
file->pend_read = FALSE;
file->in_read = 0;
file->in_used = got;
while (used) {
if (!WriteFile(file->handle, data, used, &put, &file->ov_write)) {
- if (GetLastError() != ERROR_IO_PENDING)
+ if (GetLastError() != ERROR_IO_PENDING) {
+ altos_set_last_windows_error();
return LIBALTOS_ERROR;
+ }
ret = WaitForSingleObject(file->ov_write.hEvent, INFINITE);
switch (ret) {
case WAIT_OBJECT_0:
- if (!GetOverlappedResult(file->handle, &file->ov_write, &put, FALSE))
+ if (!GetOverlappedResult(file->handle, &file->ov_write, &put, FALSE)) {
+ altos_set_last_windows_error();
return LIBALTOS_ERROR;
+ }
break;
default:
+ altos_set_last_windows_error();
return LIBALTOS_ERROR;
}
}
0, NULL, OPEN_EXISTING,
FILE_FLAG_OVERLAPPED, NULL);
if (file->handle == INVALID_HANDLE_VALUE) {
+ altos_set_last_windows_error();
free(file);
return NULL;
}
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
if (!GetCommState(file->handle, &dcbSerialParams)) {
+ altos_set_last_windows_error();
CloseHandle(file->handle);
free(file);
return NULL;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity = NOPARITY;
if (!SetCommState(file->handle, &dcbSerialParams)) {
+ altos_set_last_windows_error();
CloseHandle(file->handle);
free(file);
return NULL;
return file->in_data[file->in_read++];
}
+struct altos_bt_list *
+altos_bt_list_start(int inquiry_time)
+{
+ return NULL;
+}
+
+int
+altos_bt_list_next(struct altos_bt_list *bt_list,
+ struct altos_bt_device *device)
+{
+ return 0;
+}
+
+void
+altos_bt_list_finish(struct altos_bt_list *bt_list)
+{
+ 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)
+{
+ return NULL;
+}
+
#endif
//%mutable;
};
+struct altos_error {
+ int code;
+ char string[1024];
+};
+
#define LIBALTOS_SUCCESS 0
#define LIBALTOS_ERROR -1
#define LIBALTOS_TIMEOUT -2
PUBLIC void
altos_fini(void);
+PUBLIC void
+altos_get_last_error(struct altos_error *error);
+
PUBLIC struct altos_list *
altos_list_start(void);
PUBLIC int
altos_getchar(struct altos_file *file, int timeout);
-// #define HAS_BLUETOOTH 1
-#if HAS_BLUETOOTH
-
PUBLIC struct altos_bt_list *
altos_bt_list_start(int inquiry_time);
PUBLIC struct altos_file *
altos_bt_open(struct altos_bt_device *device);
-#endif
-
#endif /* _LIBALTOS_H_ */
dnl Process this file with autoconf to create configure.
AC_PREREQ(2.57)
-AC_INIT([altos], 1.0.1)
-AC_CONFIG_SRCDIR([src/ao.h])
+AC_INIT([altos], 1.0.9.0)
+AC_CONFIG_SRCDIR([src/core/ao.h])
AM_INIT_AUTOMAKE([foreign dist-bzip2])
AM_MAINTAINER_MODE
+++ /dev/null
-/*
- * Copyright © 2009 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.
- */
-
-/* Defines for the 25LC1024 1Mbit SPI Bus Serial EEPROM */
-
-#ifndef _25LC1024_H_
-#define _25LC1024_H_
-
-#define EE_READ 0x03
-#define EE_WRITE 0x02
-#define EE_WREN 0x06
-#define EE_WRDI 0x04
-#define EE_RDSR 0x05
-#define EE_WRSR 0x01
-#define EE_PE 0x42
-#define EE_SE 0xd8
-#define EE_CE 0xc7
-#define EE_RDID 0xab
-#define EE_DPD 0xb9
-
-#define EE_STATUS_WIP (1 << 0)
-#define EE_STATUS_WEL (1 << 1)
-#define EE_STATUS_BP0 (1 << 2)
-#define EE_STATUS_BP1 (1 << 3)
-#define EE_STATUS_WPEN (1 << 7)
-
-#endif /* _25LC1024_H_ */
# AltOS build
#
#
-CC=sdcc
+
+vpath make-altitude util
+vpath make-kalman util
+vpath kalman.5c kalman
+vpath kalman_filter.5c kalman
+vpath load_csv.5c kalman
+vpath matrix.5c kalman
include Version
telemini-v1.0 telenano-v0.1 \
telebt-v0.0 telebt-v0.1 \
telemetrum-v0.1-sky telemetrum-v0.1-sirf \
- tidongle test
+ telelaunch-v0.1 \
+ tidongle test telescience-v0.1 telepyro-v0.1
-all: all-recursive
+all: all-local all-recursive
RECURSIVE_TARGETS = all-recursive clean-recursive install-recursive
distclean: clean
-clean: clean-recursive
+clean: clean-local clean-recursive
install: install-recursive
uninstall:
+
+all-recursive: all-local
+
+all-local: altitude.h ao_kalman.h
+
+altitude.h: make-altitude
+ nickle $< > $@
+
+ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c
+ bash $< kalman > $@
+
+clean-local:
+ rm -f altitude.h ao_kalman.h
+++ /dev/null
-#
-# AltOS build
-#
-#
-vpath %.c ..
-vpath %.h ..
-vpath make-altitude ..
-vpath make-kalman ..
-vpath kalman.5c ../kalman
-vpath kalman_filter.5c ../kalman
-vpath load_csv.5c ../kalman
-vpath matrix.5c ../kalman
-vpath ao-make-product.5c ..
-
-CC=sdcc
-
-ifndef VERSION
-include ../Version
-endif
-
-CFLAGS=--model-small --debug --opt-code-speed -DCODESIZE=$(CODESIZE)
-
-CODESIZE ?= 0x8000
-
-LDFLAGS=--out-fmt-ihx --code-loc 0x0000 --code-size $(CODESIZE) \
- --xram-loc 0xf000 --xram-size 0xda2 --iram-size 0xff
-
-INC = \
- ao.h \
- ao_pins.h \
- cc1111.h \
- altitude.h \
- ao_kalman.h \
- 25lc1024.h
-
-#
-# Common AltOS sources
-#
-ALTOS_SRC = \
- ao_cmd.c \
- ao_dma.c \
- ao_mutex.c \
- ao_panic.c \
- ao_task.c \
- ao_timer.c \
- ao_romconfig.c \
- _bp.c
-
-#
-# Shared AltOS drivers
-#
-ALTOS_DRIVER_SRC = \
- ao_config.c \
- ao_led.c \
- ao_radio.c \
- ao_stdio.c
-
-BEEP_DRIVER_SRC = \
- ao_beep.c
-
-USB_DRIVER_SRC = \
- ao_usb.c
-
-TELE_COMMON_SRC = \
- ao_packet.c
-
-#
-# Receiver code
-#
-TELE_RECEIVER_SRC =\
- ao_monitor.c \
- ao_gps_print.c \
- ao_packet_master.c \
- ao_state.c \
- ao_rssi.c
-
-#
-# Shared Tele drivers (on TeleMetrum, TeleTerra, TeleDongle)
-#
-
-TELE_DRIVER_SRC = \
- ao_convert.c
-
-#
-# Serial port driver
-#
-SERIAL_DRIVER_SRC = \
- ao_serial.c
-
-#
-# Spi bus driver
-#
-SPI_DRIVER_SRC = \
- ao_spi.c
-
-#
-# Debug dongle driver (only on TI)
-#
-DBG_SRC = \
- ao_dbg.c
-
-#
-# Drivers only on TeleMetrum
-#
-TM_DRIVER_SRC = \
- ao_adc.c \
- ao_gps_report.c \
- ao_ignite.c \
- ao_packet_slave.c \
- $(BEEP_DRIVER_SRC) \
- $(USB_DRIVER_SRC)
-
-#
-# 25LC1024 driver source
-EE_DRIVER_SRC = \
- ao_storage.c \
- ao_ee.c
-
-#
-# AT45DB161D driver source
-
-FLASH_DRIVER_SRC = \
- ao_storage.c \
- ao_flash.c
-
-#
-# Numonyx M25P80 driver source
-#
-
-M25_DRIVER_SRC = \
- ao_storage.c \
- ao_m25.c
-
-#
-# SiRF driver source
-#
-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
-
-#
-# Companion port driver source
-#
-COMPANION_SRC = \
- ao_companion.c
-
-#
-# Tasks run on TeleMetrum
-#
-TM_TASK_SRC = \
- ao_flight.c \
- ao_sample.c \
- ao_kalman.c \
- ao_log.c \
- ao_log_big.c \
- ao_report.c \
- ao_telemetry.c
-
-TM_MAIN_SRC = \
- ao_telemetrum.c
-
-#
-# Base sources for TeleMetrum
-#
-TM_BASE_SRC = \
- $(ALTOS_SRC) \
- $(ALTOS_DRIVER_SRC) \
- $(TELE_DRIVER_SRC) \
- $(SERIAL_DRIVER_SRC) \
- $(TELE_COMMON_SRC) \
- $(TM_DRIVER_SRC) \
- $(TM_TASK_SRC) \
- $(TM_MAIN_SRC)
-
-#
-# Sources for TeleMini
-TMINI_DRIVER_SRC = \
- ao_adc.c \
- ao_ignite.c \
- ao_config.c \
- ao_storage.c \
- ao_packet_slave.c \
- ao_intflash.c
-
-TMINI_TASK_SRC = \
- ao_flight.c \
- ao_sample.c \
- ao_kalman.c \
- ao_log.c \
- ao_log_tiny.c \
- ao_report.c \
- ao_telemetry.c
-
-TMINI_MAIN_SRC = \
- ao_telemini.c
-
-TMINI_BASE_SRC = \
- $(ALTOS_SRC) \
- $(ALTOS_DRIVER_SRC) \
- $(TELE_DRIVER_SRC) \
- $(TELE_COMMON_SRC) \
- $(TMINI_DRIVER_SRC) \
- $(TMINI_TASK_SRC) \
- $(TMINI_MAIN_SRC)
-
-#
-# Sources for TeleNano
-TNANO_DRIVER_SRC = \
- ao_adc.c \
- ao_config.c \
- ao_storage.c \
- ao_packet_slave.c \
- ao_intflash.c
-
-TNANO_TASK_SRC = \
- ao_flight_nano.c \
- ao_sample.c \
- ao_kalman.c \
- ao_log.c \
- ao_log_tiny.c \
- ao_report.c \
- ao_telemetry.c
-
-TNANO_MAIN_SRC = \
- ao_telenano.c
-
-TNANO_BASE_SRC = \
- $(ALTOS_SRC) \
- $(ALTOS_DRIVER_SRC) \
- $(TELE_DRIVER_SRC) \
- $(TELE_COMMON_SRC) \
- $(TNANO_DRIVER_SRC) \
- $(TNANO_TASK_SRC) \
- $(TNANO_MAIN_SRC)
-
-#
-# Sources for TeleBluetooth
-#
-
-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)
-
-TBT_V_0_1_SRC = \
- $(TBT_BASE_SRC) \
- $(SPI_DRIVER_SRC) \
- $(M25_DRIVER_SRC) \
- $(BEEP_DRIVER_SRC) \
- ao_log_telem.c
-
-#
-# TI Dongle sources
-#
-TI_MAIN_SRC = \
- ao_tidongle.c
-
-#
-# All sources for the TI debug dongle
-#
-TI_SRC = \
- $(ALTOS_SRC) \
- $(ALTOS_DRIVER_SRC) \
- $(TELE_RECEIVER_SRC) \
- $(TELE_COMMON_SRC) \
- $(USB_DRIVER_SRC) \
- $(TI_MAIN_SRC) \
- $(DBG_SRC)
-
-TT_MAIN_SRC = \
- ao_teleterra.c
-#
-# All sources for TeleTerra
-#
-TT_SRC = \
- $(ALTOS_SRC) \
- $(ALTOS_DRIVER_SRC) \
- $(TELE_RECEIVER_SRC) \
- $(TELE_DRIVER_SRC) \
- $(TELE_COMMON_SRC) \
- $(USB_DRIVER_SRC) \
- $(TT_MAIN_SRC)
-
-
-#
-# Sources for TeleDongle
-#
-
-TD_MAIN_SRC = \
- ao_teledongle.c
-
-TD_SRC = \
- $(ALTOS_SRC) \
- $(ALTOS_DRIVER_SRC) \
- $(TELE_RECEIVER_SRC) \
- $(TELE_COMMON_SRC) \
- $(USB_DRIVER_SRC) \
- $(TD_MAIN_SRC)
-
-include Makefile.defs
-
-CFLAGS += $(PRODUCT_DEF) -I.
-
-NICKLE=nickle
-CHECK_STACK=sh ../check-stack
-
-REL=$(SRC:.c=.rel) ao_product.rel
-ADB=$(REL:.rel=.adb)
-ASM=$(REL:.rel=.asm)
-LNK=$(REL:.rel=.lnk)
-LST=$(REL:.rel=.lst)
-RST=$(REL:.rel=.rst)
-SYM=$(REL:.rel=.sym)
-
-PCDB=$(PROG:.ihx=.cdb)
-PLNK=$(PROG:.ihx=.lnk)
-PMAP=$(PROG:.ihx=.map)
-PMEM=$(PROG:.ihx=.mem)
-PAOM=$(PROG:.ihx=)
-
-V=0
-# The user has explicitly enabled quiet compilation.
-ifeq ($(V),0)
-quiet = @printf " $1 $2 $@\n"; $($1)
-endif
-# Otherwise, print the full command line.
-quiet ?= $($1)
-
-%.rel : %.c $(INC)
- $(call quiet,CC,$(PRODUCT_DEF)) $(CFLAGS) -c -o$@ $<
-
-all: ../$(PROG)
-
-../$(PROG): $(REL) Makefile Makefile.defs ../Makefile.proto
- $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) ..
- $(call quiet,CHECK_STACK) ../ao.h $(PMEM)
-
-../altitude.h: make-altitude
- nickle $< > $@
-
-../ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c
- sh $< > $@
-
-ao_product.h: ao-make-product.5c ../Version
- $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
-
-$(REL): ao_product.h
-
-distclean: clean
-
-clean:
- rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM)
- rm -f $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM)
- rm -f ao_product.h
- rm -f ../$(PROG)
-
-install:
-
-uninstall:
+++ /dev/null
-/*-------------------------------------------------------------------------
-
- _bp.c :- just declares bp as a variable
-
- Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999)
-
- This library is free software; you can redistribute it and/or modify it
- under the terms of the GNU Library General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- This library 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 Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public License
- along with this program; if not, write to the Free Software
- Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
- In other words, you are welcome to use, share and improve this program.
- You are forbidden to forbid anyone else to use, share and improve
- what you give them. Help stamp out software-hoarding!
--------------------------------------------------------------------------*/
-
-__data unsigned char bp ;
+++ /dev/null
-/*max error 3.197865153490684 at 0.782%. Average error 0.260150920474668*/
-#define NALT 129
-#define ALT_FRAC_BITS 8
- 15835, /* 10.56 kPa 0.000% */
- 15332, /* 11.42 kPa 0.781% */
- 14868, /* 12.29 kPa 1.563% */
- 14435, /* 13.16 kPa 2.344% */
- 14030, /* 14.02 kPa 3.125% */
- 13649, /* 14.90 kPa 3.906% */
- 13290, /* 15.76 kPa 4.688% */
- 12950, /* 16.63 kPa 5.469% */
- 12627, /* 17.50 kPa 6.250% */
- 12320, /* 18.37 kPa 7.031% */
- 12027, /* 19.24 kPa 7.813% */
- 11747, /* 20.10 kPa 8.594% */
- 11479, /* 20.97 kPa 9.375% */
- 11222, /* 21.84 kPa 10.156% */
- 10975, /* 22.71 kPa 10.938% */
- 10736, /* 23.58 kPa 11.719% */
- 10504, /* 24.44 kPa 12.500% */
- 10278, /* 25.31 kPa 13.281% */
- 10059, /* 26.18 kPa 14.063% */
- 9846, /* 27.05 kPa 14.844% */
- 9638, /* 27.91 kPa 15.625% */
- 9435, /* 28.78 kPa 16.406% */
- 9237, /* 29.65 kPa 17.188% */
- 9044, /* 30.52 kPa 17.969% */
- 8855, /* 31.39 kPa 18.750% */
- 8670, /* 32.26 kPa 19.531% */
- 8490, /* 33.13 kPa 20.313% */
- 8313, /* 33.99 kPa 21.094% */
- 8140, /* 34.86 kPa 21.875% */
- 7970, /* 35.73 kPa 22.656% */
- 7803, /* 36.60 kPa 23.438% */
- 7640, /* 37.47 kPa 24.219% */
- 7480, /* 38.33 kPa 25.000% */
- 7322, /* 39.20 kPa 25.781% */
- 7168, /* 40.07 kPa 26.563% */
- 7016, /* 40.94 kPa 27.344% */
- 6867, /* 41.80 kPa 28.125% */
- 6720, /* 42.67 kPa 28.906% */
- 6575, /* 43.54 kPa 29.688% */
- 6433, /* 44.41 kPa 30.469% */
- 6294, /* 45.28 kPa 31.250% */
- 6156, /* 46.15 kPa 32.031% */
- 6020, /* 47.01 kPa 32.813% */
- 5887, /* 47.88 kPa 33.594% */
- 5755, /* 48.75 kPa 34.375% */
- 5625, /* 49.62 kPa 35.156% */
- 5497, /* 50.49 kPa 35.938% */
- 5371, /* 51.35 kPa 36.719% */
- 5247, /* 52.22 kPa 37.500% */
- 5124, /* 53.09 kPa 38.281% */
- 5003, /* 53.96 kPa 39.063% */
- 4883, /* 54.83 kPa 39.844% */
- 4765, /* 55.69 kPa 40.625% */
- 4648, /* 56.56 kPa 41.406% */
- 4533, /* 57.43 kPa 42.188% */
- 4419, /* 58.30 kPa 42.969% */
- 4307, /* 59.17 kPa 43.750% */
- 4196, /* 60.03 kPa 44.531% */
- 4086, /* 60.90 kPa 45.313% */
- 3977, /* 61.77 kPa 46.094% */
- 3870, /* 62.63 kPa 46.875% */
- 3764, /* 63.51 kPa 47.656% */
- 3659, /* 64.38 kPa 48.438% */
- 3555, /* 65.24 kPa 49.219% */
- 3453, /* 66.11 kPa 50.000% */
- 3351, /* 66.98 kPa 50.781% */
- 3250, /* 67.85 kPa 51.563% */
- 3151, /* 68.72 kPa 52.344% */
- 3052, /* 69.58 kPa 53.125% */
- 2955, /* 70.45 kPa 53.906% */
- 2858, /* 71.32 kPa 54.688% */
- 2763, /* 72.19 kPa 55.469% */
- 2668, /* 73.06 kPa 56.250% */
- 2574, /* 73.92 kPa 57.031% */
- 2482, /* 74.79 kPa 57.813% */
- 2390, /* 75.66 kPa 58.594% */
- 2298, /* 76.52 kPa 59.375% */
- 2208, /* 77.40 kPa 60.156% */
- 2119, /* 78.26 kPa 60.938% */
- 2030, /* 79.13 kPa 61.719% */
- 1942, /* 80.00 kPa 62.500% */
- 1855, /* 80.87 kPa 63.281% */
- 1769, /* 81.74 kPa 64.063% */
- 1683, /* 82.60 kPa 64.844% */
- 1598, /* 83.47 kPa 65.625% */
- 1514, /* 84.34 kPa 66.406% */
- 1430, /* 85.21 kPa 67.188% */
- 1347, /* 86.08 kPa 67.969% */
- 1265, /* 86.94 kPa 68.750% */
- 1184, /* 87.81 kPa 69.531% */
- 1103, /* 88.68 kPa 70.313% */
- 1023, /* 89.55 kPa 71.094% */
- 943, /* 90.41 kPa 71.875% */
- 864, /* 91.28 kPa 72.656% */
- 786, /* 92.15 kPa 73.438% */
- 708, /* 93.02 kPa 74.219% */
- 631, /* 93.89 kPa 75.000% */
- 554, /* 94.76 kPa 75.781% */
- 478, /* 95.63 kPa 76.563% */
- 403, /* 96.49 kPa 77.344% */
- 328, /* 97.36 kPa 78.125% */
- 254, /* 98.23 kPa 78.906% */
- 180, /* 99.10 kPa 79.688% */
- 106, /* 99.97 kPa 80.469% */
- 34, /* 100.83 kPa 81.250% */
- -39, /* 101.70 kPa 82.031% */
- -111, /* 102.57 kPa 82.813% */
- -182, /* 103.44 kPa 83.594% */
- -253, /* 104.30 kPa 84.375% */
- -323, /* 105.17 kPa 85.156% */
- -393, /* 106.04 kPa 85.938% */
- -462, /* 106.91 kPa 86.719% */
- -531, /* 107.78 kPa 87.500% */
- -600, /* 108.65 kPa 88.281% */
- -668, /* 109.51 kPa 89.063% */
- -736, /* 110.38 kPa 89.844% */
- -803, /* 111.25 kPa 90.625% */
- -870, /* 112.12 kPa 91.406% */
- -936, /* 112.99 kPa 92.188% */
- -1002, /* 113.85 kPa 92.969% */
- -1068, /* 114.72 kPa 93.750% */
- -1133, /* 115.59 kPa 94.531% */
- -1198, /* 116.46 kPa 95.313% */
- -1262, /* 117.33 kPa 96.094% */
- -1326, /* 118.19 kPa 96.875% */
- -1389, /* 119.06 kPa 97.656% */
- -1453, /* 119.93 kPa 98.438% */
- -1516, /* 120.80 kPa 99.219% */
- -1578, /* 121.67 kPa 100.000% */
+++ /dev/null
-#!/bin/sh
-
-autoimport ParseArgs;
-
-void
-write_ucs2(string a, string description)
-{
- int len = String::length(a);
-
- printf("/* %s */\n", description);
- printf("#define AO_%s_LEN 0x%02x\n", description, len * 2 + 2);
- printf("#define AO_%s_STRING \"%s\"\n", description, a);
- printf("#define AO_%s_UCS2", description);
- for (int i = 0; i < len; i++) {
- int c = a[i];
- if (i > 0)
- printf(",");
- if (0x20 <= c && c < 128)
- printf(" '%c', 0", c);
- else
- printf(" LE_WORD(0x%04x),", c);
- }
- printf("\n\n");
-}
-
-void
-write_string(string a, string description)
-{
- printf ("/* %s */\n", description);
- printf ("#define AO_%s_STRING \"%s\"\n", description, a);
-}
-
-void
-write_int(int a, string description)
-{
- printf ("/* %s */\n", description);
- printf ("#define AO_%s_NUMBER %d\n\n", description, a);
-}
-
-void
-write_hex(int a, string description)
-{
- printf ("/* %s */\n", description);
- printf ("#define AO_%s_NUMBER 0x%04x\n\n", description, a);
-}
-
-string manufacturer = "altusmetrum.org";
-string product = "TeleMetrum";
-string version = "0.0";
-int serial = 1;
-int user_argind = 0;
-int id_product = 0x000a;
-
-argdesc argd = {
- .args = {
- {
- .var = { .arg_string = &manufacturer },
- .abbr = 'm',
- .name = "manufacturer",
- .expr_name = "manf",
- .desc = "Manufacturer name." },
- {
- .var = { .arg_string = &product },
- .abbr = 'p',
- .name = "product",
- .expr_name = "prod",
- .desc = "Product name." },
- {
- .var = { .arg_int = &id_product },
- .abbr = 'i',
- .name = "id_product",
- .expr_name = "id_p",
- .desc = "Product ID." },
- {
- .var = { .arg_int = &serial },
- .abbr = 's',
- .name = "serial",
- .expr_name = "number",
- .desc = "Serial number." },
- {
- .var = { .arg_string = &version },
- .abbr = 'v',
- .name = "version",
- .expr_name = "string",
- .desc = "Program version." },
- },
- .prog_name = "usb descriptors",
-};
-
-void
-main()
-{
- string[dim(argv)-1] nargv = {[n] = argv[n+1]};
- parseargs(&argd, &nargv);
- write_ucs2(manufacturer, "iManufacturer");
- write_ucs2(product, "iProduct");
- write_ucs2(sprintf("%06d", serial), "iSerial");
- write_int(serial, "iSerial");
- write_hex(id_product, "idProduct");
- write_string(version, "iVersion");
-}
-
-main();
+++ /dev/null
-/*
- * Copyright © 2009 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.
- */
-
-#ifndef _AO_H_
-#define _AO_H_
-
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <stddef.h>
-#include "cc1111.h"
-#include "ao_pins.h"
-
-#define TRUE 1
-#define FALSE 0
-
-/* Convert a __data pointer into an __xdata pointer */
-#define DATA_TO_XDATA(a) ((void __xdata *) ((uint8_t) (a) | 0xff00))
-
-/* Stack runs from above the allocated __data space to 0xfe, which avoids
- * writing to 0xff as that triggers the stack overflow indicator
- */
-#define AO_STACK_START 0x90
-#define AO_STACK_END 0xfe
-#define AO_STACK_SIZE (AO_STACK_END - AO_STACK_START + 1)
-
-/* An AltOS task */
-struct ao_task {
- __xdata void *wchan; /* current wait channel (NULL if running) */
- uint16_t alarm; /* abort ao_sleep time */
- uint8_t stack_count; /* amount of saved stack */
- uint8_t task_id; /* unique id */
- __code char *name; /* task name */
- uint8_t stack[AO_STACK_SIZE]; /* saved stack */
-};
-
-extern __xdata struct ao_task *__data ao_cur_task;
-
-#define AO_NUM_TASKS 16 /* maximum number of tasks */
-#define AO_NO_TASK 0 /* no task id */
-
-/*
- ao_task.c
- */
-
-/* Suspend the current task until wchan is awoken.
- * returns:
- * 0 on normal wake
- * 1 on alarm
- */
-uint8_t
-ao_sleep(__xdata void *wchan);
-
-/* Wake all tasks sleeping on wchan */
-void
-ao_wakeup(__xdata void *wchan);
-
-/* set an alarm to go off in 'delay' ticks */
-void
-ao_alarm(uint16_t delay);
-
-/* Yield the processor to another task */
-void
-ao_yield(void) __naked;
-
-/* Add a task to the run queue */
-void
-ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant;
-
-/* Terminate the current task */
-void
-ao_exit(void);
-
-/* Dump task info to console */
-void
-ao_task_info(void);
-
-/* Start the scheduler. This will not return */
-void
-ao_start_scheduler(void);
-
-/*
- * ao_panic.c
- */
-
-#define AO_PANIC_NO_TASK 1 /* AO_NUM_TASKS is not large enough */
-#define AO_PANIC_DMA 2 /* Attempt to start DMA while active */
-#define AO_PANIC_MUTEX 3 /* Mis-using mutex API */
-#define AO_PANIC_EE 4 /* Mis-using eeprom API */
-#define AO_PANIC_LOG 5 /* Failing to read/write log data */
-#define AO_PANIC_CMD 6 /* Too many command sets registered */
-#define AO_PANIC_STDIO 7 /* Too many stdio handlers registered */
-#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
-ao_panic(uint8_t reason);
-
-/*
- * ao_timer.c
- */
-
-/* Our timer runs at 100Hz */
-#define AO_HERTZ 100
-#define AO_MS_TO_TICKS(ms) ((ms) / (1000 / AO_HERTZ))
-#define AO_SEC_TO_TICKS(s) ((s) * AO_HERTZ)
-
-/* Returns the current time in ticks */
-uint16_t
-ao_time(void);
-
-/* Suspend the current task until ticks time has passed */
-void
-ao_delay(uint16_t ticks);
-
-/* Set the ADC interval */
-void
-ao_timer_set_adc_interval(uint8_t interval) __critical;
-
-/* Timer interrupt */
-void
-ao_timer_isr(void) __interrupt 9;
-
-/* Initialize the timer */
-void
-ao_timer_init(void);
-
-/* Initialize the hardware clock. Must be called first */
-void
-ao_clock_init(void);
-
-/*
- * One set of samples read from the A/D converter or telemetry
- */
-struct ao_adc {
- uint16_t tick; /* tick when the sample was read */
- int16_t accel; /* accelerometer */
- int16_t pres; /* pressure sensor */
- int16_t temp; /* temperature sensor */
- int16_t v_batt; /* battery voltage */
- int16_t sense_d; /* drogue continuity sense */
- int16_t sense_m; /* main continuity sense */
-};
-
-#ifndef HAS_ADC
-#error Please define HAS_ADC
-#endif
-
-#if HAS_ADC
-
-#if HAS_ACCEL
-#ifndef HAS_ACCEL_REF
-#error Please define HAS_ACCEL_REF
-#endif
-#else
-#define HAS_ACCEL_REF 0
-#endif
-
-/*
- * ao_adc.c
- */
-
-#define AO_ADC_RING 32
-#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1))
-#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1))
-
-
-/*
- * A/D data is stored in a ring, with the next sample to be written
- * at ao_adc_head
- */
-extern volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING];
-extern volatile __data uint8_t ao_adc_head;
-#if HAS_ACCEL_REF
-extern volatile __xdata uint16_t ao_accel_ref[AO_ADC_RING];
-#endif
-
-/* Trigger a conversion sequence (called from the timer interrupt) */
-void
-ao_adc_poll(void);
-
-/* Suspend the current task until another A/D sample is converted */
-void
-ao_adc_sleep(void);
-
-/* Get a copy of the last complete A/D sample set */
-void
-ao_adc_get(__xdata struct ao_adc *packet);
-
-/* The A/D interrupt handler */
-
-void
-ao_adc_isr(void) __interrupt 1;
-
-/* Initialize the A/D converter */
-void
-ao_adc_init(void);
-
-#endif /* HAS_ADC */
-
-/*
- * ao_beep.c
- */
-
-/*
- * Various pre-defined beep frequencies
- *
- * frequency = 1/2 (24e6/32) / beep
- */
-
-#define AO_BEEP_LOW 150 /* 2500Hz */
-#define AO_BEEP_MID 94 /* 3989Hz */
-#define AO_BEEP_HIGH 75 /* 5000Hz */
-#define AO_BEEP_OFF 0 /* off */
-
-#define AO_BEEP_g 240 /* 1562.5Hz */
-#define AO_BEEP_gs 227 /* 1652Hz (1655Hz) */
-#define AO_BEEP_aa 214 /* 1752Hz (1754Hz) */
-#define AO_BEEP_bbf 202 /* 1856Hz (1858Hz) */
-#define AO_BEEP_bb 190 /* 1974Hz (1969Hz) */
-#define AO_BEEP_cc 180 /* 2083Hz (2086Hz) */
-#define AO_BEEP_ccs 170 /* 2205Hz (2210Hz) */
-#define AO_BEEP_dd 160 /* 2344Hz (2341Hz) */
-#define AO_BEEP_eef 151 /* 2483Hz (2480Hz) */
-#define AO_BEEP_ee 143 /* 2622Hz (2628Hz) */
-#define AO_BEEP_ff 135 /* 2778Hz (2784Hz) */
-#define AO_BEEP_ffs 127 /* 2953Hz (2950Hz) */
-#define AO_BEEP_gg 120 /* 3125Hz */
-#define AO_BEEP_ggs 113 /* 3319Hz (3311Hz) */
-#define AO_BEEP_aaa 107 /* 3504Hz (3508Hz) */
-#define AO_BEEP_bbbf 101 /* 3713Hz (3716Hz) */
-#define AO_BEEP_bbb 95 /* 3947Hz (3937Hz) */
-#define AO_BEEP_ccc 90 /* 4167Hz (4171Hz) */
-#define AO_BEEP_cccs 85 /* 4412Hz (4419Hz) */
-#define AO_BEEP_ddd 80 /* 4688Hz (4682Hz) */
-#define AO_BEEP_eeef 76 /* 4934Hz (4961Hz) */
-#define AO_BEEP_eee 71 /* 5282Hz (5256Hz) */
-#define AO_BEEP_fff 67 /* 5597Hz (5568Hz) */
-#define AO_BEEP_fffs 64 /* 5859Hz (5899Hz) */
-#define AO_BEEP_ggg 60 /* 6250Hz */
-
-/* Set the beeper to the specified tone */
-void
-ao_beep(uint8_t beep);
-
-/* Turn on the beeper for the specified time */
-void
-ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant;
-
-/* Initialize the beeper */
-void
-ao_beep_init(void);
-
-/*
- * ao_led.c
- */
-
-#define AO_LED_NONE 0
-
-/* Turn on the specified LEDs */
-void
-ao_led_on(uint8_t colors);
-
-/* Turn off the specified LEDs */
-void
-ao_led_off(uint8_t colors);
-
-/* Set all of the LEDs to the specified state */
-void
-ao_led_set(uint8_t colors);
-
-/* Toggle the specified LEDs */
-void
-ao_led_toggle(uint8_t colors);
-
-/* Turn on the specified LEDs for the indicated interval */
-void
-ao_led_for(uint8_t colors, uint16_t ticks) __reentrant;
-
-/* Initialize the LEDs */
-void
-ao_led_init(uint8_t enable);
-
-/*
- * ao_romconfig.c
- */
-
-#define AO_ROMCONFIG_VERSION 2
-
-extern __code __at (0x00a0) uint16_t ao_romconfig_version;
-extern __code __at (0x00a2) uint16_t ao_romconfig_check;
-extern __code __at (0x00a4) uint16_t ao_serial_number;
-extern __code __at (0x00a6) uint32_t ao_radio_cal;
-
-#ifndef HAS_USB
-#error Please define HAS_USB
-#endif
-
-#if HAS_USB
-extern __code __at (0x00aa) uint8_t ao_usb_descriptors [];
-#endif
-
-/*
- * ao_usb.c
- */
-
-/* Put one character to the USB output queue */
-void
-ao_usb_putchar(char c);
-
-/* Get one character from the USB input queue */
-char
-ao_usb_getchar(void);
-
-/* Poll for a charcter on the USB input queue.
- * returns AO_READ_AGAIN if none are available
- */
-char
-ao_usb_pollchar(void);
-
-/* Flush the USB output queue */
-void
-ao_usb_flush(void);
-
-#if HAS_USB
-/* USB interrupt handler */
-void
-ao_usb_isr(void) __interrupt 6;
-#endif
-
-/* Enable the USB controller */
-void
-ao_usb_enable(void);
-
-/* Disable the USB controller */
-void
-ao_usb_disable(void);
-
-/* Initialize the USB system */
-void
-ao_usb_init(void);
-
-/*
- * ao_cmd.c
- */
-
-enum ao_cmd_status {
- ao_cmd_success = 0,
- ao_cmd_lex_error = 1,
- ao_cmd_syntax_error = 2,
-};
-
-extern __pdata uint16_t ao_cmd_lex_i;
-extern __pdata uint32_t ao_cmd_lex_u32;
-extern __pdata char ao_cmd_lex_c;
-extern __pdata enum ao_cmd_status ao_cmd_status;
-
-void
-ao_cmd_lex(void);
-
-void
-ao_cmd_put8(uint8_t v);
-
-void
-ao_cmd_put16(uint16_t v);
-
-void
-ao_cmd_white(void);
-
-void
-ao_cmd_hex(void);
-
-void
-ao_cmd_decimal(void);
-
-uint8_t
-ao_match_word(__code char *word);
-
-struct ao_cmds {
- void (*func)(void);
- __code char *help;
-};
-
-void
-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
- */
-
-/* Allocate a DMA channel. the 'done' parameter will be set when the
- * dma is finished and will be used to wakeup any waiters
- */
-
-uint8_t
-ao_dma_alloc(__xdata uint8_t * done);
-
-/* Setup a DMA channel */
-void
-ao_dma_set_transfer(uint8_t id,
- void __xdata *srcaddr,
- void __xdata *dstaddr,
- uint16_t count,
- uint8_t cfg0,
- uint8_t cfg1);
-
-/* Start a DMA channel */
-void
-ao_dma_start(uint8_t id);
-
-/* Manually trigger a DMA channel */
-void
-ao_dma_trigger(uint8_t id);
-
-/* Abort a running DMA transfer */
-void
-ao_dma_abort(uint8_t id);
-
-/* DMA interrupt routine */
-void
-ao_dma_isr(void) __interrupt 8;
-
-/*
- * ao_mutex.c
- */
-
-void
-ao_mutex_get(__xdata uint8_t *ao_mutex) __reentrant;
-
-void
-ao_mutex_put(__xdata uint8_t *ao_mutex) __reentrant;
-
-/*
- * Storage interface, provided by one of the eeprom or flash
- * drivers
- */
-
-/* Total bytes of available storage */
-extern __pdata uint32_t ao_storage_total;
-
-/* Block size - device is erased in these units. At least 256 bytes */
-extern __pdata uint32_t ao_storage_block;
-
-/* Byte offset of config block. Will be ao_storage_block bytes long */
-extern __pdata uint32_t ao_storage_config;
-
-/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */
-extern __pdata uint16_t ao_storage_unit;
-
-#define AO_STORAGE_ERASE_LOG (ao_storage_config + AO_CONFIG_MAX_SIZE)
-
-/* Initialize above values. Can only be called once the OS is running */
-void
-ao_storage_setup(void) __reentrant;
-
-/* Write data. Returns 0 on failure, 1 on success */
-uint8_t
-ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant;
-
-/* Read data. Returns 0 on failure, 1 on success */
-uint8_t
-ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant;
-
-/* Erase a block of storage. This always clears ao_storage_block bytes */
-uint8_t
-ao_storage_erase(uint32_t pos) __reentrant;
-
-/* Flush any pending writes to stable storage */
-void
-ao_storage_flush(void) __reentrant;
-
-/* Initialize the storage code */
-void
-ao_storage_init(void);
-
-/*
- * Low-level functions wrapped by ao_storage.c
- */
-
-/* Read data within a storage unit */
-uint8_t
-ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant;
-
-/* Write data within a storage unit */
-uint8_t
-ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant;
-
-/* Initialize low-level device bits */
-void
-ao_storage_device_init(void);
-
-/* Print out information about flash chips */
-void
-ao_storage_device_info(void) __reentrant;
-
-/*
- * ao_log.c
- */
-
-/* We record flight numbers in the first record of
- * the log. Tasks may wait for this to be initialized
- * by sleeping on this variable.
- */
-extern __xdata uint16_t ao_flight_number;
-
-extern __pdata uint32_t ao_log_current_pos;
-extern __pdata uint32_t ao_log_end_pos;
-extern __pdata uint32_t ao_log_start_pos;
-extern __xdata uint8_t ao_log_running;
-extern __pdata enum flight_state ao_log_state;
-
-/* required functions from the underlying log system */
-
-#define AO_LOG_FORMAT_UNKNOWN 0 /* unknown; altosui will have to guess */
-#define AO_LOG_FORMAT_FULL 1 /* 8 byte typed log records */
-#define AO_LOG_FORMAT_TINY 2 /* two byte state/baro records */
-#define AO_LOG_FORMAT_TELEMETRY 3 /* 32 byte ao_telemetry records */
-#define AO_LOG_FORMAT_TELESCIENCE 4 /* 32 byte typed telescience records */
-#define AO_LOG_FORMAT_NONE 127 /* No log at all */
-
-extern __code uint8_t ao_log_format;
-
-/* Return the flight number from the given log slot, 0 if none */
-uint16_t
-ao_log_flight(uint8_t slot);
-
-/* Flush the log */
-void
-ao_log_flush(void);
-
-/* Logging thread main routine */
-void
-ao_log(void);
-
-/* functions provided in ao_log.c */
-
-/* Figure out the current flight number */
-void
-ao_log_scan(void) __reentrant;
-
-/* Return the position of the start of the given log slot */
-uint32_t
-ao_log_pos(uint8_t slot);
-
-/* Start logging to eeprom */
-void
-ao_log_start(void);
-
-/* Stop logging */
-void
-ao_log_stop(void);
-
-/* Initialize the logging system */
-void
-ao_log_init(void);
-
-/* Write out the current flight number to the erase log */
-void
-ao_log_write_erase(uint8_t pos);
-
-/* Returns true if there are any logs stored in eeprom */
-uint8_t
-ao_log_present(void);
-
-/* Returns true if there is no more storage space available */
-uint8_t
-ao_log_full(void);
-
-/*
- * ao_log_big.c
- */
-
-/*
- * The data log is recorded in the eeprom as a sequence
- * of data packets.
- *
- * Each packet starts with a 4-byte header that has the
- * packet type, the packet checksum and the tick count. Then
- * they all contain 2 16 bit values which hold packet-specific
- * data.
- *
- * For each flight, the first packet
- * is FLIGHT packet, indicating the serial number of the
- * device and a unique number marking the number of flights
- * recorded by this device.
- *
- * During flight, data from the accelerometer and barometer
- * are recorded in SENSOR packets, using the raw 16-bit values
- * read from the A/D converter.
- *
- * Also during flight, but at a lower rate, the deployment
- * sensors are recorded in DEPLOY packets. The goal here is to
- * detect failure in the deployment circuits.
- *
- * STATE packets hold state transitions as the flight computer
- * transitions through different stages of the flight.
- */
-#define AO_LOG_FLIGHT 'F'
-#define AO_LOG_SENSOR 'A'
-#define AO_LOG_TEMP_VOLT 'T'
-#define AO_LOG_DEPLOY 'D'
-#define AO_LOG_STATE 'S'
-#define AO_LOG_GPS_TIME 'G'
-#define AO_LOG_GPS_LAT 'N'
-#define AO_LOG_GPS_LON 'W'
-#define AO_LOG_GPS_ALT 'H'
-#define AO_LOG_GPS_SAT 'V'
-#define AO_LOG_GPS_DATE 'Y'
-
-#define AO_LOG_POS_NONE (~0UL)
-
-struct ao_log_record {
- char type;
- uint8_t csum;
- uint16_t tick;
- union {
- struct {
- int16_t ground_accel;
- uint16_t flight;
- } flight;
- struct {
- int16_t accel;
- int16_t pres;
- } sensor;
- struct {
- int16_t temp;
- int16_t v_batt;
- } temp_volt;
- struct {
- int16_t drogue;
- int16_t main;
- } deploy;
- struct {
- uint16_t state;
- uint16_t reason;
- } state;
- struct {
- uint8_t hour;
- uint8_t minute;
- uint8_t second;
- uint8_t flags;
- } gps_time;
- int32_t gps_latitude;
- int32_t gps_longitude;
- struct {
- int16_t altitude;
- uint16_t unused;
- } gps_altitude;
- struct {
- uint16_t svid;
- uint8_t unused;
- uint8_t c_n;
- } gps_sat;
- struct {
- uint8_t year;
- uint8_t month;
- uint8_t day;
- uint8_t extra;
- } gps_date;
- struct {
- uint16_t d0;
- uint16_t d1;
- } anon;
- } u;
-};
-
-/* Write a record to the eeprom log */
-uint8_t
-ao_log_data(__xdata struct ao_log_record *log) __reentrant;
-
-/*
- * ao_flight.c
- */
-
-enum ao_flight_state {
- ao_flight_startup = 0,
- ao_flight_idle = 1,
- ao_flight_pad = 2,
- ao_flight_boost = 3,
- ao_flight_fast = 4,
- ao_flight_coast = 5,
- ao_flight_drogue = 6,
- ao_flight_main = 7,
- ao_flight_landed = 8,
- ao_flight_invalid = 9
-};
-
-extern __pdata enum ao_flight_state ao_flight_state;
-
-extern __pdata uint16_t ao_launch_time;
-extern __pdata uint8_t ao_flight_force_idle;
-
-/* Flight thread */
-void
-ao_flight(void);
-
-/* Initialize flight thread */
-void
-ao_flight_init(void);
-
-/*
- * ao_flight_nano.c
- */
-
-void
-ao_flight_nano_init(void);
-
-/*
- * ao_sample.c
- */
-
-/*
- * Barometer calibration
- *
- * We directly sample the barometer. The specs say:
- *
- * Pressure range: 15-115 kPa
- * Voltage at 115kPa: 2.82
- * Output scale: 27mV/kPa
- *
- * If we want to detect launch with the barometer, we need
- * a large enough bump to not be fooled by noise. At typical
- * launch elevations (0-2000m), a 200Pa pressure change cooresponds
- * to about a 20m elevation change. This is 5.4mV, or about 3LSB.
- * As all of our calculations are done in 16 bits, we'll actually see a change
- * of 16 times this though
- *
- * 27 mV/kPa * 32767 / 3300 counts/mV = 268.1 counts/kPa
- */
-
-/* Accelerometer calibration
- *
- * We're sampling the accelerometer through a resistor divider which
- * consists of 5k and 10k resistors. This multiplies the values by 2/3.
- * That goes into the cc1111 A/D converter, which is running at 11 bits
- * of precision with the bits in the MSB of the 16 bit value. Only positive
- * values are used, so values should range from 0-32752 for 0-3.3V. The
- * specs say we should see 40mV/g (uncalibrated), multiply by 2/3 for what
- * the A/D converter sees (26.67 mV/g). We should see 32752/3300 counts/mV,
- * for a final computation of:
- *
- * 26.67 mV/g * 32767/3300 counts/mV = 264.8 counts/g
- *
- * Zero g was measured at 16000 (we would expect 16384).
- * Note that this value is only require to tell if the
- * rocket is standing upright. Once that is determined,
- * the value of the accelerometer is averaged for 100 samples
- * to find the resting accelerometer value, which is used
- * for all further flight computations
- */
-
-#define GRAVITY 9.80665
-
-/*
- * Above this height, the baro sensor doesn't work
- */
-#define AO_MAX_BARO_HEIGHT 12000
-
-/*
- * Above this speed, baro measurements are unreliable
- */
-#define AO_MAX_BARO_SPEED 200
-
-#define ACCEL_NOSE_UP (ao_accel_2g >> 2)
-
-/*
- * Speed and acceleration are scaled by 16 to provide a bit more
- * resolution while still having reasonable range. Note that this
- * limits speed to 2047m/s (around mach 6) and acceleration to
- * 2047m/s² (over 200g)
- */
-
-#define AO_M_TO_HEIGHT(m) ((int16_t) (m))
-#define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16))
-#define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16))
-
-extern __pdata uint16_t ao_sample_tick; /* time of last data */
-extern __pdata int16_t ao_sample_pres; /* most recent pressure sensor reading */
-extern __pdata int16_t ao_sample_alt; /* MSL of ao_sample_pres */
-extern __pdata int16_t ao_sample_height; /* AGL of ao_sample_pres */
-extern __data uint8_t ao_sample_adc; /* Ring position of last processed sample */
-
-#if HAS_ACCEL
-extern __pdata int16_t ao_sample_accel; /* most recent accel sensor reading */
-#endif
-
-extern __pdata int16_t ao_ground_pres; /* startup pressure */
-extern __pdata int16_t ao_ground_height; /* MSL of ao_ground_pres */
-
-#if HAS_ACCEL
-extern __pdata int16_t ao_ground_accel; /* startup acceleration */
-extern __pdata int16_t ao_accel_2g; /* factory accel calibration */
-extern __pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */
-#endif
-
-void ao_sample_init(void);
-
-/* returns FALSE in preflight mode, TRUE in flight mode */
-uint8_t ao_sample(void);
-
-/*
- * ao_kalman.c
- */
-
-#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5))
-#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5))
-#define from_fix(x) ((x) >> 16)
-
-extern __pdata int16_t ao_height; /* meters */
-extern __pdata int16_t ao_speed; /* m/s * 16 */
-extern __pdata int16_t ao_accel; /* m/s² * 16 */
-extern __pdata int16_t ao_max_height; /* max of ao_height */
-extern __pdata int16_t ao_avg_height; /* running average of height */
-
-extern __pdata int16_t ao_error_h;
-extern __pdata int16_t ao_error_h_sq_avg;
-
-#if HAS_ACCEL
-extern __pdata int16_t ao_error_a;
-#endif
-
-void ao_kalman(void);
-
-/*
- * ao_report.c
- */
-
-void
-ao_report_init(void);
-
-/*
- * ao_convert.c
- *
- * Given raw data, convert to SI units
- */
-
-/* pressure from the sensor to altitude in meters */
-int16_t
-ao_pres_to_altitude(int16_t pres) __reentrant;
-
-int16_t
-ao_altitude_to_pres(int16_t alt) __reentrant;
-
-int16_t
-ao_temp_to_dC(int16_t temp) __reentrant;
-
-/*
- * ao_dbg.c
- *
- * debug another telemetrum board
- */
-
-/* Send a byte to the dbg target */
-void
-ao_dbg_send_byte(uint8_t byte);
-
-/* Receive a byte from the dbg target */
-uint8_t
-ao_dbg_recv_byte(void);
-
-/* Start a bulk transfer to/from dbg target memory */
-void
-ao_dbg_start_transfer(uint16_t addr);
-
-/* End a bulk transfer to/from dbg target memory */
-void
-ao_dbg_end_transfer(void);
-
-/* Write a byte to dbg target memory */
-void
-ao_dbg_write_byte(uint8_t byte);
-
-/* Read a byte from dbg target memory */
-uint8_t
-ao_dbg_read_byte(void);
-
-/* Enable dbg mode, switching use of the pins */
-void
-ao_dbg_debug_mode(void);
-
-/* Reset the dbg target */
-void
-ao_dbg_reset(void);
-
-void
-ao_dbg_init(void);
-
-/*
- * ao_serial.c
- */
-
-#ifndef HAS_SERIAL_1
-#error Please define HAS_SERIAL_1
-#endif
-
-#if HAS_SERIAL_1
-#ifndef USE_SERIAL_STDIN
-#error Please define USE_SERIAL_STDIN
-#endif
-
-void
-ao_serial_rx1_isr(void) __interrupt 3;
-
-void
-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_19200 2
-#define AO_SERIAL_SPEED_57600 3
-
-void
-ao_serial_set_speed(uint8_t speed);
-
-void
-ao_serial_init(void);
-#endif
-
-/*
- * ao_spi.c
- */
-
-extern __xdata uint8_t ao_spi_mutex;
-
-#define ao_spi_get_mask(reg,mask) do {\
- ao_mutex_get(&ao_spi_mutex); \
- (reg) &= ~(mask); \
- } while (0)
-
-#define ao_spi_put_mask(reg,mask) do { \
- (reg) |= (mask); \
- ao_mutex_put(&ao_spi_mutex); \
- } while (0)
-
-#define ao_spi_get_bit(bit) do {\
- ao_mutex_get(&ao_spi_mutex); \
- (bit) = 0; \
- } while (0)
-
-#define ao_spi_put_bit(bit) do { \
- (bit) = 1; \
- ao_mutex_put(&ao_spi_mutex); \
- } while (0)
-
-/*
- * The SPI mutex must be held to call either of these
- * functions -- this mutex covers the entire SPI operation,
- * from chip select low to chip select high
- */
-
-void
-ao_spi_send(void __xdata *block, uint16_t len) __reentrant;
-
-void
-ao_spi_recv(void __xdata *block, uint16_t len) __reentrant;
-
-void
-ao_spi_init(void);
-
-/*
- * ao_telemetry.c
- */
-#define AO_MAX_CALLSIGN 8
-#define AO_MAX_VERSION 8
-#define AO_MAX_TELEMETRY 128
-
-struct ao_telemetry_generic {
- uint16_t serial; /* 0 */
- uint16_t tick; /* 2 */
- uint8_t type; /* 4 */
- uint8_t payload[27]; /* 5 */
- /* 32 */
-};
-
-#define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01
-#define AO_TELEMETRY_SENSOR_TELEMINI 0x02
-#define AO_TELEMETRY_SENSOR_TELENANO 0x03
-
-struct ao_telemetry_sensor {
- uint16_t serial; /* 0 */
- uint16_t tick; /* 2 */
- uint8_t type; /* 4 */
-
- uint8_t state; /* 5 flight state */
- int16_t accel; /* 6 accelerometer (TM only) */
- int16_t pres; /* 8 pressure sensor */
- int16_t temp; /* 10 temperature sensor */
- int16_t v_batt; /* 12 battery voltage */
- int16_t sense_d; /* 14 drogue continuity sense (TM/Tm) */
- int16_t sense_m; /* 16 main continuity sense (TM/Tm) */
-
- int16_t acceleration; /* 18 m/s² * 16 */
- int16_t speed; /* 20 m/s * 16 */
- int16_t height; /* 22 m */
-
- int16_t ground_pres; /* 24 average pres on pad */
- int16_t ground_accel; /* 26 average accel on pad */
- int16_t accel_plus_g; /* 28 accel calibration at +1g */
- int16_t accel_minus_g; /* 30 accel calibration at -1g */
- /* 32 */
-};
-
-#define AO_TELEMETRY_CONFIGURATION 0x04
-
-struct ao_telemetry_configuration {
- uint16_t serial; /* 0 */
- uint16_t tick; /* 2 */
- uint8_t type; /* 4 */
-
- uint8_t device; /* 5 device type */
- uint16_t flight; /* 6 flight number */
- uint8_t config_major; /* 8 Config major version */
- uint8_t config_minor; /* 9 Config minor version */
- uint16_t apogee_delay; /* 10 Apogee deploy delay in seconds */
- uint16_t main_deploy; /* 12 Main deploy alt in meters */
- uint16_t flight_log_max; /* 14 Maximum flight log size in kB */
- char callsign[AO_MAX_CALLSIGN]; /* 16 Radio operator identity */
- char version[AO_MAX_VERSION]; /* 24 Software version */
- /* 32 */
-};
-
-#define AO_TELEMETRY_LOCATION 0x05
-
-#define AO_GPS_MODE_NOT_VALID 'N'
-#define AO_GPS_MODE_AUTONOMOUS 'A'
-#define AO_GPS_MODE_DIFFERENTIAL 'D'
-#define AO_GPS_MODE_ESTIMATED 'E'
-#define AO_GPS_MODE_MANUAL 'M'
-#define AO_GPS_MODE_SIMULATED 'S'
-
-struct ao_telemetry_location {
- uint16_t serial; /* 0 */
- uint16_t tick; /* 2 */
- uint8_t type; /* 4 */
-
- uint8_t flags; /* 5 Number of sats and other flags */
- int16_t altitude; /* 6 GPS reported altitude (m) */
- int32_t latitude; /* 8 latitude (degrees * 10⁷) */
- int32_t longitude; /* 12 longitude (degrees * 10⁷) */
- uint8_t year; /* 16 (- 2000) */
- uint8_t month; /* 17 (1-12) */
- uint8_t day; /* 18 (1-31) */
- uint8_t hour; /* 19 (0-23) */
- uint8_t minute; /* 20 (0-59) */
- uint8_t second; /* 21 (0-59) */
- uint8_t pdop; /* 22 (m * 5) */
- uint8_t hdop; /* 23 (m * 5) */
- uint8_t vdop; /* 24 (m * 5) */
- uint8_t mode; /* 25 */
- uint16_t ground_speed; /* 26 cm/s */
- int16_t climb_rate; /* 28 cm/s */
- uint8_t course; /* 30 degrees / 2 */
- uint8_t unused[1]; /* 31 */
- /* 32 */
-};
-
-#define AO_TELEMETRY_SATELLITE 0x06
-
-struct ao_telemetry_satellite_info {
- uint8_t svid;
- uint8_t c_n_1;
-};
-
-struct ao_telemetry_satellite {
- uint16_t serial; /* 0 */
- uint16_t tick; /* 2 */
- uint8_t type; /* 4 */
- uint8_t channels; /* 5 number of reported sats */
-
- struct ao_telemetry_satellite_info sats[12]; /* 6 */
- uint8_t unused[2]; /* 30 */
- /* 32 */
-};
-
-#define AO_TELEMETRY_COMPANION 0x07
-
-#define AO_COMPANION_MAX_CHANNELS 12
-
-struct ao_telemetry_companion {
- uint16_t serial; /* 0 */
- uint16_t tick; /* 2 */
- uint8_t type; /* 4 */
- uint8_t board_id; /* 5 */
-
- uint8_t update_period; /* 6 */
- uint8_t channels; /* 7 */
- uint16_t companion_data[AO_COMPANION_MAX_CHANNELS]; /* 8 */
- /* 32 */
-};
-
-union ao_telemetry_all {
- struct ao_telemetry_generic generic;
- struct ao_telemetry_sensor sensor;
- struct ao_telemetry_configuration configuration;
- struct ao_telemetry_location location;
- struct ao_telemetry_satellite satellite;
- struct ao_telemetry_companion companion;
-};
-
-/*
- * ao_gps.c
- */
-
-#define AO_GPS_NUM_SAT_MASK (0xf << 0)
-#define AO_GPS_NUM_SAT_SHIFT (0)
-
-#define AO_GPS_VALID (1 << 4)
-#define AO_GPS_RUNNING (1 << 5)
-#define AO_GPS_DATE_VALID (1 << 6)
-#define AO_GPS_COURSE_VALID (1 << 7)
-
-extern __pdata uint16_t ao_gps_tick;
-extern __xdata uint8_t ao_gps_mutex;
-extern __xdata struct ao_telemetry_location ao_gps_data;
-extern __xdata struct ao_telemetry_satellite ao_gps_tracking_data;
-
-struct ao_gps_orig {
- uint8_t year;
- uint8_t month;
- uint8_t day;
- uint8_t hour;
- uint8_t minute;
- uint8_t second;
- uint8_t flags;
- int32_t latitude; /* degrees * 10⁷ */
- int32_t longitude; /* degrees * 10⁷ */
- int16_t altitude; /* m */
- uint16_t ground_speed; /* cm/s */
- uint8_t course; /* degrees / 2 */
- uint8_t hdop; /* * 5 */
- int16_t climb_rate; /* cm/s */
- uint16_t h_error; /* m */
- uint16_t v_error; /* m */
-};
-
-struct ao_gps_sat_orig {
- uint8_t svid;
- uint8_t c_n_1;
-};
-
-#define AO_MAX_GPS_TRACKING 12
-
-struct ao_gps_tracking_orig {
- uint8_t channels;
- struct ao_gps_sat_orig sats[AO_MAX_GPS_TRACKING];
-};
-
-void
-ao_gps(void);
-
-void
-ao_gps_print(__xdata struct ao_gps_orig *gps_data);
-
-void
-ao_gps_tracking_print(__xdata struct ao_gps_tracking_orig *gps_tracking_data);
-
-void
-ao_gps_init(void);
-
-/*
- * ao_gps_report.c
- */
-
-void
-ao_gps_report(void);
-
-void
-ao_gps_report_init(void);
-
-/*
- * ao_telemetry_orig.c
- */
-
-struct ao_telemetry_orig {
- uint16_t serial;
- uint16_t flight;
- uint8_t flight_state;
- int16_t accel;
- int16_t ground_accel;
- union {
- struct {
- int16_t speed;
- int16_t unused;
- } k;
- int32_t flight_vel;
- } u;
- int16_t height;
- int16_t ground_pres;
- int16_t accel_plus_g;
- int16_t accel_minus_g;
- struct ao_adc adc;
- struct ao_gps_orig gps;
- char callsign[AO_MAX_CALLSIGN];
- struct ao_gps_tracking_orig gps_tracking;
-};
-
-struct ao_telemetry_tiny {
- uint16_t serial;
- uint16_t flight;
- uint8_t flight_state;
- int16_t height; /* AGL in meters */
- int16_t speed; /* in m/s * 16 */
- int16_t accel; /* in m/s² * 16 */
- int16_t ground_pres; /* sensor units */
- struct ao_adc adc; /* raw ADC readings */
- char callsign[AO_MAX_CALLSIGN];
-};
-
-/*
- * ao_radio_recv tacks on rssi and status bytes
- */
-
-struct ao_telemetry_raw_recv {
- uint8_t packet[AO_MAX_TELEMETRY + 2];
-};
-
-struct ao_telemetry_orig_recv {
- struct ao_telemetry_orig telemetry_orig;
- int8_t rssi;
- uint8_t status;
-};
-
-struct ao_telemetry_tiny_recv {
- struct ao_telemetry_tiny telemetry_tiny;
- int8_t rssi;
- uint8_t status;
-};
-
-/* Set delay between telemetry reports (0 to disable) */
-
-#define AO_TELEMETRY_INTERVAL_PAD AO_MS_TO_TICKS(1000)
-#define AO_TELEMETRY_INTERVAL_FLIGHT AO_MS_TO_TICKS(100)
-#define AO_TELEMETRY_INTERVAL_RECOVER AO_MS_TO_TICKS(1000)
-
-void
-ao_telemetry_set_interval(uint16_t interval);
-
-void
-ao_rdf_set(uint8_t rdf);
-
-void
-ao_telemetry_init(void);
-
-void
-ao_telemetry_orig_init(void);
-
-void
-ao_telemetry_tiny_init(void);
-
-/*
- * ao_radio.c
- */
-
-extern __xdata uint8_t ao_radio_dma;
-extern __xdata uint8_t ao_radio_dma_done;
-extern __xdata uint8_t ao_radio_done;
-extern __xdata uint8_t ao_radio_mutex;
-
-void
-ao_radio_general_isr(void) __interrupt 16;
-
-void
-ao_radio_get(uint8_t len);
-
-#define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
-
-void
-ao_radio_set_packet(void);
-
-void
-ao_radio_send(__xdata void *data, uint8_t size) __reentrant;
-
-uint8_t
-ao_radio_recv(__xdata void *data, uint8_t size) __reentrant;
-
-void
-ao_radio_recv_abort(void);
-
-void
-ao_radio_rdf(int ms);
-
-void
-ao_radio_rdf_abort(void);
-
-void
-ao_radio_idle(void);
-
-void
-ao_radio_init(void);
-
-/*
- * ao_monitor.c
- */
-
-extern const char const * const ao_state_names[];
-
-void
-ao_monitor(void);
-
-#define AO_MONITORING_OFF 0
-#define AO_MONITORING_ORIG 1
-#define AO_MONITORING_TINY 2
-
-void
-ao_set_monitor(uint8_t monitoring);
-
-void
-ao_monitor_init(uint8_t led, uint8_t monitoring) __reentrant;
-
-/*
- * ao_stdio.c
- */
-
-#define AO_READ_AGAIN ((char) -1)
-
-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 __pdata int8_t ao_cur_stdio;
-extern __pdata int8_t ao_num_stdios;
-
-void
-flush(void);
-
-extern __xdata uint8_t ao_stdin_ready;
-
-uint8_t
-ao_echo(void);
-
-int8_t
-ao_add_stdio(char (*pollchar)(void),
- void (*putchar)(char) __reentrant,
- void (*flush)(void)) __reentrant;
-
-/*
- * ao_ignite.c
- */
-
-enum ao_igniter {
- ao_igniter_drogue = 0,
- ao_igniter_main = 1
-};
-
-void
-ao_ignite(enum ao_igniter igniter);
-
-enum ao_igniter_status {
- ao_igniter_unknown, /* unknown status (ambiguous voltage) */
- ao_igniter_ready, /* continuity detected */
- ao_igniter_active, /* igniter firing */
- ao_igniter_open, /* open circuit detected */
-};
-
-enum ao_igniter_status
-ao_igniter_status(enum ao_igniter igniter);
-
-void
-ao_ignite_set_pins(void);
-
-void
-ao_igniter_init(void);
-
-/*
- * ao_config.c
- */
-
-#define AO_CONFIG_MAJOR 1
-#define AO_CONFIG_MINOR 8
-
-struct ao_config {
- uint8_t major;
- uint8_t minor;
- uint16_t main_deploy;
- int16_t accel_plus_g; /* changed for minor version 2 */
- uint8_t radio_channel;
- char callsign[AO_MAX_CALLSIGN + 1];
- uint8_t apogee_delay; /* minor version 1 */
- int16_t accel_minus_g; /* minor version 2 */
- uint32_t radio_cal; /* minor version 3 */
- uint32_t flight_log_max; /* minor version 4 */
- uint8_t ignite_mode; /* minor version 5 */
- uint8_t pad_orientation; /* minor version 6 */
- uint32_t radio_setting; /* minor version 7 */
- uint8_t radio_enable; /* minor version 8 */
-};
-
-#define AO_IGNITE_MODE_DUAL 0
-#define AO_IGNITE_MODE_APOGEE 1
-#define AO_IGNITE_MODE_MAIN 2
-
-#define AO_PAD_ORIENTATION_ANTENNA_UP 0
-#define AO_PAD_ORIENTATION_ANTENNA_DOWN 1
-
-extern __xdata struct ao_config ao_config;
-
-#define AO_CONFIG_MAX_SIZE 128
-
-void
-ao_config_get(void);
-
-void
-ao_config_put(void);
-
-void
-ao_config_init(void);
-
-/*
- * ao_rssi.c
- */
-
-void
-ao_rssi_set(int rssi_value);
-
-void
-ao_rssi_init(uint8_t rssi_led);
-
-/*
- * ao_product.c
- *
- * values which need to be defined for
- * each instance of a product
- */
-
-extern const char ao_version[];
-extern const char ao_manufacturer[];
-extern const char ao_product[];
-
-/*
- * Fifos
- */
-
-#define AO_FIFO_SIZE 32
-
-struct ao_fifo {
- uint8_t insert;
- uint8_t remove;
- char fifo[AO_FIFO_SIZE];
-};
-
-#define ao_fifo_insert(f,c) do { \
- (f).fifo[(f).insert] = (c); \
- (f).insert = ((f).insert + 1) & (AO_FIFO_SIZE-1); \
-} while(0)
-
-#define ao_fifo_remove(f,c) do {\
- c = (f).fifo[(f).remove]; \
- (f).remove = ((f).remove + 1) & (AO_FIFO_SIZE-1); \
-} while(0)
-
-#define ao_fifo_full(f) ((((f).insert + 1) & (AO_FIFO_SIZE-1)) == (f).remove)
-#define ao_fifo_empty(f) ((f).insert == (f).remove)
-
-/*
- * ao_packet.c
- *
- * Packet-based command interface
- */
-
-#define AO_PACKET_MAX 64
-#define AO_PACKET_SYN (uint8_t) 0xff
-
-struct ao_packet {
- uint8_t addr;
- uint8_t len;
- uint8_t seq;
- uint8_t ack;
- uint8_t d[AO_PACKET_MAX];
- uint8_t callsign[AO_MAX_CALLSIGN];
-};
-
-struct ao_packet_recv {
- struct ao_packet packet;
- int8_t rssi;
- uint8_t status;
-};
-
-extern __xdata struct ao_packet_recv ao_rx_packet;
-extern __xdata struct ao_packet ao_tx_packet;
-extern __xdata struct ao_task ao_packet_task;
-extern __xdata uint8_t ao_packet_enable;
-extern __xdata uint8_t ao_packet_master_sleeping;
-extern __pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used;
-
-void
-ao_packet_send(void);
-
-uint8_t
-ao_packet_recv(void);
-
-void
-ao_packet_flush(void);
-
-void
-ao_packet_putchar(char c) __reentrant;
-
-char
-ao_packet_pollchar(void) __critical;
-
-/* ao_packet_master.c */
-
-void
-ao_packet_master_init(void);
-
-/* ao_packet_slave.c */
-
-void
-ao_packet_slave_start(void);
-
-void
-ao_packet_slave_stop(void);
-
-void
-ao_packet_slave_init(uint8_t enable);
-
-/* ao_btm.c */
-
-/* If bt_link is on P2, this interrupt is shared by USB, so the USB
- * code calls this function. Otherwise, it's a regular ISR.
- */
-
-void
-ao_btm_isr(void)
-#if BT_LINK_ON_P1
- __interrupt 15
-#endif
- ;
-
-void
-ao_btm_init(void);
-
-/* ao_companion.c */
-
-#define AO_COMPANION_SETUP 1
-#define AO_COMPANION_FETCH 2
-#define AO_COMPANION_NOTIFY 3
-
-struct ao_companion_command {
- uint8_t command;
- uint8_t flight_state;
- uint16_t tick;
- uint16_t serial;
- uint16_t flight;
-};
-
-struct ao_companion_setup {
- uint16_t board_id;
- uint16_t board_id_inverse;
- uint8_t update_period;
- uint8_t channels;
-};
-
-extern __pdata uint8_t ao_companion_running;
-extern __xdata struct ao_companion_setup ao_companion_setup;
-extern __xdata uint8_t ao_companion_mutex;
-extern __xdata uint16_t ao_companion_data[AO_COMPANION_MAX_CHANNELS];
-
-void
-ao_companion_init(void);
-
-#endif /* _AO_H_ */
+++ /dev/null
-/*
- * Copyright © 2009 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"
-#include "ao_pins.h"
-
-volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING];
-#if HAS_ACCEL_REF
-volatile __xdata uint16_t ao_accel_ref[AO_ADC_RING];
-#endif
-volatile __data uint8_t ao_adc_head;
-
-void
-ao_adc_poll(void)
-{
-#if HAS_ACCEL_REF
- ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 2;
-#else
-# ifdef TELENANO_V_0_1
- ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 1;
-# else
- ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 0;
-# endif
-#endif
-}
-
-void
-ao_adc_get(__xdata struct ao_adc *packet)
-{
- uint8_t i = ao_adc_ring_prev(ao_sample_adc);
- memcpy(packet, &ao_adc_ring[i], sizeof (struct ao_adc));
-}
-
-void
-ao_adc_isr(void) __interrupt 1
-{
- uint8_t sequence;
- uint8_t __xdata *a;
-
- sequence = (ADCCON2 & ADCCON2_SCH_MASK) >> ADCCON2_SCH_SHIFT;
-#if IGNITE_ON_P2
- /* TeleMetrum readings */
-#if HAS_ACCEL_REF
- if (sequence == 2) {
- a = (uint8_t __xdata *) (&ao_accel_ref[ao_adc_head]);
- sequence = 0;
- } else
-#endif
- {
- if (sequence == ADCCON3_ECH_TEMP)
- sequence = 2;
- a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].accel + sequence);
- sequence++;
- }
-#define GOT_ADC
- a[0] = ADCL;
- a[1] = ADCH;
- if (sequence < 6) {
-#if HAS_EXTERNAL_TEMP == 0
- /* start next channel conversion */
- /* v0.2 replaces external temp sensor with internal one */
- if (sequence == 2)
- ADCCON3 = ADCCON3_EREF_1_25 | ADCCON3_EDIV_512 | ADCCON3_ECH_TEMP;
- else
-#endif
- ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | sequence;
- }
-#endif
-
-#if IGNITE_ON_P0
- /* TeleMini readings */
- a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].pres);
-#ifdef TELEMINI_V_1_0
- switch (sequence) {
- case 0:
- /* pressure */
- a += 0;
- sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 1;
- break;
- case 1:
- /* drogue sense */
- a += 6;
- sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 2;
- break;
- case 2:
- /* main sense */
- a += 8;
- sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 3;
- break;
- case 3:
- /* battery */
- a += 4;
- sequence = ADCCON3_EREF_1_25 | ADCCON3_EDIV_512 | ADCCON3_ECH_TEMP;
- break;
- case ADCCON3_ECH_TEMP:
- a += 2;
- sequence = 0;
- break;
- }
-#define GOT_ADC
-#endif
-#ifdef TELENANO_V_0_1
- switch (sequence) {
- case 1:
- /* pressure */
- a += 0;
- sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 3;
- break;
- case 3:
- /* battery */
- a += 4;
- sequence = ADCCON3_EREF_1_25 | ADCCON3_EDIV_512 | ADCCON3_ECH_TEMP;
- break;
- case ADCCON3_ECH_TEMP:
- a += 2;
- sequence = 0;
- break;
- }
-#define GOT_ADC
-#endif
- a[0] = ADCL;
- a[1] = ADCH;
- if (sequence) {
- /* Start next conversion */
- ADCCON3 = sequence;
- }
-#endif
-#ifndef GOT_ADC
-#error No known ADC configuration set
-#endif
-
- else {
- /* record this conversion series */
- ao_adc_ring[ao_adc_head].tick = ao_time();
- ao_adc_head = ao_adc_ring_next(ao_adc_head);
- ao_wakeup(DATA_TO_XDATA(&ao_adc_head));
- }
-}
-
-static void
-ao_adc_dump(void) __reentrant
-{
- static __xdata struct ao_adc packet;
- ao_adc_get(&packet);
- printf("tick: %5u accel: %5d pres: %5d temp: %5d batt: %5d drogue: %5d main: %5d\n",
- packet.tick, packet.accel, packet.pres, packet.temp,
- packet.v_batt, packet.sense_d, packet.sense_m);
-}
-
-__code struct ao_cmds ao_adc_cmds[] = {
- { ao_adc_dump, "a\0Current ADC" },
- { 0, NULL },
-};
-
-void
-ao_adc_init(void)
-{
-#if IGNITE_ON_P2
- /* TeleMetrum configuration */
- ADCCFG = ((1 << 0) | /* acceleration */
- (1 << 1) | /* pressure */
-#if HAS_EXTERNAL_TEMP
- (1 << 2) | /* v0.1 temperature */
-#endif
- (1 << 3) | /* battery voltage */
- (1 << 4) | /* drogue sense */
- (1 << 5)); /* main sense */
-#endif
-
-#if IGNITE_ON_P0
- /* TeleMini configuration */
- ADCCFG = ((1 << 0) | /* pressure */
- (1 << 1) | /* drogue sense */
- (1 << 2) | /* main sense */
- (1 << 3)); /* battery voltage */
-#endif
-
- /* enable interrupts */
- ADCIF = 0;
- IEN0 |= IEN0_ADCIE;
- ao_cmd_register(&ao_adc_cmds[0]);
-}
+++ /dev/null
-/*
- * Copyright © 2009 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"
-
-volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING];
-volatile __data uint8_t ao_adc_head;
-
-/* Stub for systems which have no ADC */
-void
-ao_adc_poll(void)
-{
-}
--- /dev/null
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+#if !HAS_AES
+#error Must define HAS_AES 1
+#endif
+
+__xdata uint8_t ao_aes_mutex;
+__xdata uint8_t ao_aes_done;
+__xdata uint8_t ao_aes_dma_in, ao_aes_dma_out;
+__xdata uint8_t ao_aes_dma_in_done, ao_aes_dma_out_done;
+__pdata enum ao_aes_mode ao_aes_current_mode;
+
+void
+ao_aes_isr(void) __interrupt 4
+{
+ S0CON = 0;
+ if (ENCCCS & ENCCCS_RDY) {
+ ao_aes_done = 1;
+ ao_wakeup(&ao_aes_done);
+ }
+}
+
+void
+ao_aes_set_mode(enum ao_aes_mode mode)
+{
+ ao_aes_current_mode = mode;
+}
+
+void
+ao_aes_set_key(__xdata uint8_t *in)
+{
+ ao_dma_set_transfer(ao_aes_dma_in,
+ in,
+ &ENCDIXADDR,
+ AO_AES_LEN,
+ DMA_CFG0_WORDSIZE_8 |
+ DMA_CFG0_TMODE_SINGLE |
+ DMA_CFG0_TRIGGER_ENC_DW,
+ DMA_CFG1_SRCINC_1 |
+ DMA_CFG1_DESTINC_0 |
+ DMA_CFG1_PRIORITY_LOW);
+ ao_dma_start(ao_aes_dma_in);
+ ao_aes_done = 0;
+ ENCCCS = ENCCCS_MODE_CBC_MAC |
+ ENCCCS_CMD_LOAD_KEY;
+ ENCCCS |= ENCCCS_START;
+ __critical while (!ao_aes_done)
+ ao_sleep(&ao_aes_done);
+}
+
+void
+ao_aes_zero_iv(void)
+{
+ uint8_t b;
+
+ ENCCCS = ENCCCS_MODE_CBC_MAC | ENCCCS_CMD_LOAD_IV | ENCCCS_START;
+ for (b = 0; b < AO_AES_LEN; b++)
+ ENCDI = 0;
+}
+
+void
+ao_aes_run(__xdata uint8_t *in,
+ __xdata uint8_t *out)
+{
+ uint8_t b;
+ if (in) {
+ ao_dma_set_transfer(ao_aes_dma_in,
+ in,
+ &ENCDIXADDR,
+ AO_AES_LEN,
+ DMA_CFG0_WORDSIZE_8 |
+ DMA_CFG0_TMODE_SINGLE |
+ DMA_CFG0_TRIGGER_ENC_DW,
+ DMA_CFG1_SRCINC_1 |
+ DMA_CFG1_DESTINC_0 |
+ DMA_CFG1_PRIORITY_LOW);
+ }
+ if (out) {
+ ao_dma_set_transfer(ao_aes_dma_out,
+ &ENCDOXADDR,
+ out,
+ AO_AES_LEN,
+ DMA_CFG0_WORDSIZE_8 |
+ DMA_CFG0_TMODE_SINGLE |
+ DMA_CFG0_TRIGGER_ENC_UP,
+ DMA_CFG1_SRCINC_0 |
+ DMA_CFG1_DESTINC_1 |
+ DMA_CFG1_PRIORITY_LOW);
+ }
+ switch (ao_aes_current_mode) {
+ case ao_aes_mode_cbc_mac:
+ if (out)
+ b = (ENCCCS_MODE_CBC |
+ ENCCCS_CMD_ENCRYPT);
+ else
+ b = (ENCCCS_MODE_CBC_MAC |
+ ENCCCS_CMD_ENCRYPT);
+ break;
+ default:
+ return;
+ }
+ ao_aes_done = 0;
+ if (in)
+ ao_dma_start(ao_aes_dma_in);
+ if (out)
+ ao_dma_start(ao_aes_dma_out);
+ ENCCCS = b;
+ ENCCCS |= ENCCCS_START;
+ if (out) {
+ __critical while (!ao_aes_dma_out_done)
+ ao_sleep(&ao_aes_dma_out_done);
+ } else {
+ __critical while (!ao_aes_done)
+ ao_sleep(&ao_aes_done);
+ }
+}
+
+void
+ao_aes_init(void)
+{
+ ao_aes_dma_in = ao_dma_alloc(&ao_aes_dma_in_done);
+ ao_aes_dma_out = ao_dma_alloc(&ao_aes_dma_out_done);
+ S0CON = 0;
+ ENCIE = 1;
+}
+++ /dev/null
-/*
- * Copyright © 2009 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
-ao_beep(uint8_t beep)
-{
- if (beep == 0) {
- P2_0 = 0;
- P2SEL = (P2SEL & ~P2SEL_SELP2_0_MASK) | P2SEL_SELP2_0_GPIO;
- T4CTL = 0;
- } else {
- P2SEL = (P2SEL & ~P2SEL_SELP2_0_MASK) | P2SEL_SELP2_0_PERIPHERAL;
- T4CC0 = beep;
- T4CTL = TxCTL_DIV_32 | TxCTL_MODE_MODULO | TxCTL_START;
- }
-}
-
-void
-ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant
-{
- ao_beep(beep);
- ao_delay(ticks);
- ao_beep(0);
-}
-
-void
-ao_beep_init(void)
-{
- /* Our beeper is on P2_0, which is hooked to timer 4 using
- * configuration alternative 2
- */
- P2_0 = 0;
- P2SEL = (P2SEL & ~P2SEL_SELP2_0_MASK) | P2SEL_SELP2_0_GPIO;
- PERCFG = (PERCFG & ~PERCFG_T4CFG_ALT_MASK) | PERCFG_T4CFG_ALT_2;
- T4CCTL0 = TxCCTLy_CMP_TOGGLE|TxCCTLy_CMP_MODE_ENABLE;
-}
+++ /dev/null
-/*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-int8_t ao_btm_stdio;
-__xdata uint8_t ao_btm_connected;
-
-#define AO_BTM_MAX_REPLY 16
-__xdata char ao_btm_reply[AO_BTM_MAX_REPLY];
-
-extern volatile __xdata struct ao_fifo ao_usart1_rx_fifo;
-
-/*
- * Read a line of data from the serial port, truncating
- * it after a few characters.
- */
-
-uint8_t
-ao_btm_get_line(void)
-{
- uint8_t ao_btm_reply_len = 0;
- char c;
-
- for (;;) {
-
- while ((c = ao_serial_pollchar()) != AO_READ_AGAIN) {
- if (ao_btm_reply_len < sizeof (ao_btm_reply))
- ao_btm_reply[ao_btm_reply_len++] = c;
- if (c == '\r' || c == '\n')
- goto done;
- }
- for (c = 0; c < 10; c++) {
- ao_delay(AO_MS_TO_TICKS(10));
- if (!ao_fifo_empty(ao_usart1_rx_fifo))
- break;
- }
- if (c == 10)
- goto done;
- }
-done:
- for (c = ao_btm_reply_len; c < sizeof (ao_btm_reply);)
- ao_btm_reply[c++] = '\0';
- return ao_btm_reply_len;
-}
-
-/*
- * Drain the serial port completely
- */
-void
-ao_btm_drain()
-{
- while (ao_btm_get_line())
- ;
-}
-
-/*
- * Set the stdio echo for the bluetooth link
- */
-void
-ao_btm_echo(uint8_t echo)
-{
- ao_stdios[ao_btm_stdio].echo = echo;
-}
-
-/*
- * Delay between command charaters; the BT module
- * can't keep up with 57600 baud
- */
-
-void
-ao_btm_putchar(char c)
-{
- ao_serial_putchar(c);
- ao_delay(1);
-}
-
-/*
- * Wait for the bluetooth device to return
- * status from the previously executed command
- */
-uint8_t
-ao_btm_wait_reply(void)
-{
- for (;;) {
- ao_btm_get_line();
- if (!strncmp(ao_btm_reply, "OK", 2))
- return 1;
- if (!strncmp(ao_btm_reply, "ERROR", 5))
- return -1;
- if (ao_btm_reply[0] == '\0')
- return 0;
- }
-}
-
-void
-ao_btm_string(__code char *cmd)
-{
- char c;
-
- while (c = *cmd++)
- ao_btm_putchar(c);
-}
-
-uint8_t
-ao_btm_cmd(__code char *cmd)
-{
- ao_btm_drain();
- ao_btm_string(cmd);
- return ao_btm_wait_reply();
-}
-
-uint8_t
-ao_btm_set_name(void)
-{
- char sn[8];
- char *s = sn + 8;
- char c;
- int n;
- ao_btm_string("ATN=TeleBT-");
- *--s = '\0';
- *--s = '\r';
- n = ao_serial_number;
- do {
- *--s = '0' + n % 10;
- } while (n /= 10);
- while ((c = *s++))
- ao_btm_putchar(c);
- return ao_btm_wait_reply();
-}
-
-uint8_t
-ao_btm_try_speed(uint8_t speed)
-{
- ao_serial_set_speed(speed);
- ao_btm_drain();
- (void) ao_btm_cmd("\rATE0\rATQ0\r");
- if (ao_btm_cmd("AT\r") == 1)
- return 1;
- return 0;
-}
-
-/*
- * A thread to initialize the bluetooth device and
- * hang around to blink the LED when connected
- */
-void
-ao_btm(void)
-{
- /*
- * Wait for the bluetooth device to boot
- */
- ao_delay(AO_SEC_TO_TICKS(3));
-
-#if HAS_BEEP
- ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200));
-#endif
-
- /*
- * 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;
-
-#if BT_LINK_ON_P2
-#define BT_PICTL_ICON PICTL_P2ICON
-#define BT_PIFG P2IFG
-#define BT_PDIR P2DIR
-#define BT_PINP P2INP
-#define BT_IEN2_PIE IEN2_P2IE
-#endif
-#if BT_LINK_ON_P1
-#define BT_PICTL_ICON PICTL_P1ICON
-#define BT_PIFG P1IFG
-#define BT_PDIR P1DIR
-#define BT_PINP P1INP
-#define BT_IEN2_PIE IEN2_P1IE
-#endif
-
-void
-ao_btm_check_link() __critical
-{
- /* Check the pin and configure the interrupt detector to wait for the
- * pin to flip the other way
- */
- if (BT_LINK_PIN) {
- ao_btm_connected = 0;
- PICTL |= BT_PICTL_ICON;
- } else {
- ao_btm_connected = 1;
- PICTL &= ~BT_PICTL_ICON;
- }
-}
-
-void
-ao_btm_isr(void)
-#if BT_LINK_ON_P1
- __interrupt 15
-#endif
-{
-#if BT_LINK_ON_P1
- P1IF = 0;
-#endif
- if (BT_PIFG & (1 << BT_LINK_PIN_INDEX)) {
- ao_btm_check_link();
- ao_wakeup(&ao_btm_connected);
- }
- BT_PIFG = 0;
-}
-
-void
-ao_btm_init (void)
-{
- ao_serial_init();
- ao_serial_set_speed(AO_SERIAL_SPEED_19200);
-
-#if BT_LINK_ON_P1
- /*
- * Configure ser reset line
- */
-
- P1_6 = 0;
- P1DIR |= (1 << 6);
-#endif
-
- /*
- * Configure link status line
- */
-
- /* Set pin to input */
- BT_PDIR &= ~(1 << BT_LINK_PIN_INDEX);
-
- /* Set pin to tri-state */
- BT_PINP |= (1 << BT_LINK_PIN_INDEX);
-
- /* Enable interrupts */
- IEN2 |= BT_IEN2_PIE;
-
- /* Check current pin state */
- ao_btm_check_link();
-
-#if BT_LINK_ON_P2
- /* Eable the pin interrupt */
- PICTL |= PICTL_P2IEN;
-#endif
-#if BT_LINK_ON_P1
- /* Enable pin interrupt */
- P1IEN |= (1 << BT_LINK_PIN_INDEX);
-#endif
-
- ao_add_task(&ao_btm_task, ao_btm, "bt");
-}
+++ /dev/null
-/*
- * Copyright © 2009 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"
-
-__pdata uint16_t ao_cmd_lex_i;
-__pdata uint32_t ao_cmd_lex_u32;
-__pdata char ao_cmd_lex_c;
-__pdata enum ao_cmd_status ao_cmd_status;
-
-#define CMD_LEN 32
-
-static __xdata char cmd_line[CMD_LEN];
-static __pdata uint8_t cmd_len;
-static __pdata uint8_t cmd_i;
-
-static void
-put_string(__code char *s)
-{
- char c;
- while (c = *s++)
- putchar(c);
-}
-
-static void
-readline(void)
-{
- __pdata char c;
- if (ao_echo())
- put_string("> ");
- cmd_len = 0;
- for (;;) {
- flush();
- c = getchar();
- /* backspace/delete */
- if (c == '\010' || c == '\177') {
- if (cmd_len != 0) {
- if (ao_echo())
- put_string("\010 \010");
- --cmd_len;
- }
- continue;
- }
-
- /* ^U */
- if (c == '\025') {
- while (cmd_len != 0) {
- if (ao_echo())
- put_string("\010 \010");
- --cmd_len;
- }
- continue;
- }
-
- /* map CR to NL */
- if (c == '\r')
- c = '\n';
-
- if (c == '\n') {
- if (ao_echo())
- putchar('\n');
- break;
- }
-
- if (cmd_len >= CMD_LEN - 2) {
- if (ao_echo())
- putchar('\007');
- continue;
- }
- cmd_line[cmd_len++] = c;
- if (ao_echo())
- putchar(c);
- }
- cmd_line[cmd_len++] = '\n';
- cmd_line[cmd_len++] = '\0';
- cmd_i = 0;
-}
-
-void
-ao_cmd_lex(void)
-{
- ao_cmd_lex_c = '\n';
- if (cmd_i < cmd_len)
- ao_cmd_lex_c = cmd_line[cmd_i++];
-}
-
-static void
-putnibble(uint8_t v)
-{
- if (v < 10)
- putchar(v + '0');
- else
- putchar(v + ('a' - 10));
-}
-
-void
-ao_cmd_put16(uint16_t v)
-{
- ao_cmd_put8(v >> 8);
- ao_cmd_put8(v);
-}
-
-void
-ao_cmd_put8(uint8_t v)
-{
- putnibble((v >> 4) & 0xf);
- putnibble(v & 0xf);
-}
-
-void
-ao_cmd_white(void)
-{
- while (ao_cmd_lex_c == ' ' || ao_cmd_lex_c == '\t')
- ao_cmd_lex();
-}
-
-void
-ao_cmd_hex(void)
-{
- __pdata uint8_t r = ao_cmd_lex_error;
- uint8_t n;
-
- ao_cmd_lex_i = 0;
- ao_cmd_white();
- for(;;) {
- if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9')
- n = (ao_cmd_lex_c - '0');
- else if ('a' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'f')
- n = (ao_cmd_lex_c - 'a' + 10);
- else if ('A' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'F')
- n = (ao_cmd_lex_c - 'A' + 10);
- else
- break;
- ao_cmd_lex_i = (ao_cmd_lex_i << 4) | n;
- r = ao_cmd_success;
- ao_cmd_lex();
- }
- if (r != ao_cmd_success)
- ao_cmd_status = r;
-}
-
-void
-ao_cmd_decimal(void)
-{
- __pdata uint8_t r = ao_cmd_lex_error;
-
- ao_cmd_lex_u32 = 0;
- ao_cmd_white();
- for(;;) {
- if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9')
- ao_cmd_lex_u32 = (ao_cmd_lex_u32 * 10) + (ao_cmd_lex_c - '0');
- else
- break;
- r = ao_cmd_success;
- ao_cmd_lex();
- }
- if (r != ao_cmd_success)
- ao_cmd_status = r;
- ao_cmd_lex_i = (uint16_t) ao_cmd_lex_u32;
-}
-
-uint8_t
-ao_match_word(__code char *word)
-{
- while (*word) {
- if (ao_cmd_lex_c != *word) {
- ao_cmd_status = ao_cmd_syntax_error;
- return 0;
- }
- word++;
- ao_cmd_lex();
- }
- return 1;
-}
-
-static void
-eol(void)
-{
- while (ao_cmd_lex_c != '\n')
- ao_cmd_lex();
-}
-
-static void
-echo(void)
-{
- ao_cmd_hex();
- if (ao_cmd_status == ao_cmd_success)
- ao_stdios[ao_cur_stdio].echo = ao_cmd_lex_i != 0;
-}
-
-static void
-ao_reboot(void)
-{
- ao_cmd_white();
- if (!ao_match_word("eboot"))
- return;
- WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_64;
- ao_delay(AO_SEC_TO_TICKS(2));
- ao_panic(AO_PANIC_REBOOT);
-}
-
-static void
-version(void)
-{
- printf("manufacturer %s\n", ao_manufacturer);
- printf("product %s\n", ao_product);
- printf("serial-number %u\n", ao_serial_number);
-#if HAS_EEPROM
- printf("log-format %u\n", ao_log_format);
-#endif
- printf("software-version %s\n", ao_version);
-}
-
-#define NUM_CMDS 11
-
-static __code struct ao_cmds *__xdata (ao_cmds[NUM_CMDS]);
-static __pdata uint8_t ao_ncmds;
-
-static void
-help(void)
-{
- register uint8_t cmds;
- register uint8_t cmd;
- register __code struct ao_cmds * cs;
-
- for (cmds = 0; cmds < ao_ncmds; cmds++) {
- cs = ao_cmds[cmds];
- for (cmd = 0; cs[cmd].func; cmd++)
- printf("%-45s %s\n",
- cs[cmd].help,
- cs[cmd].help+1+strlen(cs[cmd].help));
- }
-}
-
-static void
-report(void)
-{
- switch(ao_cmd_status) {
- case ao_cmd_lex_error:
- case ao_cmd_syntax_error:
- puts("Syntax error");
- ao_cmd_status = 0;
- break;
- }
-}
-
-void
-ao_cmd_register(__code struct ao_cmds *cmds)
-{
- if (ao_ncmds >= NUM_CMDS)
- ao_panic(AO_PANIC_CMD);
- ao_cmds[ao_ncmds++] = cmds;
-}
-
-void
-ao_cmd(void)
-{
- char c;
- uint8_t cmd, cmds;
- __code struct ao_cmds * __xdata cs;
- void (*__xdata func)(void);
-
- for (;;) {
- readline();
- ao_cmd_lex();
- ao_cmd_white();
- c = ao_cmd_lex_c;
- ao_cmd_lex();
- if (c == '\r' || c == '\n')
- continue;
- func = (void (*)(void)) NULL;
- for (cmds = 0; cmds < ao_ncmds; cmds++) {
- cs = ao_cmds[cmds];
- for (cmd = 0; cs[cmd].func; cmd++)
- if (cs[cmd].help[0] == c) {
- func = cs[cmd].func;
- break;
- }
- if (func)
- break;
- }
- if (func)
- (*func)();
- else
- ao_cmd_status = ao_cmd_syntax_error;
- report();
- }
-}
-
-__xdata struct ao_task ao_cmd_task;
-
-__code struct ao_cmds ao_base_cmds[] = {
- { help, "?\0Help" },
- { ao_task_info, "T\0Show tasks" },
- { echo, "E <0 off, 1 on>\0Set echo mode" },
- { ao_reboot, "r eboot\0Reboot" },
- { version, "v\0Version" },
- { 0, NULL },
-};
-
-void
-ao_cmd_init(void)
-{
- ao_cmd_register(&ao_base_cmds[0]);
- ao_add_task(&ao_cmd_task, ao_cmd, "cmd");
-}
+++ /dev/null
-/*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-#define ao_spi_slow() (U0GCR = (UxGCR_CPOL_NEGATIVE | \
- UxGCR_CPHA_FIRST_EDGE | \
- UxGCR_ORDER_MSB | \
- (13 << UxGCR_BAUD_E_SHIFT)))
-
-#define ao_spi_fast() (U0GCR = (UxGCR_CPOL_NEGATIVE | \
- UxGCR_CPHA_FIRST_EDGE | \
- UxGCR_ORDER_MSB | \
- (17 << UxGCR_BAUD_E_SHIFT)))
-
-#define COMPANION_SELECT() do { ao_spi_get_bit(COMPANION_CS); ao_spi_slow(); } while (0)
-#define COMPANION_DESELECT() do { ao_spi_fast(); ao_spi_put_bit(COMPANION_CS); } while (0)
-
-static __xdata struct ao_companion_command ao_companion_command;
-__xdata struct ao_companion_setup ao_companion_setup;
-
-__xdata uint16_t ao_companion_data[AO_COMPANION_MAX_CHANNELS];
-__pdata uint8_t ao_companion_running;
-__xdata uint8_t ao_companion_mutex;
-
-static void
-ao_companion_send_command(uint8_t command)
-{
- ao_companion_command.command = command;
- ao_companion_command.flight_state = ao_flight_state;
- ao_companion_command.tick = ao_time();
- ao_companion_command.serial = ao_serial_number;
- ao_companion_command.flight = ao_flight_number;
- ao_spi_send(&ao_companion_command, sizeof (ao_companion_command));
-}
-
-static uint8_t
-ao_companion_get_setup(void)
-{
- COMPANION_SELECT();
- ao_companion_send_command(AO_COMPANION_SETUP);
- ao_spi_recv(&ao_companion_setup, sizeof (ao_companion_setup));
- COMPANION_DESELECT();
- return (ao_companion_setup.board_id ==
- ~ao_companion_setup.board_id_inverse);
-}
-
-static void
-ao_companion_get_data(void)
-{
- COMPANION_SELECT();
- ao_companion_send_command(AO_COMPANION_FETCH);
- ao_mutex_get(&ao_companion_mutex);
- ao_spi_recv(&ao_companion_data, ao_companion_setup.channels * 2);
- ao_mutex_put(&ao_companion_mutex);
- COMPANION_DESELECT();
-}
-
-static void
-ao_companion_notify(void)
-{
- COMPANION_SELECT();
- ao_companion_send_command(AO_COMPANION_NOTIFY);
- COMPANION_DESELECT();
-}
-
-void
-ao_companion(void)
-{
- uint8_t i;
- while (!ao_flight_number)
- ao_sleep(&ao_flight_number);
- for (i = 0; i < 10; i++) {
- ao_delay(AO_SEC_TO_TICKS(1));
- if ((ao_companion_running = ao_companion_get_setup()))
- break;
- }
- while (ao_companion_running) {
- ao_alarm(ao_companion_setup.update_period);
- if (ao_sleep(DATA_TO_XDATA(&ao_flight_state)))
- ao_companion_get_data();
- else
- ao_companion_notify();
- }
- ao_exit();
-}
-
-void
-ao_companion_status(void) __reentrant
-{
- uint8_t i;
- printf("Companion running: %d\n", ao_companion_running);
- printf("device: %d\n", ao_companion_setup.board_id);
- printf("update period: %d\n", ao_companion_setup.update_period);
- printf("channels: %d\n", ao_companion_setup.channels);
- printf("data:");
- for(i = 0; i < ao_companion_setup.channels; i++)
- printf(" %5u", ao_companion_data[i]);
- printf("\n");
-}
-
-__code struct ao_cmds ao_companion_cmds[] = {
- { ao_companion_status, "L\0Companion link status" },
- { 0, NULL },
-};
-
-static __xdata struct ao_task ao_companion_task;
-
-void
-ao_companion_init(void)
-{
- COMPANION_CS_PORT |= COMPANION_CS_MASK; /* raise all CS pins */
- COMPANION_CS_DIR |= COMPANION_CS_MASK; /* set CS pins as outputs */
- COMPANION_CS_SEL &= ~COMPANION_CS_MASK; /* set CS pins as GPIO */
-
- ao_cmd_register(&ao_companion_cmds[0]);
- ao_add_task(&ao_companion_task, ao_companion, "companion");
-}
+++ /dev/null
-/*
- * Copyright © 2009 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"
-
-__xdata struct ao_config ao_config;
-__pdata uint8_t ao_config_loaded;
-__pdata uint8_t ao_config_dirty;
-__xdata uint8_t ao_config_mutex;
-
-#define AO_CONFIG_DEFAULT_MAIN_DEPLOY 250
-#define AO_CONFIG_DEFAULT_RADIO_CHANNEL 0
-#define AO_CONFIG_DEFAULT_CALLSIGN "N0CALL"
-#define AO_CONFIG_DEFAULT_ACCEL_ZERO_G 16000
-#define AO_CONFIG_DEFAULT_APOGEE_DELAY 0
-#define AO_CONFIG_DEFAULT_IGNITE_MODE AO_IGNITE_MODE_DUAL
-#define AO_CONFIG_DEFAULT_PAD_ORIENTATION AO_PAD_ORIENTATION_ANTENNA_UP
-#if HAS_EEPROM
-#ifndef USE_INTERNAL_FLASH
-#error Please define USE_INTERNAL_FLASH
-#endif
-#endif
-#if USE_INTERNAL_FLASH
-#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ao_storage_config
-#else
-#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ((uint32_t) 192 * (uint32_t) 1024)
-#endif
-
-#if HAS_EEPROM
-static void
-_ao_config_put(void)
-{
- ao_storage_setup();
- ao_storage_erase(ao_storage_config);
- ao_storage_write(ao_storage_config, &ao_config, sizeof (ao_config));
- ao_log_write_erase(0);
- ao_storage_flush();
-}
-
-void
-ao_config_put(void)
-{
- ao_mutex_get(&ao_config_mutex);
- _ao_config_put();
- ao_mutex_put(&ao_config_mutex);
-}
-#endif
-
-static void
-_ao_config_get(void)
-{
- if (ao_config_loaded)
- return;
-#if HAS_EEPROM
- ao_storage_setup();
- ao_storage_read(ao_storage_config, &ao_config, sizeof (ao_config));
-#endif
- if (ao_config.major != AO_CONFIG_MAJOR) {
- ao_config.major = AO_CONFIG_MAJOR;
- ao_config.minor = 0;
- ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY;
- ao_config.radio_channel = AO_CONFIG_DEFAULT_RADIO_CHANNEL;
- memset(&ao_config.callsign, '\0', sizeof (ao_config.callsign));
- memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN,
- sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1);
- }
- if (ao_config.minor < AO_CONFIG_MINOR) {
- /* Fixups for minor version 1 */
- if (ao_config.minor < 1)
- ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY;
- /* Fixups for minor version 2 */
- if (ao_config.minor < 2) {
- ao_config.accel_plus_g = 0;
- ao_config.accel_minus_g = 0;
- }
- /* Fixups for minor version 3 */
- if (ao_config.minor < 3)
- ao_config.radio_cal = ao_radio_cal;
- /* Fixups for minor version 4 */
- if (ao_config.minor < 4)
- ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX;
- /* Fixupes for minor version 5 */
- if (ao_config.minor < 5)
- ao_config.ignite_mode = AO_CONFIG_DEFAULT_IGNITE_MODE;
- if (ao_config.minor < 6)
- ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION;
- if (ao_config.minor < 7)
- ao_config.radio_setting = ao_config.radio_cal;
- if (ao_config.minor < 8)
- ao_config.radio_enable = TRUE;
- ao_config.minor = AO_CONFIG_MINOR;
- ao_config_dirty = 1;
- }
- ao_config_loaded = 1;
-}
-
-static void
-_ao_config_edit_start(void)
-{
- ao_mutex_get(&ao_config_mutex);
- _ao_config_get();
-}
-
-static void
-_ao_config_edit_finish(void)
-{
- ao_config_dirty = 1;
- ao_mutex_put(&ao_config_mutex);
-}
-
-void
-ao_config_get(void)
-{
- _ao_config_edit_start();
- ao_mutex_put(&ao_config_mutex);
-}
-
-void
-ao_config_callsign_show(void)
-{
- printf ("Callsign: \"%s\"\n", ao_config.callsign);
-}
-
-void
-ao_config_callsign_set(void) __reentrant
-{
- uint8_t c;
- static __xdata char callsign[AO_MAX_CALLSIGN + 1];
-
- memset(callsign, '\0', sizeof callsign);
- ao_cmd_white();
- c = 0;
- while (ao_cmd_lex_c != '\n') {
- if (c < AO_MAX_CALLSIGN)
- callsign[c++] = ao_cmd_lex_c;
- else
- ao_cmd_status = ao_cmd_lex_error;
- ao_cmd_lex();
- }
- if (ao_cmd_status != ao_cmd_success)
- return;
- _ao_config_edit_start();
- memcpy(&ao_config.callsign, &callsign,
- AO_MAX_CALLSIGN + 1);
- _ao_config_edit_finish();
-}
-
-void
-ao_config_radio_channel_show(void) __reentrant
-{
- printf("Radio channel: %d\n",
- ao_config.radio_channel);
-}
-
-void
-ao_config_radio_channel_set(void) __reentrant
-{
- ao_cmd_decimal();
- if (ao_cmd_status != ao_cmd_success)
- return;
- _ao_config_edit_start();
- ao_config.radio_channel = ao_cmd_lex_i;
- _ao_config_edit_finish();
- ao_radio_recv_abort();
-}
-
-#if HAS_ADC
-
-void
-ao_config_main_deploy_show(void) __reentrant
-{
- printf("Main deploy: %d meters\n",
- ao_config.main_deploy);
-}
-
-void
-ao_config_main_deploy_set(void) __reentrant
-{
- ao_cmd_decimal();
- if (ao_cmd_status != ao_cmd_success)
- return;
- _ao_config_edit_start();
- ao_config.main_deploy = ao_cmd_lex_i;
- _ao_config_edit_finish();
-}
-
-#if HAS_ACCEL
-void
-ao_config_accel_calibrate_show(void) __reentrant
-{
- printf("Accel cal +1g: %d -1g: %d\n",
- ao_config.accel_plus_g, ao_config.accel_minus_g);
-}
-
-#define ACCEL_CALIBRATE_SAMPLES 1024
-#define ACCEL_CALIBRATE_SHIFT 10
-
-static int16_t
-ao_config_accel_calibrate_auto(char *orientation) __reentrant
-{
- uint16_t i;
- int32_t accel_total;
- uint8_t cal_adc_ring;
-
- printf("Orient antenna %s and press a key...", orientation);
- flush();
- (void) getchar();
- puts("\r\n"); flush();
- puts("Calibrating..."); flush();
- i = ACCEL_CALIBRATE_SAMPLES;
- accel_total = 0;
- cal_adc_ring = ao_sample_adc;
- while (i) {
- ao_sleep(DATA_TO_XDATA(&ao_sample_adc));
- while (i && cal_adc_ring != ao_sample_adc) {
- accel_total += (int32_t) ao_adc_ring[cal_adc_ring].accel;
- cal_adc_ring = ao_adc_ring_next(cal_adc_ring);
- i--;
- }
- }
- return accel_total >> ACCEL_CALIBRATE_SHIFT;
-}
-
-void
-ao_config_accel_calibrate_set(void) __reentrant
-{
- int16_t up, down;
- ao_cmd_decimal();
- if (ao_cmd_status != ao_cmd_success)
- return;
- if (ao_cmd_lex_i == 0) {
- up = ao_config_accel_calibrate_auto("up");
- down = ao_config_accel_calibrate_auto("down");
- } else {
- up = ao_cmd_lex_i;
- ao_cmd_decimal();
- if (ao_cmd_status != ao_cmd_success)
- return;
- down = ao_cmd_lex_i;
- }
- if (up >= down) {
- printf("Invalid accel: up (%d) down (%d)\n",
- up, down);
- return;
- }
- _ao_config_edit_start();
- ao_config.accel_plus_g = up;
- ao_config.accel_minus_g = down;
- _ao_config_edit_finish();
-}
-#endif /* HAS_ACCEL */
-
-void
-ao_config_apogee_delay_show(void) __reentrant
-{
- printf("Apogee delay: %d seconds\n",
- ao_config.apogee_delay);
-}
-
-void
-ao_config_apogee_delay_set(void) __reentrant
-{
- ao_cmd_decimal();
- if (ao_cmd_status != ao_cmd_success)
- return;
- _ao_config_edit_start();
- ao_config.apogee_delay = ao_cmd_lex_i;
- _ao_config_edit_finish();
-}
-
-#endif /* HAS_ADC */
-
-void
-ao_config_radio_cal_show(void) __reentrant
-{
- printf("Radio cal: %ld\n", ao_config.radio_cal);
-}
-
-void
-ao_config_radio_cal_set(void) __reentrant
-{
- ao_cmd_decimal();
- if (ao_cmd_status != ao_cmd_success)
- return;
- _ao_config_edit_start();
- ao_config.radio_setting = ao_config.radio_cal = ao_cmd_lex_u32;
- _ao_config_edit_finish();
-}
-
-#if HAS_EEPROM
-void
-ao_config_log_show(void) __reentrant
-{
- printf("Max flight log: %d kB\n", (int16_t) (ao_config.flight_log_max >> 10));
-}
-
-void
-ao_config_log_set(void) __reentrant
-{
- uint16_t block = (uint16_t) (ao_storage_block >> 10);
- uint16_t config = (uint16_t) (ao_storage_config >> 10);
-
- ao_cmd_decimal();
- if (ao_cmd_status != ao_cmd_success)
- return;
- if (ao_log_present())
- printf("Storage must be empty before changing log size\n");
- else if (block > 1024 && (ao_cmd_lex_i & (block - 1)))
- printf("Flight log size must be multiple of %d kB\n", block);
- else if (ao_cmd_lex_i > config)
- printf("Flight log max %d kB\n", config);
- else {
- _ao_config_edit_start();
- ao_config.flight_log_max = (uint32_t) ao_cmd_lex_i << 10;
- _ao_config_edit_finish();
- }
-}
-#endif /* HAS_EEPROM */
-
-#if HAS_IGNITE
-void
-ao_config_ignite_mode_show(void) __reentrant
-{
- printf("Ignite mode: %d\n", ao_config.ignite_mode);
-}
-
-void
-ao_config_ignite_mode_set(void) __reentrant
-{
- ao_cmd_decimal();
- if (ao_cmd_status != ao_cmd_success)
- return;
- _ao_config_edit_start();
- ao_config.ignite_mode = ao_cmd_lex_i;
- _ao_config_edit_finish();
-}
-#endif
-
-#if HAS_ACCEL
-void
-ao_config_pad_orientation_show(void) __reentrant
-{
- printf("Pad orientation: %d\n", ao_config.pad_orientation);
-}
-
-void
-ao_config_pad_orientation_set(void) __reentrant
-{
- ao_cmd_decimal();
- if (ao_cmd_status != ao_cmd_success)
- return;
- _ao_config_edit_start();
- ao_cmd_lex_i &= 1;
- if (ao_config.pad_orientation != ao_cmd_lex_i) {
- uint16_t t;
- t = ao_config.accel_plus_g;
- ao_config.accel_plus_g = 0x7fff - ao_config.accel_minus_g;
- ao_config.accel_minus_g = 0x7fff - t;
- }
- ao_config.pad_orientation = ao_cmd_lex_i;
- _ao_config_edit_finish();
-}
-#endif
-
-void
-ao_config_radio_setting_show(void) __reentrant
-{
- printf("Radio setting: %ld\n", ao_config.radio_setting);
-}
-
-void
-ao_config_radio_setting_set(void) __reentrant
-{
- ao_cmd_decimal();
- if (ao_cmd_status != ao_cmd_success)
- return;
- _ao_config_edit_start();
- ao_config.radio_setting = ao_cmd_lex_u32;
- ao_config.radio_channel = 0;
- _ao_config_edit_finish();
- ao_radio_recv_abort();
-}
-
-void
-ao_config_radio_enable_show(void) __reentrant
-{
- printf("Radio enable: %d\n", ao_config.radio_enable);
-}
-
-void
-ao_config_radio_enable_set(void) __reentrant
-{
- ao_cmd_decimal();
- if (ao_cmd_status != ao_cmd_success)
- return;
- _ao_config_edit_start();
- ao_config.radio_enable = ao_cmd_lex_i;
- _ao_config_edit_finish();
-}
-
-struct ao_config_var {
- __code char *str;
- void (*set)(void) __reentrant;
- void (*show)(void) __reentrant;
-};
-
-static void
-ao_config_help(void) __reentrant;
-
-static void
-ao_config_show(void) __reentrant;
-
-static void
-ao_config_write(void) __reentrant;
-
-__code struct ao_config_var ao_config_vars[] = {
-#if HAS_ADC
- { "m <meters>\0Main deploy (in meters)",
- ao_config_main_deploy_set, ao_config_main_deploy_show, },
- { "d <delay>\0Apogee delay (in seconds)",
- ao_config_apogee_delay_set, ao_config_apogee_delay_show },
-#endif /* HAS_ADC */
- { "r <channel>\0Radio channel (freq = 434.550 + chan * .1)",
- ao_config_radio_channel_set, ao_config_radio_channel_show },
- { "c <call>\0Callsign (8 char max)",
- ao_config_callsign_set, ao_config_callsign_show },
- { "R <setting>\0Radio freq control (freq = 434.550 * setting/cal)",
- ao_config_radio_setting_set, ao_config_radio_setting_show },
- { "e <0 disable, 1 enable>\0Enable telemetry and RDF",
- ao_config_radio_enable_set, ao_config_radio_enable_show },
-#if HAS_ACCEL
- { "a <+g> <-g>\0Accel calib (0 for auto)",
- ao_config_accel_calibrate_set,ao_config_accel_calibrate_show },
-#endif /* HAS_ACCEL */
- { "f <cal>\0Radio calib (cal = rf/(xtal/2^16))",
- ao_config_radio_cal_set, ao_config_radio_cal_show },
-#if HAS_EEPROM
- { "l <size>\0Flight log size in kB",
- ao_config_log_set, ao_config_log_show },
-#endif
-#if HAS_IGNITE
- { "i <0 dual, 1 apogee, 2 main>\0Set igniter mode",
- ao_config_ignite_mode_set, ao_config_ignite_mode_show },
-#endif
-#if HAS_ACCEL
- { "o <0 antenna up, 1 antenna down>\0Set pad orientation",
- ao_config_pad_orientation_set,ao_config_pad_orientation_show },
-#endif
- { "s\0Show",
- ao_config_show, 0 },
-#if HAS_EEPROM
- { "w\0Write to eeprom",
- ao_config_write, 0 },
-#endif
- { "?\0Help",
- ao_config_help, 0 },
- { 0, 0, 0 }
-};
-
-void
-ao_config_set(void)
-{
- char c;
- uint8_t cmd;
- void (*__xdata func)(void) __reentrant;
-
- ao_cmd_white();
- c = ao_cmd_lex_c;
- ao_cmd_lex();
- func = 0;
- for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++)
- if (ao_config_vars[cmd].str[0] == c) {
- (*ao_config_vars[cmd].set)();
- return;
- }
- ao_cmd_status = ao_cmd_syntax_error;
-}
-
-static void
-ao_config_help(void) __reentrant
-{
- uint8_t cmd;
- for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++)
- printf("%-20s %s\n",
- ao_config_vars[cmd].str,
- ao_config_vars[cmd].str+1+strlen(ao_config_vars[cmd].str));
-}
-
-static void
-ao_config_show(void) __reentrant
-{
- uint8_t cmd;
- printf("Config version: %d.%d\n",
- ao_config.major, ao_config.minor);
- for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++)
- if (ao_config_vars[cmd].show)
- (*ao_config_vars[cmd].show)();
-}
-
-#if HAS_EEPROM
-static void
-ao_config_write(void) __reentrant
-{
- uint8_t saved = 0;
- ao_mutex_get(&ao_config_mutex);
- if (ao_config_dirty) {
- _ao_config_put();
- ao_config_dirty = 0;
- saved = 1;
- }
- ao_mutex_put(&ao_config_mutex);
- if (saved)
- puts("Saved");
- else
- puts("Nothing to save");
-}
-#endif
-
-__code struct ao_cmds ao_config_cmds[] = {
- { ao_config_set, "c <var> <value>\0Set config variable (? for help, s to show)" },
- { 0, NULL },
-};
-
-void
-ao_config_init(void)
-{
- ao_cmd_register(&ao_config_cmds[0]);
-}
+++ /dev/null
-/*
- * Copyright © 2009 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.
- */
-
-#if !defined(AO_CONVERT_TEST) && !defined(AO_FLIGHT_TEST)
-#include "ao.h"
-#endif
-
-static const int16_t altitude_table[] = {
-#include "altitude.h"
-};
-
-#define ALT_FRAC_SCALE (1 << ALT_FRAC_BITS)
-#define ALT_FRAC_MASK (ALT_FRAC_SCALE - 1)
-
-int16_t
-ao_pres_to_altitude(int16_t pres) __reentrant
-{
- uint8_t o;
- int16_t part;
-
- if (pres < 0)
- pres = 0;
- o = pres >> ALT_FRAC_BITS;
- part = pres & ALT_FRAC_MASK;
-
- return ((int32_t) altitude_table[o] * (ALT_FRAC_SCALE - part) +
- (int32_t) altitude_table[o+1] * part + (ALT_FRAC_SCALE >> 1)) >> ALT_FRAC_BITS;
-}
-
-int16_t
-ao_altitude_to_pres(int16_t alt) __reentrant
-{
- int16_t span, sub_span;
- uint8_t l, h, m;
- int32_t pres;
-
- l = 0;
- h = NALT - 1;
- while ((h - l) != 1) {
- m = (l + h) >> 1;
- if (altitude_table[m] < alt)
- h = m;
- else
- l = m;
- }
- span = altitude_table[l] - altitude_table[h];
- sub_span = altitude_table[l] - alt;
- pres = ((((int32_t) l * (span - sub_span) + (int32_t) h * sub_span) << ALT_FRAC_BITS) + (span >> 1)) / span;
- if (pres > 32767)
- pres = 32767;
- if (pres < 0)
- pres = 0;
- return (int16_t) pres;
-}
-
-int16_t
-ao_temp_to_dC(int16_t temp) __reentrant
-{
- int16_t ret;
-
- /* Output voltage at 0°C = 0.755V
- * Coefficient = 0.00247V/°C
- * Reference voltage = 1.25V
- *
- * temp = ((value / 32767) * 1.25 - 0.755) / 0.00247
- * = (value - 19791.268) / 32768 * 1.25 / 0.00247
- * ≃ (value - 19791) * 1012 / 65536
- */
- ret = ((temp - 19791) * 1012L) >> 16;
- return ret;
-}
+++ /dev/null
-/*
- * Copyright © 2010 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include <stdint.h>
-#define AO_CONVERT_TEST
-#include "ao_host.h"
-#include "ao_convert.c"
-
-#define STEP 1
-
-static inline i_abs(int i) { return i < 0 ? -i : i; }
-
-main ()
-{
- int i;
- int16_t p_to_a, p_to_a_to_p;
- int16_t a_to_p, a_to_p_to_a;
- int max_p_error = 0, max_p_error_p = -1;
- int max_a_error = 0, max_a_error_a = -1;
- int p_error;
- int a_error;
- int ret = 0;
-
- for (i = 0; i < 32767 + STEP; i += STEP) {
- if (i > 32767)
- i = 32767;
- p_to_a = ao_pres_to_altitude(i);
- p_to_a_to_p = ao_altitude_to_pres(p_to_a);
- p_error = i_abs(p_to_a_to_p - i);
- if (p_error > max_p_error) {
- max_p_error = p_error;
- max_p_error_p = i;
- }
-// printf ("pres %d alt %d pres %d\n",
-// i, p_to_a, p_to_a_to_p);
- }
- for (i = -1578; i < 15835 + STEP; i += STEP) {
- if (i > 15835)
- i = 15835;
- a_to_p = ao_altitude_to_pres(i);
- a_to_p_to_a = ao_pres_to_altitude(a_to_p);
- a_error = i_abs(a_to_p_to_a - i);
- if (a_error > max_a_error) {
- max_a_error = a_error;
- max_a_error_a = i;
- }
-// printf ("alt %d pres %d alt %d\n",
-// i, a_to_p, a_to_p_to_a);
- }
- if (max_p_error > 2) {
- printf ("max p error %d at %d\n", max_p_error,
- max_p_error_p);
- ret++;
- }
- if (max_a_error > 1) {
- printf ("max a error %d at %d\n", max_a_error,
- max_a_error_a);
- ret++;
- }
- return ret;
-}
+++ /dev/null
-/*
- * Copyright © 2009 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"
-#include "ao_pins.h"
-
-static void
-ao_dbg_send_bits(uint8_t msk, uint8_t val) __reentrant
-{
- DBG_PORT = (DBG_PORT & ~msk) | (val & msk);
- _asm
- nop
- nop
- _endasm;
-}
-
-void
-ao_dbg_send_byte(uint8_t byte)
-{
- __pdata uint8_t b, d;
-
- DBG_PORT |= DBG_DATA;
- DBG_PORT_DIR |= DBG_DATA;
- for (b = 0; b < 8; b++) {
- d = 0;
- if (byte & 0x80)
- d = DBG_DATA;
- byte <<= 1;
- ao_dbg_send_bits(DBG_CLOCK|DBG_DATA, DBG_CLOCK|d);
- ao_dbg_send_bits(DBG_CLOCK|DBG_DATA, 0 |d);
- }
- DBG_PORT_DIR &= ~DBG_DATA;
-}
-
-uint8_t
-ao_dbg_recv_byte(void)
-{
- __pdata uint8_t byte, b;
-
- byte = 0;
- for (b = 0; b < 8; b++) {
- byte = byte << 1;
- ao_dbg_send_bits(DBG_CLOCK, DBG_CLOCK);
- if (DBG_DATA_PIN)
- byte |= 1;
- ao_dbg_send_bits(DBG_CLOCK, 0);
- }
- return byte;
-}
-
-/* 8051 instructions
- */
-#define NOP 0x00
-#define MOV_direct_data 0x75
-#define LJMP 0x02
-#define MOV_Rn_data(n) (0x78 | (n))
-#define DJNZ_Rn_rel(n) (0xd8 | (n))
-#define MOV_A_direct 0xe5
-#define MOV_direct1_direct2 0x85
-#define MOV_direct_A 0xf5
-#define MOV_DPTR_data16 0x90
-#define MOV_A_data 0x74
-#define MOVX_atDPTR_A 0xf0
-#define MOVX_A_atDPTR 0xe0
-#define INC_DPTR 0xa3
-#define TRAP 0xa5
-#define SJMP 0x80
-#define JB 0x20
-
-#define DEBUG_INSTR(l) (0x54 | (l))
-
-#define SFR_PSW 0xD0
-#define SFR_DPL0 0x82
-#define SFR_DPH0 0x83
-#define SFR_DPL1 0x84
-#define SFR_DPH1 0x85
-
-__pdata uint8_t save_acc;
-__pdata uint8_t save_psw;
-__pdata uint8_t save_dpl0;
-__pdata uint8_t save_dph0;
-__pdata uint8_t save_dpl1;
-__pdata uint8_t save_dph1;
-
-static uint8_t
-ao_dbg_inst1(uint8_t a) __reentrant
-{
- ao_dbg_send_byte(DEBUG_INSTR(1));
- ao_dbg_send_byte(a);
- return ao_dbg_recv_byte();
-}
-
-static uint8_t
-ao_dbg_inst2(uint8_t a, uint8_t b) __reentrant
-{
- ao_dbg_send_byte(DEBUG_INSTR(2));
- ao_dbg_send_byte(a);
- ao_dbg_send_byte(b);
- return ao_dbg_recv_byte();
-}
-
-static uint8_t
-ao_dbg_inst3(uint8_t a, uint8_t b, uint8_t c) __reentrant
-{
- ao_dbg_send_byte(DEBUG_INSTR(3));
- ao_dbg_send_byte(a);
- ao_dbg_send_byte(b);
- ao_dbg_send_byte(c);
- return ao_dbg_recv_byte();
-}
-
-void
-ao_dbg_start_transfer(uint16_t addr)
-{
- save_acc = ao_dbg_inst1(NOP);
- save_psw = ao_dbg_inst2(MOV_A_direct, SFR_PSW);
- save_dpl0 = ao_dbg_inst2(MOV_A_direct, SFR_DPL0);
- save_dph0 = ao_dbg_inst2(MOV_A_direct, SFR_DPH0);
- save_dpl1 = ao_dbg_inst2(MOV_A_direct, SFR_DPL1);
- save_dph1 = ao_dbg_inst2(MOV_A_direct, SFR_DPH1);
- ao_dbg_inst3(MOV_DPTR_data16, addr >> 8, addr);
-}
-
-void
-ao_dbg_end_transfer(void)
-{
- ao_dbg_inst3(MOV_direct_data, SFR_DPL0, save_dpl0);
- ao_dbg_inst3(MOV_direct_data, SFR_DPH0, save_dph0);
- ao_dbg_inst3(MOV_direct_data, SFR_DPL1, save_dpl1);
- ao_dbg_inst3(MOV_direct_data, SFR_DPH1, save_dph1);
- ao_dbg_inst3(MOV_direct_data, SFR_PSW, save_psw);
- ao_dbg_inst2(MOV_A_data, save_acc);
-}
-
-void
-ao_dbg_write_byte(uint8_t byte)
-{
- ao_dbg_inst2(MOV_A_data, byte);
- ao_dbg_inst1(MOVX_atDPTR_A);
- ao_dbg_inst1(INC_DPTR);
-}
-
-uint8_t
-ao_dbg_read_byte(void)
-{
- ao_dbg_inst1(MOVX_A_atDPTR);
- return ao_dbg_inst1(INC_DPTR);
-}
-
-static void
-ao_dbg_set_pins(void)
-{
- /* Make the DBG pins GPIOs. On TeleMetrum, this will
- * disable the SPI link, so don't expect SPI to work after
- * using the debugger.
- */
- DBG_PORT_SEL &= ~(DBG_CLOCK|DBG_DATA|DBG_RESET_N);
-
- /* make DBG_DATA tri-state */
- DBG_PORT_INP |= DBG_DATA;
-
- /* Raise RESET_N and CLOCK */
- DBG_PORT |= DBG_RESET_N | DBG_CLOCK;
-
- /* RESET_N and CLOCK are outputs now */
- DBG_PORT_DIR |= DBG_RESET_N | DBG_CLOCK;
- DBG_PORT_DIR &= ~DBG_DATA;
-}
-
-static void
-ao_dbg_long_delay(void)
-{
- uint8_t n;
-
- for (n = 0; n < 20; n++)
- _asm nop _endasm;
-}
-
-#define AO_RESET_LOW_DELAY AO_MS_TO_TICKS(100)
-#define AO_RESET_HIGH_DELAY AO_MS_TO_TICKS(100)
-
-void
-ao_dbg_debug_mode(void)
-{
- ao_dbg_set_pins();
- ao_dbg_long_delay();
- ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N);
- ao_dbg_long_delay();
- ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 );
- ao_delay(AO_RESET_LOW_DELAY);
- ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 );
- ao_dbg_long_delay();
- ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 );
- ao_dbg_long_delay();
- ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 );
- ao_dbg_long_delay();
- ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA|DBG_RESET_N);
- ao_delay(AO_RESET_HIGH_DELAY);
-}
-
-void
-ao_dbg_reset(void)
-{
- ao_dbg_set_pins();
- ao_dbg_long_delay();
- ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N);
- ao_dbg_long_delay();
- ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 );
- ao_delay(AO_RESET_LOW_DELAY);
- ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 );
- ao_dbg_long_delay();
- ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 );
- ao_dbg_long_delay();
- ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 );
- ao_dbg_long_delay();
- ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N);
- ao_delay(AO_RESET_HIGH_DELAY);
-}
-
-static void
-debug_enable(void)
-{
- ao_dbg_debug_mode();
-}
-
-static void
-debug_reset(void)
-{
- ao_dbg_reset();
-}
-
-static void
-debug_put(void)
-{
- for (;;) {
- ao_cmd_white ();
- if (ao_cmd_lex_c == '\n')
- break;
- ao_cmd_hex();
- if (ao_cmd_status != ao_cmd_success)
- break;
- ao_dbg_send_byte(ao_cmd_lex_i);
- }
-}
-
-static void
-debug_get(void)
-{
- __pdata uint16_t count;
- __pdata uint16_t i;
- __pdata uint8_t byte;
- ao_cmd_hex();
- if (ao_cmd_status != ao_cmd_success)
- return;
- count = ao_cmd_lex_i;
- if (count > 256) {
- ao_cmd_status = ao_cmd_syntax_error;
- return;
- }
- for (i = 0; i < count; i++) {
- if (i && (i & 7) == 0)
- putchar('\n');
- byte = ao_dbg_recv_byte();
- ao_cmd_put8(byte);
- putchar(' ');
- }
- putchar('\n');
-}
-
-static uint8_t
-getnibble(void)
-{
- __pdata char c;
-
- c = getchar();
- if ('0' <= c && c <= '9')
- return c - '0';
- if ('a' <= c && c <= 'f')
- return c - ('a' - 10);
- if ('A' <= c && c <= 'F')
- return c - ('A' - 10);
- ao_cmd_status = ao_cmd_lex_error;
- return 0;
-}
-
-static void
-debug_input(void)
-{
- __pdata uint16_t count;
- __pdata uint16_t addr;
- __pdata uint8_t b;
- __pdata uint8_t i;
-
- ao_cmd_hex();
- count = ao_cmd_lex_i;
- ao_cmd_hex();
- addr = ao_cmd_lex_i;
- if (ao_cmd_status != ao_cmd_success)
- return;
- ao_dbg_start_transfer(addr);
- i = 0;
- while (count--) {
- if (!(i++ & 7))
- putchar('\n');
- b = ao_dbg_read_byte();
- ao_cmd_put8(b);
- }
- ao_dbg_end_transfer();
- putchar('\n');
-}
-
-static void
-debug_output(void)
-{
- __pdata uint16_t count;
- __pdata uint16_t addr;
- __pdata uint8_t b;
-
- ao_cmd_hex();
- count = ao_cmd_lex_i;
- ao_cmd_hex();
- addr = ao_cmd_lex_i;
- if (ao_cmd_status != ao_cmd_success)
- return;
- ao_dbg_start_transfer(addr);
- while (count--) {
- b = getnibble() << 4;
- b |= getnibble();
- if (ao_cmd_status != ao_cmd_success)
- return;
- ao_dbg_write_byte(b);
- }
- ao_dbg_end_transfer();
-}
-
-__code struct ao_cmds ao_dbg_cmds[7] = {
- { debug_enable, "D\0Enable debug" },
- { debug_get, "G <count>\0Get data" },
- { debug_input, "I <count> <addr>\0Input <count> at <addr>" },
- { debug_output, "O <count> <addr>\0Output <count> at <addr>" },
- { debug_put, "P <byte> ...\0Put data" },
- { debug_reset, "R\0Reset" },
- { 0, NULL },
-};
-
-void
-ao_dbg_init(void)
-{
- ao_cmd_register(&ao_dbg_cmds[0]);
-}
+++ /dev/null
-/*
- * Copyright © 2009 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"
-
-#define NUM_DMA 5
-
-/*
- * The config address for DMA0 is programmed
- * separately from that of DMA1-4, but for simplicity,
- * we make them all contiguous.
- */
-
-static __xdata struct cc_dma_channel ao_dma_config[NUM_DMA];
-static __xdata uint8_t * __xdata ao_dma_done[NUM_DMA];
-static __data uint8_t ao_next_dma;
-
-uint8_t
-ao_dma_alloc(__xdata uint8_t *done)
-{
- uint8_t id;
-
- if (ao_next_dma == NUM_DMA)
- ao_panic(AO_PANIC_DMA);
- id = ao_next_dma++;
- ao_dma_done[id] = done;
-
- /* When the first dma object is allocated, set up the DMA
- * controller
- */
- if (id == 0) {
- DMAIRQ = 0;
- DMAIF = 0;
- IEN1 |= IEN1_DMAIE;
- }
-
- return id;
-}
-
-void
-ao_dma_set_transfer(uint8_t id,
- void __xdata *srcaddr,
- void __xdata *dstaddr,
- uint16_t count,
- uint8_t cfg0,
- uint8_t cfg1)
-{
- if (DMAARM & (1 << id))
- ao_panic(AO_PANIC_DMA);
- ao_dma_config[id].src_high = ((uint16_t) srcaddr) >> 8;
- ao_dma_config[id].src_low = ((uint16_t) srcaddr);
- ao_dma_config[id].dst_high = ((uint16_t) dstaddr) >> 8;
- ao_dma_config[id].dst_low = ((uint16_t) dstaddr);
- ao_dma_config[id].len_high = count >> 8;
- ao_dma_config[id].len_low = count;
- ao_dma_config[id].cfg0 = cfg0;
- ao_dma_config[id].cfg1 = cfg1 | DMA_CFG1_IRQMASK;
- if (id == 0) {
- DMA0CFGH = ((uint16_t) (&ao_dma_config[0])) >> 8;
- DMA0CFGL = ((uint16_t) (&ao_dma_config[0]));
- } else {
- DMA1CFGH = ((uint16_t) (&ao_dma_config[1])) >> 8;
- DMA1CFGL = ((uint16_t) (&ao_dma_config[1]));
- }
-}
-
-#define nop() _asm nop _endasm;
-
-void
-ao_dma_start(uint8_t id)
-{
- uint8_t mask = (1 << id);
- DMAIRQ &= ~mask;
- DMAARM = 0x80 | mask;
- nop(); nop(); nop(); nop();
- nop(); nop(); nop(); nop();
- *(ao_dma_done[id]) = 0;
- DMAARM = mask;
- nop(); nop(); nop(); nop();
- nop(); nop(); nop(); nop();
- nop();
-}
-
-void
-ao_dma_trigger(uint8_t id)
-{
- DMAREQ |= (1 << id);
-}
-
-void
-ao_dma_abort(uint8_t id)
-{
- uint8_t mask = (1 << id);
- DMAARM = 0x80 | mask;
- DMAIRQ &= ~mask;
-}
-
-void
-ao_dma_isr(void) __interrupt 8
-{
- uint8_t id, mask;
-
- /* Find the first DMA channel which is done */
- mask = 1;
- for (id = 0; id < ao_next_dma; id++) {
- if (DMAIRQ & mask) {
- /* Clear CPU interrupt flag */
- DMAIF = 0;
- /* Clear the completed ID */
- DMAIRQ = ~mask;
- *(ao_dma_done[id]) = 1;
- ao_wakeup(ao_dma_done[id]);
- break;
- }
- mask <<= 1;
- }
-}
+++ /dev/null
-/*
- * Copyright © 2009 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"
-#include "25lc1024.h"
-
-#define EE_BLOCK_SIZE ((uint16_t) (256))
-#define EE_BLOCK_SHIFT 8
-#define EE_DEVICE_SIZE ((uint32_t) 128 * (uint32_t) 1024)
-
-/* Total bytes of available storage */
-__pdata uint32_t ao_storage_total;
-
-/* Block size - device is erased in these units. At least 256 bytes */
-__pdata uint32_t ao_storage_block;
-
-/* Byte offset of config block. Will be ao_storage_block bytes long */
-__pdata uint32_t ao_storage_config;
-
-/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */
-__pdata uint16_t ao_storage_unit;
-
-/*
- * Using SPI on USART 0, with P1_2 as the chip select
- */
-
-#define EE_CS P1_2
-#define EE_CS_INDEX 2
-
-static __xdata uint8_t ao_ee_mutex;
-
-#define ao_ee_delay() do { \
- _asm nop _endasm; \
- _asm nop _endasm; \
- _asm nop _endasm; \
-} while(0)
-
-#define ao_ee_cs_low() ao_spi_get_bit(EE_CS)
-
-#define ao_ee_cs_high() ao_spi_put_bit(EE_CS)
-
-struct ao_ee_instruction {
- uint8_t instruction;
- uint8_t address[3];
-} __xdata ao_ee_instruction;
-
-static void
-ao_ee_write_enable(void)
-{
- ao_ee_cs_low();
- ao_ee_instruction.instruction = EE_WREN;
- ao_spi_send(&ao_ee_instruction, 1);
- ao_ee_cs_high();
-}
-
-static uint8_t
-ao_ee_rdsr(void)
-{
- ao_ee_cs_low();
- ao_ee_instruction.instruction = EE_RDSR;
- ao_spi_send(&ao_ee_instruction, 1);
- ao_spi_recv(&ao_ee_instruction, 1);
- ao_ee_cs_high();
- return ao_ee_instruction.instruction;
-}
-
-static void
-ao_ee_wrsr(uint8_t status)
-{
- ao_ee_cs_low();
- ao_ee_instruction.instruction = EE_WRSR;
- ao_ee_instruction.address[0] = status;
- ao_spi_send(&ao_ee_instruction, 2);
- ao_ee_cs_high();
-}
-
-#define EE_BLOCK_NONE 0xffff
-
-static __xdata uint8_t ao_ee_data[EE_BLOCK_SIZE];
-static __pdata uint16_t ao_ee_block = EE_BLOCK_NONE;
-static __pdata uint8_t ao_ee_block_dirty;
-
-/* Write the current block to the EEPROM */
-static void
-ao_ee_write_block(void)
-{
- uint8_t status;
-
- status = ao_ee_rdsr();
- if (status & (EE_STATUS_BP0|EE_STATUS_BP1|EE_STATUS_WPEN)) {
- status &= ~(EE_STATUS_BP0|EE_STATUS_BP1|EE_STATUS_WPEN);
- ao_ee_wrsr(status);
- }
- ao_ee_write_enable();
- ao_ee_cs_low();
- ao_ee_instruction.instruction = EE_WRITE;
- ao_ee_instruction.address[0] = ao_ee_block >> 8;
- ao_ee_instruction.address[1] = ao_ee_block;
- ao_ee_instruction.address[2] = 0;
- ao_spi_send(&ao_ee_instruction, 4);
- ao_spi_send(ao_ee_data, EE_BLOCK_SIZE);
- ao_ee_cs_high();
- for (;;) {
- uint8_t status = ao_ee_rdsr();
- if ((status & EE_STATUS_WIP) == 0)
- break;
- }
-}
-
-/* Read the current block from the EEPROM */
-static void
-ao_ee_read_block(void)
-{
- ao_ee_cs_low();
- ao_ee_instruction.instruction = EE_READ;
- ao_ee_instruction.address[0] = ao_ee_block >> 8;
- ao_ee_instruction.address[1] = ao_ee_block;
- ao_ee_instruction.address[2] = 0;
- ao_spi_send(&ao_ee_instruction, 4);
- ao_spi_recv(ao_ee_data, EE_BLOCK_SIZE);
- ao_ee_cs_high();
-}
-
-static void
-ao_ee_flush_internal(void)
-{
- if (ao_ee_block_dirty) {
- ao_ee_write_block();
- ao_ee_block_dirty = 0;
- }
-}
-
-static void
-ao_ee_fill(uint16_t block)
-{
- if (block != ao_ee_block) {
- ao_ee_flush_internal();
- ao_ee_block = block;
- ao_ee_read_block();
- }
-}
-
-uint8_t
-ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant
-{
- uint16_t block = (uint16_t) (pos >> EE_BLOCK_SHIFT);
-
- /* Transfer the data */
- ao_mutex_get(&ao_ee_mutex); {
- if (len != EE_BLOCK_SIZE)
- ao_ee_fill(block);
- else {
- ao_ee_flush_internal();
- ao_ee_block = block;
- }
- memcpy(ao_ee_data + (uint16_t) (pos & 0xff), buf, len);
- ao_ee_block_dirty = 1;
- } ao_mutex_put(&ao_ee_mutex);
- return 1;
-}
-
-uint8_t
-ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant
-{
- uint16_t block = (uint16_t) (pos >> EE_BLOCK_SHIFT);
-
- /* Transfer the data */
- ao_mutex_get(&ao_ee_mutex); {
- ao_ee_fill(block);
- memcpy(buf, ao_ee_data + (uint16_t) (pos & 0xff), len);
- } ao_mutex_put(&ao_ee_mutex);
- return 1;
-}
-
-void
-ao_storage_flush(void) __reentrant
-{
- ao_mutex_get(&ao_ee_mutex); {
- ao_ee_flush_internal();
- } ao_mutex_put(&ao_ee_mutex);
-}
-
-uint8_t
-ao_storage_erase(uint32_t pos) __reentrant
-{
- ao_mutex_get(&ao_ee_mutex); {
- ao_ee_flush_internal();
- ao_ee_block = (uint16_t) (pos >> EE_BLOCK_SHIFT);
- memset(ao_ee_data, 0xff, EE_BLOCK_SIZE);
- ao_ee_block_dirty = 1;
- } ao_mutex_put(&ao_ee_mutex);
- return 1;
-}
-
-static void
-ee_store(void) __reentrant
-{
-}
-
-void
-ao_storage_setup(void)
-{
- if (ao_storage_total == 0) {
- ao_storage_total = EE_DEVICE_SIZE;
- ao_storage_block = EE_BLOCK_SIZE;
- ao_storage_config = EE_DEVICE_SIZE - EE_BLOCK_SIZE;
- ao_storage_unit = EE_BLOCK_SIZE;
- }
-}
-
-void
-ao_storage_device_info(void) __reentrant
-{
-}
-
-/*
- * To initialize the chip, set up the CS line and
- * the SPI interface
- */
-void
-ao_storage_device_init(void)
-{
- /* set up CS */
- EE_CS = 1;
- P1DIR |= (1 << EE_CS_INDEX);
- P1SEL &= ~(1 << EE_CS_INDEX);
-}
+++ /dev/null
-/*
- * Copyright © 2009 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"
-
-/*
- * For hardware without eeprom, the config code still
- * wants to call these functions
- */
-uint8_t
-ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant
-{
- (void) buf;
- (void) len;
- return 1;
-}
-
-uint8_t
-ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant
-{
- memset(buf, '\0', len);
- return 1;
-}
+++ /dev/null
-/*
- * Copyright © 2009 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"
-#include "at45db161d.h"
-
-/* Total bytes of available storage */
-__pdata uint32_t ao_storage_total;
-
-/* Block size - device is erased in these units. At least 256 bytes */
-__pdata uint32_t ao_storage_block;
-
-/* Byte offset of config block. Will be ao_storage_block bytes long */
-__pdata uint32_t ao_storage_config;
-
-/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */
-__pdata uint16_t ao_storage_unit;
-
-#define FLASH_CS P1_1
-#define FLASH_CS_INDEX 1
-
-#define FLASH_BLOCK_SIZE_MAX 512
-
-__xdata uint8_t ao_flash_mutex;
-
-#define ao_flash_delay() do { \
- _asm nop _endasm; \
- _asm nop _endasm; \
- _asm nop _endasm; \
-} while(0)
-
-#define ao_flash_cs_low() ao_spi_get_bit(FLASH_CS)
-
-#define ao_flash_cs_high() ao_spi_put_bit(FLASH_CS)
-
-struct ao_flash_instruction {
- uint8_t instruction;
- uint8_t address[3];
-} __xdata ao_flash_instruction;
-
-static void
-ao_flash_set_pagesize_512(void)
-{
- ao_flash_cs_low();
- ao_flash_instruction.instruction = FLASH_SET_CONFIG;
- ao_flash_instruction.address[0] = FLASH_SET_512_BYTE_0;
- ao_flash_instruction.address[1] = FLASH_SET_512_BYTE_1;
- ao_flash_instruction.address[2] = FLASH_SET_512_BYTE_2;
- ao_spi_send(&ao_flash_instruction, 4);
- ao_flash_cs_high();
-}
-
-
-static uint8_t
-ao_flash_read_status(void)
-{
- ao_flash_cs_low();
- ao_flash_instruction.instruction = FLASH_READ_STATUS;
- ao_spi_send(&ao_flash_instruction, 1);
- ao_spi_recv(&ao_flash_instruction, 1);
- ao_flash_cs_high();
- return ao_flash_instruction.instruction;
-}
-
-#define FLASH_BLOCK_NONE 0xffff
-
-static __xdata uint8_t ao_flash_data[FLASH_BLOCK_SIZE_MAX];
-static __pdata uint16_t ao_flash_block = FLASH_BLOCK_NONE;
-static __pdata uint8_t ao_flash_block_dirty;
-static __pdata uint8_t ao_flash_write_pending;
-static __pdata uint8_t ao_flash_setup_done;
-static __pdata uint8_t ao_flash_block_shift;
-static __pdata uint16_t ao_flash_block_size;
-static __pdata uint16_t ao_flash_block_mask;
-
-void
-ao_storage_setup(void) __reentrant
-{
- uint8_t status;
-
- if (ao_flash_setup_done)
- return;
-
- ao_mutex_get(&ao_flash_mutex);
- if (ao_flash_setup_done) {
- ao_mutex_put(&ao_flash_mutex);
- return;
- }
-
- /* On first use, check to see if the flash chip has
- * been programmed to use 512 byte pages. If not, do so.
- * And then, because the flash part must be power cycled
- * for that change to take effect, panic.
- */
- status = ao_flash_read_status();
-
- if (!(status & FLASH_STATUS_PAGESIZE_512)) {
- ao_flash_set_pagesize_512();
- ao_panic(AO_PANIC_FLASH);
- }
-
- switch (status & 0x3c) {
-
- /* AT45DB321D */
- case 0x34:
- ao_flash_block_shift = 9;
- ao_storage_total = ((uint32_t) 4 * (uint32_t) 1024 * (uint32_t) 1024);
- break;
-
- /* AT45DB161D */
- case 0x2c:
- ao_flash_block_shift = 9;
- ao_storage_total = ((uint32_t) 2 * (uint32_t) 1024 * (uint32_t) 1024);
- break;
-
- /* AT45DB081D */
- case 0x24:
- ao_flash_block_shift = 8;
- ao_storage_total = ((uint32_t) 1024 * (uint32_t) 1024);
- break;
-
- /* AT45DB041D */
- case 0x1c:
- ao_flash_block_shift = 8;
- ao_storage_total = ((uint32_t) 512 * (uint32_t) 1024);
- break;
-
- /* AT45DB021D */
- case 0x14:
- ao_flash_block_shift = 8;
- ao_storage_total = ((uint32_t) 256 * (uint32_t) 1024);
- break;
-
- /* AT45DB011D */
- case 0x0c:
- ao_flash_block_shift = 8;
- ao_storage_total = ((uint32_t) 128 * (uint32_t) 1024);
- break;
-
- default:
- ao_panic(AO_PANIC_FLASH);
- }
- ao_flash_block_size = 1 << ao_flash_block_shift;
- ao_flash_block_mask = ao_flash_block_size - 1;
-
- ao_storage_block = ao_flash_block_size;
- ao_storage_config = ao_storage_total - ao_storage_block;
- ao_storage_unit = ao_flash_block_size;
-
- ao_flash_setup_done = 1;
- ao_mutex_put(&ao_flash_mutex);
-}
-
-static void
-ao_flash_wait_write(void)
-{
- if (ao_flash_write_pending) {
- for (;;) {
- uint8_t status = ao_flash_read_status();
- if ((status & FLASH_STATUS_RDY))
- break;
- }
- ao_flash_write_pending = 0;
- }
-}
-
-/* Write the current block to the FLASHPROM */
-static void
-ao_flash_write_block(void)
-{
- ao_flash_wait_write();
- ao_flash_cs_low();
- ao_flash_instruction.instruction = FLASH_WRITE;
-
- /* 13/14 block bits + 9/8 byte bits (always 0) */
- ao_flash_instruction.address[0] = ao_flash_block >> (16 - ao_flash_block_shift);
- ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8);
- ao_flash_instruction.address[2] = 0;
- ao_spi_send(&ao_flash_instruction, 4);
- ao_spi_send(ao_flash_data, ao_storage_block);
- ao_flash_cs_high();
- ao_flash_write_pending = 1;
-}
-
-/* Read the current block from the FLASHPROM */
-static void
-ao_flash_read_block(void)
-{
- ao_flash_wait_write();
- ao_flash_cs_low();
- ao_flash_instruction.instruction = FLASH_READ;
-
- /* 13/14 block bits + 9/8 byte bits (always 0) */
- ao_flash_instruction.address[0] = ao_flash_block >> (16 - ao_flash_block_shift);
- ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8);
- ao_flash_instruction.address[2] = 0;
- ao_spi_send(&ao_flash_instruction, 4);
- ao_spi_recv(ao_flash_data, ao_flash_block_size);
- ao_flash_cs_high();
-}
-
-static void
-ao_flash_flush_internal(void)
-{
- if (ao_flash_block_dirty) {
- ao_flash_write_block();
- ao_flash_block_dirty = 0;
- }
-}
-
-static void
-ao_flash_fill(uint16_t block)
-{
- if (block != ao_flash_block) {
- ao_flash_flush_internal();
- ao_flash_block = block;
- ao_flash_read_block();
- }
-}
-
-uint8_t
-ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant
-{
- uint16_t block = (uint16_t) (pos >> ao_flash_block_shift);
-
- /* Transfer the data */
- ao_mutex_get(&ao_flash_mutex); {
- if (len != ao_flash_block_size)
- ao_flash_fill(block);
- else {
- ao_flash_flush_internal();
- ao_flash_block = block;
- }
- memcpy(ao_flash_data + (uint16_t) (pos & ao_flash_block_mask),
- buf,
- len);
- ao_flash_block_dirty = 1;
- } ao_mutex_put(&ao_flash_mutex);
- return 1;
-}
-
-uint8_t
-ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant
-{
- uint16_t block = (uint16_t) (pos >> ao_flash_block_shift);
-
- /* Transfer the data */
- ao_mutex_get(&ao_flash_mutex); {
- ao_flash_fill(block);
- memcpy(buf,
- ao_flash_data + (uint16_t) (pos & ao_flash_block_mask),
- len);
- } ao_mutex_put(&ao_flash_mutex);
- return 1;
-}
-
-void
-ao_storage_flush(void) __reentrant
-{
- ao_mutex_get(&ao_flash_mutex); {
- ao_flash_flush_internal();
- } ao_mutex_put(&ao_flash_mutex);
-}
-
-uint8_t
-ao_storage_erase(uint32_t pos) __reentrant
-{
- ao_mutex_get(&ao_flash_mutex); {
- ao_flash_flush_internal();
- ao_flash_block = (uint16_t) (pos >> ao_flash_block_shift);
- memset(ao_flash_data, 0xff, ao_flash_block_size);
- ao_flash_block_dirty = 1;
- } ao_mutex_put(&ao_flash_mutex);
- return 1;
-}
-
-void
-ao_storage_device_info(void) __reentrant
-{
- uint8_t status;
-
- ao_storage_setup();
- ao_mutex_get(&ao_flash_mutex); {
- status = ao_flash_read_status();
- printf ("Flash status: 0x%02x\n", status);
- printf ("Flash block shift: %d\n", ao_flash_block_shift);
- printf ("Flash block size: %d\n", ao_flash_block_size);
- printf ("Flash block mask: %d\n", ao_flash_block_mask);
- printf ("Flash device size: %ld\n", ao_storage_total);
- } ao_mutex_put(&ao_flash_mutex);
-}
-
-/*
- * To initialize the chip, set up the CS line and
- * the SPI interface
- */
-void
-ao_storage_device_init(void)
-{
- /* set up CS */
- FLASH_CS = 1;
- P1DIR |= (1 << FLASH_CS_INDEX);
- P1SEL &= ~(1 << FLASH_CS_INDEX);
-}
+++ /dev/null
-/*
- * Copyright © 2009 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.
- */
-
-#ifndef AO_FLIGHT_TEST
-#include "ao.h"
-#endif
-
-#ifndef HAS_ACCEL
-#error Please define HAS_ACCEL
-#endif
-
-#ifndef HAS_GPS
-#error Please define HAS_GPS
-#endif
-
-#ifndef HAS_USB
-#error Please define HAS_USB
-#endif
-
-/* Main flight thread. */
-
-__pdata enum ao_flight_state ao_flight_state; /* current flight state */
-__pdata uint16_t ao_launch_tick; /* time of launch detect */
-
-/*
- * track min/max data over a long interval to detect
- * resting
- */
-__pdata uint16_t ao_interval_end;
-__pdata int16_t ao_interval_min_height;
-__pdata int16_t ao_interval_max_height;
-__pdata uint8_t ao_flight_force_idle;
-
-/* We also have a clock, which can be used to sanity check things in
- * case of other failures
- */
-
-#define BOOST_TICKS_MAX AO_SEC_TO_TICKS(15)
-
-/* Landing is detected by getting constant readings from both pressure and accelerometer
- * for a fairly long time (AO_INTERVAL_TICKS)
- */
-#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(10)
-
-#define abs(a) ((a) < 0 ? -(a) : (a))
-
-void
-ao_flight(void)
-{
- ao_sample_init();
- ao_flight_state = ao_flight_startup;
- for (;;) {
-
- /*
- * Process ADC samples, just looping
- * until the sensors are calibrated.
- */
- if (!ao_sample())
- continue;
-
- switch (ao_flight_state) {
- case ao_flight_startup:
-
- /* Check to see what mode we should go to.
- * - Invalid mode if accel cal appears to be out
- * - pad mode if we're upright,
- * - idle mode otherwise
- */
-#if HAS_ACCEL
- if (ao_config.accel_plus_g == 0 ||
- ao_config.accel_minus_g == 0 ||
- ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP ||
- ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP)
- {
- /* Detected an accel value outside -1.5g to 1.5g
- * (or uncalibrated values), so we go into invalid mode
- */
- ao_flight_state = ao_flight_invalid;
-
- } else
-#endif
- if (!ao_flight_force_idle
-#if HAS_ACCEL
- && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP
-#endif
- )
- {
- /* Set pad mode - we can fly! */
- ao_flight_state = ao_flight_pad;
-#if HAS_USB
- /* Disable the USB controller in flight mode
- * to save power
- */
- ao_usb_disable();
-#endif
-
- /* Disable packet mode in pad state */
- ao_packet_slave_stop();
-
- /* Turn on telemetry system */
- ao_rdf_set(1);
- ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD);
-
- /* signal successful initialization by turning off the LED */
- ao_led_off(AO_LED_RED);
- } else {
- /* Set idle mode */
- ao_flight_state = ao_flight_idle;
-
- /* signal successful initialization by turning off the LED */
- ao_led_off(AO_LED_RED);
- }
- /* wakeup threads due to state change */
- ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
-
- break;
- case ao_flight_pad:
-
- /* pad to boost:
- *
- * barometer: > 20m vertical motion
- * OR
- * accelerometer: > 2g AND velocity > 5m/s
- *
- * The accelerometer should always detect motion before
- * the barometer, but we use both to make sure this
- * transition is detected. If the device
- * doesn't have an accelerometer, then ignore the
- * speed and acceleration as they are quite noisy
- * on the pad.
- */
- if (ao_height > AO_M_TO_HEIGHT(20)
-#if HAS_ACCEL
- || (ao_accel > AO_MSS_TO_ACCEL(20) &&
- ao_speed > AO_MS_TO_SPEED(5))
-#endif
- )
- {
- ao_flight_state = ao_flight_boost;
- ao_launch_tick = ao_sample_tick;
-
- /* start logging data */
- ao_log_start();
-
- /* Increase telemetry rate */
- ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT);
-
- /* disable RDF beacon */
- ao_rdf_set(0);
-
-#if HAS_GPS
- /* Record current GPS position by waking up GPS log tasks */
- ao_wakeup(&ao_gps_data);
- ao_wakeup(&ao_gps_tracking_data);
-#endif
-
- ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
- }
- break;
- case ao_flight_boost:
-
- /* boost to fast:
- *
- * accelerometer: start to fall at > 1/4 G
- * OR
- * time: boost for more than 15 seconds
- *
- * Detects motor burn out by the switch from acceleration to
- * deceleration, or by waiting until the maximum burn duration
- * (15 seconds) has past.
- */
- if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) ||
- (int16_t) (ao_sample_tick - ao_launch_tick) > BOOST_TICKS_MAX)
- {
-#if HAS_ACCEL
- ao_flight_state = ao_flight_fast;
-#else
- ao_flight_state = ao_flight_coast;
-#endif
- ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
- }
- break;
-#if HAS_ACCEL
- case ao_flight_fast:
- /*
- * This is essentially the same as coast,
- * but the barometer is being ignored as
- * it may be unreliable.
- */
- if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED))
- {
- ao_flight_state = ao_flight_coast;
- ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
- }
- break;
-#endif
- case ao_flight_coast:
-
- /* apogee detect: coast to drogue deploy:
- *
- * speed: < 0
- *
- * Also make sure the model altitude is tracking
- * the measured altitude reasonably closely; otherwise
- * we're probably transsonic.
- */
- if (ao_speed < 0
-#if !HAS_ACCEL
- && (ao_sample_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100)
-#endif
- )
- {
- /* ignite the drogue charge */
- ao_ignite(ao_igniter_drogue);
-
- /* slow down the telemetry system */
- ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER);
-
- /* Turn the RDF beacon back on */
- ao_rdf_set(1);
-
- /* and enter drogue state */
- ao_flight_state = ao_flight_drogue;
- ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
- }
-
- break;
- case ao_flight_drogue:
-
- /* drogue to main deploy:
- *
- * barometer: reach main deploy altitude
- *
- * Would like to use the accelerometer for this test, but
- * the orientation of the flight computer is unknown after
- * drogue deploy, so we ignore it. Could also detect
- * high descent rate using the pressure sensor to
- * recognize drogue deploy failure and eject the main
- * at that point. Perhaps also use the drogue sense lines
- * to notice continutity?
- */
- if (ao_height <= ao_config.main_deploy)
- {
- ao_ignite(ao_igniter_main);
-
- /*
- * Start recording min/max height
- * to figure out when the rocket has landed
- */
-
- /* initialize interval values */
- ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS;
-
- ao_interval_min_height = ao_interval_max_height = ao_avg_height;
-
- ao_flight_state = ao_flight_main;
- ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
- }
- break;
-
- /* fall through... */
- case ao_flight_main:
-
- /* main to land:
- *
- * barometer: altitude stable
- */
-
- if (ao_avg_height < ao_interval_min_height)
- ao_interval_min_height = ao_avg_height;
- if (ao_avg_height > ao_interval_max_height)
- ao_interval_max_height = ao_avg_height;
-
- if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) {
- if (ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(4))
- {
- ao_flight_state = ao_flight_landed;
-
- /* turn off the ADC capture */
- ao_timer_set_adc_interval(0);
-
- ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
- }
- ao_interval_min_height = ao_interval_max_height = ao_avg_height;
- ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS;
- }
- break;
- case ao_flight_landed:
- break;
- }
- }
-}
-
-static __xdata struct ao_task flight_task;
-
-void
-ao_flight_init(void)
-{
- ao_flight_state = ao_flight_startup;
- ao_add_task(&flight_task, ao_flight, "flight");
-}
+++ /dev/null
-/*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-/* Main flight thread. */
-
-__pdata enum ao_flight_state ao_flight_state; /* current&