telegps/TeleGPS-Windows-$(VERSION_DASH).exe \
micropeak/MicroPeak-Windows-$(VERSION_DASH).exe
+fat_android = \
+ altosdroid/bin/AltosDroid-debug.apk \
+ altosdroid/bin/AltosDroid-release.apk
+
keithp-fat: fat
ssh keithp.com mkdir -p public_html/altos-$(VERSION)
- scp -p $(fat_linux) $(fat_mac) $(fat_windows) keithp.com:public_html/altos-$(VERSION)
+ scp -p $(fat_linux) $(fat_mac) $(fat_windows) $(fat_android) keithp.com:public_html/altos-$(VERSION)
set-java-versions:
$(top_srcdir)/fix-java-versions org.altusmetrum.altoslib=$(ALTOSLIB_VERSION) org.altusmetrum.altosuilib=$(ALTOSUILIB_VERSION)
src/teledongle-v3.0/*.elf \
src/telegps-v1.0/*.elf \
src/telemega-v1.0/*.elf \
+ src/telemega-v2.0/*.elf \
src/telemetrum-v2.0/*.elf \
~/altusmetrumllc/Binaries/
cp src/easymega-v1.0/flash-loader/*.elf \
src/teledongle-v3.0/flash-loader/*.elf \
src/telegps-v1.0/flash-loader/*.elf \
src/telemega-v1.0/flash-loader/*.elf \
+ src/telemega-v2.0/flash-loader/*.elf \
src/telemetrum-v2.0/flash-loader/*.elf \
~/altusmetrumllc/Binaries/loaders/
(cd ~/altusmetrumllc ; git add Binaries ; git commit -a)
google-play-services_lib
src/org/altusmetrum/AltosDroid/BuildInfo.java
res/drawable/*led.png
+AndroidManifest.xml
<uses-permission android:name="org.altusmetrum.AltosDroid.permission.MAPS_RECEIVE"/>
<!-- Permissions needed to access USB OTG -->
- <uses-feature android:name="android.hardware.usb.host" />
+ <uses-feature android:name="android.hardware.usb.host" android:required="false" />
<application android:label="@string/app_name"
android:icon="@drawable/app_icon"
android:theme="@android:style/Theme.Dialog"
android:configChanges="orientation|keyboardHidden" />
+ <activity android:name=".IdleModeActivity"
+ android:label="@string/idle_mode"
+ android:theme="@android:style/Theme.Dialog"
+ android:configChanges="orientation|keyboardHidden" />
+
+ <activity android:name=".IgniterActivity"
+ android:label="@string/igniters"
+ android:theme="@android:style/Theme.Dialog"
+ android:configChanges="orientation|keyboardHidden" />
+
+ <activity android:name=".SetupActivity"
+ android:label="@string/setup"
+ android:theme="@android:style/Theme.Dialog"
+ android:configChanges="orientation" />
+
+ <activity android:name=".ManageFrequenciesActivity"
+ android:label="@string/manage_frequencies"
+ android:theme="@android:style/Theme.Dialog"
+ android:configChanges="orientation|keyboard" />
+
<service android:name=".TelemetryService" />
<meta-data android:name="com.google.android.maps.v2.API_KEY"
- android:value="AIzaSyDSr6u4i9TJmVGhgGk4g0wUUhTy9FGyn0s"/>
+ android:value="@GOOGLEKEY@"/>
<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
</application>
LAYOUTS=$(LAYOUT_DIR)/*.xml
MENUS=$(MENU_DIR)/*.xml
VALUES=$(VALUES_DIR)/*.xml
-XMLS=$(XML_DIR)/*.xml
+XMLS=$(XML_DIR)/*.xml AndroidManifest.xml
RES=$(LAYOUTS) $(MENUS) $(VALUES) $(XMLS)
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!--
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Copyright © 2016 Keith Packard <keithp@keithp.com>
- http://www.apache.org/licenses/LICENSE-2.0
+ 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.
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright © 2016 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.
+
+-->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="horizontal"
+ >
+ <TextView
+ android:id="@+id/frequency"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:padding="10dp"
+ android:layout_weight="1"
+ />
+</LinearLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright © 2016 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.
+
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ >
+ <TextView android:id="@+id/set_callsign_label"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/set_callsign_label"
+ />
+ <EditText android:id="@+id/set_callsign"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:hint="@string/set_callsign_label"/>
+ <Button android:id="@+id/connect_idle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/connect_idle"
+ />
+ <Button android:id="@+id/disconnect_idle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/disconnect_idle"
+ />
+ <Button android:id="@+id/reboot_idle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/reboot_idle"
+ />
+ <Button android:id="@+id/igniters_idle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/igniters_idle"
+ />
+</LinearLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright © 2016 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.
+
+-->
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+ <TextView
+ android:id="@+id/igniter_status"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:padding="10dp"
+ android:layout_alignParentRight="true"
+ />
+ <TextView
+ android:id="@+id/igniter_name"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:padding="10dp"
+ android:layout_alignParentLeft="@+id/igniter_status"
+ />
+</RelativeLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright © 2016 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.
+
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ >
+
+ <ListView android:id="@+id/igniters"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:fadeScrollbars="false"
+ android:scrollbars="vertical"
+ android:choiceMode="singleChoice"
+ />
+
+ <ToggleButton android:id="@+id/igniter_arm"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textOn="@string/igniter_armed"
+ android:textOff="@string/igniter_arm"
+ />
+
+ <Button android:id="@+id/igniter_fire"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/igniter_fire"
+ />
+
+</LinearLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright © 2016 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.
+
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ >
+
+ <LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/set_layout"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ >
+ <EditText
+ android:id="@+id/set_frequency"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:padding="10dp"
+ android:layout_weight="1"
+ android:hint="@string/frequency"
+ android:inputType="number|numberDecimal"/>
+ />
+ <TextView
+ android:id="@+id/mhz"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:padding="10dp"
+ android:layout_weight="0"
+ android:text="@string/mhz"
+ />
+ <EditText
+ android:id="@+id/set_description"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:padding="10dp"
+ android:layout_weight="2"
+ android:hint="@string/description"
+ />
+ </LinearLayout>
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ >
+ <Button android:id="@+id/set"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/set"
+ android:layout_weight="1"
+ />
+
+ <Button android:id="@+id/remove"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/remove"
+ android:layout_weight="1"
+ />
+
+ <Button android:id="@+id/done"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/done"
+ android:layout_weight="1"
+ />
+ </LinearLayout>
+
+ <ListView android:id="@+id/frequencies"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:fadeScrollbars="false"
+ android:scrollbars="vertical"
+ android:choiceMode="singleChoice"
+ />
+
+
+</LinearLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright © 2016 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.
+
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ >
+ <TableLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:stretchColumns="2,3"
+ android:layout_weight="0"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TableRow
+ android:layout_gravity="center"
+ android:layout_weight="1"
+ android:padding="2dip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <TextView
+ android:id="@+id/select_rate_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/telemetry_rate"
+ />
+ <Spinner android:id="@+id/select_rate"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:prompt="@string/telemetry_rate"
+ android:spinnerMode="dropdown"
+ />
+ </TableRow>
+ <TableRow
+ android:layout_gravity="center"
+ android:layout_weight="1"
+ android:padding="2dip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <TextView
+ android:id="@+id/set_units_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/set_units"
+ />
+ <Spinner android:id="@+id/set_units"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:prompt="@string/set_units"
+ android:spinnerMode="dropdown"
+ />
+ </TableRow>
+ <TableRow
+ android:layout_gravity="center"
+ android:layout_weight="1"
+ android:padding="2dip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <TextView
+ android:id="@+id/map_type_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/map_type"
+ />
+ <Spinner android:id="@+id/map_type"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:prompt="@string/map_type"
+ android:spinnerMode="dropdown"
+ />
+ </TableRow>
+ <TableRow
+ android:layout_gravity="center"
+ android:layout_weight="1"
+ android:padding="2dip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <TextView
+ android:id="@+id/map_source_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/map_source"
+ />
+ <Spinner android:id="@+id/map_source"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:prompt="@string/map_source"
+ android:spinnerMode="dropdown"
+ />
+ </TableRow>
+ </TableLayout>
+ <Button android:id="@+id/preload_maps"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/preload_maps"
+ />
+ <Button android:id="@+id/manage_frequencies"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/manage_frequencies"
+ />
+ <Button android:id="@+id/done"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/done"
+ />
+</LinearLayout>
<item android:id="@+id/select_freq"
android:icon="@android:drawable/ic_menu_preferences"
android:title="@string/select_freq" />
- <item android:id="@+id/select_rate"
- android:icon="@android:drawable/ic_menu_preferences"
- android:title="@string/select_rate" />
- <item android:id="@+id/change_units"
- android:icon="@android:drawable/ic_menu_view"
- android:title="@string/change_units" />
- <item android:id="@+id/preload_maps"
- android:icon="@android:drawable/ic_menu_mapmode"
- android:title="@string/preload_maps" />
- <item android:id="@+id/map_type"
- android:icon="@android:drawable/ic_menu_mapmode"
- android:title="@string/map_type" />
- <item android:id="@+id/map_source"
- android:icon="@android:drawable/ic_menu_mapmode"
- android:title="@string/map_source" />
+
<item android:id="@+id/select_tracker"
android:icon="@android:drawable/ic_menu_view"
android:title="@string/select_tracker"/>
<item android:id="@+id/delete_track"
android:icon="@android:drawable/ic_notification_clear_all"
android:title="@string/delete_track"/>
+
+ <item android:id="@+id/setup"
+ android:icon="@android:drawable/ic_menu_preferences"
+ android:title="@string/setup" />
+ <item android:id="@+id/idle_mode"
+ android:icon="@android:drawable/ic_menu_preferences"
+ android:title="@string/idle_mode" />
+
<item android:id="@+id/quit"
android:icon="@android:drawable/ic_menu_close_clear_cancel"
android:title="@string/quit" />
<string name="connect_device">Connect a device</string>
<string name="disconnect_device">Disconnect device</string>
<string name="quit">Quit</string>
+ <string name="setup">Setup</string>
<string name="select_freq">Select radio frequency</string>
<string name="select_rate">Select data rate</string>
<string name="change_units">Change units</string>
<string name="preload_radius">Radius</string>
<string name="preload_load">Load Map</string>
+
+ <!-- Idle mode -->
+ <string name="idle_mode">Idle Mode</string>
+ <string name="set_callsign_label">Callsign</string>
+ <string name="connect_idle">Monitor</string>
+ <string name="disconnect_idle">Disconnect</string>
+ <string name="reboot_idle">Reboot</string>
+ <string name="igniters_idle">Fire Igniters</string>
+
+ <!-- igniters -->
+ <string name="igniters">Igniters</string>
+ <string name="igniter_arm">Arm</string>
+ <string name="igniter_armed">Armed</string>
+ <string name="igniter_fire">Fire</string>
+
+ <!-- setup -->
+ <string name="telemetry_rate">Telemetry Rate</string>
+ <string name="set_units">Units</string>
+ <string name="map_type">Map Type</string>
+ <string name="map_source">Map Source</string>
+ <string name="preload_maps">Preload Maps</string>
+ <string name="manage_frequencies">Manage Frequencies</string>
+ <string name="done">OK</string>
+
+ <!-- manage frequencies -->
+ <string name="set">Set</string>
+ <string name="mhz">MHz</string>
+ <string name="remove">Remove</string>
+ <string name="done">OK</string>
+ <string name="frequency">Frequency</string>
+ <string name="description">Description</string>
</resources>
import android.os.Handler;
//import android.os.Message;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosBluetooth extends AltosDroidLink {
import java.io.*;
import java.lang.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import android.app.Activity;
import android.graphics.*;
import android.widget.*;
import android.app.AlertDialog;
import android.location.Location;
+import android.location.LocationManager;
+import android.location.LocationListener;
import android.hardware.usb.*;
import android.graphics.*;
import android.graphics.drawable.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
-public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
+public class AltosDroid extends FragmentActivity implements AltosUnitsListener, LocationListener {
// Actions sent to the telemetry server at startup time
public static final int MSG_STATE = 1;
public static final int MSG_UPDATE_AGE = 2;
+ public static final int MSG_IDLE_MODE = 3;
+ public static final int MSG_IGNITER_STATUS = 4;
// Intent request codes
public static final int REQUEST_CONNECT_DEVICE = 1;
public static final int REQUEST_ENABLE_BT = 2;
public static final int REQUEST_PRELOAD_MAPS = 3;
- public static final int REQUEST_MAP_TYPE = 4;
+ public static final int REQUEST_IDLE_MODE = 5;
+ public static final int REQUEST_IGNITERS = 6;
+ public static final int REQUEST_SETUP = 7;
- public int map_type = AltosMap.maptype_hybrid;
+ public static final String EXTRA_IDLE_MODE = "idle_mode";
+ public static final String EXTRA_IDLE_RESULT = "idle_result";
+ public static final String EXTRA_TELEMETRY_SERVICE = "telemetry_service";
+
+ // Setup result bits
+ public static final int SETUP_BAUD = 1;
+ public static final int SETUP_UNITS = 2;
+ public static final int SETUP_MAP_SOURCE = 4;
+ public static final int SETUP_MAP_TYPE = 8;
public static FragmentManager fm;
// field to display the version at the bottom of the screen
private TextView mVersion;
- private double frequency;
- private int telemetry_rate;
+ private boolean idle_mode = false;
+
+ public Location location = null;
// Tabs
TabHost mTabHost;
case MSG_UPDATE_AGE:
ad.update_age();
break;
+ case MSG_IDLE_MODE:
+ ad.idle_mode = (Boolean) msg.obj;
+ ad.update_state(null);
+ break;
}
}
};
switch (telemetry_state.connect) {
case TelemetryState.CONNECT_CONNECTED:
if (telemetry_state.config != null) {
- String str = String.format("S/N %d %6.3f MHz", telemetry_state.config.serial,
- telemetry_state.frequency);
+ String str = String.format("S/N %d %6.3f MHz%s", telemetry_state.config.serial,
+ telemetry_state.frequency, idle_mode ? " (idle)" : "");
if (telemetry_state.telemetry_rate != AltosLib.ao_telemetry_rate_38400)
str = str.concat(String.format(" %d bps",
AltosLib.ao_telemetry_rate_values[telemetry_state.telemetry_rate]));
state = newest_state;
}
- update_ui(telemetry_state, state, telemetry_state.location);
+ update_ui(telemetry_state, state);
start_timer();
}
}
}
- void update_ui(TelemetryState telem_state, AltosState state, Location location) {
+ void update_ui(TelemetryState telem_state, AltosState state) {
int prev_state = AltosLib.ao_flight_invalid;
mCallsignView.setText(state.callsign);
}
if (saved_state == null || state.serial != saved_state.serial) {
- mSerialView.setText(String.format("%d", state.serial));
+ if (state.serial == AltosLib.MISSING)
+ mSerialView.setText("");
+ else
+ mSerialView.setText(String.format("%d", state.serial));
}
if (saved_state == null || state.flight != saved_state.flight) {
if (state.flight == AltosLib.MISSING)
}
}
if (saved_state == null || state.rssi != saved_state.rssi) {
- mRSSIView.setText(String.format("%d", state.rssi));
+ if (state.rssi == AltosLib.MISSING)
+ mRSSIView.setText("");
+ else
+ mRSSIView.setText(String.format("%d", state.rssi));
}
}
return tab_view;
}
- public void set_map_source(int source) {
- for (AltosDroidTab mTab : mTabs)
- mTab.set_map_source(source);
- }
-
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAgeOldColor = getResources().getColor(R.color.old_color);
}
- private boolean ensureBluetooth() {
+ private void ensureBluetooth() {
// Get local Bluetooth adapter
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
- // If the adapter is null, then Bluetooth is not supported
- if (mBluetoothAdapter == null) {
- Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();
- return false;
- }
-
- if (!mBluetoothAdapter.isEnabled()) {
+ /* if there is a BT adapter and it isn't turned on, then turn it on */
+ if (mBluetoothAdapter != null && !mBluetoothAdapter.isEnabled()) {
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, AltosDroid.REQUEST_ENABLE_BT);
}
-
- return true;
}
private boolean check_usb() {
return;
}
AltosDebug.debug("Starting by looking for bluetooth devices");
- if (ensureBluetooth())
- return;
- finish();
+ ensureBluetooth();
}
}
public void onResume() {
super.onResume();
AltosDebug.debug("+ ON RESUME +");
+
+ // Listen for GPS and Network position updates
+ LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
+ locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, this);
+
+ location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
+
+ if (location != null)
+ AltosDebug.debug("Resume, location is %f,%f\n",
+ location.getLatitude(),
+ location.getLongitude());
+
+ update_ui(telemetry_state, saved_state);
}
@Override
public void onPause() {
super.onPause();
AltosDebug.debug("- ON PAUSE -");
+ // Stop listening for location updates
+ ((LocationManager) getSystemService(Context.LOCATION_SERVICE)).removeUpdates(this);
}
@Override
if (resultCode == Activity.RESULT_OK) {
// Bluetooth is now enabled, so set up a chat session
//setupChat();
+ AltosDebug.debug("BT enabled");
+ bluetoothEnabled(data);
} else {
// User did not enable Bluetooth or an error occured
- AltosDebug.error("BT not enabled");
- stopService(new Intent(AltosDroid.this, TelemetryService.class));
- Toast.makeText(this, R.string.bt_not_enabled, Toast.LENGTH_SHORT).show();
- finish();
+ AltosDebug.debug("BT not enabled");
}
break;
- case REQUEST_MAP_TYPE:
+ case REQUEST_IDLE_MODE:
if (resultCode == Activity.RESULT_OK)
- set_map_type(data);
+ idle_mode(data);
+ break;
+ case REQUEST_IGNITERS:
break;
+ case REQUEST_SETUP:
+ if (resultCode == Activity.RESULT_OK)
+ note_setup_changes(data);
+ break;
+ }
+ }
+
+ private void note_setup_changes(Intent data) {
+ int changes = data.getIntExtra(SetupActivity.EXTRA_SETUP_CHANGES, 0);
+
+ if ((changes & SETUP_BAUD) != 0) {
+ try {
+ mService.send(Message.obtain(null, TelemetryService.MSG_SETBAUD,
+ AltosPreferences.telemetry_rate(1)));
+ } catch (RemoteException re) {
+ }
+ }
+ if ((changes & SETUP_UNITS) != 0) {
+ /* nothing to do here */
+ }
+ if ((changes & SETUP_MAP_SOURCE) != 0) {
+ /* nothing to do here */
}
+ if ((changes & SETUP_MAP_TYPE) != 0) {
+ /* nothing to do here */
+ }
+ set_switch_time();
}
private void connectUsb(UsbDevice device) {
}
}
+ private void bluetoothEnabled(Intent data) {
+ try {
+ mService.send(Message.obtain(null, TelemetryService.MSG_BLUETOOTH_ENABLED, null));
+ } catch (RemoteException e) {
+ AltosDebug.debug("send BT enabled message failed");
+ }
+ }
+
private void connectDevice(Intent data) {
// Attempt to connect to the device
try {
}
}
- private void set_map_type(Intent data) {
- int type = data.getIntExtra(MapTypeActivity.EXTRA_MAP_TYPE, -1);
+ private void idle_mode(Intent data) {
+ int type = data.getIntExtra(IdleModeActivity.EXTRA_IDLE_RESULT, -1);
+ Message msg;
- AltosDebug.debug("intent set_map_type %d\n", type);
- if (type != -1) {
- map_type = type;
- for (AltosDroidTab mTab : mTabs)
- mTab.set_map_type(map_type);
+ AltosDebug.debug("intent idle_mode %d", type);
+ switch (type) {
+ case IdleModeActivity.IDLE_MODE_CONNECT:
+ msg = Message.obtain(null, TelemetryService.MSG_MONITOR_IDLE_START);
+ try {
+ mService.send(msg);
+ } catch (RemoteException re) {
+ }
+ break;
+ case IdleModeActivity.IDLE_MODE_DISCONNECT:
+ msg = Message.obtain(null, TelemetryService.MSG_MONITOR_IDLE_STOP);
+ try {
+ mService.send(msg);
+ } catch (RemoteException re) {
+ }
+ break;
+ case IdleModeActivity.IDLE_MODE_REBOOT:
+ msg = Message.obtain(null, TelemetryService.MSG_REBOOT);
+ try {
+ mService.send(msg);
+ } catch (RemoteException re) {
+ }
+ break;
+ case IdleModeActivity.IDLE_MODE_IGNITERS:
+ Intent serverIntent = new Intent(this, IgniterActivity.class);
+ startActivityForResult(serverIntent, REQUEST_IGNITERS);
+ break;
}
}
}
}
- void setFrequency(String freq) {
- try {
- setFrequency (AltosParse.parse_double_net(freq.substring(11, 17)));
- } catch (ParseException e) {
- }
+ void setFrequency(AltosFrequency frequency) {
+ setFrequency (frequency.frequency);
}
void setBaud(int baud) {
Intent serverIntent = null;
switch (item.getItemId()) {
case R.id.connect_scan:
- if (ensureBluetooth()) {
- // Launch the DeviceListActivity to see devices and do scan
- serverIntent = new Intent(this, DeviceListActivity.class);
- startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
- }
+ ensureBluetooth();
+ // Launch the DeviceListActivity to see devices and do scan
+ serverIntent = new Intent(this, DeviceListActivity.class);
+ startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
return true;
case R.id.disconnect:
/* Disconnect the device
disconnectDevice();
finish();
return true;
+ case R.id.setup:
+ serverIntent = new Intent(this, SetupActivity.class);
+ startActivityForResult(serverIntent, REQUEST_SETUP);
+ return true;
case R.id.select_freq:
// Set the TBT radio frequency
- final String[] frequencies = {
- "Channel 0 (434.550MHz)",
- "Channel 1 (434.650MHz)",
- "Channel 2 (434.750MHz)",
- "Channel 3 (434.850MHz)",
- "Channel 4 (434.950MHz)",
- "Channel 5 (435.050MHz)",
- "Channel 6 (435.150MHz)",
- "Channel 7 (435.250MHz)",
- "Channel 8 (435.350MHz)",
- "Channel 9 (435.450MHz)"
- };
+ final AltosFrequency[] frequencies = AltosPreferences.common_frequencies();
+ String[] frequency_strings = new String[frequencies.length];
+ for (int i = 0; i < frequencies.length; i++)
+ frequency_strings[i] = frequencies[i].toString();
AlertDialog.Builder builder_freq = new AlertDialog.Builder(this);
builder_freq.setTitle("Pick a frequency");
- builder_freq.setItems(frequencies,
+ builder_freq.setItems(frequency_strings,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
setFrequency(frequencies[item]);
AlertDialog alert_freq = builder_freq.create();
alert_freq.show();
return true;
- case R.id.select_rate:
- // Set the TBT baud rate
-
- final String[] rates = {
- "38400",
- "9600",
- "2400",
- };
-
- AlertDialog.Builder builder_rate = new AlertDialog.Builder(this);
- builder_rate.setTitle("Pick a baud rate");
- builder_rate.setItems(rates,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int item) {
- setBaud(rates[item]);
- }
- });
- AlertDialog alert_rate = builder_rate.create();
- alert_rate.show();
- return true;
- case R.id.change_units:
- boolean imperial = AltosPreferences.imperial_units();
- AltosPreferences.set_imperial_units(!imperial);
- return true;
- case R.id.preload_maps:
- serverIntent = new Intent(this, PreloadMapActivity.class);
- startActivityForResult(serverIntent, REQUEST_PRELOAD_MAPS);
- return true;
- case R.id.map_type:
- serverIntent = new Intent(this, MapTypeActivity.class);
- startActivityForResult(serverIntent, REQUEST_MAP_TYPE);
- return true;
- case R.id.map_source:
- int source = AltosDroidPreferences.map_source();
- int new_source = source == AltosDroidPreferences.MAP_SOURCE_ONLINE ? AltosDroidPreferences.MAP_SOURCE_OFFLINE : AltosDroidPreferences.MAP_SOURCE_ONLINE;
- AltosDroidPreferences.set_map_source(new_source);
- set_map_source(new_source);
- return true;
case R.id.select_tracker:
if (serials != null) {
String[] trackers = new String[serials.length+1];
}
return true;
+ case R.id.idle_mode:
+ serverIntent = new Intent(this, IdleModeActivity.class);
+ serverIntent.putExtra(EXTRA_IDLE_MODE, idle_mode);
+ startActivityForResult(serverIntent, REQUEST_IDLE_MODE);
+ return true;
}
return false;
}
static String direction(AltosGreatCircle from_receiver,
- Location receiver) {
+ Location receiver) {
if (from_receiver == null)
return null;
else
return String.format("right %d°", iheading);
}
+
+ public void onLocationChanged(Location location) {
+ this.location = location;
+ AltosDebug.debug("Location changed to %f,%f",
+ location.getLatitude(),
+ location.getLongitude());
+ update_ui(telemetry_state, saved_state);
+ }
+
+ public void onStatusChanged(String provider, int status, Bundle extras) {
+ AltosDebug.debug("Location status now %d\n", status);
+ }
+
+ public void onProviderEnabled(String provider) {
+ AltosDebug.debug("Location provider enabled %s\n", provider);
+ }
+
+ public void onProviderDisabled(String provider) {
+ AltosDebug.debug("Location provider disabled %s\n", provider);
+ }
}
import android.os.Handler;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public abstract class AltosDroidLink extends AltosLink {
}
buffer_off = 0;
}
- if (AltosDebug.D)
- debug_input(in_buffer[buffer_off]);
+// if (AltosDebug.D)
+// debug_input(in_buffer[buffer_off]);
return in_buffer[buffer_off++];
}
public void print(String data) {
byte[] bytes = data.getBytes();
- AltosDebug.debug("print(): begin");
+// AltosDebug.debug(data.replace('\n', '\\'));
for (byte b : bytes)
putchar(b);
- AltosDebug.debug("print(): Wrote bytes: '" + data.replace('\n', '\\') + "'");
}
public AltosDroidLink(Handler handler) {
import java.util.*;
import java.io.*;
import android.location.Location;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public interface AltosDroidMapInterface {
public void onCreateView(AltosDroid altos_droid);
+ public void onDestroyView();
+
public void set_visible(boolean visible);
public void center(double lat, double lon, double accuracy);
--- /dev/null
+/*
+ * Copyright © 2016 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 org.altusmetrum.AltosDroid;
+
+public interface AltosDroidMapSourceListener {
+ public void map_source_changed(int map_source);
+}
*/
package org.altusmetrum.AltosDroid;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
import android.content.Context;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosDroidPreferences extends AltosPreferences {
}
}
+ static LinkedList<AltosDroidMapSourceListener> map_source_listeners;
+
public static void set_map_source(int map_source) {
synchronized(backend) {
AltosDroidPreferences.map_source = map_source;
backend.putInt(mapSourcePreference, map_source);
flush_preferences();
}
+ if (map_source_listeners != null) {
+ for (AltosDroidMapSourceListener l : map_source_listeners) {
+ l.map_source_changed(map_source);
+ }
+ }
}
public static int map_source() {
return map_source;
}
}
+
+ public static void register_map_source_listener(AltosDroidMapSourceListener l) {
+ synchronized(backend) {
+ if (map_source_listeners == null)
+ map_source_listeners = new LinkedList<AltosDroidMapSourceListener>();
+ map_source_listeners.add(l);
+ }
+ }
+
+ public static void unregister_map_source_listener(AltosDroidMapSourceListener l) {
+ synchronized(backend) {
+ map_source_listeners.remove(l);
+ }
+ }
}
import android.os.Environment;
import android.util.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
-public class AltosDroidPreferencesBackend implements AltosPreferencesBackend {
+public class AltosDroidPreferencesBackend extends AltosPreferencesBackend {
public final static String NAME = "org.altusmetrum.AltosDroid";
private Context context = null;
private SharedPreferences prefs = null;
}
public AltosPreferencesBackend node(String key) {
+ if (!nodeExists(key))
+ putBoolean(key, true);
return new AltosDroidPreferencesBackend(context, key);
}
public File homeDirectory() {
return Environment.getExternalStorageDirectory();
}
+
+ public void debug(String format, Object ... arguments) {
+ AltosDebug.debug(format, arguments);
+ }
}
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import android.location.Location;
import android.app.Activity;
import android.graphics.Color;
public abstract String tab_name();
- public void set_map_type(int map_type) {
- }
-
- public void set_map_source(int map_source) {
- }
-
public void units_changed(boolean imperial_units) {
if (!isHidden())
show(last_telem_state, last_state, last_from_receiver, last_receiver);
import java.util.*;
import java.io.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import android.app.Activity;
import android.graphics.*;
}
}
-public class AltosMapOffline extends View implements ScaleGestureDetector.OnScaleGestureListener, AltosMapInterface, AltosDroidMapInterface {
+public class AltosMapOffline extends View implements ScaleGestureDetector.OnScaleGestureListener, AltosMapInterface, AltosDroidMapInterface, AltosMapTypeListener {
ScaleGestureDetector scale_detector;
boolean scaling;
AltosMap map;
if (canvas.quickReject(pt.x, pt.y, pt.x + px_size, pt.y + px_size, Canvas.EdgeType.AA))
return;
- AltosImage altos_image = cache.get(this, store, px_size, px_size);
+ AltosImage altos_image = this.get_image();
MapImage map_image = (MapImage) altos_image;
if (t.has_location()) {
String message = null;
switch (status) {
- case AltosMapTile.loading:
- message = "Loading...";
+ case AltosMapTile.fetching:
+ message = "Fetching...";
break;
case AltosMapTile.bad_request:
message = "Internal error";
}
}
- public MapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
- super(listener, upper_left, center, zoom, maptype, px_size, 2);
+ public MapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
+ super(cache, upper_left, center, zoom, maptype, px_size, 2);
}
}
- public AltosMapTile new_tile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
- return new MapTile(listener, upper_left, center, zoom, maptype, px_size);
+ public AltosMapTile new_tile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
+ return new MapTile(cache, upper_left, center, zoom, maptype, px_size);
}
public AltosMapPath new_path() {
}
public void show(TelemetryState telem_state, AltosState state, AltosGreatCircle from_receiver, Location receiver) {
+ boolean changed = false;
+
if (state != null) {
map.show(state, null);
if (state.pad_lat != AltosLib.MISSING && pad == null)
}
}
if (receiver != null) {
- here = new AltosLatLon(receiver.getLatitude(), receiver.getLongitude());
+ AltosLatLon new_here = new AltosLatLon(receiver.getLatitude(), receiver.getLongitude());
+ if (!new_here.equals(here)) {
+ here = new_here;
+ AltosDebug.debug("Location changed, redraw");
+ repaint();
+ }
}
}
public void onCreateView(AltosDroid altos_droid) {
this.altos_droid = altos_droid;
map = new AltosMap(this);
- map.set_maptype(altos_droid.map_type);
+ AltosPreferences.register_map_type_listener(this);
+ map.set_maptype(AltosPreferences.map_type());
pad_bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pad);
/* arrow at the bottom of the launchpad image */
here_off_y = here_bitmap.getHeight() / 2;
}
- public void set_map_type(int map_type) {
+ public void onDestroyView() {
+ AltosPreferences.unregister_map_type_listener(this);
+ }
+
+ public void map_type_changed(int map_type) {
if (map != null)
map.set_maptype(map_type);
}
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import com.google.android.gms.maps.*;
import com.google.android.gms.maps.model.*;
}
}
-public class AltosMapOnline implements AltosDroidMapInterface, GoogleMap.OnMarkerClickListener, GoogleMap.OnMapClickListener {
+public class AltosMapOnline implements AltosDroidMapInterface, GoogleMap.OnMarkerClickListener, GoogleMap.OnMapClickListener, AltosMapTypeListener {
public SupportMapFragment mMapFragment;
private GoogleMap mMap;
private boolean mapLoaded = false;
public void onCreateView(AltosDroid altos_droid) {
this.altos_droid = altos_droid;
- final int map_type = altos_droid.map_type;
+ final int map_type = AltosPreferences.map_type();
+ AltosPreferences.register_map_type_listener(this);
mMapFragment = new SupportMapFragment() {
@Override
public void onActivityCreated(Bundle savedInstanceState) {
};
}
-// public void onActivityCreated() {
-// getChildFragmentManager().beginTransaction().add(R.id.map, mMapFragment).commit();
-// }
+ public void onDestroyView() {
+ AltosPreferences.unregister_map_type_listener(this);
+ }
private double pixel_distance(LatLng a, LatLng b) {
Projection projection = mMap.getProjection();
public void setupMap(int map_type) {
mMap = mMapFragment.getMap();
if (mMap != null) {
- set_map_type(map_type);
+ map_type_changed(map_type);
mMap.setMyLocationEnabled(true);
mMap.getUiSettings().setTiltGesturesEnabled(false);
mMap.getUiSettings().setZoomControlsEnabled(false);
mPadMarker.setVisible(true);
}
}
- if (state.gps != null) {
+ if (state.gps != null && state.gps.lat != AltosLib.MISSING) {
target_position = new AltosLatLon(state.gps.lat, state.gps.lon);
if (state.gps.locked && state.gps.nsat >= 4)
}
- public void set_map_type(int map_type) {
+ public void map_type_changed(int map_type) {
if (mMap != null) {
if (map_type == AltosMap.maptype_hybrid)
mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
import android.app.*;
import android.os.Handler;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosUsb extends AltosDroidLink {
import android.speech.tts.TextToSpeech.OnInitListener;
import android.location.Location;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosVoice {
--- /dev/null
+/*
+ * Copyright © 2016 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 org.altusmetrum.AltosDroid;
+
+import java.util.*;
+import org.altusmetrum.AltosDroid.R;
+
+import android.app.Activity;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.view.View;
+import android.view.Window;
+import android.view.View.OnClickListener;
+import android.widget.*;
+import android.widget.AdapterView.*;
+
+import org.altusmetrum.altoslib_10.*;
+
+public class IdleModeActivity extends Activity {
+ private EditText callsign;
+ private Button connect;
+ private Button disconnect;
+ private Button reboot;
+ private Button igniters;
+
+ public static final String EXTRA_IDLE_MODE = "idle_mode";
+ public static final String EXTRA_IDLE_RESULT = "idle_result";
+
+ public static final int IDLE_MODE_CONNECT = 1;
+ public static final int IDLE_MODE_REBOOT = 2;
+ public static final int IDLE_MODE_IGNITERS = 3;
+ public static final int IDLE_MODE_DISCONNECT = 4;
+
+ private void done(int type) {
+ AltosPreferences.set_callsign(callsign());
+ Intent intent = new Intent();
+ intent.putExtra(EXTRA_IDLE_RESULT, type);
+ setResult(Activity.RESULT_OK, intent);
+ finish();
+ }
+
+ private String callsign() {
+ return callsign.getEditableText().toString();
+ }
+
+ public void connect_idle() {
+ done(IDLE_MODE_CONNECT);
+ }
+
+ public void disconnect_idle() {
+ AltosDebug.debug("Disconnect idle button pressed");
+ done(IDLE_MODE_DISCONNECT);
+ }
+
+ public void reboot_idle() {
+ done(IDLE_MODE_REBOOT);
+ }
+
+ public void igniters_idle() {
+ done(IDLE_MODE_IGNITERS);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Setup the window
+ requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+ setContentView(R.layout.idle_mode);
+
+ callsign = (EditText) findViewById(R.id.set_callsign);
+ callsign.setText(new StringBuffer(AltosPreferences.callsign()));
+
+ connect = (Button) findViewById(R.id.connect_idle);
+ connect.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ connect_idle();
+ }
+ });
+ disconnect = (Button) findViewById(R.id.disconnect_idle);
+ disconnect.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ disconnect_idle();
+ }
+ });
+
+ boolean idle_mode = getIntent().getBooleanExtra(AltosDroid.EXTRA_IDLE_MODE, false);
+
+ if (idle_mode)
+ connect.setVisibility(View.GONE);
+ else
+ disconnect.setVisibility(View.GONE);
+
+ reboot = (Button) findViewById(R.id.reboot_idle);
+ reboot.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ reboot_idle();
+ }
+ });
+ igniters = (Button) findViewById(R.id.igniters_idle);
+ igniters.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ igniters_idle();
+ }
+ });
+
+ // Set result CANCELED incase the user backs out
+ setResult(Activity.RESULT_CANCELED);
+ }
+}
--- /dev/null
+/*
+ * Copyright © 2016 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 org.altusmetrum.AltosDroid;
+
+import java.lang.ref.WeakReference;
+import java.util.*;
+import org.altusmetrum.AltosDroid.R;
+
+import android.app.Activity;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.content.*;
+import android.graphics.*;
+import android.os.*;
+import android.view.*;
+import android.view.View.*;
+import android.widget.*;
+import android.widget.AdapterView.*;
+
+import org.altusmetrum.altoslib_10.*;
+
+class IgniterItem {
+ public String name;
+ public String pretty;
+ public String status;
+ public LinearLayout igniter_view = null;
+ public TextView pretty_view = null;
+ public TextView status_view = null;
+
+ private void update() {
+ if (pretty_view != null)
+ pretty_view.setText(pretty);
+ if (status_view != null)
+ status_view.setText(status);
+ }
+
+ public void set(String name, String pretty, String status) {
+ if (!name.equals(this.name) ||
+ !pretty.equals(this.pretty) ||
+ !status.equals(this.status))
+ {
+ this.name = name;
+ this.pretty = pretty;
+ this.status = status;
+ update();
+ }
+ }
+
+ public void realize(LinearLayout igniter_view,
+ TextView pretty_view,
+ TextView status_view) {
+ if (igniter_view != this.igniter_view ||
+ pretty_view != this.pretty_view ||
+ status_view != this.status_view)
+ {
+ this.igniter_view = igniter_view;
+ this.pretty_view = pretty_view;
+ this.status_view = status_view;
+ update();
+ }
+ }
+
+ public IgniterItem() {
+ }
+}
+
+class IgniterAdapter extends ArrayAdapter<IgniterItem> {
+ int resource;
+ int selected_item = -1;
+
+ public IgniterAdapter(Context context, int in_resource) {
+ super(context, in_resource);
+ resource = in_resource;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ IgniterItem item = getItem(position);
+ if (item.igniter_view == null) {
+ LinearLayout igniter_view = new LinearLayout(getContext());
+ String inflater = Context.LAYOUT_INFLATER_SERVICE;
+ LayoutInflater li = (LayoutInflater) getContext().getSystemService(inflater);
+ li.inflate(resource, igniter_view, true);
+
+ item.realize(igniter_view,
+ (TextView) igniter_view.findViewById(R.id.igniter_name),
+ (TextView) igniter_view.findViewById(R.id.igniter_status));
+ }
+ if (position == selected_item)
+ item.igniter_view.setBackgroundColor(Color.RED);
+ else
+ item.igniter_view.setBackgroundColor(Color.BLACK);
+ return item.igniter_view;
+ }
+}
+
+public class IgniterActivity extends Activity {
+ private ListView igniters_view;
+ private ToggleButton arm;
+ private Button fire;
+
+ private HashMap<String,IgniterItem> igniters = new HashMap<String,IgniterItem>();;
+
+ private IgniterAdapter igniters_adapter;
+
+ private boolean is_bound;
+ private Messenger service = null;
+ private final Messenger messenger = new Messenger(new IncomingHandler(this));
+
+ private Timer query_timer;
+ private boolean query_timer_running;
+
+ private Timer arm_timer;
+ private int arm_remaining;
+
+ public static final int IGNITER_QUERY = 1;
+ public static final int IGNITER_FIRE = 2;
+
+ // The Handler that gets information back from the Telemetry Service
+ static class IncomingHandler extends Handler {
+ private final WeakReference<IgniterActivity> igniter_activity;
+ IncomingHandler(IgniterActivity ia) { igniter_activity = new WeakReference<IgniterActivity>(ia); }
+
+ @Override
+ public void handleMessage(Message msg) {
+ IgniterActivity ia = igniter_activity.get();
+
+ switch (msg.what) {
+ case AltosDroid.MSG_IGNITER_STATUS:
+ ia.igniter_status((HashMap <String,Integer>) msg.obj);
+ break;
+ }
+ }
+ };
+
+
+ private ServiceConnection connection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className, IBinder binder) {
+ service = new Messenger(binder);
+ query_timer_tick();
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ // This is called when the connection with the service has been unexpectedly disconnected - process crashed.
+ service = null;
+ }
+ };
+
+ void doBindService() {
+ bindService(new Intent(this, TelemetryService.class), connection, Context.BIND_AUTO_CREATE);
+ is_bound = true;
+ }
+
+ void doUnbindService() {
+ if (is_bound) {
+ // If we have received the service, and hence registered with it, then now is the time to unregister.
+ unbindService(connection);
+ is_bound = false;
+ }
+ }
+
+ private void done() {
+ Intent intent = new Intent();
+ setResult(Activity.RESULT_OK, intent);
+ finish();
+ }
+
+ class FireThread extends Thread {
+ private final String igniter;
+
+ @Override
+ public void run() {
+ Message msg = Message.obtain(null, TelemetryService.MSG_IGNITER_FIRE, igniter);
+ try {
+ service.send(msg);
+ } catch (RemoteException re) {
+ }
+ }
+
+ public FireThread(String igniter) {
+ this.igniter = igniter;
+ }
+ }
+
+ private void fire_igniter() {
+ if (igniters_adapter.selected_item >= 0) {
+ IgniterItem item = igniters_adapter.getItem(igniters_adapter.selected_item);
+ FireThread ft = new FireThread(item.name);
+ ft.run();
+ arm.setChecked(false);
+ }
+ }
+
+ private void arm_igniter(boolean is_checked) {
+ if (is_checked) {
+ arm_timer_stop();
+ arm_timer = new Timer();
+ arm_remaining = 10;
+ arm_set_text();
+ fire.setEnabled(true);
+ arm_timer.scheduleAtFixedRate(new TimerTask() {
+ public void run() {
+ arm_timer_tick();
+ }},
+ 1000L, 1000L);
+ } else {
+ arm_timer_stop();
+ fire.setEnabled(false);
+ }
+ }
+
+ private synchronized void query_timer_tick() {
+ if (query_timer_running)
+ return;
+ if (service == null)
+ return;
+ query_timer_running = true;
+ Thread thread = new Thread(new Runnable() {
+ public void run() {
+ try {
+ Message msg = Message.obtain(null, TelemetryService.MSG_IGNITER_QUERY);
+ msg.replyTo = messenger;
+ if (service == null) {
+ synchronized(IgniterActivity.this) {
+ query_timer_running = false;
+ }
+ } else
+ service.send(msg);
+ } catch (RemoteException re) {
+ AltosDebug.debug("igniter query thread failed");
+ synchronized(IgniterActivity.this) {
+ query_timer_running = false;
+ }
+ }
+ }
+ });
+ thread.start();
+ }
+
+ private boolean set_igniter(HashMap <String,Integer> status, String name, String pretty) {
+ if (!status.containsKey(name))
+ return false;
+
+ IgniterItem item;
+ if (!igniters.containsKey(name)) {
+ item = new IgniterItem();
+ igniters.put(name, item);
+ igniters_adapter.add(item);
+ } else
+ item = igniters.get(name);
+
+ item.set(name, pretty, AltosIgnite.status_string(status.get(name)));
+ return true;
+ }
+
+ private synchronized void igniter_status(HashMap <String,Integer> status) {
+ query_timer_running = false;
+ if (status == null) {
+ AltosDebug.debug("no igniter status");
+ return;
+ }
+ set_igniter(status, "drogue", "Apogee");
+ set_igniter(status, "main", "Main");
+ for (int extra = 0;; extra++) {
+ String name = String.format("%d", extra);
+ String pretty = String.format("%c", 'A' + extra);
+ if (!set_igniter(status, name, pretty))
+ break;
+ }
+ }
+
+ private synchronized void arm_timer_stop() {
+ if (arm_timer != null) {
+ arm_timer.cancel();
+ arm_timer = null;
+ }
+ arm_remaining = 0;
+ }
+
+ private void arm_set_text() {
+ String text = String.format("Armed %d", arm_remaining);
+
+ if (arm.isChecked())
+ arm.setText(text);
+ arm.setTextOn(text);
+ }
+
+ private void arm_timer_tick() {
+ --arm_remaining;
+ if (arm_remaining <= 0) {
+ arm_timer_stop();
+ runOnUiThread(new Runnable() {
+ public void run() {
+ arm.setChecked(false);
+ fire.setEnabled(false);
+ }
+ });
+ } else {
+ runOnUiThread(new Runnable() {
+ public void run() {
+ arm_set_text();
+ }
+ });
+ }
+ }
+
+ private void select_item(int position) {
+ if (position != igniters_adapter.selected_item) {
+ if (igniters_adapter.selected_item >= 0)
+ igniters_view.setItemChecked(igniters_adapter.selected_item, false);
+ if (position >= 0) {
+ igniters_view.setItemChecked(position, true);
+ arm.setEnabled(true);
+ } else
+ arm.setEnabled(false);
+ igniters_adapter.selected_item = position;
+ }
+ }
+
+ private class IgniterItemClickListener implements ListView.OnItemClickListener {
+ @Override
+ public void onItemClick(AdapterView<?> av, View v, int position, long id) {
+ AltosDebug.debug("select %d\n", position);
+ select_item(position);
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Setup the window
+ requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+ setContentView(R.layout.igniters);
+
+ igniters_view = (ListView) findViewById(R.id.igniters);
+ igniters_view.setClickable(true);
+
+ igniters_adapter = new IgniterAdapter(this, R.layout.igniter_status);
+
+ igniters_view.setAdapter(igniters_adapter);
+ igniters_view.setOnItemClickListener(new IgniterItemClickListener());
+
+ fire = (Button) findViewById(R.id.igniter_fire);
+ fire.setEnabled(false);
+ fire.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ fire_igniter();
+ }
+ });
+
+ arm = (ToggleButton) findViewById(R.id.igniter_arm);
+ arm.setEnabled(false);
+ arm.setOnCheckedChangeListener(new ToggleButton.OnCheckedChangeListener() {
+ public void onCheckedChanged(CompoundButton v, boolean is_checked) {
+ arm_igniter(is_checked);
+ }
+ });
+
+ // Set result CANCELED incase the user backs out
+ setResult(Activity.RESULT_CANCELED);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ doBindService();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ query_timer = new Timer(true);
+ query_timer.scheduleAtFixedRate(new TimerTask() {
+ public void run() {
+ query_timer_tick();
+ }},
+ 0L, 5000L);
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ if (query_timer != null) {
+ query_timer.cancel();
+ query_timer = null;
+ }
+ arm_timer_stop();
+ arm.setChecked(false);
+ fire.setEnabled(false);
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ doUnbindService();
+ }
+}
--- /dev/null
+/*
+ * Copyright © 2016 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 org.altusmetrum.AltosDroid;
+
+import java.lang.ref.WeakReference;
+import java.util.*;
+import java.text.*;
+import org.altusmetrum.AltosDroid.R;
+
+import android.app.Activity;
+import android.content.*;
+import android.graphics.*;
+import android.os.*;
+import android.view.*;
+import android.view.View.*;
+import android.view.inputmethod.*;
+import android.widget.*;
+import android.widget.AdapterView.*;
+
+import org.altusmetrum.altoslib_10.*;
+
+class FrequencyItem {
+ public AltosFrequency frequency;
+ public LinearLayout frequency_view = null;
+ public TextView pretty_view = null;
+
+ private void update() {
+ if (pretty_view != null && frequency != null)
+ pretty_view.setText(frequency.toString());
+ }
+
+ public void realize(LinearLayout frequency_view,
+ TextView pretty_view) {
+ if (frequency_view != this.frequency_view ||
+ pretty_view != this.pretty_view)
+ {
+ this.frequency_view = frequency_view;
+ this.pretty_view = pretty_view;
+ update();
+ }
+ }
+
+ public void set_frequency(AltosFrequency frequency) {
+ this.frequency = frequency;
+ update();
+ }
+
+ public FrequencyItem(AltosFrequency frequency) {
+ this.frequency = frequency;
+ }
+}
+
+class FrequencyAdapter extends ArrayAdapter<FrequencyItem> {
+ int resource;
+ int selected_item = -1;
+
+ public FrequencyAdapter(Context context, int in_resource) {
+ super(context, in_resource);
+ resource = in_resource;
+ }
+
+ public int count() {
+ int count;
+
+ for (count = 0;; count++) {
+ try {
+ getItem(count);
+ } catch (IndexOutOfBoundsException ie) {
+ return count;
+ }
+ }
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ FrequencyItem item = getItem(position);
+ if (item.frequency_view == null) {
+ LinearLayout frequency_view = new LinearLayout(getContext());
+ String inflater = Context.LAYOUT_INFLATER_SERVICE;
+ LayoutInflater li = (LayoutInflater) getContext().getSystemService(inflater);
+ li.inflate(resource, frequency_view, true);
+
+ item.realize(frequency_view,
+ (TextView) frequency_view.findViewById(R.id.frequency));
+ }
+ if (position == selected_item)
+ item.frequency_view.setBackgroundColor(Color.RED);
+ else
+ item.frequency_view.setBackgroundColor(Color.BLACK);
+ return item.frequency_view;
+ }
+}
+
+public class ManageFrequenciesActivity extends Activity {
+ private ListView frequencies_view;
+
+ private Button set;
+ private Button remove;
+ private Button done;
+
+ private EditText set_frequency;
+ private EditText set_description;
+
+ private HashMap<String,FrequencyItem> frequencies = new HashMap<String,FrequencyItem>();;
+
+ private FrequencyAdapter frequencies_adapter;
+
+ private boolean is_bound;
+ private boolean changed = false;
+
+ private void done() {
+
+ if (changed) {
+ AltosFrequency[] frequencies = new AltosFrequency[frequencies_adapter.count()];
+ for (int i = 0; i < frequencies.length; i++)
+ frequencies[i] = frequencies_adapter.getItem(i).frequency;
+ AltosPreferences.set_common_frequencies(frequencies);
+ }
+
+ Intent intent = new Intent();
+ setResult(Activity.RESULT_OK, intent);
+ finish();
+ }
+
+ private void load_item() {
+ if (frequencies_adapter.selected_item >= 0) {
+ FrequencyItem item = frequencies_adapter.getItem(frequencies_adapter.selected_item);
+
+ set_frequency.setText(item.frequency.frequency_string());
+ set_description.setText(item.frequency.description);
+ } else {
+ set_frequency.setText("");
+ set_description.setText("");
+ }
+ }
+
+ private void select_item(int position) {
+ if (position != frequencies_adapter.selected_item) {
+ if (frequencies_adapter.selected_item >= 0)
+ frequencies_view.setItemChecked(frequencies_adapter.selected_item, false);
+ if (position >= 0)
+ frequencies_view.setItemChecked(position, true);
+ frequencies_adapter.selected_item = position;
+ } else {
+ if (frequencies_adapter.selected_item >= 0)
+ frequencies_view.setItemChecked(frequencies_adapter.selected_item, false);
+ frequencies_adapter.selected_item = -1;
+ }
+ load_item();
+ }
+
+ private int insert_item(AltosFrequency frequency) {
+ FrequencyItem new_item = new FrequencyItem(frequency);
+ int pos;
+ for (pos = 0; pos < frequencies_adapter.getCount(); pos++) {
+ FrequencyItem item = frequencies_adapter.getItem(pos);
+ if (item.frequency.frequency == new_item.frequency.frequency) {
+ item.set_frequency(frequency);
+ return pos;
+ }
+ if (item.frequency.frequency > new_item.frequency.frequency)
+ break;
+ }
+ frequencies_adapter.insert(new_item, pos);
+ return pos;
+ }
+
+ private class FrequencyItemClickListener implements ListView.OnItemClickListener {
+ @Override
+ public void onItemClick(AdapterView<?> av, View v, int position, long id) {
+ select_item(position);
+ }
+ }
+
+ private void hide_keyboard() {
+ InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
+ View view = getCurrentFocus();
+ if (view != null)
+ imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
+ }
+
+ private void set() {
+ String frequency_text = set_frequency.getEditableText().toString();
+ String description_text = set_description.getEditableText().toString();
+
+ try {
+ double f = AltosParse.parse_double_locale(frequency_text);
+
+ int pos = insert_item(new AltosFrequency(f, description_text));
+ frequencies_adapter.selected_item = -1;
+ select_item(pos);
+ changed = true;
+ } catch (ParseException pe) {
+ }
+ hide_keyboard();
+ }
+
+ private void remove() {
+ if (frequencies_adapter.selected_item >= 0) {
+ frequencies_adapter.remove(frequencies_adapter.getItem(frequencies_adapter.selected_item));
+ select_item(-1);
+ frequencies_view.setAdapter(frequencies_adapter);
+ changed = true;
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Setup the window
+ requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+ setContentView(R.layout.manage_frequencies);
+
+ frequencies_view = (ListView) findViewById(R.id.frequencies);
+ frequencies_view.setClickable(true);
+
+ frequencies_adapter = new FrequencyAdapter(this, R.layout.frequency);
+
+ frequencies_view.setAdapter(frequencies_adapter);
+ frequencies_view.setOnItemClickListener(new FrequencyItemClickListener());
+
+ AltosFrequency[] frequencies = AltosPreferences.common_frequencies();
+ for (AltosFrequency frequency : frequencies)
+ insert_item(frequency);
+
+ set_frequency = (EditText) findViewById(R.id.set_frequency);
+ set_description = (EditText) findViewById(R.id.set_description);
+
+ set = (Button) findViewById(R.id.set);
+ set.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ set();
+ }
+ });
+
+ remove = (Button) findViewById(R.id.remove);
+ remove.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ remove();
+ }
+ });
+
+ done = (Button) findViewById(R.id.done);
+ done.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ done();
+ }
+ });
+
+ // Set result CANCELED incase the user backs out
+ setResult(Activity.RESULT_CANCELED);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ }
+}
import android.widget.*;
import android.widget.AdapterView.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class MapTypeActivity extends Activity {
private Button hybrid;
import android.location.LocationListener;
import android.location.Criteria;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
/**
* This Activity appears as a dialog. It lists any paired devices and
}
AltosMap map;
- AltosMapLoader loader;
class PreloadMapImage implements AltosImage {
public void flush() {
public void paint(AltosMapTransform t) {
}
- public PreloadMapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
- super(listener, upper_left, center, zoom, maptype, px_size, 2);
+ public PreloadMapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
+ super(cache, upper_left, center, zoom, maptype, px_size, 2);
}
}
- public AltosMapTile new_tile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
- return new PreloadMapTile(listener, upper_left, center, zoom, maptype, px_size);
+ public AltosMapTile new_tile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
+ return new PreloadMapTile(cache, upper_left, center, zoom, maptype, px_size);
}
public int width() {
AltosDebug.debug("PreloadMap load %f %f %d %d %f %d\n",
lat, lon, min, max, r, t);
- loader.load(lat, lon, min, max, r, t);
+ new AltosMapLoader(map, this, lat, lon, min, max, r, t);
} catch (ParseException e) {
AltosDebug.debug("PreloadMap load raised exception %s", e.toString());
}
map = new AltosMap(this);
- loader = new AltosMapLoader(map, this);
-
// Listen for GPS and Network position updates
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
--- /dev/null
+/*
+ * Copyright © 2016 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 org.altusmetrum.AltosDroid;
+
+import java.lang.ref.WeakReference;
+import java.util.*;
+import org.altusmetrum.AltosDroid.R;
+
+import android.app.Activity;
+import android.bluetooth.*;
+import android.content.*;
+import android.os.*;
+import android.view.*;
+import android.view.View.*;
+import android.widget.*;
+import android.widget.AdapterView.*;
+
+import org.altusmetrum.altoslib_10.*;
+
+public class SetupActivity extends Activity {
+ private Spinner select_rate;
+ private Spinner set_units;
+ private Spinner map_type;
+ private Spinner map_source;
+ private Button manage_frequencies;
+ private Button preload_maps;
+ private Button done;
+
+ private boolean is_bound;
+ private Messenger service = null;
+
+ public final static String EXTRA_SETUP_CHANGES = "setup_changes";
+
+ private ServiceConnection connection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className, IBinder binder) {
+ service = new Messenger(binder);
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ // This is called when the connection with the service has been unexpectedly disconnected - process crashed.
+ service = null;
+ }
+ };
+
+ void doBindService() {
+ bindService(new Intent(this, TelemetryService.class), connection, Context.BIND_AUTO_CREATE);
+ is_bound = true;
+ }
+
+ void doUnbindService() {
+ if (is_bound) {
+ // If we have received the service, and hence registered with it, then now is the time to unregister.
+ unbindService(connection);
+ is_bound = false;
+ }
+ }
+
+ static final String[] rates = {
+ "38400",
+ "9600",
+ "2400",
+ };
+
+ static final String[] map_types = {
+ "Hybrid",
+ "Satellite",
+ "Roadmap",
+ "Terrain"
+ };
+
+ static final int[] map_type_values = {
+ AltosMap.maptype_hybrid,
+ AltosMap.maptype_satellite,
+ AltosMap.maptype_roadmap,
+ AltosMap.maptype_terrain,
+ };
+
+ static final String[] map_sources = {
+ "Online",
+ "Offline"
+ };
+
+ private int set_telemetry_rate;
+ private int set_map_source;
+ private int set_map_type;
+ private boolean set_imperial_units;
+
+ private int changes = 0;
+
+ private void add_change(int change) {
+ changes |= change;
+ }
+
+ private void done() {
+ Intent intent = new Intent();
+ if ((changes & AltosDroid.SETUP_BAUD) != 0)
+ AltosPreferences.set_telemetry_rate(1, set_telemetry_rate);
+ if ((changes & AltosDroid.SETUP_UNITS) != 0)
+ AltosPreferences.set_imperial_units(set_imperial_units);
+ if ((changes & AltosDroid.SETUP_MAP_SOURCE) != 0)
+ AltosDroidPreferences.set_map_source(set_map_source);
+ if ((changes & AltosDroid.SETUP_MAP_TYPE) != 0)
+ AltosPreferences.set_map_type(set_map_type);
+ intent.putExtra(EXTRA_SETUP_CHANGES, changes);
+ setResult(Activity.RESULT_OK, intent);
+ finish();
+ }
+
+ private void add_strings(Spinner spinner, String[] strings, int def) {
+ ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item);
+
+ for (int i = 0; i < strings.length; i++)
+ adapter.add(strings[i]);
+
+ spinner.setAdapter(adapter);
+ if (def >= 0)
+ spinner.setSelection(def);
+ }
+
+ private int default_rate_pos() {
+ int default_rate = AltosPreferences.telemetry_rate(1);
+
+ for (int pos = 0; pos < rates.length; pos++) {
+ if (string_to_rate(rates[pos]) == default_rate)
+ return pos;
+ }
+ return -1;
+ }
+
+ private void setBaud(int baud) {
+ try {
+ service.send(Message.obtain(null, TelemetryService.MSG_SETBAUD, baud));
+ set_telemetry_rate = baud;
+ add_change(AltosDroid.SETUP_BAUD);
+ } catch (RemoteException e) {
+ }
+ }
+
+ private int string_to_rate(String baud) {
+ int rate = AltosLib.ao_telemetry_rate_38400;
+ try {
+ int value = Integer.parseInt(baud);
+ switch (value) {
+ case 2400:
+ rate = AltosLib.ao_telemetry_rate_2400;
+ break;
+ case 9600:
+ rate = AltosLib.ao_telemetry_rate_9600;
+ break;
+ case 38400:
+ rate = AltosLib.ao_telemetry_rate_38400;
+ break;
+ }
+ } catch (NumberFormatException e) {
+ }
+ return rate;
+ }
+
+ private void setBaud(String baud) {
+ setBaud(string_to_rate(baud));
+ }
+
+ private void select_rate(int pos) {
+ setBaud(rates[pos]);
+ }
+
+ static final String[] units = {
+ "Metric",
+ "Imperial"
+ };
+
+ private int default_units_pos() {
+ boolean imperial = AltosPreferences.imperial_units();
+
+ if (imperial)
+ return 1;
+ return 0;
+ }
+
+ private void set_units(int pos) {
+ switch (pos) {
+ default:
+ set_imperial_units = false;
+ break;
+ case 1:
+ set_imperial_units = true;
+ break;
+ }
+ add_change(AltosDroid.SETUP_UNITS);
+ }
+
+ private int default_map_type_pos() {
+ int default_map_type = AltosPreferences.map_type();
+
+ for (int pos = 0; pos < map_types.length; pos++)
+ if (map_type_values[pos] == default_map_type)
+ return pos;
+ return 0;
+ }
+
+ private void select_map_type(int pos) {
+ set_map_type = map_type_values[pos];
+ add_change(AltosDroid.SETUP_MAP_TYPE);
+ }
+
+ private int default_map_source_pos() {
+ int default_source = AltosDroidPreferences.map_source();
+
+ switch (default_source) {
+ case AltosDroidPreferences.MAP_SOURCE_OFFLINE:
+ return 1;
+ default:
+ return 0;
+ }
+ }
+
+ private void select_map_source(int pos) {
+ switch (pos) {
+ default:
+ set_map_source = AltosDroidPreferences.MAP_SOURCE_ONLINE;
+ break;
+ case 1:
+ set_map_source = AltosDroidPreferences.MAP_SOURCE_OFFLINE;
+ break;
+ }
+ add_change(AltosDroid.SETUP_MAP_SOURCE);
+ }
+
+ private void manage_frequencies(){
+ Intent intent = new Intent(this, ManageFrequenciesActivity.class);
+ startActivity(intent);
+ }
+
+ private void preload_maps(){
+ Intent intent = new Intent(this, PreloadMapActivity.class);
+ startActivity(intent);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Setup the window
+ requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+ setContentView(R.layout.setup);
+
+ select_rate = (Spinner) findViewById(R.id.select_rate);
+ add_strings(select_rate, rates, default_rate_pos());
+ select_rate.setOnItemSelectedListener(new OnItemSelectedListener() {
+ public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+ select_rate(pos);
+ }
+ public void onNothingSelected(AdapterView<?> parent) {
+ }
+ });
+
+ set_units = (Spinner) findViewById(R.id.set_units);
+ add_strings(set_units, units, default_units_pos());
+ set_units.setOnItemSelectedListener(new OnItemSelectedListener() {
+ public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+ set_units(pos);
+ }
+ public void onNothingSelected(AdapterView<?> parent) {
+ }
+ });
+
+ map_type = (Spinner) findViewById(R.id.map_type);
+ add_strings(map_type, map_types, default_map_type_pos());
+ map_type.setOnItemSelectedListener(new OnItemSelectedListener() {
+ public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+ select_map_type(pos);
+ }
+ public void onNothingSelected(AdapterView<?> parent) {
+ }
+ });
+
+ map_source = (Spinner) findViewById(R.id.map_source);
+ add_strings(map_source, map_sources, default_map_source_pos());
+ map_source.setOnItemSelectedListener(new OnItemSelectedListener() {
+ public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+ select_map_source(pos);
+ }
+ public void onNothingSelected(AdapterView<?> parent) {
+ }
+ });
+
+
+ manage_frequencies = (Button) findViewById(R.id.manage_frequencies);
+ manage_frequencies.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ manage_frequencies();
+ }
+ });
+
+ preload_maps = (Button) findViewById(R.id.preload_maps);
+ preload_maps.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ preload_maps();
+ }
+ });
+
+ done = (Button) findViewById(R.id.done);
+ done.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ done();
+ }
+ });
+
+ // Set result for when the user backs out
+ setResult(Activity.RESULT_CANCELED);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ doBindService();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ doUnbindService();
+ }
+}
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import android.app.Activity;
import android.os.Bundle;
set_value(speed_view, AltosConvert.speed, 6, state.speed());
set_value(height_view, AltosConvert.height, 6, state.height());
set_value(max_speed_view, AltosConvert.speed, 6, state.max_speed());
- set_value(max_height_view, AltosConvert.speed, 6, state.max_height());
+ set_value(max_height_view, AltosConvert.height, 6, state.max_height());
if (from_receiver != null) {
elevation_view.setText(AltosDroid.number("%3.0f°", from_receiver.elevation));
set_value(range_view, AltosConvert.distance, 6, from_receiver.range);
import java.util.*;
import java.io.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import android.app.Activity;
import android.graphics.*;
import android.location.Location;
import android.content.*;
-public class TabMap extends AltosDroidTab {
+public class TabMap extends AltosDroidTab implements AltosDroidMapSourceListener {
AltosLatLon here;
map_offline.onCreateView(altos_droid);
map_online = new AltosMapOnline(view.getContext());
map_online.onCreateView(altos_droid);
- set_map_source(AltosDroidPreferences.map_source());
+ map_source_changed(AltosDroidPreferences.map_source());
+ AltosDroidPreferences.register_map_source_listener(this);
return view;
}
@Override
public void onDestroyView() {
super.onDestroyView();
+ map_offline.onDestroyView();
+ map_online.onDestroyView();
+ AltosDroidPreferences.unregister_map_source_listener(this);
}
public String tab_name() { return AltosDroid.tab_map_name; }
}
}
- @Override
- public void set_map_type(int map_type) {
- if (map_offline != null)
- map_offline.set_map_type(map_type);
- if (map_online != null)
- map_online.set_map_type(map_type);
- }
-
- @Override
- public void set_map_source(int map_source) {
+ public void map_source_changed(int map_source) {
this.map_source = map_source;
if (map_source == AltosDroidPreferences.MAP_SOURCE_OFFLINE) {
if (map_online != null)
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import android.app.Activity;
import android.os.Bundle;
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import android.app.Activity;
import android.os.Bundle;
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import android.content.BroadcastReceiver;
import android.content.Context;
import java.util.concurrent.*;
import android.os.Handler;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class TelemetryReader extends Thread {
import android.os.RemoteException;
import android.os.Looper;
import android.widget.Toast;
-import android.location.Location;
-import android.location.LocationManager;
-import android.location.LocationListener;
import android.location.Criteria;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
-public class TelemetryService extends Service implements LocationListener {
+public class TelemetryService extends Service implements AltosIdleMonitorListener {
static final int MSG_REGISTER_CLIENT = 1;
static final int MSG_UNREGISTER_CLIENT = 2;
static final int MSG_SETBAUD = 11;
static final int MSG_DISCONNECT = 12;
static final int MSG_DELETE_SERIAL = 13;
+ static final int MSG_BLUETOOTH_ENABLED = 14;
+ static final int MSG_MONITOR_IDLE_START= 15;
+ static final int MSG_MONITOR_IDLE_STOP = 16;
+ static final int MSG_REBOOT = 17;
+ static final int MSG_IGNITER_QUERY = 18;
+ static final int MSG_IGNITER_FIRE = 19;
// Unique Identification Number for the Notification.
// We use it on Notification start, and to cancel it.
// Last data seen; send to UI when it starts
private TelemetryState telemetry_state;
+ // Idle monitor if active
+ AltosIdleMonitor idle_monitor = null;
+
+ // Igniter bits
+ AltosIgnite ignite = null;
+ boolean ignite_running;
+
// Handler of incoming messages from clients.
static class IncomingHandler extends Handler {
private final WeakReference<TelemetryService> service;
@Override
public void handleMessage(Message msg) {
+ DeviceAddress address;
+
TelemetryService s = service.get();
AltosDroidLink bt = null;
if (s == null)
return;
+
switch (msg.what) {
/* Messages from application */
break;
case MSG_CONNECT:
AltosDebug.debug("Connect command received");
- DeviceAddress address = (DeviceAddress) msg.obj;
+ address = (DeviceAddress) msg.obj;
AltosDroidPreferences.set_active_device(address);
s.start_altos_bluetooth(address, false);
break;
s.telemetry_state.crc_errors = (Integer) msg.obj;
s.send_to_clients();
break;
+ case MSG_BLUETOOTH_ENABLED:
+ AltosDebug.debug("TelemetryService notes that BT is now enabled");
+ address = AltosDroidPreferences.active_device();
+ if (address != null && !address.address.startsWith("USB"))
+ s.start_altos_bluetooth(address, false);
+ break;
+ case MSG_MONITOR_IDLE_START:
+ AltosDebug.debug("start monitor idle");
+ s.start_idle_monitor();
+ break;
+ case MSG_MONITOR_IDLE_STOP:
+ AltosDebug.debug("stop monitor idle");
+ s.stop_idle_monitor();
+ break;
+ case MSG_REBOOT:
+ AltosDebug.debug("reboot");
+ s.reboot_remote();
+ break;
+ case MSG_IGNITER_QUERY:
+ AltosDebug.debug("igniter query");
+ s.igniter_query(msg.replyTo);
+ break;
+ case MSG_IGNITER_FIRE:
+ AltosDebug.debug("igniter fire");
+ s.igniter_fire((String) msg.obj);
+ break;
default:
super.handleMessage(msg);
}
telem.update_state(state);
telemetry_state.states.put(telem.serial, state);
if (state != null) {
- AltosPreferences.set_state(telem.serial, state, null);
+ AltosPreferences.set_state(state);
}
send_to_clients();
}
/* On connect, send the current state to the new client
*/
- send_to_client(client, message());
+ send_to_client(client);
+ send_idle_mode_to_client(client);
/* If we've got an address from a previous session, then
* go ahead and try to reconnect to the device
}
}
- private void send_to_client(Messenger client, Message m) {
+ private void send_to_client(Messenger client) {
+ Message m = message();
try {
client.send(m);
} catch (RemoteException e) {
}
private void send_to_clients() {
- Message m = message();
for (Messenger client : clients)
- send_to_client(client, m);
+ send_to_client(client);
}
- private void disconnect(boolean notify) {
- AltosDebug.debug("disconnect(): begin");
-
- telemetry_state.connect = TelemetryState.CONNECT_DISCONNECTED;
- telemetry_state.address = null;
+ private void send_idle_mode_to_client(Messenger client) {
+ Message m = Message.obtain(null, AltosDroid.MSG_IDLE_MODE, idle_monitor != null);
+ try {
+ client.send(m);
+ } catch (RemoteException e) {
+ AltosDebug.error("Client %s disappeared", client.toString());
+ remove_client(client);
+ }
+ }
- if (altos_link != null)
- altos_link.closing();
+ private void send_idle_mode_to_clients() {
+ for (Messenger client : clients)
+ send_idle_mode_to_client(client);
+ }
- stop_receiver_voltage_timer();
+ private void telemetry_start() {
+ if (telemetry_reader == null && idle_monitor == null && !ignite_running) {
+ telemetry_reader = new TelemetryReader(altos_link, handler);
+ telemetry_reader.start();
+ }
+ }
+ private void telemetry_stop() {
if (telemetry_reader != null) {
AltosDebug.debug("disconnect(): stopping TelemetryReader");
telemetry_reader.interrupt();
}
telemetry_reader = null;
}
+ }
+
+ private void disconnect(boolean notify) {
+ AltosDebug.debug("disconnect(): begin");
+
+ telemetry_state.connect = TelemetryState.CONNECT_DISCONNECTED;
+ telemetry_state.address = null;
+
+ if (idle_monitor != null)
+ stop_idle_monitor();
+
+ if (altos_link != null)
+ altos_link.closing();
+
+ stop_receiver_voltage_timer();
+
+ telemetry_stop();
if (telemetry_logger != null) {
AltosDebug.debug("disconnect(): stopping TelemetryLogger");
telemetry_logger.stop();
AltosDebug.debug("disconnect(): stopping AltosDroidLink");
altos_link.close();
altos_link = null;
+ ignite = null;
}
telemetry_state.config = null;
if (notify) {
}
private void start_altos_bluetooth(DeviceAddress address, boolean pause) {
- // Get the BLuetoothDevice object
- BluetoothDevice device = bluetooth_adapter.getRemoteDevice(address.address);
+ if (bluetooth_adapter == null || !bluetooth_adapter.isEnabled())
+ return;
disconnect(false);
+
+ // Get the BluetoothDevice object
+ BluetoothDevice device = bluetooth_adapter.getRemoteDevice(address.address);
+
this.address = address;
AltosDebug.debug("start_altos_bluetooth(): Connecting to %s (%s)", device.getName(), device.getAddress());
altos_link = new AltosBluetooth(device, handler, pause);
send_to_clients();
}
+ private void start_idle_monitor() {
+ if (altos_link != null && idle_monitor == null) {
+ telemetry_stop();
+ idle_monitor = new AltosIdleMonitor(this, altos_link, true, false);
+ idle_monitor.set_callsign(AltosPreferences.callsign());
+ idle_monitor.start();
+ send_idle_mode_to_clients();
+ }
+ }
+
+ private void stop_idle_monitor() {
+ if (idle_monitor != null) {
+ try {
+ idle_monitor.abort();
+ } catch (InterruptedException ie) {
+ }
+ idle_monitor = null;
+ telemetry_start();
+ send_idle_mode_to_clients();
+ }
+ }
+
+ private void reboot_remote() {
+ if (altos_link != null) {
+ stop_idle_monitor();
+ try {
+ altos_link.start_remote();
+ altos_link.printf("r eboot\n");
+ altos_link.flush_output();
+ } catch (TimeoutException te) {
+ } catch (InterruptedException ie) {
+ } finally {
+ try {
+ altos_link.stop_remote();
+ } catch (InterruptedException ie) {
+ }
+ }
+ }
+ }
+
+ private void ensure_ignite() {
+ if (ignite == null)
+ ignite = new AltosIgnite(altos_link, true, false);
+ }
+
+ private synchronized void igniter_query(Messenger client) {
+ ensure_ignite();
+ HashMap<String,Integer> status_map = null;
+ ignite_running = true;
+ try {
+ stop_idle_monitor();
+ try {
+ status_map = ignite.status();
+ } catch (InterruptedException ie) {
+ AltosDebug.debug("ignite.status interrupted");
+ } catch (TimeoutException te) {
+ AltosDebug.debug("ignite.status timeout");
+ }
+ } finally {
+ ignite_running = false;
+ }
+ Message m = Message.obtain(null, AltosDroid.MSG_IGNITER_STATUS, status_map);
+ try {
+ client.send(m);
+ } catch (RemoteException e) {
+ }
+ }
+
+ private synchronized void igniter_fire(String igniter) {
+ ensure_ignite();
+ ignite_running = true;
+ stop_idle_monitor();
+ try {
+ ignite.fire(igniter);
+ } catch (InterruptedException ie) {
+ } finally {
+ ignite_running = false;
+ }
+ }
+
// Timer for receiver battery voltage monitoring
Timer receiver_voltage_timer;
private void update_receiver_voltage() {
- if (altos_link != null) {
+ if (altos_link != null && idle_monitor == null && !ignite_running) {
try {
double voltage = altos_link.monitor_battery();
telemetry_state.receiver_battery = voltage;
+ send_to_clients();
} catch (InterruptedException ie) {
}
}
telemetry_state.connect = TelemetryState.CONNECT_CONNECTED;
telemetry_state.address = address;
- telemetry_reader = new TelemetryReader(altos_link, handler);
- telemetry_reader.start();
+ telemetry_start();
AltosDebug.debug("connected TelemetryReader started");
// Get local Bluetooth adapter
bluetooth_adapter = BluetoothAdapter.getDefaultAdapter();
- // If the adapter is null, then Bluetooth is not supported
- if (bluetooth_adapter == null) {
- Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();
- }
-
telemetry_state = new TelemetryState();
// Create a reference to the NotificationManager so that we can update our notifcation text later
telemetry_state.latest_serial = AltosPreferences.latest_state();
for (int serial : serials) {
- AltosSavedState saved_state = AltosPreferences.state(serial);
+ AltosState saved_state = AltosPreferences.state(serial);
if (saved_state != null) {
- if (serial == 0) {
- serial = saved_state.state.serial;
- AltosPreferences.set_state(serial, saved_state.state, saved_state.listener_state);
- AltosPreferences.remove_state(0);
- }
if (telemetry_state.latest_serial == 0)
telemetry_state.latest_serial = serial;
- AltosDebug.debug("recovered old state serial %d flight %d\n",
+ AltosDebug.debug("recovered old state serial %d flight %d",
serial,
- saved_state.state.flight);
- if (saved_state.state.gps != null)
- AltosDebug.debug("\tposition %f,%f\n",
- saved_state.state.gps.lat,
- saved_state.state.gps.lon);
- telemetry_state.states.put(serial, saved_state.state);
+ saved_state.flight);
+ if (saved_state.gps != null)
+ AltosDebug.debug("\tposition %f,%f",
+ saved_state.gps.lat,
+ saved_state.gps.lon);
+ telemetry_state.states.put(serial, saved_state);
+ } else {
+ AltosDebug.debug("Failed to recover state for %d", serial);
}
}
-
- // Listen for GPS and Network position updates
- LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
-
- locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, this);
}
@Override
@Override
public void onDestroy() {
- // Stop listening for location updates
- ((LocationManager) getSystemService(Context.LOCATION_SERVICE)).removeUpdates(this);
-
// Stop the bluetooth Comms threads
disconnect(true);
return messenger.getBinder();
}
-
- public void onLocationChanged(Location location) {
- telemetry_state.location = location;
- AltosDebug.debug("location changed");
+ /* AltosIdleMonitorListener */
+ public void update(AltosState state, AltosListenerState listener_state) {
+ telemetry_state.states.put(state.serial, state);
+ telemetry_state.receiver_battery = listener_state.battery;
send_to_clients();
}
- public void onStatusChanged(String provider, int status, Bundle extras) {
+ public void failed() {
}
- public void onProviderEnabled(String provider) {
+ public void error(String reason) {
+ stop_idle_monitor();
}
-
- public void onProviderDisabled(String provider) {
- }
-
}
package org.altusmetrum.AltosDroid;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import android.location.Location;
public class TelemetryState {
int connect;
DeviceAddress address;
AltosConfigData config;
- Location location;
int crc_errors;
double receiver_battery;
double frequency;
connect = CONNECT_NONE;
config = null;
states = new HashMap<Integer,AltosState>();
- location = null;
crc_errors = 0;
receiver_battery = AltosLib.MISSING;
frequency = AltosPreferences.frequency(0);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosCRCException extends Exception {
public int rssi;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.*;
import java.text.*;
}
+ public boolean mma655x_inverted() throws AltosUnknownProduct {
+ if (product.startsWith("EasyMega-v1"))
+ return false;
+ if (product.startsWith("TeleMetrum-v2"))
+ return true;
+ if (product.startsWith("TeleMega-v2"))
+ return false;
+ if (product.startsWith("TeleMega-v1"))
+ return false;
+ throw new AltosUnknownProduct(product);
+ }
+
public void get_values(AltosConfigValues source) throws AltosConfigDataException {
/* HAS_FLIGHT */
radio_enable = source.radio_enable();
if (callsign != null)
callsign = source.callsign();
- if (radio_calibration >= 0)
- radio_calibration = source.radio_calibration();
if (telemetry_rate >= 0)
telemetry_rate = source.telemetry_rate();
if (apogee_lockout >= 0)
link.printf("c L %d\n", apogee_lockout);
- /* Don't mess with radio calibration when remote */
- if (radio_calibration > 0 && !remote)
- link.printf("c f %d\n", radio_calibration);
-
/* HAS_RADIO */
if (has_frequency()) {
boolean has_frequency = radio_frequency >= 0;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosConfigDataException extends Exception {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosConfigValues {
/* set and get all of the dialog values */
public abstract void set_radio_calibration(int new_radio_calibration);
- public abstract int radio_calibration() throws AltosConfigDataException;
-
public abstract void set_radio_enable(int new_radio_enable);
public abstract int radio_enable();
/*
* Sensor data conversion functions
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosConvert {
/*
return miles_to_meters(mps) / 3600;
}
+ public static double mps_to_fps(double mps) {
+ return meters_to_miles(mps) * 5280;
+ }
+
+ public static double fps_to_mps(double mps) {
+ return miles_to_meters(mps) / 5280;
+ }
+
public static double meters_to_mach(double meters) {
return meters / 343; /* something close to mach at usual rocket sites */
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosDistance extends AltosUnits {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.text.*;
import java.util.concurrent.*;
eeprom = new AltosEepromTM(this, offset);
break;
case AltosLib.AO_LOG_FORMAT_TINY:
- eeprom = new AltosEepromTm(this, offset, state);
+ eeprom = new AltosEepromTMini(this, offset, state);
break;
case AltosLib.AO_LOG_FORMAT_TELEMETRY:
case AltosLib.AO_LOG_FORMAT_TELESCIENCE:
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
body = new AltosEepromIterable(AltosEepromTM.read(input));
break;
case AltosLib.AO_LOG_FORMAT_TINY:
- body = new AltosEepromIterable(AltosEepromTm.read(input));
+ body = new AltosEepromIterable(AltosEepromTMini.read(input));
break;
case AltosLib.AO_LOG_FORMAT_TELEMETRY:
case AltosLib.AO_LOG_FORMAT_TELESCIENCE:
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.text.*;
import java.util.concurrent.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosEepromMonitor {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
--- /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 org.altusmetrum.altoslib_10;
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
+public class AltosEepromTMini extends AltosEeprom {
+ public int i;
+ public int a;
+ public int b;
+
+ public static final int record_length = 2;
+
+ public void write(PrintStream out) {
+ out.printf("%c %4x %4x %4x\n", cmd, tick, a, b);
+ }
+
+ public int record_length() { return record_length; }
+
+ public String string() {
+ return String.format("%c %4x %4x %4x\n", cmd, tick, a, b);
+ }
+
+ public void update_state(AltosState state) {
+ super.update_state(state);
+
+ switch (cmd) {
+ case AltosLib.AO_LOG_FLIGHT:
+ state.set_state(AltosLib.ao_flight_boost);
+ state.set_flight(b);
+ break;
+ case AltosLib.AO_LOG_PRESSURE:
+ if (tick == 0)
+ state.set_ground_pressure(AltosConvert.barometer_to_pressure(b));
+ else
+ state.set_pressure(AltosConvert.barometer_to_pressure(b));
+ break;
+ case AltosLib.AO_LOG_STATE:
+ state.set_state(a);
+ break;
+ }
+ }
+
+ public AltosEepromTMini (AltosEepromChunk chunk, int start, AltosState state) throws ParseException {
+ int value = chunk.data16(start);
+
+ int i = (chunk.address + start) / record_length;
+
+ cmd = chunk.data(start);
+ valid = true;
+
+ valid = !chunk.erased(start, record_length);
+
+ switch (i) {
+ case 0:
+ cmd = AltosLib.AO_LOG_FLIGHT;
+ tick = 0;
+ a = 0;
+ b = value;
+ break;
+ case 1:
+ cmd = AltosLib.AO_LOG_PRESSURE;
+ tick = 0;
+ a = 0;
+ b = value;
+ break;
+ default:
+ if ((value & 0x8000) != 0) {
+ cmd = AltosLib.AO_LOG_STATE;
+ tick = state.tick;
+ a = value & 0x7fff;
+ b = 0;
+ } else {
+ if (state.ascent)
+ tick = state.tick + 10;
+ else
+ tick = state.tick + 100;
+ cmd = AltosLib.AO_LOG_PRESSURE;
+ a = 0;
+ b = value;
+ }
+ break;
+ }
+ }
+
+ public AltosEepromTMini (String line) {
+ valid = false;
+ tick = 0;
+ a = 0;
+ b = 0;
+ if (line == null) {
+ cmd = AltosLib.AO_LOG_INVALID;
+ } else {
+ try {
+ String[] tokens = line.split("\\s+");
+
+ if (tokens[0].length() == 1) {
+ if (tokens.length != 4) {
+ cmd = AltosLib.AO_LOG_INVALID;
+ } else {
+ cmd = tokens[0].codePointAt(0);
+ tick = Integer.parseInt(tokens[1],16);
+ valid = true;
+ a = Integer.parseInt(tokens[2],16);
+ b = Integer.parseInt(tokens[3],16);
+ }
+ } else {
+ cmd = AltosLib.AO_LOG_INVALID;
+ }
+ } catch (NumberFormatException ne) {
+ cmd = AltosLib.AO_LOG_INVALID;
+ }
+ }
+ }
+
+ public AltosEepromTMini(int in_cmd, int in_tick, int in_a, int in_b) {
+ valid = true;
+ cmd = in_cmd;
+ tick = in_tick;
+ a = in_a;
+ b = in_b;
+ }
+
+ static public LinkedList<AltosEeprom> read(FileInputStream input) {
+ LinkedList<AltosEeprom> tms = new LinkedList<AltosEeprom>();
+
+ for (;;) {
+ try {
+ String line = AltosLib.gets(input);
+ if (line == null)
+ break;
+ AltosEepromTMini tm = new AltosEepromTMini(line);
+ tms.add(tm);
+ } catch (IOException ie) {
+ break;
+ }
+ }
+
+ return tms;
+ }
+
+}
+++ /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 org.altusmetrum.altoslib_9;
-
-import java.io.*;
-import java.util.*;
-import java.text.*;
-
-public class AltosEepromTm extends AltosEeprom {
- public int i;
- public int a;
- public int b;
-
- public static final int record_length = 2;
-
- public void write(PrintStream out) {
- out.printf("%c %4x %4x %4x\n", cmd, tick, a, b);
- }
-
- public int record_length() { return record_length; }
-
- public String string() {
- return String.format("%c %4x %4x %4x\n", cmd, tick, a, b);
- }
-
- public void update_state(AltosState state) {
- super.update_state(state);
-
- switch (cmd) {
- case AltosLib.AO_LOG_FLIGHT:
- state.set_state(AltosLib.ao_flight_boost);
- state.set_flight(b);
- break;
- case AltosLib.AO_LOG_PRESSURE:
- if (tick == 0)
- state.set_ground_pressure(AltosConvert.barometer_to_pressure(b));
- else
- state.set_pressure(AltosConvert.barometer_to_pressure(b));
- break;
- case AltosLib.AO_LOG_STATE:
- state.set_state(a);
- break;
- }
- }
-
- public AltosEepromTm (AltosEepromChunk chunk, int start, AltosState state) throws ParseException {
- int value = chunk.data16(start);
-
- int i = (chunk.address + start) / record_length;
-
- cmd = chunk.data(start);
- valid = true;
-
- valid = !chunk.erased(start, record_length);
-
- switch (i) {
- case 0:
- cmd = AltosLib.AO_LOG_FLIGHT;
- tick = 0;
- a = 0;
- b = value;
- break;
- case 1:
- cmd = AltosLib.AO_LOG_PRESSURE;
- tick = 0;
- a = 0;
- b = value;
- break;
- default:
- if ((value & 0x8000) != 0) {
- cmd = AltosLib.AO_LOG_STATE;
- tick = state.tick;
- a = value & 0x7fff;
- b = 0;
- } else {
- if (state.ascent)
- tick = state.tick + 10;
- else
- tick = state.tick + 100;
- cmd = AltosLib.AO_LOG_PRESSURE;
- a = 0;
- b = value;
- }
- break;
- }
- }
-
- public AltosEepromTm (String line) {
- valid = false;
- tick = 0;
- a = 0;
- b = 0;
- if (line == null) {
- cmd = AltosLib.AO_LOG_INVALID;
- } else {
- try {
- String[] tokens = line.split("\\s+");
-
- if (tokens[0].length() == 1) {
- if (tokens.length != 4) {
- cmd = AltosLib.AO_LOG_INVALID;
- } else {
- cmd = tokens[0].codePointAt(0);
- tick = Integer.parseInt(tokens[1],16);
- valid = true;
- a = Integer.parseInt(tokens[2],16);
- b = Integer.parseInt(tokens[3],16);
- }
- } else {
- cmd = AltosLib.AO_LOG_INVALID;
- }
- } catch (NumberFormatException ne) {
- cmd = AltosLib.AO_LOG_INVALID;
- }
- }
- }
-
- public AltosEepromTm(int in_cmd, int in_tick, int in_a, int in_b) {
- valid = true;
- cmd = in_cmd;
- tick = in_tick;
- a = in_a;
- b = in_b;
- }
-
- static public LinkedList<AltosEeprom> read(FileInputStream input) {
- LinkedList<AltosEeprom> tms = new LinkedList<AltosEeprom>();
-
- for (;;) {
- try {
- String line = AltosLib.gets(input);
- if (line == null)
- break;
- AltosEepromTm tm = new AltosEepromTm(line);
- tms.add(tm);
- } catch (IOException ie) {
- break;
- }
- }
-
- return tms;
- }
-
-}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.File;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosFlashListener {
public void position(String label, int percent);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosFlightDisplay extends AltosUnitsListener, AltosFontListener {
void reset();
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.text.*;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
}
if (state == null)
- return 0;
+ return AltosLib.MISSING;
double landed_height = state.height();
boolean above = true;
- double landed_time = -1000;
+ double landed_time = AltosLib.MISSING;
for (AltosState s : states) {
state = s;
if (state.height() > landed_height + 10) {
above = true;
} else {
- if (above && state.height() < landed_height + 2) {
+ if (above && Math.abs(state.height() - landed_height) < 2) {
above = false;
landed_time = state.time;
}
}
}
- if (landed_time == -1000)
- landed_time = state.time;
return landed_time;
}
break;
}
if (state == null)
- return 0;
+ return AltosLib.MISSING;
- if (boost_time == AltosLib.MISSING)
- boost_time = state.time;
return boost_time;
}
has_imu = false;
has_mag = false;
has_orient = false;
+
+ for (int s = AltosLib.ao_flight_startup; s <= AltosLib.ao_flight_landed; s++) {
+ state_count[s] = 0;
+ state_speed[s] = 0.0;
+ state_accel[s] = 0.0;
+ }
+
for (AltosState state : states) {
if (serial == AltosLib.MISSING && state.serial != AltosLib.MISSING)
serial = state.serial;
has_flight_data = true;
int state_id = state.state();
- if (state.time >= boost_time && state_id < AltosLib.ao_flight_boost)
+ if (boost_time != AltosLib.MISSING && state.time >= boost_time && state_id < AltosLib.ao_flight_boost) {
state_id = AltosLib.ao_flight_boost;
- if (state.time >= landed_time && state_id < AltosLib.ao_flight_landed)
+ }
+ if (landed_time != AltosLib.MISSING && state.time >= landed_time && state_id < AltosLib.ao_flight_landed) {
state_id = AltosLib.ao_flight_landed;
+ }
+
if (state.gps != null && state.gps.locked) {
year = state.gps.year;
month = state.gps.month;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosFontListener {
void font_size_changed(int font_size);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
-public class AltosFrequency {
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
+public class AltosFrequency implements Serializable {
public double frequency;
public String description;
frequency, description);
}
+ public String frequency_string() {
+ return String.format("%7.3f", frequency);
+ }
+
public boolean close(double f) {
double diff = Math.abs(frequency - f);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.text.*;
import java.util.concurrent.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
+import java.text.*;
+import java.util.concurrent.*;
+import java.io.*;
-public class AltosGPSSat {
+public class AltosGPSSat implements Serializable {
public int svid;
public int c_n0;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.lang.Math;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosHeight extends AltosUnits {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.LinkedList;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosHexsym {
String name;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.*;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
static final int idle_sensor_tmini = 14;
static final int idle_sensor_tgps = 15;
- public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException, TimeoutException {
+ public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException, TimeoutException, AltosUnknownProduct {
for (int idler : idlers) {
AltosIdle idle = null;
switch (idler) {
double frequency;
String callsign;
- public void update_state(AltosState state) throws InterruptedException {
+ public void update_state(AltosState state) throws InterruptedException, AltosUnknownProduct {
try {
+ boolean matched = false;
/* Fetch config data from remote */
AltosConfigData config_data = new AltosConfigData(link);
state.set_state(AltosLib.ao_flight_stateless);
for (AltosIdler idler : idlers) {
if (idler.matches(config_data)) {
idler.update_state(state, link, config_data);
+ matched = true;
break;
}
}
+ if (!matched)
+ throw new AltosUnknownProduct(config_data.product);
state.set_received_time(System.currentTimeMillis());
} catch (TimeoutException te) {
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.concurrent.*;
AltosIdleFetch fetch;
boolean remote;
+ boolean close_on_exit;
double frequency;
String callsign;
return link.reply_abort;
}
- boolean update_state(AltosState state) throws InterruptedException, TimeoutException {
+ boolean update_state(AltosState state) throws InterruptedException, TimeoutException, AltosUnknownProduct {
boolean worked = false;
boolean aborted = false;
update_state(state);
listener.update(state, listener_state);
} catch (TimeoutException te) {
+ } catch (AltosUnknownProduct ae) {
+ listener.error(String.format("Unknown product \"%s\"", ae.product));
}
if (link.has_error || link.reply_abort) {
listener.failed();
}
} catch (InterruptedException ie) {
}
- try {
- link.close();
- } catch (InterruptedException ie) {
+ if (close_on_exit) {
+ try {
+ link.close();
+ } catch (InterruptedException ie) {
+ }
}
}
- public AltosIdleMonitor(AltosIdleMonitorListener in_listener, AltosLink in_link, boolean in_remote)
- throws FileNotFoundException, InterruptedException, TimeoutException {
+ public AltosIdleMonitor(AltosIdleMonitorListener in_listener, AltosLink in_link, boolean in_remote, boolean in_close_on_exit) {
listener = in_listener;
link = in_link;
remote = in_remote;
+ close_on_exit = in_close_on_exit;
listener_state = new AltosListenerState();
fetch = new AltosIdleFetch(link);
}
+
+ public AltosIdleMonitor(AltosIdleMonitorListener in_listener, AltosLink in_link, boolean in_remote) {
+ this(in_listener, in_link, in_remote, true);
+ }
}
+
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosIdleMonitorListener {
public void update(AltosState state, AltosListenerState listener_state);
+ public void error(String reason);
public void failed();
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.*;
import java.io.*;
public class AltosIgnite {
AltosLink link;
boolean remote;
+ boolean close_on_exit;
boolean link_started;
boolean have_npyro = false;
int npyro;
public void close() throws InterruptedException {
stop_link();
- link.close();
+ if (close_on_exit)
+ link.close();
link = null;
}
- public AltosIgnite(AltosLink in_link, boolean in_remote)
- throws FileNotFoundException, TimeoutException, InterruptedException {
-
+ public AltosIgnite(AltosLink in_link, boolean in_remote, boolean in_close_on_exit) {
link = in_link;
remote = in_remote;
+ close_on_exit = in_close_on_exit;
+ }
+
+ public AltosIgnite(AltosLink in_link, boolean in_remote) {
+ this(in_link, in_remote, true);
}
-}
\ No newline at end of file
+}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosLatLon {
public double lat;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosLatitude extends AltosLocation {
public String pos() { return "N"; }
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.lang.*;
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.lang.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.lang.*;
public void run() {
try {
- url = new URL(AltosLib.launch_sites_url);
+ String path;
+
+ path = System.getenv(AltosLib.launch_sites_env);
+ if (path == null)
+ path = AltosLib.launch_sites_url;
+ url = new URL(path);
URLConnection uc = url.openConnection();
InputStreamReader in_stream = new InputStreamReader(uc.getInputStream(), AltosLib.unicode_set);
add(line);
}
} catch (Exception e) {
+ System.out.printf("file exception %s\n", e.toString());
} finally {
notify_complete();
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.*;
import java.io.*;
};
public static final String launch_sites_url = "http://www.altusmetrum.org/AltOS/launch-sites.txt";
+ public static final String launch_sites_env = "LAUNCH_SITES";
// public static final String launch_sites_url = "file:///home/keithp/misc/text/altusmetrum/AltOS/launch-sites.txt";
public static final int ao_telemetry_standard_len = 32;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosLine {
public String line;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.concurrent.*;
boolean can_cancel = can_cancel_reply();
String reply = null;
- if (!can_cancel && remote)
- System.out.printf("Uh-oh, reading remote serial device from swing thread\n");
+// if (!can_cancel && remote)
+// System.out.printf("Uh-oh, reading remote serial device from swing thread\n");
if (remote && can_cancel) {
timeout = 500;
if (config_data.has_monitor_battery()) {
try {
- String[] items = adc();
- for (int i = 0; i < items.length;) {
- if (items[i].equals("batt")) {
- monitor_batt = Integer.parseInt(items[i+1]);
- i += 2;
- continue;
+ String[] items = adc();
+ for (int i = 0; i < items.length;) {
+ if (items[i].equals("batt")) {
+ monitor_batt = Integer.parseInt(items[i+1]);
+ i += 2;
+ continue;
+ }
+ i++;
}
- i++;
- }
} catch (TimeoutException te) {
}
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public abstract class AltosLocation extends AltosUnits {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.text.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosLongitude extends AltosLocation {
public String pos() { return "E"; }
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.*;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.lang.*;
upper_left = floor(transform.screen_point(new AltosPointInt(0, 0)));
lower_right = floor(transform.screen_point(new AltosPointInt(width(), height())));
}
- for (AltosPointInt point : tiles.keySet()) {
+
+ Enumeration<AltosPointInt> keyEnumeration = tiles.keys();
+
+ while (keyEnumeration.hasMoreElements()) {
+ AltosPointInt point = keyEnumeration.nextElement();
if (point.x < upper_left.x || lower_right.x < point.x ||
point.y < upper_left.y || lower_right.y < point.y) {
tiles.remove(point);
if (!tiles.containsKey(point)) {
AltosLatLon ul = transform.lat_lon(point);
AltosLatLon center = transform.lat_lon(new AltosPointDouble(x + AltosMap.px_size/2, y + AltosMap.px_size/2));
- AltosMapTile tile = map_interface.new_tile(this, ul, center, zoom, maptype, px_size);
+ AltosMapTile tile = map_interface.new_tile(cache, ul, center, zoom, maptype, px_size);
+ tile.add_listener(this);
tiles.put(point, tile);
}
}
centre(lat, lon);
tiles.clear();
make_tiles();
- for (AltosMapTile tile : tiles.values()) {
- tile.add_store_listener(this);
- if (tile.store_status() != AltosMapTile.loading)
- listener.notify_tile(tile, tile.store_status());
- }
repaint();
}
/* AltosMapTileListener methods */
public synchronized void notify_tile(AltosMapTile tile, int status) {
- for (AltosPointInt point : tiles.keySet()) {
+ Enumeration<AltosPointInt> keyEnumeration = tiles.keys();
+
+ while (keyEnumeration.hasMoreElements()) {
+ AltosPointInt point = keyEnumeration.nextElement();
if (tile == tiles.get(point)) {
AltosPointInt screen = transform.screen(point);
repaint(screen.x, screen.y, AltosMap.px_size, AltosMap.px_size);
if (distance > drag_far)
dragged = true;
- if (transform == null) {
- debug("Transform not set in drag\n");
+ if (transform == null)
return;
- }
AltosLatLon new_centre = transform.screen_lat_lon(new AltosPointInt(width() / 2 - dx, height() / 2 - dy));
centre(new_centre);
private void drag_stop(int x, int y) {
if (!dragged) {
if (transform == null) {
- debug("Transform not set in stop\n");
return;
}
map_interface.select_object (transform.screen_lat_lon(new AltosPointInt(x,y)));
}
private void line_start(int x, int y) {
- if (line != null) {
+ if (line != null && transform != null) {
line.pressed(new AltosPointInt(x, y), transform);
repaint();
}
}
private void line(int x, int y) {
- if (line != null) {
+ if (line != null && transform != null) {
line.dragged(new AltosPointInt(x, y), transform);
repaint();
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.net.*;
public class AltosMapCache implements AltosMapCacheListener {
/* An entry in the MapCache */
- class MapCacheElement implements AltosMapStoreListener {
+ class MapCacheElement implements AltosMapTileListener {
AltosMapTile tile; /* Notify when image has been loaded */
AltosImage image;
- AltosMapStore store;
long used;
class loader implements Runnable {
public void run() {
- if (image != null)
- tile.notify_image(image);
- try {
- image = map_interface.load_image(store.file);
- } catch (Exception ex) {
+ if (image == null) {
+ try {
+ image = map_interface.load_image(tile.store.file);
+ } catch (Exception ex) {
+ }
}
- if (image == null)
- tile.set_status(AltosMapTile.failed);
- else
- tile.set_status(AltosMapTile.success);
tile.notify_image(image);
}
}
}
public boolean has_map() {
- return store.status() == AltosMapTile.success;
+ return tile.status == AltosMapTile.loaded;
}
- public synchronized void notify_store(AltosMapStore store, int status) {
- switch (status) {
- case AltosMapTile.loading:
- break;
- case AltosMapTile.success:
+ public synchronized void notify_tile(AltosMapTile tile, int status) {
+ if (status == AltosMapTile.fetched) {
+ System.out.printf("tile fetched, loading image\n");
load();
- break;
- default:
- tile.set_status(status);
- tile.notify_image(null);
}
}
- public MapCacheElement(AltosMapTile tile, AltosMapStore store) throws IOException {
+ public MapCacheElement(AltosMapTile tile) {
this.tile = tile;
this.image = null;
- this.store = store;
this.used = 0;
-
- int status = store.status();
- switch (status) {
- case AltosMapTile.loading:
- store.add_listener(this);
- break;
- case AltosMapTile.success:
- load();
- break;
- default:
- tile.set_status(status);
- tile.notify_image(null);
- break;
- }
+ tile.add_listener(this);
}
}
}
}
- public AltosImage get(AltosMapTile tile, AltosMapStore store, int width, int height) {
+ public AltosImage get(AltosMapTile tile) {
int oldest = -1;
long age = used;
oldest = i;
break;
}
- if (store.equals(element.store)) {
+ if (tile.store.equals(element.tile.store)) {
element.used = used++;
return element.image;
}
}
}
- try {
- element = new MapCacheElement(tile, store);
- element.used = used++;
- if (elements[oldest] != null)
- elements[oldest].flush();
+ element = new MapCacheElement(tile);
+ element.used = used++;
+ if (elements[oldest] != null)
+ elements[oldest].flush();
- elements[oldest] = element;
-
- if (element.image == null)
- tile.set_status(AltosMapTile.loading);
- else
- tile.set_status(AltosMapTile.success);
-
- return element.image;
- } catch (IOException e) {
- tile.set_status(AltosMapTile.failed);
- return null;
- }
+ elements[oldest] = element;
+ System.out.printf("AltosMapCache.get image ? %s\n",
+ element.image == null ? "false" : "true");
+ return element.image;
}
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosMapCacheListener {
public void map_cache_changed(int map_cache);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.net.*;
public abstract AltosMapMark new_mark(double lat, double lon, int state);
- public abstract AltosMapTile new_tile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size);
+ public abstract AltosMapTile new_tile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size);
public abstract int width();
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.lang.Math;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
import java.net.URL;
import java.net.URLConnection;
-public class AltosMapLoader implements AltosMapTileListener, AltosMapStoreListener {
+public class AltosMapLoader extends Thread implements AltosMapTileListener {
AltosMapLoaderListener listener;
double latitude, longitude;
for (int y = (int) upper_left.y; y <= lower_right.y; y += AltosMap.px_size) {
for (int x = (int) upper_left.x; x <= lower_right.x; x += AltosMap.px_size) {
- listener.debug("Make tile at %d, %d\n", x, y);
AltosPointInt point = new AltosPointInt(x, y);
AltosLatLon ul = transform.lat_lon(point);
AltosLatLon center = transform.lat_lon(new AltosPointDouble(x + AltosMap.px_size/2, y + AltosMap.px_size/2));
- AltosMapTile tile = map.map_interface.new_tile(this, ul, center, zoom, maptype, AltosMap.px_size);
- tile.add_store_listener(this);
- if (tile.store_status() != AltosMapTile.loading)
- notify_tile(tile, tile.store_status());
+ AltosMapTile tile = map.map_interface.new_tile(null, ul, center, zoom, maptype, AltosMap.px_size);
+ tile.add_listener(this);
}
}
}
do_load();
}
- private void start_load() {
+ public void run() {
cur_z = min_z;
int ntype = 0;
cur_type = next_type(0);
+ tiles_total = 0;
for (int z = min_z; z <= max_z; z++)
- tiles_total += tiles_per_layer(z);
+ tiles_total += tiles_per_layer(z) * ntype;
layers_total = (max_z - min_z + 1) * ntype;
layers_loaded = 0;
tiles_loaded_total = 0;
- listener.debug("total tiles %d\n", tiles_total);
+ listener.debug("total tiles %d layers %d\n", tiles_total, layers_total);
listener.loader_start(tiles_total);
do_load();
}
- public void load(double latitude, double longitude, int min_z, int max_z, double radius, int all_types) {
- listener.debug("lat %f lon %f min_z %d max_z %d radius %f all_types %d\n",
- latitude, longitude, min_z, max_z, radius, all_types);
- this.latitude = latitude;
- this.longitude = longitude;
- this.min_z = min_z;
- this.max_z = max_z;
- this.radius = radius;
- this.all_types = all_types;
- start_load();
- }
-
- public synchronized void notify_store(AltosMapStore store, int status) {
+ public synchronized void notify_tile(AltosMapTile tile, int status) {
boolean do_next = false;
- if (status == AltosMapTile.loading)
+ if (status == AltosMapTile.fetching)
return;
+ tile.remove_listener(this);
+
if (layers_loaded >= layers_total)
return;
++tiles_loaded_total;
++tiles_loaded_layer;
- listener.debug("total %d layer %d\n", tiles_loaded_total, tiles_loaded_layer);
+
+ listener.debug("AltosMapLoader.notify_tile status %d total %d of %d layer %d of %d\n",
+ status, tiles_loaded_total, tiles_total, tiles_loaded_layer, tiles_this_layer);
if (tiles_loaded_layer == tiles_this_layer) {
++layers_loaded;
listener.debug("%d layers loaded\n", layers_loaded);
- if (layers_loaded == layers_total) {
- listener.loader_done(tiles_total);
- return;
- } else {
- do_next = true;
- }
+ do_next = true;
}
- listener.loader_notify(tiles_loaded_total,
- tiles_total, store.file.toString());
- if (do_next)
- next_load();
- }
- public synchronized void notify_tile(AltosMapTile tile, int status) {
- notify_store(tile.store, status);
+ if (tiles_loaded_total == tiles_total)
+ listener.loader_done(tiles_total);
+ else {
+ listener.loader_notify(tiles_loaded_total,
+ tiles_total, tile.store.file.toString());
+ if (do_next)
+ next_load();
+ }
}
- public AltosMapCache cache() { return map.cache(); }
-
- public AltosMapLoader(AltosMap map, AltosMapLoaderListener listener) {
+ public AltosMapLoader(AltosMap map, AltosMapLoaderListener listener,
+ double latitude, double longitude, int min_z, int max_z, double radius, int all_types) {
+ listener.debug("lat %f lon %f min_z %d max_z %d radius %f all_types %d\n",
+ latitude, longitude, min_z, max_z, radius, all_types);
this.map = map;
this.listener = listener;
+ this.latitude = latitude;
+ this.longitude = longitude;
+ this.min_z = min_z;
+ this.max_z = max_z;
+ this.radius = radius;
+ this.all_types = all_types;
+ start();
}
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosMapLoaderListener {
public abstract void loader_start(int max);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.lang.Math;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.lang.Math;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.lang.Math;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosMapRectangle {
AltosLatLon ul, lr;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.net.*;
public synchronized void add_listener(AltosMapStoreListener listener) {
if (!listeners.contains(listener))
listeners.add(listener);
+ listener.notify_store(this, status);
}
public synchronized void remove_listener(AltosMapStoreListener listener) {
file.delete();
return AltosMapTile.bad_request;
}
- return AltosMapTile.success;
+ return AltosMapTile.fetched;
}
static Object fetch_lock = new Object();
static final long forbidden_interval = 60l * 1000l * 1000l * 1000l;
static final long google_maps_ratelimit_ms = 1200;
- static Object loader_lock = new Object();
+ static Object fetcher_lock = new Object();
static LinkedList<AltosMapStore> waiting = new LinkedList<AltosMapStore>();
static LinkedList<AltosMapStore> running = new LinkedList<AltosMapStore>();
- static final int concurrent_loaders = 128;
+ static final int concurrent_fetchers = 128;
- static void start_loaders() {
- while (!waiting.isEmpty() && running.size() < concurrent_loaders) {
+ static void start_fetchers() {
+ while (!waiting.isEmpty() && running.size() < concurrent_fetchers) {
AltosMapStore s = waiting.remove();
running.add(s);
- Thread lt = s.make_loader_thread();
+ Thread lt = s.make_fetcher_thread();
lt.start();
}
}
- void finish_loader() {
- synchronized(loader_lock) {
+ void finish_fetcher() {
+ synchronized(fetcher_lock) {
running.remove(this);
- start_loaders();
+ start_fetchers();
}
}
- void add_loader() {
- synchronized(loader_lock) {
+ void add_fetcher() {
+ synchronized(fetcher_lock) {
waiting.add(this);
- start_loaders();
+ start_fetchers();
}
}
- class loader implements Runnable {
+ class fetcher implements Runnable {
public void run() {
try {
if (file.exists()) {
- notify_listeners(AltosMapTile.success);
+ notify_listeners(AltosMapTile.fetched);
return;
}
synchronized (fetch_lock) {
long startTime = System.nanoTime();
new_status = fetch_url();
- if (new_status == AltosMapTile.success) {
+ if (new_status == AltosMapTile.fetched) {
long duration_ms = (System.nanoTime() - startTime) / 1000000;
if (duration_ms < google_maps_ratelimit_ms) {
try {
}
notify_listeners(new_status);
} finally {
- finish_loader();
+ finish_fetcher();
}
}
}
- private Thread make_loader_thread() {
- return new Thread(new loader());
+ private Thread make_fetcher_thread() {
+ return new Thread(new fetcher());
}
- private void load() {
- add_loader();
+ private void fetch() {
+ add_fetcher();
}
private AltosMapStore (String url, File file) {
this.file = file;
if (file.exists())
- status = AltosMapTile.success;
+ status = AltosMapTile.fetched;
else {
- status = AltosMapTile.loading;
- load();
+ status = AltosMapTile.fetching;
+ fetch();
}
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosMapStoreListener {
abstract void notify_store(AltosMapStore store, int status);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
-public abstract class AltosMapTile implements AltosFontListener {
- AltosMapTileListener listener;
+public abstract class AltosMapTile implements AltosFontListener, AltosMapStoreListener {
+ LinkedList<AltosMapTileListener> listeners = new LinkedList<AltosMapTileListener>();
public AltosLatLon upper_left, center;
public int px_size;
int zoom;
int maptype;
int scale;
+ private AltosMapCache cache;
public AltosMapStore store;
- public AltosMapCache cache;
public int status;
- static public final int success = 0;
- static public final int loading = 1;
- static public final int failed = 2;
- static public final int bad_request = 3;
- static public final int forbidden = 4;
+ static public final int loaded = 0; /* loaded from file */
+ static public final int fetched = 1; /* downloaded to file */
+ static public final int fetching = 2; /* downloading from net */
+ static public final int failed = 3; /* loading from file failed */
+ static public final int bad_request = 4;/* downloading failed */
+ static public final int forbidden = 5; /* downloading failed */
private File map_file() {
double lat = center.lat;
public void font_size_changed(int font_size) {
}
- public void set_status(int status) {
+ private synchronized void notify_listeners(int status) {
this.status = status;
- listener.notify_tile(this, status);
+ for (AltosMapTileListener listener : listeners)
+ listener.notify_tile(this, status);
}
- public void notify_image(AltosImage image) {
- listener.notify_tile(this, status);
+ public void notify_store(AltosMapStore store, int status) {
+// System.out.printf("AltosMapTile.notify_store %d\n", status);
+ notify_listeners(status);
}
- public int store_status() {
- return store.status();
+ public void notify_image(AltosImage image) {
+ if (image == null)
+ status = failed;
+ else
+ status = loaded;
+ notify_listeners(status);
}
- public void add_store_listener(AltosMapStoreListener listener) {
- store.add_listener(listener);
+ public abstract void paint(AltosMapTransform t);
+
+ public AltosImage get_image() {
+ if (cache == null)
+ return null;
+ return cache.get(this);
}
- public void remove_store_listener(AltosMapStoreListener listener) {
- store.remove_listener(listener);
+ public synchronized void add_listener(AltosMapTileListener listener) {
+ if (!listeners.contains(listener))
+ listeners.add(listener);
+ listener.notify_tile(this, status);
}
- public abstract void paint(AltosMapTransform t);
+ public synchronized void remove_listener(AltosMapTileListener listener) {
+ listeners.remove(listener);
+ }
- public AltosMapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size, int scale) {
- this.listener = listener;
+ public AltosMapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size, int scale) {
+ this.cache = cache;
this.upper_left = upper_left;
- this.cache = listener.cache();
while (center.lon < -180.0)
center.lon += 360.0;
this.px_size = px_size;
this.scale = scale;
- status = AltosMapTile.loading;
store = AltosMapStore.get(map_url(), map_file());
+ store.add_listener(this);
}
- public AltosMapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
- this(listener, upper_left, center, zoom, maptype, px_size, 1);
+ public AltosMapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
+ this(cache, upper_left, center, zoom, maptype, px_size, 1);
}
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosMapTileListener {
abstract public void notify_tile(AltosMapTile tile, int status);
-
- abstract public AltosMapCache cache();
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.lang.Math;
--- /dev/null
+/*
+ * Copyright © 2012 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 org.altusmetrum.altoslib_10;
+
+public interface AltosMapTypeListener {
+ public void map_type_changed(int map_type);
+}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosMapZoomListener {
abstract public void zoom_changed(int zoom);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.*;
public class AltosMma655x implements Cloneable {
- int accel;
+ private int accel;
public boolean parse_line(String line) throws NumberFormatException {
if (line.startsWith("MMA655X value")) {
return n;
}
- static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException {
+ static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException, AltosUnknownProduct {
try {
AltosMma655x mma655x = new AltosMma655x(link);
- if (mma655x != null)
- state.set_accel(mma655x.accel);
+ if (mma655x != null) {
+ int accel = mma655x.accel;
+ if (config_data.mma655x_inverted())
+ accel = 4095 - accel;
+ if (config_data.pad_orientation == 1)
+ accel = 4095 - accel;
+ state.set_accel(accel);
+ }
} catch (TimeoutException te) {
} catch (NumberFormatException ne) {
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.*;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosNoSymbol extends Exception {
public AltosNoSymbol(String name) {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosOrient extends AltosUnits {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.*;
import java.text.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosPointDouble {
public double x, y;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosPointInt {
public int x, y;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
public final static String frequency_count = "COUNT";
public final static String frequency_format = "FREQUENCY-%d";
public final static String description_format = "DESCRIPTION-%d";
+ public final static String frequenciesPreference = "FREQUENCIES";
/* Units preference */
public static int map_cache = 9;
+ final static String mapTypePreference = "MAP-TYPE";
+ static int map_type;
+
public static AltosFrequency[] load_common_frequencies() {
+
AltosFrequency[] frequencies = null;
- boolean existing = false;
- existing = backend.nodeExists(common_frequencies_node_name);
- if (existing) {
- AltosPreferencesBackend node = backend.node(common_frequencies_node_name);
- int count = node.getInt(frequency_count, 0);
+ frequencies = (AltosFrequency[]) backend.getSerializable(frequenciesPreference, null);
+
+ if (frequencies == null) {
+ if (backend.nodeExists(common_frequencies_node_name)) {
+ AltosPreferencesBackend node = backend.node(common_frequencies_node_name);
+ int count = node.getInt(frequency_count, 0);
- frequencies = new AltosFrequency[count];
- for (int i = 0; i < count; i++) {
- double frequency;
- String description;
+ frequencies = new AltosFrequency[count];
+ for (int i = 0; i < count; i++) {
+ double frequency;
+ String description;
- frequency = node.getDouble(String.format(frequency_format, i), 0.0);
- description = node.getString(String.format(description_format, i), null);
- frequencies[i] = new AltosFrequency(frequency, description);
+ frequency = node.getDouble(String.format(frequency_format, i), 0.0);
+ description = node.getString(String.format(description_format, i), null);
+ frequencies[i] = new AltosFrequency(frequency, description);
+ }
}
- } else {
+ }
+
+ if (frequencies == null) {
frequencies = new AltosFrequency[10];
for (int i = 0; i < 10; i++) {
frequencies[i] = new AltosFrequency(434.550 + i * .1,
return frequencies;
}
- public static void save_common_frequencies(AltosFrequency[] frequencies) {
- AltosPreferencesBackend node = backend.node(common_frequencies_node_name);
-
- node.putInt(frequency_count, frequencies.length);
- for (int i = 0; i < frequencies.length; i++) {
- node.putDouble(String.format(frequency_format, i), frequencies[i].frequency);
- node.putString(String.format(description_format, i), frequencies[i].description);
- }
- }
public static int launcher_serial;
public static int launcher_channel;
map_cache = backend.getInt(mapCachePreference, 9);
map_cache_listeners = new LinkedList<AltosMapCacheListener>();
+ map_type = backend.getInt(mapTypePreference, AltosMap.maptype_hybrid);
}
public static void flush_preferences() {
}
}
- public static void set_state(int serial, AltosState state, AltosListenerState listener_state) {
-
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
-
- try {
- ObjectOutputStream oos = new ObjectOutputStream(baos);
+ public static void set_state(AltosState state) {
- AltosSavedState saved_state = new AltosSavedState(state, listener_state);
- oos.writeObject(saved_state);
-
- byte[] bytes = baos.toByteArray();
-
- synchronized(backend) {
- backend.putBytes(String.format(statePreferenceFormat, serial), bytes);
- backend.putInt(statePreferenceLatest, serial);
- flush_preferences();
- }
- } catch (IOException ie) {
+ synchronized(backend) {
+ backend.putSerializable(String.format(statePreferenceFormat, state.serial), state);
+ backend.putInt(statePreferenceLatest, state.serial);
+ flush_preferences();
}
}
return latest;
}
- public static AltosSavedState state(int serial) {
- byte[] bytes = null;
-
+ public static AltosState state(int serial) {
synchronized(backend) {
- bytes = backend.getBytes(String.format(statePreferenceFormat, serial), null);
- }
-
- if (bytes == null)
- return null;
-
- ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
-
- try {
- ObjectInputStream ois = new ObjectInputStream(bais);
- AltosSavedState saved_state = (AltosSavedState) ois.readObject();
- return saved_state;
- } catch (IOException ie) {
- } catch (ClassNotFoundException ce) {
+ try {
+ return (AltosState) backend.getSerializable(String.format(statePreferenceFormat, serial), null);
+ } catch (Exception e) {
+ return null;
+ }
}
- return null;
}
public static void set_scanning_telemetry(int new_scanning_telemetry) {
public static void set_common_frequencies(AltosFrequency[] frequencies) {
synchronized(backend) {
common_frequencies = frequencies;
- save_common_frequencies(frequencies);
+ backend.putSerializable(frequenciesPreference, frequencies);
flush_preferences();
}
}
return map_cache;
}
}
+
+ static LinkedList<AltosMapTypeListener> map_type_listeners;
+
+ public static void set_map_type(int map_type) {
+ synchronized(backend) {
+ AltosPreferences.map_type = map_type;
+ backend.putInt(mapTypePreference, map_type);
+ flush_preferences();
+ }
+ if (map_type_listeners != null) {
+ for (AltosMapTypeListener l : map_type_listeners) {
+ l.map_type_changed(map_type);
+ }
+ }
+ }
+
+ public static int map_type() {
+ synchronized(backend) {
+ return map_type;
+ }
+ }
+
+ public static void register_map_type_listener(AltosMapTypeListener l) {
+ synchronized(backend) {
+ if (map_type_listeners == null)
+ map_type_listeners = new LinkedList<AltosMapTypeListener>();
+ map_type_listeners.add(l);
+ }
+ }
+
+ public static void unregister_map_type_listener(AltosMapTypeListener l) {
+ synchronized(backend) {
+ map_type_listeners.remove(l);
+ }
+ }
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
-import java.io.File;
+import java.io.*;
+import java.util.*;
+import java.text.*;
-public interface AltosPreferencesBackend {
+public abstract class AltosPreferencesBackend {
- public String getString(String key, String def);
- public void putString(String key, String value);
+ public abstract String getString(String key, String def);
+ public abstract void putString(String key, String value);
- public int getInt(String key, int def);
- public void putInt(String key, int value);
+ public abstract int getInt(String key, int def);
+ public abstract void putInt(String key, int value);
- public double getDouble(String key, double def);
- public void putDouble(String key, double value);
+ public abstract double getDouble(String key, double def);
+ public abstract void putDouble(String key, double value);
- public boolean getBoolean(String key, boolean def);
- public void putBoolean(String key, boolean value);
+ public abstract boolean getBoolean(String key, boolean def);
+ public abstract void putBoolean(String key, boolean value);
- public byte[] getBytes(String key, byte[] def);
- public void putBytes(String key, byte[] value);
+ public abstract byte[] getBytes(String key, byte[] def);
+ public abstract void putBytes(String key, byte[] value);
- public boolean nodeExists(String key);
- public AltosPreferencesBackend node(String key);
+ public Serializable getSerializable(String key, Serializable def) {
+ byte[] bytes = null;
- public String[] keys();
- public void remove(String key);
+ bytes = getBytes(key, null);
+ if (bytes == null)
+ return def;
- public void flush();
+ ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
- public File homeDirectory();
+ try {
+ ObjectInputStream ois = new ObjectInputStream(bais);
+ Serializable object = (Serializable) ois.readObject();
+ return object;
+ } catch (IOException ie) {
+ debug("IO exception %s\n", ie.toString());
+ } catch (ClassNotFoundException ce) {
+ debug("ClassNotFoundException %s\n", ce.toString());
+ }
+ return def;
+ }
+
+ public void putSerializable(String key, Serializable object) {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ try {
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+
+ oos.writeObject(object);
+ byte[] bytes = baos.toByteArray();
+
+ putBytes(key, bytes);
+ } catch (IOException ie) {
+ debug("set_state failed %s\n", ie.toString());
+ }
+ }
+
+ public abstract boolean nodeExists(String key);
+ public abstract AltosPreferencesBackend node(String key);
+
+ public abstract String[] keys();
+ public abstract void remove(String key);
+
+ public abstract void flush();
+
+ public abstract File homeDirectory();
+
+ public abstract void debug(String format, Object ... arguments);
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.*;
import java.text.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosQuaternion {
double r; /* real bit */
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosRectangle {
public int x, y, width, height;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosRotation {
private AltosQuaternion rotation;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.TimeoutException;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.TimeoutException;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.TimeoutException;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.TimeoutException;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.TimeoutException;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.TimeoutException;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.TimeoutException;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosSpeed extends AltosUnits {
public double value(double v, boolean imperial_units) {
if (imperial_units)
- return AltosConvert.meters_to_mph(v);
+ return AltosConvert.mps_to_fps(v);
return v;
}
public double inverse(double v, boolean imperial_units) {
if (imperial_units)
- return AltosConvert.mph_to_meters(v);
+ return AltosConvert.fps_to_mps(v);
return v;
}
public String show_units(boolean imperial_units) {
if (imperial_units)
- return "mph";
+ return "fps";
return "m/s";
}
public String say_units(boolean imperial_units) {
if (imperial_units)
- return "miles per hour";
+ return "feet per second";
return "meters per second";
}
public int show_fraction(int width, boolean imperial_units) {
return width / 9;
}
-}
\ No newline at end of file
+}
* Track flight state from telemetry or eeprom data stream
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosStateUpdate {
- public void update_state(AltosState state) throws InterruptedException;
-}
\ No newline at end of file
+ public void update_state(AltosState state) throws InterruptedException, AltosUnknownProduct;
+}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.text.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetryCompanion extends AltosTelemetryStandard {
AltosCompanion companion;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetryConfiguration extends AltosTelemetryStandard {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.text.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetryLocation extends AltosTelemetryStandard {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.text.*;
import java.util.HashMap;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetryMegaData extends AltosTelemetryStandard {
int state;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetryMegaSensor extends AltosTelemetryStandard {
int accel;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetryMetrumData extends AltosTelemetryStandard {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetryMetrumSensor extends AltosTelemetryStandard {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetryMini extends AltosTelemetryStandard {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetryRaw extends AltosTelemetryStandard {
public AltosTelemetryRaw(int[] bytes) {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.text.*;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetrySatellite extends AltosTelemetryStandard {
int channels;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetrySensor extends AltosTelemetryStandard {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public abstract class AltosTelemetryStandard extends AltosTelemetry {
int[] bytes;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTemperature extends AltosUnits {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.text.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosUnitsListener {
public void units_changed(boolean imperial_units);
--- /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 org.altusmetrum.altoslib_10;
+
+public class AltosUnknownProduct extends Exception {
+ public String product;
+
+ public AltosUnknownProduct (String in_product) {
+ product = in_product;
+ }
+}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosVersion {
public final static String version = "@VERSION@";
- public final static String google_maps_api_key = @GOOGLEKEY@;
+ public final static String google_maps_api_key = "@GOOGLEKEY@";
public static boolean has_google_maps_api_key() {
return google_maps_api_key != null && google_maps_api_key.length() > 1;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosVoltage extends AltosUnits {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosWriter {
AltosEepromDownload.java \
AltosEepromFile.java \
AltosEepromTM.java \
- AltosEepromTm.java \
+ AltosEepromTMini.java \
AltosEepromHeader.java \
AltosEepromIterable.java \
AltosEepromList.java \
AltosTelemetrySatellite.java \
AltosTelemetryStandard.java \
AltosUnitsListener.java \
+ AltosUnknownProduct.java \
AltosMs5607.java \
AltosIMU.java \
AltosMag.java \
AltosLaunchSites.java \
AltosMapLoaderListener.java \
AltosMapLoader.java \
+ AltosMapTypeListener.java \
AltosVersion.java
JAR=altoslib_$(ALTOSLIB_VERSION).jar
import java.awt.*;
import libaltosJNI.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class Altos extends AltosUILib {
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosAscent extends AltosUIFlightTab {
JLabel cur, max;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosCompanionInfo extends JTable implements AltosFlightDisplay {
private AltosFlightInfoTableModel model;
import java.io.*;
import java.util.concurrent.*;
import java.text.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosConfig implements ActionListener {
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosConfigPyroUI
extends AltosUIDialog
import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosConfigTD implements ActionListener {
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosConfigTDUI
extends AltosUIDialog
import javax.swing.*;
import javax.swing.event.*;
import java.text.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosConfigUI
extends AltosUIDialog
JComboBox<String> apogee_delay_value;
JComboBox<String> apogee_lockout_value;
AltosUIFreqList radio_frequency_value;
- JTextField radio_calibration_value;
+ JLabel radio_calibration_value;
JRadioButton radio_enable_value;
AltosUIRateList rate_value;
JComboBox<String> aprs_interval_value;
return product != null && product.startsWith("TeleMetrum");
}
- void set_radio_calibration_tool_tip() {
- if (radio_calibration_value.isEnabled())
- radio_calibration_value.setToolTipText("Tune radio output to match desired frequency");
- else
- radio_calibration_value.setToolTipText("Cannot tune radio while connected over packet mode");
- }
-
void set_radio_enable_tool_tip() {
if (radio_enable_value.isEnabled())
radio_enable_value.setToolTipText("Enable/Disable telemetry and RDF transmissions");
c.anchor = GridBagConstraints.LINE_START;
c.insets = ir;
c.ipady = 5;
- radio_calibration_value = new JTextField(String.format("%d", 1186611));
- radio_calibration_value.getDocument().addDocumentListener(this);
- if (remote)
- radio_calibration_value.setEnabled(false);
+ radio_calibration_value = new JLabel(String.format("%d", 1186611));
pane.add(radio_calibration_value, c);
- set_radio_calibration_tool_tip();
row++;
/* Radio Enable */
radio_calibration_value.setText(String.format("%d", new_radio_calibration));
}
- public int radio_calibration() throws AltosConfigDataException {
- return parse_int("radio calibration", radio_calibration_value.getText(), false);
- }
-
public void set_radio_enable(int new_radio_enable) {
radio_enable_label.setVisible(new_radio_enable >= 0);
radio_enable_value.setVisible(new_radio_enable >= 0);
import java.beans.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosConfigureUI
extends AltosUIConfigure
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosDescent extends AltosUIFlightTab {
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosFlightStatus extends JComponent implements AltosFlightDisplay {
GridBagLayout layout;
import java.text.*;
import java.util.prefs.*;
import java.util.concurrent.LinkedBlockingQueue;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosFlightStatusTableModel extends AbstractTableModel {
private String[] columnNames = {
package altosui;
import java.awt.event.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosFlightStatusUpdate implements ActionListener {
import javax.swing.*;
import java.util.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay {
AltosVoice voice;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import java.io.*;
import java.util.concurrent.*;
import java.util.Arrays;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDisplay, AltosIdleMonitorListener, DocumentListener {
AltosDevice device;
SwingUtilities.invokeLater(r);
}
+ public void error(final String reason) {
+ Runnable r = new Runnable() {
+ public void run() {
+ disconnect();
+ JOptionPane.showMessageDialog(AltosIdleMonitorUI.this,
+ reason,
+ "Error fetching data",
+ JOptionPane.ERROR_MESSAGE);
+ }
+ };
+ SwingUtilities.invokeLater(r);
+ }
+
Container bag;
AltosUIFreqList frequencies;
JTextField callsign_value;
import java.text.*;
import java.util.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosIgniteUI
extends AltosUIDialog
int time_remaining;
boolean timer_running;
+ int poll_remaining;
+
LinkedBlockingQueue<String> command_queue;
class Igniter {
void set_ignite_status() {
getting_status = false;
+ poll_remaining = 2;
if (!visible) {
visible = true;
setVisible(true);
}
void poll_ignite_status() {
+ if (poll_remaining > 0) {
+ --poll_remaining;
+ return;
+ }
if (!getting_status) {
getting_status = true;
send_command("get_status");
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosIgnitor extends AltosUIFlightTab {
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosLanded extends AltosUIFlightTab implements ActionListener {
import java.io.*;
import java.util.concurrent.*;
import java.awt.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosLaunch {
AltosDevice device;
import java.io.*;
import java.text.*;
import java.util.concurrent.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
class FireButton extends JButton {
protected void processMouseEvent(MouseEvent e) {
package altosui;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosPad extends AltosUIFlightTab {
import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosUI extends AltosUIFrame {
public AltosVoice voice = new AltosVoice();
; Definitions for Java Detection
-!define JRE_VERSION "1.6"
-!define JRE32_URL "http://javadl.sun.com/webapps/download/AutoDL?BundleId=52247&/jre-6u27-windows-i586.exe"
-!define JRE64_URL "http://javadl.sun.com/webapps/download/AutoDL?BundleId=52249&/jre-6u27-windows-x64.exe"
-
-Var JavaDownload
-Var JavaBits
+!define JAVA_VERSION "6.0"
+
+Function GetFileVersion
+ !define GetFileVersion `!insertmacro GetFileVersionCall`
+
+ !macro GetFileVersionCall _FILE _RESULT
+ Push `${_FILE}`
+ Call GetFileVersion
+ Pop ${_RESULT}
+ !macroend
+
+ Exch $0
+ Push $1
+ Push $2
+ Push $3
+ Push $4
+ Push $5
+ Push $6
+ ClearErrors
+
+ GetDllVersion '$0' $1 $2
+ IfErrors error
+ IntOp $3 $1 >> 16
+ IntOp $3 $3 & 0x0000FFFF
+ IntOp $4 $1 & 0x0000FFFF
+ IntOp $5 $2 >> 16
+ IntOp $5 $5 & 0x0000FFFF
+ IntOp $6 $2 & 0x0000FFFF
+ StrCpy $0 '$3.$4.$5.$6'
+ goto end
+
+ error:
+ SetErrors
+ StrCpy $0 ''
+
+ end:
+ Pop $6
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Exch $0
+FunctionEnd
-Function GetJRE
- ${If} ${RunningX64}
- StrCpy $JavaDownload ${JRE64_URL}
- StrCpy $JavaBits "64"
- ${Else}
- StrCpy $JavaDownload ${JRE32_URL}
- StrCpy $JavaBits "32"
- ${EndIf}
-
- MessageBox MB_OK "This product uses Java ${JRE_VERSION}, \
- $JavaBits bits, it will now \
- be downloaded and installed"
-
- StrCpy $2 "$TEMP\Java Runtime Environment.exe"
- nsisdl::download /TIMEOUT=30000 $JavaDownload $2
- Pop $R0 ;Get the return value
- StrCmp $R0 "success" +3
- MessageBox MB_OK "Download failed: $R0"
- Quit
- ExecWait $2
- Delete $2
+Function openLinkNewWindow
+ Push $3
+ Exch
+ Push $2
+ Exch
+ Push $1
+ Exch
+ Push $0
+ Exch
+
+ ReadRegStr $1 HKCU "Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.html\UserChoice" "Progid"
+ IfErrors iexplore
+
+ Goto foundbrowser
+iexplore:
+ StrCpy $1 "IE.AssocFile.HTM"
+
+foundbrowser:
+
+ StrCpy $2 "\shell\open\command"
+
+ StrCpy $3 $1$2
+
+ ReadRegStr $0 HKCR $3 ""
+
+# Get browser path
+ DetailPrint $0
+
+ StrCpy $2 '"'
+ StrCpy $1 $0 1
+ StrCmp $1 $2 +2 # if path is not enclosed in " look for space as final char
+ StrCpy $2 ' '
+ StrCpy $3 1
+ loop:
+ StrCpy $1 $0 1 $3
+ DetailPrint $1
+ StrCmp $1 $2 found
+ StrCmp $1 "" found
+ IntOp $3 $3 + 1
+ Goto loop
+
+ found:
+ StrCpy $1 $0 $3
+ StrCmp $2 " " +2
+ StrCpy $1 '$1"'
+
+ Pop $0
+ Exec '$1 $0'
+ Pop $0
+ Pop $1
+ Pop $2
+ Pop $3
FunctionEnd
+
+!macro _OpenURL URL
+Push "${URL}"
+Call openLinkNewWindow
+!macroend
+
+!define OpenURL '!insertmacro "_OpenURL"'
Function DoDetectJRE
- DetailPrint "Desired Java version ${JRE_VERSION}"
-
- ; Check in HKCU for CurrentVersion
-
- ClearErrors
- ReadRegStr $2 HKCU "SOFTWARE\JavaSoft\Java Runtime Environment" \
- "CurrentVersion"
-
- IfErrors hkcuwow_version
-
- DetailPrint "HKEY_CURRENT_USER Java version $2"
-
- ${VersionCompare} $2 ${JRE_VERSION} $3
-
- IntCmp $3 1 yes yes no
-
-hkcuwow_version:
-
- ; Check in HKCU Wow6432Node for CurrentVersion
-
- ClearErrors
- ReadRegStr $2 HKCU "SOFTWARE\Wow6432Node\JavaSoft\Java Runtime Environment" \
- "CurrentVersion"
-
- Iferrors hklm_version
-
- DetailPrint "HKEY_CURRENT_USER Wow6432Node Java version $2"
+ DetailPrint "Desired Java version ${JAVA_VERSION}"
- ${VersionCompare} $2 ${JRE_VERSION} $3
-
- IntCmp $3 1 yes yes no
-
-hklm_version:
-
- ; Check in HKLM for CurrentVersion
-
- ClearErrors
- ReadRegStr $2 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment" \
- "CurrentVersion"
+ SearchPath $0 javaw.exe
+ IfErrors no
- IfErrors hklmwow_version
-
- DetailPrint "HKEY_LOCAL_MACHINE Java version $2"
-
- ${VersionCompare} $2 ${JRE_VERSION} $3
-
- IntCmp $3 1 yes yes no
-
-hklmwow_version:
-
- ; Check in HKLM Wow6432Node for CurrentVersion
-
- ClearErrors
- ReadRegStr $2 HKLM "SOFTWARE\Wow6432Node\JavaSoft\Java Runtime Environment" \
- "CurrentVersion"
-
- Iferrors hkcu_any
-
- DetailPrint "HKEY_LOCAL_MACHINE Wow6432Node Java version $2"
-
- ${VersionCompare} $2 ${JRE_VERSION} $3
+ DetailPrint "Detected java in $0"
- IntCmp $3 1 yes yes no
+ ${GetFileVersion} "$0" $1
+ IfErrors no
-hkcu_any:
+ DetailPrint "Java version $1"
- ; Check in HKCU for any Java install
-
- StrCpy $0 0
-
-hkcu_any_loop:
- EnumRegKey $1 HKCU "SOFTWARE\JavaSoft" $0
-
- StrCmp $1 "Java Runtime Environment" found_hkcu
-
- StrCmp $1 "" hklm_any
-
- IntOp $0 $0 + 1
-
- Goto hkcu_any_loop
-
-found_hkcu:
-
- DetailPrint "HKEY_CURRENT_USER has SOFTWARE\JavaSoft\$1"
-
- Goto maybe
-
-hklm_any:
-
- ; Check in HKCU for any Java install
-
- StrCpy $0 0
-
-hklm_any_loop:
- EnumRegKey $1 HKLM "SOFTWARE\JavaSoft" $0
-
- StrCmp $1 "Java Runtime Environment" found_hklm
-
- StrCmp $1 "" no
-
- IntOp $0 $0 + 1
-
- Goto hklm_any_loop
-
-found_hklm:
-
- DetailPrint "HKEY_CURRENT_USER has SOFTWARE\JavaSoft\$1"
-
- Goto maybe
+ ${VersionCompare} $1 ${JAVA_VERSION} $2
+ IntCmp $2 1 yes yes old
yes:
StrCpy $0 2
Goto done
-maybe:
+old:
StrCpy $0 1
Goto done
var quit
var skip
+Function GetJRE
+ ${OpenURL} "java.com"
+ MessageBox MB_OK "Click OK to continue after completing the Java Install."
+FunctionEnd
+
Function DetectJRE
Call DoDetectJRE
- IntCmp $0 1 ask_maybe ask_no yes
+ IntCmp $0 1 ask_old ask_no yes
ask_no:
- StrCpy $0 "No Java detected. Download and install?"
+ StrCpy $0 "Cannot find Java. Download and install?"
Goto ask
-ask_maybe:
- StrCpy $0 "Cannot determine installed Java version. Download and install?"
+ask_old:
+ StrCpy $0 "Java version appears to be too old. Download and install?"
Goto ask
ask:
MessageBox MB_YESNOCANCEL $0 IDYES do_java IDNO skip_java
-bail:
- Abort
-
do_java:
Call GetJRE
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import libaltosJNI.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosBTDevice extends altos_bt_device implements AltosDevice {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.util.*;
import libaltosJNI.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosBTDeviceIterator implements Iterator<AltosBTDevice> {
AltosBTDevice current;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosBTKnown implements Iterable<AltosBTDevice> {
LinkedList<AltosBTDevice> devices = new LinkedList<AltosBTDevice>();
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
import javax.swing.plaf.basic.*;
import java.util.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosBTManage extends AltosUIDialog implements ActionListener, Iterable<AltosBTDevice> {
LinkedBlockingQueue<AltosBTDevice> found_devices;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosCSVUI
extends AltosUIDialog
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.text.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
class AltosEditFreqUI extends AltosUIDialog implements ActionListener {
Frame frame;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.io.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosDataChooser extends JFileChooser {
JFrame frame;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import libaltosJNI.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import javax.swing.*;
import java.awt.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import javax.swing.*;
import java.awt.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import javax.swing.*;
import java.io.*;
import java.text.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosDisplayThread extends Thread {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosEepromDelete implements Runnable {
AltosEepromList flights;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosEepromManage implements ActionListener {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMonitor {
JFrame owner;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
class AltosEepromItem implements ActionListener {
AltosEepromLog log;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.io.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosFlashUI
extends AltosUIDialog
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import javax.swing.table.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import javax.swing.*;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosFlightStatsTable extends JComponent implements AltosFontListener {
GridBagLayout layout;
}
new FlightStat(layout, y++, "Maximum speed",
String.format("%5.0f m/s", stats.max_speed),
- String.format("%5.0f mph", AltosConvert.meters_to_mph(stats.max_speed)),
+ String.format("%5.0f fps", AltosConvert.mps_to_fps(stats.max_speed)),
String.format("Mach %4.1f", AltosConvert.meters_to_mach(stats.max_speed)));
- if (stats.max_acceleration != AltosLib.MISSING) {
+ if (stats.max_acceleration != AltosLib.MISSING)
new FlightStat(layout, y++, "Maximum boost acceleration",
String.format("%5.0f m/s²", stats.max_acceleration),
String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.max_acceleration)),
String.format("%5.0f G", AltosConvert.meters_to_g(stats.max_acceleration)));
+ if (stats.state_accel[AltosLib.ao_flight_boost] != AltosLib.MISSING)
new FlightStat(layout, y++, "Average boost acceleration",
String.format("%5.0f m/s²", stats.state_accel[AltosLib.ao_flight_boost]),
String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.state_accel[AltosLib.ao_flight_boost])),
String.format("%5.0f G", AltosConvert.meters_to_g(stats.state_accel[AltosLib.ao_flight_boost])));
- }
if (stats.state_speed[AltosLib.ao_flight_drogue] != AltosLib.MISSING)
new FlightStat(layout, y++, "Drogue descent rate",
String.format("%5.0f m/s", stats.state_speed[AltosLib.ao_flight_drogue]),
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosGraphDataPoint implements AltosUIDataPoint {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.lang.*;
import java.io.*;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
class AltosGraphIterator implements Iterator<AltosUIDataPoint> {
AltosGraphDataSet dataSet;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosInfoTable extends JTable implements AltosFlightDisplay, HierarchyListener {
private AltosFlightInfoTableModel model;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import javax.swing.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import javax.swing.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
public interface AltosPositionListener {
public void position_changed(int position);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosRomconfigUI
extends AltosUIDialog
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.text.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
class AltosScanResult {
String callsign;
* Deal with TeleDongle on a serial port
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.io.*;
import java.util.*;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import libaltosJNI.*;
/*
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
public class AltosSerialInUseException extends Exception {
public AltosDevice device;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
class DelegatingRenderer implements ListCellRenderer<Object> {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
public class AltosUIDataMissing extends Exception {
public int id;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
public interface AltosUIDataPoint {
public abstract double x() throws AltosUIDataMissing;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
public interface AltosUIDataSet {
public abstract String name();
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public abstract class AltosUIFlightTab extends JComponent implements AltosFlightDisplay, HierarchyListener {
public GridBagLayout layout;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosUIFreqList extends JComboBox<AltosFrequency> {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import javax.swing.*;
import javax.imageio.ImageIO;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public abstract class AltosUIIndicator implements AltosFontListener, AltosUnitsListener {
JLabel label;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import libaltosJNI.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosUILib extends AltosLib {
String OS = System.getProperty("os.name");
- if (OS.startsWith("Linux")) {
+ if (OS.startsWith("L") || OS.startsWith("W"))
has_bluetooth = true;
- }
initialized = true;
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
public interface AltosUIListener {
public void ui_changed(String look_and_feel);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.concurrent.*;
import javax.imageio.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosUIMapNew extends JComponent implements AltosFlightDisplay, AltosMapInterface {
}
class MapTile extends AltosMapTile {
- public MapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
- super(listener, upper_left, center, zoom, maptype, px_size);
+ public MapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
+ super(cache, upper_left, center, zoom, maptype, px_size);
}
public void paint(AltosMapTransform t) {
if (!g.hitClip(point.x, point.y, px_size, px_size))
return;
- AltosImage altos_image = cache.get(this, store, px_size, px_size);
-
+ AltosImage altos_image = get_image();
AltosUIImage ui_image = (AltosUIImage) altos_image;
-
- Image image = null;
+ Image image = null;
if (ui_image != null)
image = ui_image.image;
if (t.has_location()) {
String message = null;
switch (status) {
- case AltosMapTile.loading:
- message = "Loading...";
+ case AltosMapTile.fetching:
+ message = "Fetching...";
break;
case AltosMapTile.bad_request:
message = "Internal error";
return new MapMark(lat, lon, state);
}
- public AltosMapTile new_tile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
- return new MapTile(listener, upper_left, center, zoom, maptype, px_size);
+ public AltosMapTile new_tile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
+ return new MapTile(cache, upper_left, center, zoom, maptype, px_size);
}
public int width() {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
import java.lang.Math;
import java.net.URL;
import java.net.URLConnection;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
class AltosUIMapPos extends Box {
AltosUIFrame owner;
JProgressBar pbar;
- AltosMapLoader loader;
-
JLabel site_list_label;
JComboBox<AltosLaunchSite> site_list;
}
public void debug(String format, Object ... arguments) {
- System.out.printf(format, arguments);
+ if (AltosSerial.debug)
+ System.out.printf(format, arguments);
}
r = r * 1000;
loading = true;
- loader.load(latitude, longitude, min_z, max_z, r, all_types());
+ new AltosMapLoader(map.map, this,
+ latitude, longitude,
+ min_z, max_z, r, all_types());
+
} catch (ParseException pe) {
load_button.setSelected(false);
}
map = new AltosUIMapNew();
- loader = new AltosMapLoader(map.map, this);
-
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.CENTER;
c.insets = i;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.io.*;
import java.util.*;
import java.awt.Component;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosUIPreferences extends AltosPreferences {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.io.File;
import java.util.prefs.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import javax.swing.filechooser.FileSystemView;
-public class AltosUIPreferencesBackend implements AltosPreferencesBackend {
+public class AltosUIPreferencesBackend extends AltosPreferencesBackend {
private Preferences _preferences = null;
/* Use the file system view default directory */
return FileSystemView.getFileSystemView().getDefaultDirectory();
}
+
+ public void debug(String format, Object ... arguments) {
+ System.out.printf(format, arguments);
+ }
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosUIRateList extends JComboBox<String> {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.util.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosUITelemetryList extends JComboBox<String> {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public abstract class AltosUIUnitsIndicator extends AltosUIIndicator {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public abstract class AltosUIVoltageIndicator extends AltosUIUnitsIndicator {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.util.*;
import libaltosJNI.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import com.sun.speech.freetts.Voice;
import com.sun.speech.freetts.VoiceManager;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.lang.reflect.*;
import java.util.HashMap;
;;
esac
-../ao-tools/ao-cal-freq/ao-cal-freq --dev=$dev
+../ao-tools/ao-cal-freq/ao-cal-freq --tty=$dev
case $? in
0)
calline=`./get-radio-cal $dev`
echo""
echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
+ echo "\007"
ret=0
;;
esac
--- /dev/null
+#!/bin/sh
+
+if [ -x /usr/bin/dfu-util ]; then
+ DFU_UTIL=/usr/bin/dfu-util
+else
+ echo "Can't find dfu-util! Aborting."
+ exit 1
+fi
+
+if [ -x /usr/bin/ao-usbload ]; then
+ USBLOAD=/usr/bin/ao-usbload
+else
+ echo "Can't find ao-usbload! Aborting."
+ exit 1
+fi
+
+VERSION=1.0
+PRODUCT=ChaosKey
+
+echo "ChaosKey v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2015 by Keith Packard. Released under GPL v2"
+echo
+echo "Expectations:"
+echo "\tChaosKey v$VERSION powered from USB"
+echo
+
+$DFU_UTIL -a 0 -s 0x08000000:leave -D ../src/chaoskey-v$VERSION/flash-loader/chaoskey-v$VERSION*.bin || exit 1
+
+sleep 2
+
+$USBLOAD --serial=1 ../src/chaoskey-v$VERSION/chaoskey-v$VERSION*.ihx || exit 1
+
+exit $?
ao-dumpflash ao-edit-telem ao-dump-up ao-elftohex \
ao-flash ao-usbload ao-test-igniter ao-test-baro \
ao-test-flash ao-cal-accel ao-test-gps ao-usbtrng \
- ao-cal-freq
+ ao-cal-freq ao-chaosread ao-makebin
if LIBSTLINK
SUBDIRS += ao-stmload
endif
--- /dev/null
+ao-chaosread
--- /dev/null
+bin_PROGRAMS=ao-chaosread
+
+AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+
+ao_chaosread_LDADD=$(LIBUSB_LIBS)
+
+ao_chaosread_SOURCES = ao-chaosread.c
+
+man_MANS = ao-chaosread.1
--- /dev/null
+.\"
+.\" Copyright © 2016 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; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" 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.
+.\"
+.\"
+.TH AO-LOAD 1 "ao-chaosread" ""
+.SH NAME
+ao-chaosread \- read raw noise source from chaoskey
+.SH SYNOPSIS
+.B "ao-chaosread"
+.SH DESCRIPTION
+.I ao-chaosread
+reads ADC values from the noise source on the attached ChaosKey device.
+.SH OPTIONS
+.TP
+\-s serial | --serial serial
+This selects a ChaosKey by serial number instead of using the first
+one found.
+.SH USAGE
+.I ao-chaosread
+reads noise data.
+.SH AUTHOR
+Keith Packard
--- /dev/null
+/*
+ * Copyright © 2016 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 <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <libusb.h>
+#include <getopt.h>
+#include <string.h>
+#include <strings.h>
+
+#define CHAOS_SIZE 64
+
+#define CHAOS_VENDOR 0x1d50
+#define CHAOS_PRODUCT 0x60c6
+
+struct chaoskey {
+ libusb_context *ctx;
+ libusb_device_handle *handle;
+ int kernel_active;
+};
+
+libusb_device_handle *
+chaoskey_match(libusb_device *dev, char *match_serial)
+{
+ struct libusb_device_descriptor desc;
+ int ret;
+ int match_len;
+ char *device_serial = NULL;
+ libusb_device_handle *handle = NULL;
+
+ ret = libusb_get_device_descriptor(dev, &desc);
+ if (ret < 0) {
+ fprintf(stderr, "failed to get device descriptor: %s\n", libusb_strerror(ret));
+ return 0;
+ }
+
+ if (desc.idVendor != CHAOS_VENDOR)
+ return NULL;
+ if (desc.idProduct != CHAOS_PRODUCT)
+ return NULL;
+
+ ret = libusb_open(dev, &handle);
+
+ if (match_serial == NULL)
+ return handle;
+
+ if (ret < 0) {
+ fprintf(stderr, "failed to open device: %s\n", libusb_strerror(ret));
+ return NULL;
+ }
+
+ match_len = strlen(match_serial);
+ device_serial = malloc(match_len + 2);
+
+ if (!device_serial) {
+ fprintf(stderr, "malloc failed\n");
+ goto out;
+ }
+
+ ret = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, device_serial, match_len + 1);
+
+ if (ret < 0) {
+ fprintf(stderr, "failed to get serial number: %s\n", libusb_strerror(ret));
+ goto out;
+ }
+
+ device_serial[ret] = '\0';
+
+ ret = strcmp(device_serial, match_serial);
+ free(device_serial);
+ if (ret)
+ goto out;
+
+ return handle;
+
+out:
+ free(device_serial);
+ if (handle)
+ libusb_close(handle);
+ return 0;
+}
+
+struct chaoskey *
+chaoskey_open(char *serial)
+{
+ struct chaoskey *ck;
+ int ret;
+ ssize_t num;
+ libusb_device **list;
+ libusb_device *device = NULL;
+ int d;
+
+ ck = calloc(sizeof (struct chaoskey), 1);
+ if (!ck)
+ goto out;
+ ret = libusb_init(&ck->ctx);
+ if (ret ) {
+ fprintf(stderr, "libusb_init failed: %s\n", libusb_strerror(ret));
+ goto out;
+ }
+
+ num = libusb_get_device_list(ck->ctx, &list);
+ if (num < 0) {
+ fprintf(stderr, "libusb_get_device_list failed: %s\n", libusb_strerror(num));
+ goto out;
+ }
+
+ for (d = 0; d < num; d++) {
+ libusb_device_handle *handle;
+
+ handle = chaoskey_match(list[d], serial);
+ if (handle) {
+ ck->handle = handle;
+ break;
+ }
+ }
+
+ libusb_free_device_list(list, 1);
+
+ if (!ck->handle) {
+ if (serial)
+ fprintf (stderr, "No chaoskey matching %s\n", serial);
+ else
+ fprintf (stderr, "No chaoskey\n");
+ goto out;
+ }
+
+ ck->kernel_active = libusb_kernel_driver_active(ck->handle, 0);
+ if (ck->kernel_active) {
+ ret = libusb_detach_kernel_driver(ck->handle, 0);
+ if (ret)
+ goto out;
+ }
+
+ ret = libusb_claim_interface(ck->handle, 0);
+ if (ret)
+ goto out;
+
+ return ck;
+out:
+ if (ck->kernel_active)
+ libusb_attach_kernel_driver(ck->handle, 0);
+ if (ck->ctx)
+ libusb_exit(ck->ctx);
+ free(ck);
+ return NULL;
+}
+
+void
+chaoskey_close(struct chaoskey *ck)
+{
+ libusb_release_interface(ck->handle, 0);
+ if (ck->kernel_active)
+ libusb_attach_kernel_driver(ck->handle, 0);
+ libusb_close(ck->handle);
+ libusb_exit(ck->ctx);
+ free(ck);
+}
+
+void
+chaoskey_transfer_callback(struct libusb_transfer *transfer)
+{
+ struct chaoskey *ck = transfer->user_data;
+}
+
+#define ENDPOINT 0x86
+
+int
+chaoskey_read(struct chaoskey *ck, uint8_t *buffer, int len)
+{
+ int total = 0;
+
+ while (len) {
+ int ret;
+ int transferred;
+
+ ret = libusb_bulk_transfer(ck->handle, ENDPOINT, buffer, len, &transferred, 10000);
+ if (ret) {
+ if (total)
+ return total;
+ else {
+ errno = EIO;
+ return -1;
+ }
+ }
+ len -= transferred;
+ buffer += transferred;
+ }
+}
+
+static const struct option options[] = {
+ { .name = "serial", .has_arg = 1, .val = 's' },
+ { .name = "length", .has_arg = 1, .val = 'l' },
+ { 0, 0, 0, 0},
+};
+
+static void usage(char *program)
+{
+ fprintf(stderr, "usage: %s [--serial=<serial>] [--length=<length>[kMG]]\n", program);
+ exit(1);
+}
+
+int
+main (int argc, char **argv)
+{
+ struct chaoskey *ck;
+ char buf[1024];
+ int got;
+ int c;
+ char *serial = NULL;
+ char *length_string;
+ char *length_end;
+ unsigned long length = sizeof(buf);
+ int this_time;
+
+ while ((c = getopt_long(argc, argv, "s:l:", options, NULL)) != -1) {
+ switch (c) {
+ case 's':
+ serial = optarg;
+ break;
+ case 'l':
+ length_string = optarg;
+ length = strtoul(length_string, &length_end, 10);
+ if (!strcasecmp(length_end, "k"))
+ length *= 1024;
+ else if (!strcasecmp(length_end, "m"))
+ length *= 1024 * 1024;
+ else if (!strcasecmp(length_end, "g"))
+ length *= 1024 * 1024 * 1024;
+ else if (strlen(length_end))
+ usage(argv[0]);
+ break;
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+
+ ck = chaoskey_open(serial);
+ if (!ck)
+ exit(1);
+
+ while (length) {
+ this_time = sizeof(buf);
+ if (length < sizeof(buf))
+ this_time = (int) length;
+ got = chaoskey_read(ck, buf, this_time);
+ if (got < 0) {
+ perror("read");
+ exit(1);
+ }
+ write(1, buf, got);
+ length -= got;
+ }
+ exit(0);
+}
}
}
-static const char *state_names[] = {
- "startup",
- "idle",
- "pad",
- "boost",
- "fast",
- "coast",
- "drogue",
- "main",
- "landed",
- "invalid"
-};
-
-
int
main (int argc, char **argv)
{
--- /dev/null
+bin_PROGRAMS=ao-makebin
+
+AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AO_ELFTOHEX_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
+
+ao_makebin_DEPENDENCIES = $(AO_ELFTOHEX_LIBS)
+
+ao_makebin_LDADD=$(AO_ELFTOHEX_LIBS) -lelf
+
+ao_makebin_SOURCES=ao-makebin.c
+
+man_MANS = ao-makebin.1
--- /dev/null
+.\"
+.\" Copyright © 2013 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; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" 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.
+.\"
+.\"
+.TH AO-LOAD 1 "ao-makebin" ""
+.SH NAME
+ao-makebin \- construct raw binary file or DFU image from collection of ELF files
+.SH SYNOPSIS
+.B "ao-makebin"
+[\--base=\fIbase-address\fP]
+[\--output=\fIoutput.bin\fP]
+[\--dfu]
+[\--verbose]
+\fIinput.elf ...\fP
+.SH DESCRIPTION
+.I ao-makebin
+reads the specified .elf files and writes out a raw binary flash image
+.SH OPTIONS
+.TP
+\--base=\fIbase-address\fP
+This specifies the target address for the first byte of the file (default is 0)
+.TP
+\--output=\fIoutput.bin\fP
+This specifies the output file (default is stdout)
+.TP
+\--dfu
+Creates a DFU file (as documented by ST's UM0391 user manual) instead
+of a raw binary file.
+.TP
+\--verbose
+Dumps some debug information.
+.SH AUTHOR
+Keith Packard
--- /dev/null
+/*
+ * Copyright © 2016 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 <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include "ao-hex.h"
+#include "ao-elf.h"
+#include "ao-dfu.h"
+
+static const struct option options[] = {
+ { .name = "verbose", .has_arg = 0, .val = 'v' },
+ { .name = "output", .has_arg = 1, .val = 'o' },
+ { .name = "base", .has_arg = 1, .val = 'b' },
+ { .name = "align", .has_arg = 1, .val = 'a' },
+ { .name = "dfu", .has_arg = 0, .val = 'd' },
+ { 0, 0, 0, 0},
+};
+
+static void usage(char *program)
+{
+ fprintf(stderr, "usage: %s [--verbose=<level>] [--output=<output.bin>] [--base=<base-address>] [--align=<align>] [--dfu] <input.elf> ...\n", program);
+ exit(1);
+}
+
+static int
+ends_with(char *whole, char *suffix)
+{
+ int whole_len = strlen(whole);
+ int suffix_len = strlen(suffix);
+
+ if (suffix_len > whole_len)
+ return 0;
+ return strcmp(whole + whole_len - suffix_len, suffix) == 0;
+}
+
+static struct ao_dfu_info dfu_info = {
+ .bcdDevice = 0x0000,
+ .idProduct = 0xdf11,
+ .idVendor = 0x0483,
+};
+
+int
+main (int argc, char **argv)
+{
+ char *output = NULL;
+ struct ao_hex_image *image = NULL;
+ struct ao_sym *file_symbols;
+ int num_file_symbols;
+ FILE *file;
+ int c;
+ uint32_t base = 0xffffffff;
+ uint32_t align = 0;
+ uint32_t length;
+ int verbose = 0;
+ int dfu = 0;
+
+ while ((c = getopt_long(argc, argv, "dvo:b:a:", options, NULL)) != -1) {
+ switch (c) {
+ case 'o':
+ output = optarg;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ case 'b':
+ base = strtoul(optarg, NULL, 0);
+ break;
+ case 'a':
+ align = strtoul(optarg, NULL, 0);
+ break;
+ case 'd':
+ dfu = 1;
+ break;
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+
+ while (argv[optind]) {
+ char *input = argv[optind];
+ struct ao_hex_image *tmp;
+
+ if (ends_with (input, ".ihx"))
+ tmp = ao_hex_load(input, &file_symbols, &num_file_symbols);
+ else
+ tmp = ao_load_elf(input, &file_symbols, &num_file_symbols);
+
+ if (!tmp)
+ usage(argv[0]);
+
+ if (verbose)
+ fprintf(stderr, "%s: 0x%x %d\n", input, tmp->address, tmp->length);
+
+ if (image) {
+ image = ao_hex_image_cat(image, tmp);
+ if (!image)
+ usage(argv[0]);
+ } else
+ image = tmp;
+ optind++;
+ }
+
+ if (base != 0xffffffff && base > image->address) {
+ fprintf(stderr, "requested base 0x%x is after image address 0x%x\n",
+ base, image->address);
+ usage(argv[0]);
+ }
+
+ if (verbose)
+ fprintf(stderr, "%s: base 0x%x length %d\n", output ? output : "<stdout>", image->address, image->length);
+
+ if (!output)
+ file = stdout;
+ else {
+ file = fopen(output, "w");
+ if (!file) {
+ perror(output);
+ exit(1);
+ }
+ }
+
+ if (dfu) {
+ if (!ao_dfu_write(file, &dfu_info, 1, image)) {
+ fprintf(stderr, "%s: dfu_write failed: %s\n", output, strerror(errno));
+ if (output)
+ unlink(output);
+ exit(1);
+ }
+ } else {
+ while (base < image->address) {
+ fputc(0xff, file);
+ base++;
+ }
+
+ if (fwrite(image->data, 1, image->length, file) != image->length) {
+ fprintf(stderr, "%s: failed to write bin file\n", output ? output : "<stdout>");
+ if (output)
+ unlink(output);
+ exit(1);
+ }
+
+ if (align) {
+ length = image->length;
+
+ while (length % align) {
+ fputc(0xff, file);
+ length++;
+ }
+ }
+ fflush(file);
+ }
+
+ exit(0);
+}
ao-editaltos.h \
ao-elf.c \
ao-elf.h \
+ ao-dfu.c \
+ ao-dfu.h \
ao-selfload.c \
ao-selfload.h \
ao-verbose.c \
--- /dev/null
+/*
+ * Copyright © 2016 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 <stdarg.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+#include "ao-hex.h"
+#include "ao-dfu.h"
+
+static uint32_t dfu_crc;
+static FILE *dfu_file;
+static int dfu_failed;
+static int dfu_error;
+
+static uint32_t update_crc(uint32_t crc, uint8_t byte)
+{
+ int j;
+ uint32_t mask;
+
+ crc = crc ^ byte;
+ for (j = 0; j < 8; j++) {
+ mask = -(crc & 1);
+ crc = (crc >> 1) ^ (0xEDB88320 & mask);
+ }
+ return crc;
+}
+
+static void dfu_init(FILE *file)
+{
+ dfu_crc = 0xffffffff;
+ dfu_file = file;
+ dfu_failed = 0;
+ dfu_error = 0;
+}
+
+static int dfu_fini(void)
+{
+ if (fflush(dfu_file) == EOF) {
+ if (!dfu_failed) {
+ dfu_failed = 1;
+ dfu_error = errno;
+ }
+ }
+ if (dfu_failed)
+ errno = dfu_error;
+ return !dfu_failed;
+}
+
+static void dfu_8(uint8_t byte) {
+ if (putc(byte, dfu_file) == EOF) {
+ if (!dfu_failed) {
+ dfu_failed = 1;
+ dfu_error = errno;
+ }
+ }
+ dfu_crc = update_crc(dfu_crc, byte);
+}
+
+static void dfu_pad(int len) {
+ while (len--)
+ dfu_8(0);
+}
+
+static void dfu_string(char *string) {
+ char c;
+
+ while ((c = *string++))
+ dfu_8((uint8_t) c);
+}
+
+static void dfu_string_pad(char *string, int len) {
+ char c;
+
+ while ((c = *string++)) {
+ dfu_8((uint8_t) c);
+ len--;
+ }
+ dfu_pad(len);
+}
+
+static void dfu_block(uint8_t *bytes, int len) {
+ while (len--)
+ dfu_8(*bytes++);
+}
+
+static void dfu_lsb16(uint16_t value) {
+ dfu_8(value);
+ dfu_8(value>>8);
+}
+
+static void dfu_lsb32(uint32_t value) {
+ dfu_8(value);
+ dfu_8(value >> 8);
+ dfu_8(value >> 16);
+ dfu_8(value >> 24);
+}
+
+static uint32_t dfu_image_size(struct ao_hex_image *image) {
+ return 8 + image->length;
+}
+
+static uint32_t dfu_images_size(int num_image, struct ao_hex_image images[])
+{
+ uint32_t size = 0;
+ int i;
+
+ for (i = 0; i < num_image; i++)
+ size += dfu_image_size(&images[i]);
+ return size;
+}
+
+static void dfu_image(struct ao_hex_image *image)
+{
+ dfu_lsb32(image->address);
+ dfu_lsb32(image->length);
+ dfu_block(image->data, image->length);
+}
+
+static void dfu_target(char *name, int num_image, struct ao_hex_image images[])
+{
+ uint32_t images_size = dfu_images_size(num_image, images);
+ int i;
+
+ dfu_string("Target");
+ dfu_8(0);
+ if (name) {
+ dfu_8(1);
+ dfu_pad(3);
+ dfu_string_pad(name, 255);
+ } else {
+ dfu_8(0);
+ dfu_pad(3);
+ dfu_pad(255);
+ }
+ dfu_lsb32(images_size);
+ dfu_lsb32(num_image);
+ for (i = 0; i < num_image; i++)
+ dfu_image(&images[i]);
+}
+
+static uint32_t dfu_target_size(int num_image, struct ao_hex_image images[])
+{
+ return 274 + dfu_images_size(num_image, images);
+}
+
+static uint32_t
+dfu_size(int num_image, struct ao_hex_image images[])
+{
+ uint32_t size = 0;
+ size += 11; /* DFU Prefix */
+
+ size += dfu_target_size(num_image, images);
+
+ return size;
+}
+
+int
+ao_dfu_write(FILE *file, struct ao_dfu_info *info, int num_image, struct ao_hex_image images[])
+{
+ uint32_t total_size;
+
+ total_size = dfu_size(num_image, images);
+
+ dfu_init(file);
+ /* DFU Prefix */
+ dfu_string(DFU_SIGNATURE);
+ dfu_8(0x01);
+ dfu_lsb32(total_size);
+ dfu_8(0x01);
+
+ dfu_target("ST...", num_image, images);
+
+ /* DFU Suffix */
+ dfu_lsb16(info->bcdDevice);
+ dfu_lsb16(info->idProduct);
+ dfu_lsb16(info->idVendor);
+ dfu_lsb16(DFU_SPEC_VERSION);
+ dfu_string("UFD");
+ dfu_8(16);
+ dfu_lsb32(dfu_crc);
+ return dfu_fini();
+}
+
--- /dev/null
+/*
+ * Copyright © 2016 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_DFU_H_
+#define _AO_DFU_H_
+
+struct ao_dfu_info {
+ uint16_t bcdDevice;
+ uint16_t idProduct;
+ uint16_t idVendor;
+};
+
+#define DFU_SIGNATURE "DfuSe"
+#define DFU_SPEC_VERSION 0x011a
+
+#define DFU_TARGET_SIGNATURE "Target"
+
+int
+ao_dfu_write(FILE *file, struct ao_dfu_info *info, int num_image, struct ao_hex_image images[]);
+
+#endif /* _AO_DFU_H_ */
#endif
size_t nshdr;
size_t s;
-
+
if (elf_getshdrstrndx(e, &shstrndx) < 0)
return 0;
(uint32_t) phdr.p_filesz,
(uint32_t) phdr.p_memsz);
#endif
-
+
for (s = 0; s < nshdr; s++) {
scn = elf_getscn(e, s);
#endif
if (phdr.p_offset <= shdr.sh_offset && shdr.sh_offset < phdr.p_offset + phdr.p_filesz) {
-
+
if (shdr.sh_size == 0)
continue;
struct ao_sym *symbol;
int num_symbols = 0;
int size_symbols = 0;
-
+
extended_addr = 0;
for (i = 0; i < hex->nrecord; i++) {
record = hex->records[i];
free(image);
}
+uint32_t min(uint32_t a, uint32_t b) { return a < b ? a : b; }
+uint32_t max(uint32_t a, uint32_t b) { return a > b ? a : b; }
+
+struct ao_hex_image *
+ao_hex_image_cat(struct ao_hex_image *a, struct ao_hex_image *b)
+{
+ struct ao_hex_image *n;
+ uint32_t base, bound;
+ uint32_t length;
+
+ base = min(a->address, b->address);
+ bound = max(a->address + a->length, b->address + b->length);
+ length = bound - base;
+
+ n = calloc (sizeof (struct ao_hex_image) + length, 1);
+ if (!n)
+ return NULL;
+ n->address = base;
+ n->length = length;
+ memset(n->data, 0xff, length);
+ memcpy(n->data + a->address - n->address, a->data, a->length);
+ memcpy(n->data + b->address - n->address, b->data, b->length);
+ return n;
+}
+
int
ao_hex_image_equal(struct ao_hex_image *a, struct ao_hex_image *b)
{
file = fopen (filename, "r");
if (!file)
return NULL;
-
+
hex_file = ao_hex_file_read(file, filename);
fclose(file);
if (!hex_file)
ao_hex_record_set_checksum(record);
hex_file->records[nrecord++] = record;
-
+
/* Add the symbols
*/
goto write_failed;
}
ret = true;
-
+
if (fflush(file) != 0)
ret = false;
write_failed:
struct ao_hex_image *
ao_hex_load(char *filename, struct ao_sym **symbols, int *num_symbols);
+struct ao_hex_image *
+ao_hex_image_cat(struct ao_hex_image *a, struct ao_hex_image *b);
+
int
ao_hex_image_equal(struct ao_hex_image *a, struct ao_hex_image *b);
dnl Process this file with autoconf to create configure.
AC_PREREQ(2.57)
-AC_INIT([altos], 1.6.2)
-ANDROID_VERSION=10
+AC_INIT([altos], 1.6.3)
+ANDROID_VERSION=11
AC_CONFIG_SRCDIR([src/kernel/ao.h])
AM_INIT_AUTOMAKE([foreign dist-bzip2])
AM_MAINTAINER_MODE
dnl ==========================================================================
dnl Java library versions
-ALTOSUILIB_VERSION=9
-ALTOSLIB_VERSION=9
+ALTOSUILIB_VERSION=10
+ALTOSLIB_VERSION=10
AC_SUBST(ALTOSLIB_VERSION)
AC_DEFINE(ALTOSLIB_VERSION,$ALTOSLIB_VERSION,[Version of the AltosLib package])
ANDROID_RELEASE=no
if test "x$ANDROID_SDK" != "xno"; then
HAVE_ANDROID_SDK="yes"
- if test -f "$HOME/altusmetrumllc/release.keystore" -a -f "$HOME/altusmetrumllc/Passphrase"; then
+ if test -f "$HOME/altusmetrumllc/google-play-release.keystore" -a -f "$HOME/altusmetrumllc/google-play-passphrase"; then
ANDROID_RELEASE=yes
fi
else
[GOOGLEKEYFILE=$withval], [GOOGLEKEYFILE=$HOME/altusmetrumllc/google-maps-api-key])
if test -r "$GOOGLEKEYFILE" -a -s "$GOOGLEKEYFILE"; then
- GOOGLEKEY='"'`cat "$GOOGLEKEYFILE"`'"'
+ GOOGLEKEY=`cat "$GOOGLEKEYFILE"`
HAVE_GOOGLE_KEY="yes"
else
GOOGLEKEY='null'
ao-tools/ao-cal-freq/Makefile
ao-tools/ao-test-gps/Makefile
ao-tools/ao-usbtrng/Makefile
+ao-tools/ao-chaosread/Makefile
+ao-tools/ao-makebin/Makefile
ao-utils/Makefile
src/Version
])
#
RELNOTES_INC=\
+ release-notes-1.6.3.inc \
release-notes-1.6.2.inc \
release-notes-1.6.1.inc \
release-notes-1.6.inc \
doesn't, the most likely reason is that your Android
device doesn't support USB On-the-go.
- === Configuring AltosDroid
+ === AltosDroid Menu
+
+ The main AltosDroid menu has a selection of operation
+ and configuration options.
+
+ Connect a device::
+
+ Offers a menu of available TeleBT devices, and an
+ option to scan for additional devices.
+
+ Disconnect device::
+
+ Disconnects the current TeleBT or TeleDongle
+ device. You can reconnect TeleBT over bluetooth by
+ using Connect a Device. You can reconnect a USB device
+ by unplugging it and then plugging it back in.
- There are several configuration and operation
- parameters available in the AltosDroid menu.
-
Select radio frequency::
This selects which frequency to listen on by bringing
up a menu of pre-set radio frequencies. Pick the one
which matches your altimeter.
- Select data rate::
+ Select Tracker::
+
+ Switches the information displays to show data for a
+ different transmitting device. The map will always
+ show all of the devices in view. Trackers are shown
+ and selected by serial number, so make sure you note
+ the serial number of devices in each airframe.
+
+ Delete Track::
+
+ Deletes all information about a transmitting device.
+
+ Setup::
+
+ Offers additional configuration operations. See
+ <<_setup>>.
+
+ Idle Mode::
+
+ Communicate with an altimeter in Idle mode. See <<_idle_mode>>
+
+ Quit::
+
+ Shuts down AltosDroid.
+
+ === Setup
+
+ Telemetry Rate::
Altus Metrum transmitters can be configured to operate
at lower data rates to improve transmission range. If
you have configured your device to do this, this menu
item allows you to change the receiver to match.
- Change units::
-
- This toggles between metric and imperial units.
-
- Load maps::
+ Units::
- Brings up a dialog allowing you to download offline
- map tiles so that you can have maps available even if
- you have no network connectivity at the launch site.
+ Selects which units used to report values.
- Map type::
+ Map Type::
Displays a menu of map types and lets you select
one. Hybrid maps include satellite images with a
includes roads along with shadows indicating changes
in elevation, and other geographical features.
- Toggle Online/Offline maps::
+ Map Source::
- Switches between online and offline maps. Online maps
+ Select between online and offline maps. Online maps
will show a 'move to current position' icon in the
upper right corner, while offline maps will have
copyright information all over the map. Otherwise,
they're pretty similar.
- Select Tracker::
+ Preload Maps::
- Switches the information displays to show data for a
- different transmitting device. The map will always
- show all of the devices in view. Trackers are shown
- and selected by serial number, so make sure you note
- the serial number of devices in each airframe.
+ Brings up a dialog allowing you to download offline
+ map tiles so that you can have maps available even if
+ you have no network connectivity at the launch site.
+
+ Manage Frequencies::
- Delete Track::
+ This presents a dialog containing the current list of
+ frequencies that will be show in the 'Select radio
+ frequency' menu. You can change the label for existing
+ frequencies, delete or add new frequencies.
+
+ === Idle Mode
+
+ Callsign::
+
+ Lets you configure the callsign used by AltosDroid to
+ communicate with the flight computer. The callsign on
+ the two devices must match or the communication will
+ fail. This provides a modest amount of protection
+ against accidentally controlling another persons
+ flight computer.
+
+ Monitor::
+
+ This provides similar information to monitoring the
+ telemetry stream from a flight computer in flight
+ mode. The title of the application will change to
+ include (idle) so you can tell this mode is active.
+
+ Reboot::
+
+ Remotely reboots the flight computer. This is useful
+ when the flight computers turned on while the airframe
+ is horizontal and you want to restart the flight
+ computers in pad mode after raising the airframe to
+ vertical.
+
+ Fire Igniters::
+
+ Remotely control igniters for ground testing recovery
+ systems.
- Deletes all information about a transmitting device.
-
=== AltosDroid Flight Monitoring
AltosDroid is designed to mimic the AltosUI flight
Bearing::
- This is the aziumuth from true north for the rocket
+ This is the azimuth from true north for the rocket
from the android device. Use this in combination with
the Elevation value to help locate the rocket in the
sky, or at least to help point the antenna in the
Bearing::
- This is the aziumuth from true north for the rocket
+ This is the azimuth from true north for the rocket
from the android device. Use this in combination with
the Elevation value to help locate the rocket in the
sky, or at least to help point the antenna in the
Max Height::
- Shows the maximum height above launch pad.
+ Shows the maximum height above launch pad seen during
+ the flight.
Max Speed::
</legalnotice>
<revhistory>
<?dbhtml filename="altusmetrum-revhistory.html"?>
+ <revision>
+ <revnumber>1.6.3</revnumber>
+ <date>21 April 2016</date>
+ <revremark>
+ Minor release adding idle mode to AltosDroid and fixing various
+ host software bugs.
+ </revremark>
+ </revision>
<revision>
<revnumber>1.6.2</revnumber>
<date>10 January 2016</date>
</legalnotice>
<revhistory>
<?dbhtml filename="easymini-revhistory.html"?>
+ <revision>
+ <revnumber>1.6.3</revnumber>
+ <date>21 April 2016</date>
+ <revremark>
+ Minor release fixing various host software bugs.
+ </revremark>
+ </revision>
<revision>
<revnumber>1.6.2</revnumber>
<date>10 January 2016</date>
[appendix]
== Release Notes
+ :leveloffset: 2
+ include::release-notes-1.6.3.raw[]
+
+ <<<<
:leveloffset: 2
include::release-notes-1.6.2.raw[]
--- /dev/null
+= Release Notes for Version 1.6.3
+:toc!:
+:doctype: article
+
+ Version 1.6.3 adds idle mode to AltosDroid and has bug fixes
+ for our host software on desktops, laptops an android devices
+ along with BlueTooth support for Windows.
+
+ == AltOS
+
+ AltOS fixes:
+
+ * Fix hardware flow control on TeleBT v3.0. RTS/CTS is
+ wired backwards on this board, switch from using the
+ hardware to driving these pins with software.
+
+ == AltosUI and TeleGPS Applications
+
+ AltosUI and TeleGPS New Features:
+
+ * Add BlueTooth support for Windows operating system. This
+ supports connections to TeleBT over BlueTooth rather than
+ just USB.
+
+ AltosUI and TeleGPS Fixes:
+
+ * Change Java detection and install on Windows. Detection is
+ now done by looking for the 'javaw.exe' program, and
+ installation by opening a browser on the java.com web site.
+
+ * Delay polling while the Fire Igniters is visible to allow
+ for TeleMega to report back complete status over the radio.
+
+ * Disallow changing RF calibration numbers in the
+ configuration UI. There's no good reason to change this from
+ the field, and recovering is really hard if you haven't
+ written down the right number.
+
+ * Fix USB device discovery on Mac OS X El Capitan. This makes
+ the connected Altus Metrum USB devices appear again.
+
+ * Fix acceleration data presented in MonitorIdle mode for
+ TeleMetrum v2.0 flight computers.
+
+ == AltosDroid
+
+ AltosDroid new features:
+
+ * Monitor Idle mode. Check state of flight computer while in
+ idle mode over the radio link
+
+ * Fire Igniters. Remotely fire ignires for recovery system
+ ground tests.
+
+ * Remote reboot. Cause the flight computer to reboot over the
+ radio link. This provides a method for switching the flight
+ computer from idle to flight mode without needing to reach
+ the power switch.
+
+ * Configurable frequency menu. Change the set of available
+ frequencies and provide more descriptive names.
+
+ AltosDroid bug fixes:
+
+ * Don't set target location if GPS hasn't locked yet.
+
+ * Fix saving target states so they can be reloaded when the
+ application restarts. When the application is shut down and
+ restarted, all previous target state information will be
+ restored (including GPS position if available).
+
+ * Fix crash on some Android devices for offline maps when
+ changing the map scale or location.
+
+ * Don't require USB OTG support. This kept the latest
+ AltosDroid from being offered on devices without USB device
+ support, although it can work without that just fine using
+ BlueTooth.
+
+ * Don't require bluetooth to be enabled. This allows the
+ application to operate with USB devices or just show old
+ data without turning on the bluetooth radio.
+
+ * Recover old tracker positions when restarting
+ application. This finally allows you to safely stop and
+ restart the application without losing the last known
+ location of any tracker.
+
+ == Documentation
+
+ * Document TeleMega and EasyMega additional pyro channel
+ continuity audio alert pattern.
[appendix]
== Release Notes
+ :leveloffset: 2
+ include::release-notes-1.6.3.raw[]
+
+ <<<<
:leveloffset: 2
include::release-notes-1.6.2.raw[]
[appendix]
== Release Notes
+ :leveloffset: 2
+ include::release-notes-1.6.3.raw[]
+
+ <<<<
:leveloffset: 2
include::release-notes-1.6.2.raw[]
controlling the flight or transmitting telemetry
signals, but no record of the flight will be
stored in on-board flash.
+
+ |Additional Igniters
+ |four very short beeps
+ |Continuity indication for the four additional pyro
+ |channels on TeleMega and EasyMega. One high tone for
+ |no continuity, one low tone for continuity. These are
+ |produced after the continuity indicators for the two
+ |primary igniter channels.
+
|====
ifdef::radio[]
#
ifeq ($(OS),Linux)
-JAVA_CFLAGS=-I/usr/lib/jvm/java-6-openjdk/include
+OS_SRCS=libaltos_posix.c libaltos_linux.c
-OS_LIB_CFLAGS=-DLINUX -DPOSIX_TTY $(JAVA_CFLAGS)
+JAVA_CFLAGS=-I/usr/lib/jvm/default-java/include -I/usr/lib/jvm/default-java/include/linux
+
+OS_LIB_CFLAGS=-DLINUX -DPOSIX_TTY $(JAVA_CFLAGS) -shared -fPIC
OS_APP_CFLAGS=$(OS_LIB_CFLAGS)
#
ifeq ($(OS),Darwin)
+OS_SRCS=libaltos_posix.c libaltos_darwin.c
+
#OS_LIB_CFLAGS=\
# -DDARWIN -DPOSIX_TTY -arch i386 -arch x86_64 \
# --sysroot=/Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.5 \
# -iwithsysroot /System/Library/Frameworks/IOKit.framework/Headers \
# -iwithsysroot /System/Library/Frameworks/CoreFoundation.framework/Headers
-XCODE=/Applications/Xcode.app
-SDK=$(XCODE)/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk
+XCODE=/Applications/Xcode-beta.app
+SDK=$(XCODE)/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk
MINVERSION=10.5
OS_LIB_CFLAGS=\
-iwithsysroot /System/Library/Frameworks/JavaVM.framework/Headers \
-iwithsysroot /System/Library/Frameworks/IOKit.framework/Headers \
-iwithsysroot /System/Library/Frameworks/CoreFoundation.framework/Headers
-OS_APP_CFLAGS=$(OS_LIB_CFLAGS)
+OS_APP_CFLAGS=$(OS_LIB_CFLAGS) -O0 -g
OS_LDFLAGS =\
-framework IOKit -framework CoreFoundation
#
ifneq (,$(findstring MINGW,$(OS)))
+OS_SRCS=libaltos_windows.c
+
CC=gcc
OS_LIB_CFLAGS = -DWINDOWS -mconsole -DBUILD_DLL
LDFLAGS=$(OS_LDFLAGS)
HEADERS=libaltos.h
-SRCS = libaltos.c $(SWIG_WRAP)
+SRCS = libaltos_common.c $(OS_SRCS) $(SWIG_WRAP)
OBJS = $(SRCS:%.c=%.o)
LIBS = $(DARWIN_LIBS)
$(CC) -o $@ $(OS_APP_CFLAGS) cjnitest.c $(LIBNAME) $(LIBS) $(LDFLAGS)
$(LIBNAME): $(OBJS)
- $(CC) -shared $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(LDFLAGS)
+ $(CC) -shared -fPIC $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(LDFLAGS)
clean:
rm -f $(CLASSFILES) $(OBJS) $(LIBNAME) $(CJNITEST) cjnitest.o
JAVAC=javac
-AM_CFLAGS=-DLINUX -DPOSIX_TTY -I$(JVM_INCLUDE)
+AM_CFLAGS=-DLINUX -DPOSIX_TTY -I$(JVM_INCLUDE) -I$(JVM_INCLUDE)/linux
AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -source 6
altoslibdir=$(libdir)/altos
libaltos_la_LDFLAGS=-version-info 1:0:1 -Wl,-znoexecstack
libaltos_la_SOURCES=\
- libaltos.c \
+ libaltos_common.c \
+ libaltos_posix.c \
+ libaltos_linux.c \
+ libaltos_wrap.c \
+ libaltos.h \
+ libaltos_posix.h \
+ libaltos_private.h
+
+WINDOWS_SRC=\
+ libaltos_common.c\
+ libaltos_windows.c\
libaltos_wrap.c
+WINDOWS_H=\
+ libaltos.h
+
noinst_PROGRAMS=cjnitest
cjnitest_SOURCES=cjnitest.c
MINGCC32=i686-w64-mingw32-gcc
MINGCC64=x86_64-w64-mingw32-gcc
-MINGFLAGS=-Wall -DWINDOWS -DBUILD_DLL -I$(JVM_INCLUDE)
-MINGLIBS=-lsetupapi
+MINGFLAGS=-Wall -Wextra -DWINDOWS -DBUILD_DLL -mconsole -I$(JVM_INCLUDE) -I$(JVM_INCLUDE)/linux
+MINGLIBS=-lsetupapi -lws2_32
fat: all altos.dll altos64.dll
-altos.dll: $(libaltos_la_SOURCES)
- $(MINGCC32) -o $@ $(MINGFLAGS) -shared $(libaltos_la_SOURCES) $(MINGLIBS)
+altos.dll: $(WINDOWS_SRC) $(WINDOWS_H)
+ $(MINGCC32) -o $@ $(MINGFLAGS) -shared $(WINDOWS_SRC) $(MINGLIBS)
-altos64.dll: $(libaltos_la_SOURCES)
- $(MINGCC64) -o $@ $(MINGFLAGS) -shared $(libaltos_la_SOURCES) $(MINGLIBS)
+altos64.dll: $(WINDOWS_SRC) $(WINDOWS_H)
+ $(MINGCC64) -o $@ $(MINGFLAGS) -shared $(WINDOWS_SRC) $(MINGLIBS)
clean-local:
-rm -rf libaltosJNI *.class *.java classlibaltos.stamp $(SWIG_FILE) libaltos_wrap.c altos.dll altos64.dll
+++ /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 "libaltos.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define BLUETOOTH_PRODUCT_TELEBT "TeleBT"
-
-#define USE_POLL
-
-PUBLIC int
-altos_init(void)
-{
- return LIBALTOS_SUCCESS;
-}
-
-PUBLIC void
-altos_fini(void)
-{
-}
-
-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
-
-#include <unistd.h>
-
-#undef USE_POLL
-
-/* Mac OS X don't have strndup even if _GNU_SOURCE is defined */
-static char *
-altos_strndup (const char *s, size_t n)
-{
- size_t len = strlen (s);
- char *ret;
-
- if (len <= n)
- return strdup (s);
- ret = malloc(n + 1);
- strncpy(ret, s, n);
- ret[n] = '\0';
- return ret;
-}
-
-#else
-#define altos_strndup strndup
-#endif
-
-#ifdef POSIX_TTY
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <termios.h>
-#include <errno.h>
-
-#define USB_BUF_SIZE 64
-
-struct altos_file {
- int fd;
-#ifdef USE_POLL
- int pipe[2];
-#else
- int out_fd;
-#endif
- unsigned char out_data[USB_BUF_SIZE];
- int out_used;
- unsigned char in_data[USB_BUF_SIZE];
- int in_used;
- int in_read;
-};
-
-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)
-{
- struct altos_file *file = calloc (sizeof (struct altos_file), 1);
- int ret;
- struct termios term;
-
- 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) {
- altos_set_last_posix_error();
- free(file);
- return NULL;
- }
-#ifdef USE_POLL
- pipe(file->pipe);
-#else
- file->out_fd = open(device->path, O_RDWR | O_NOCTTY);
- if (file->out_fd < 0) {
- altos_set_last_posix_error();
- close(file->fd);
- free(file);
- return NULL;
- }
-#endif
- ret = tcgetattr(file->fd, &term);
- if (ret < 0) {
- altos_set_last_posix_error();
- close(file->fd);
-#ifndef USE_POLL
- close(file->out_fd);
-#endif
- free(file);
- return NULL;
- }
- cfmakeraw(&term);
- cfsetospeed(&term, B9600);
- cfsetispeed(&term, B9600);
-#ifdef USE_POLL
- term.c_cc[VMIN] = 1;
- term.c_cc[VTIME] = 0;
-#else
- term.c_cc[VMIN] = 0;
- term.c_cc[VTIME] = 1;
-#endif
- ret = tcsetattr(file->fd, TCSAFLUSH, &term);
- if (ret < 0) {
- altos_set_last_posix_error();
- close(file->fd);
-#ifndef USE_POLL
- close(file->out_fd);
-#endif
- free(file);
- return NULL;
- }
- return file;
-}
-
-PUBLIC void
-altos_close(struct altos_file *file)
-{
- if (file->fd != -1) {
- int fd = file->fd;
- file->fd = -1;
-#ifdef USE_POLL
- write(file->pipe[1], "\r", 1);
-#else
- close(file->out_fd);
- file->out_fd = -1;
-#endif
- close(fd);
- }
-}
-
-PUBLIC void
-altos_free(struct altos_file *file)
-{
- altos_close(file);
- free(file);
-}
-
-PUBLIC int
-altos_flush(struct altos_file *file)
-{
- if (file->out_used && 0) {
- printf ("flush \"");
- fwrite(file->out_data, 1, file->out_used, stdout);
- printf ("\"\n");
- }
- while (file->out_used) {
- int ret;
-
- if (file->fd < 0)
- return -EBADF;
-#ifdef USE_POLL
- ret = write (file->fd, file->out_data, file->out_used);
-#else
- ret = write (file->out_fd, file->out_data, file->out_used);
-#endif
- if (ret < 0) {
- altos_set_last_posix_error();
- return -last_error.code;
- }
- if (ret) {
- memmove(file->out_data, file->out_data + ret,
- file->out_used - ret);
- file->out_used -= ret;
- }
- }
- return 0;
-}
-
-PUBLIC int
-altos_putchar(struct altos_file *file, char c)
-{
- int ret;
-
- if (file->out_used == USB_BUF_SIZE) {
- ret = altos_flush(file);
- if (ret) {
- return ret;
- }
- }
- file->out_data[file->out_used++] = c;
- ret = 0;
- if (file->out_used == USB_BUF_SIZE)
- ret = altos_flush(file);
- return ret;
-}
-
-#ifdef USE_POLL
-#include <poll.h>
-#endif
-
-static int
-altos_fill(struct altos_file *file, int timeout)
-{
- int ret;
-#ifdef USE_POLL
- struct pollfd fd[2];
-#endif
-
- if (timeout == 0)
- timeout = -1;
- while (file->in_read == file->in_used) {
- if (file->fd < 0)
- return LIBALTOS_ERROR;
-#ifdef USE_POLL
- fd[0].fd = file->fd;
- fd[0].events = POLLIN|POLLERR|POLLHUP|POLLNVAL;
- fd[1].fd = file->pipe[0];
- fd[1].events = POLLIN;
- ret = poll(fd, 2, timeout);
- if (ret < 0) {
- altos_set_last_posix_error();
- return LIBALTOS_ERROR;
- }
- if (ret == 0)
- return LIBALTOS_TIMEOUT;
-
- if (fd[0].revents & (POLLHUP|POLLERR|POLLNVAL))
- return LIBALTOS_ERROR;
- if (fd[0].revents & POLLIN)
-#endif
- {
- ret = read(file->fd, file->in_data, USB_BUF_SIZE);
- if (ret < 0) {
- altos_set_last_posix_error();
- return LIBALTOS_ERROR;
- }
- file->in_read = 0;
- file->in_used = ret;
-#ifndef USE_POLL
- if (ret == 0 && timeout > 0)
- return LIBALTOS_TIMEOUT;
-#endif
- }
- }
- if (file->in_used && 0) {
- printf ("fill \"");
- fwrite(file->in_data, 1, file->in_used, stdout);
- printf ("\"\n");
- }
- return 0;
-}
-
-PUBLIC int
-altos_getchar(struct altos_file *file, int timeout)
-{
- int ret;
- while (file->in_read == file->in_used) {
- if (file->fd < 0)
- return LIBALTOS_ERROR;
- ret = altos_fill(file, timeout);
- if (ret)
- return ret;
- }
- return file->in_data[file->in_read++];
-}
-
-#endif /* POSIX_TTY */
-
-/*
- * Scan for Altus Metrum devices by looking through /sys
- */
-
-#ifdef LINUX
-
-#define _GNU_SOURCE
-#include <ctype.h>
-#include <dirent.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/hci.h>
-#include <bluetooth/hci_lib.h>
-#include <bluetooth/rfcomm.h>
-
-static char *
-cc_fullname (char *dir, char *file)
-{
- char *new;
- int dlen = strlen (dir);
- int flen = strlen (file);
- int slen = 0;
-
- if (dir[dlen-1] != '/')
- slen = 1;
- new = malloc (dlen + slen + flen + 1);
- if (!new)
- return 0;
- strcpy(new, dir);
- if (slen)
- strcat (new, "/");
- strcat(new, file);
- return new;
-}
-
-static char *
-cc_basename(char *file)
-{
- char *b;
-
- b = strrchr(file, '/');
- if (!b)
- return file;
- return b + 1;
-}
-
-static char *
-load_string(char *dir, char *file)
-{
- char *full = cc_fullname(dir, file);
- char line[4096];
- char *r;
- FILE *f;
- int rlen;
-
- f = fopen(full, "r");
- free(full);
- if (!f)
- return NULL;
- r = fgets(line, sizeof (line), f);
- fclose(f);
- if (!r)
- return NULL;
- rlen = strlen(r);
- if (r[rlen-1] == '\n')
- r[rlen-1] = '\0';
- return strdup(r);
-}
-
-static int
-load_hex(char *dir, char *file)
-{
- char *line;
- char *end;
- long i;
-
- line = load_string(dir, file);
- if (!line)
- return -1;
- i = strtol(line, &end, 16);
- free(line);
- if (end == line)
- return -1;
- return i;
-}
-
-static int
-load_dec(char *dir, char *file)
-{
- char *line;
- char *end;
- long i;
-
- line = load_string(dir, file);
- if (!line)
- return -1;
- i = strtol(line, &end, 10);
- free(line);
- if (end == line)
- return -1;
- return i;
-}
-
-static int
-dir_filter_tty_colon(const struct dirent *d)
-{
- return strncmp(d->d_name, "tty:", 4) == 0;
-}
-
-static int
-dir_filter_tty(const struct dirent *d)
-{
- return strncmp(d->d_name, "tty", 3) == 0;
-}
-
-struct altos_usbdev {
- char *sys;
- char *tty;
- char *manufacturer;
- char *product_name;
- int serial; /* AltOS always uses simple integer serial numbers */
- int idProduct;
- int idVendor;
-};
-
-static char *
-usb_tty(char *sys)
-{
- char *base;
- int num_configs;
- int config;
- struct dirent **namelist;
- int interface;
- int num_interfaces;
- char endpoint_base[20];
- char *endpoint_full;
- char *tty_dir;
- int ntty;
- char *tty;
-
- base = cc_basename(sys);
- num_configs = load_hex(sys, "bNumConfigurations");
- num_interfaces = load_hex(sys, "bNumInterfaces");
- for (config = 1; config <= num_configs; config++) {
- for (interface = 0; interface < num_interfaces; interface++) {
- sprintf(endpoint_base, "%s:%d.%d",
- base, config, interface);
- endpoint_full = cc_fullname(sys, endpoint_base);
-
-
- /* Check for tty:ttyACMx style names
- */
- ntty = scandir(endpoint_full, &namelist,
- dir_filter_tty_colon,
- alphasort);
- if (ntty > 0) {
- free(endpoint_full);
- tty = cc_fullname("/dev", namelist[0]->d_name + 4);
- free(namelist);
- return tty;
- }
-
- /* Check for tty/ttyACMx style names
- */
- tty_dir = cc_fullname(endpoint_full, "tty");
- ntty = scandir(tty_dir, &namelist,
- dir_filter_tty,
- alphasort);
- free (tty_dir);
- if (ntty > 0) {
- tty = cc_fullname("/dev", namelist[0]->d_name);
- free(endpoint_full);
- free(namelist);
- return tty;
- }
-
- /* Check for ttyACMx style names
- */
- ntty = scandir(endpoint_full, &namelist,
- dir_filter_tty,
- alphasort);
- free(endpoint_full);
- if (ntty > 0) {
- tty = cc_fullname("/dev", namelist[0]->d_name);
- free(namelist);
- return tty;
- }
-
- }
- }
- return NULL;
-}
-
-static struct altos_usbdev *
-usb_scan_device(char *sys)
-{
- struct altos_usbdev *usbdev;
- char *tty;
-
- tty = usb_tty(sys);
- if (!tty)
- return NULL;
- usbdev = calloc(1, sizeof (struct altos_usbdev));
- if (!usbdev)
- return NULL;
- usbdev->sys = strdup(sys);
- usbdev->manufacturer = load_string(sys, "manufacturer");
- usbdev->product_name = load_string(sys, "product");
- usbdev->serial = load_dec(sys, "serial");
- usbdev->idProduct = load_hex(sys, "idProduct");
- usbdev->idVendor = load_hex(sys, "idVendor");
- usbdev->tty = tty;
- return usbdev;
-}
-
-static void
-usbdev_free(struct altos_usbdev *usbdev)
-{
- free(usbdev->sys);
- free(usbdev->manufacturer);
- free(usbdev->product_name);
- /* this can get used as a return value */
- if (usbdev->tty)
- free(usbdev->tty);
- free(usbdev);
-}
-
-#define USB_DEVICES "/sys/bus/usb/devices"
-
-static int
-dir_filter_dev(const struct dirent *d)
-{
- const char *n = d->d_name;
- char c;
-
- while ((c = *n++)) {
- if (isdigit(c))
- continue;
- if (c == '-')
- continue;
- if (c == '.' && n != d->d_name + 1)
- continue;
- return 0;
- }
- return 1;
-}
-
-struct altos_list {
- struct altos_usbdev **dev;
- int current;
- int ndev;
-};
-
-struct altos_list *
-altos_list_start(void)
-{
- int e;
- struct dirent **ents;
- char *dir;
- struct altos_usbdev *dev;
- struct altos_list *devs;
- int n;
-
- devs = calloc(1, sizeof (struct altos_list));
- if (!devs)
- return NULL;
-
- n = scandir (USB_DEVICES, &ents,
- dir_filter_dev,
- alphasort);
- if (!n)
- return 0;
- for (e = 0; e < n; e++) {
- dir = cc_fullname(USB_DEVICES, ents[e]->d_name);
- dev = usb_scan_device(dir);
- if (!dev)
- continue;
- free(dir);
- if (devs->dev)
- devs->dev = realloc(devs->dev,
- (devs->ndev + 1) * sizeof (struct usbdev *));
- else
- devs->dev = malloc (sizeof (struct usbdev *));
- devs->dev[devs->ndev++] = dev;
- }
- free(ents);
- devs->current = 0;
- return devs;
-}
-
-PUBLIC struct altos_list *
-altos_ftdi_list_start(void)
-{
- return altos_list_start();
-}
-
-int
-altos_list_next(struct altos_list *list, struct altos_device *device)
-{
- struct altos_usbdev *dev;
- if (list->current >= list->ndev) {
- return 0;
- }
- dev = list->dev[list->current];
- strcpy(device->name, dev->product_name);
- device->vendor = dev->idVendor;
- device->product = dev->idProduct;
- strcpy(device->path, dev->tty);
- device->serial = dev->serial;
- list->current++;
- return 1;
-}
-
-void
-altos_list_finish(struct altos_list *usbdevs)
-{
- int i;
-
- if (!usbdevs)
- return;
- for (i = 0; i < usbdevs->ndev; i++)
- usbdev_free(usbdevs->dev[i]);
- free(usbdevs);
-}
-
-#include <dlfcn.h>
-
-static void *libbt;
-static int bt_initialized;
-
-static int init_bt(void) {
- if (!bt_initialized) {
- bt_initialized = 1;
- libbt = dlopen("libbluetooth.so.3", RTLD_LAZY);
- if (!libbt)
- printf("failed to find bluetooth library\n");
- }
- return libbt != NULL;
-}
-
-#define join(a,b) a ## b
-#define bt_func(name, ret, fail, formals, actuals) \
- static ret join(altos_, name) formals { \
- static ret (*name) formals; \
- if (!init_bt()) return fail; \
- name = dlsym(libbt, #name); \
- if (!name) return fail; \
- return name actuals; \
- }
-
-bt_func(ba2str, int, -1, (const bdaddr_t *ba, char *str), (ba, str))
-#define ba2str altos_ba2str
-
-bt_func(str2ba, int, -1, (const char *str, bdaddr_t *ba), (str, ba))
-#define str2ba altos_str2ba
-
-bt_func(hci_read_remote_name, int, -1, (int sock, const bdaddr_t *ba, int len, char *name, int timeout), (sock, ba, len, name, timeout))
-#define hci_read_remote_name altos_hci_read_remote_name
-
-bt_func(hci_open_dev, int, -1, (int dev_id), (dev_id))
-#define hci_open_dev altos_hci_open_dev
-
-bt_func(hci_get_route, int, -1, (bdaddr_t *bdaddr), (bdaddr))
-#define hci_get_route altos_hci_get_route
-
-bt_func(hci_inquiry, int, -1, (int adapter_id, int len, int max_rsp, const uint8_t *lap, inquiry_info **devs, long flags), (adapter_id, len, max_rsp, lap, devs, flags))
-#define hci_inquiry altos_hci_inquiry
-
-struct altos_bt_list {
- inquiry_info *ii;
- int sock;
- int dev_id;
- int rsp;
- int num_rsp;
-};
-
-#define INQUIRY_MAX_RSP 255
-
-struct altos_bt_list *
-altos_bt_list_start(int inquiry_time)
-{
- struct altos_bt_list *bt_list;
-
- bt_list = calloc(1, sizeof (struct altos_bt_list));
- if (!bt_list)
- goto no_bt_list;
-
- bt_list->ii = calloc(INQUIRY_MAX_RSP, sizeof (inquiry_info));
- if (!bt_list->ii)
- goto no_ii;
- bt_list->dev_id = hci_get_route(NULL);
- if (bt_list->dev_id < 0)
- goto no_dev_id;
-
- bt_list->sock = hci_open_dev(bt_list->dev_id);
- if (bt_list->sock < 0)
- goto no_sock;
-
- bt_list->num_rsp = hci_inquiry(bt_list->dev_id,
- inquiry_time,
- INQUIRY_MAX_RSP,
- NULL,
- &bt_list->ii,
- IREQ_CACHE_FLUSH);
- if (bt_list->num_rsp < 0)
- goto no_rsp;
-
- bt_list->rsp = 0;
- return bt_list;
-
-no_rsp:
- close(bt_list->sock);
-no_sock:
-no_dev_id:
- free(bt_list->ii);
-no_ii:
- free(bt_list);
-no_bt_list:
- return NULL;
-}
-
-int
-altos_bt_list_next(struct altos_bt_list *bt_list,
- struct altos_bt_device *device)
-{
- inquiry_info *ii;
-
- if (bt_list->rsp >= bt_list->num_rsp)
- return 0;
-
- ii = &bt_list->ii[bt_list->rsp];
- if (ba2str(&ii->bdaddr, device->addr) < 0)
- return 0;
- memset(&device->name, '\0', sizeof (device->name));
- if (hci_read_remote_name(bt_list->sock, &ii->bdaddr,
- sizeof (device->name),
- device->name, 0) < 0) {
- strcpy(device->name, "[unknown]");
- }
- bt_list->rsp++;
- return 1;
-}
-
-void
-altos_bt_list_finish(struct altos_bt_list *bt_list)
-{
- close(bt_list->sock);
- free(bt_list->ii);
- free(bt_list);
-}
-
-void
-altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device)
-{
- strncpy(device->name, name, sizeof (device->name));
- device->name[sizeof(device->name)-1] = '\0';
- strncpy(device->addr, addr, sizeof (device->addr));
- device->addr[sizeof(device->addr)-1] = '\0';
-}
-
-struct altos_file *
-altos_bt_open(struct altos_bt_device *device)
-{
- struct sockaddr_rc addr = { 0 };
- int status, i;
- struct altos_file *file;
-
- file = calloc(1, sizeof (struct altos_file));
- if (!file) {
- errno = ENOMEM;
- altos_set_last_posix_error();
- goto no_file;
- }
- addr.rc_family = AF_BLUETOOTH;
- addr.rc_channel = 1;
- if (str2ba(device->addr, &addr.rc_bdaddr) < 0) {
- altos_set_last_posix_error();
- goto no_sock;
- }
-
- for (i = 0; i < 5; i++) {
- file->fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
- if (file->fd < 0) {
- altos_set_last_posix_error();
- goto no_sock;
- }
-
- status = connect(file->fd,
- (struct sockaddr *)&addr,
- sizeof(addr));
- if (status >= 0 || errno != EBUSY)
- break;
- close(file->fd);
- usleep(100 * 1000);
- }
- if (status < 0) {
- altos_set_last_posix_error();
- goto no_link;
- }
- usleep(100 * 1000);
-
-#ifdef USE_POLL
- pipe(file->pipe);
-#else
- file->out_fd = dup(file->fd);
-#endif
- return file;
-no_link:
- close(file->fd);
-no_sock:
- free(file);
-no_file:
- return NULL;
-}
-
-#endif
-
-#ifdef DARWIN
-
-#include <IOKitLib.h>
-#include <IOKit/usb/USBspec.h>
-#include <sys/param.h>
-#include <paths.h>
-#include <CFNumber.h>
-#include <IOBSD.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-struct altos_list {
- io_iterator_t iterator;
- int ftdi;
-};
-
-static int
-get_string(io_object_t object, CFStringRef entry, char *result, int result_len)
-{
- CFTypeRef entry_as_string;
- Boolean got_string;
-
- entry_as_string = IORegistryEntrySearchCFProperty (object,
- kIOServicePlane,
- entry,
- kCFAllocatorDefault,
- kIORegistryIterateRecursively);
- if (entry_as_string) {
- got_string = CFStringGetCString(entry_as_string,
- result, result_len,
- kCFStringEncodingASCII);
-
- CFRelease(entry_as_string);
- if (got_string)
- return 1;
- }
- return 0;
-}
-
-static int
-get_number(io_object_t object, CFStringRef entry, int *result)
-{
- CFTypeRef entry_as_number;
- Boolean got_number;
-
- entry_as_number = IORegistryEntrySearchCFProperty (object,
- kIOServicePlane,
- entry,
- kCFAllocatorDefault,
- kIORegistryIterateRecursively);
- if (entry_as_number) {
- got_number = CFNumberGetValue(entry_as_number,
- kCFNumberIntType,
- result);
- if (got_number)
- return 1;
- }
- return 0;
-}
-
-PUBLIC struct altos_list *
-altos_list_start(void)
-{
- struct altos_list *list = calloc (sizeof (struct altos_list), 1);
- CFMutableDictionaryRef matching_dictionary = IOServiceMatching("IOUSBDevice");
- io_iterator_t tdIterator;
- io_object_t tdObject;
- kern_return_t ret;
- int i;
-
- ret = IOServiceGetMatchingServices(kIOMasterPortDefault, matching_dictionary, &list->iterator);
- if (ret != kIOReturnSuccess) {
- free(list);
- return NULL;
- }
- list->ftdi = 0;
- return list;
-}
-
-PUBLIC struct altos_list *
-altos_ftdi_list_start(void)
-{
- struct altos_list *list = altos_list_start();
-
- if (list)
- list->ftdi = 1;
- return list;
-}
-
-PUBLIC int
-altos_list_next(struct altos_list *list, struct altos_device *device)
-{
- io_object_t object;
- char serial_string[128];
-
- for (;;) {
- object = IOIteratorNext(list->iterator);
- if (!object)
- return 0;
-
- if (!get_number (object, CFSTR(kUSBVendorID), &device->vendor) ||
- !get_number (object, CFSTR(kUSBProductID), &device->product))
- continue;
- if (get_string (object, CFSTR("IOCalloutDevice"), device->path, sizeof (device->path)) &&
- get_string (object, CFSTR("USB Product Name"), device->name, sizeof (device->name)) &&
- get_string (object, CFSTR("USB Serial Number"), serial_string, sizeof (serial_string))) {
- device->serial = atoi(serial_string);
- return 1;
- }
- }
-}
-
-PUBLIC void
-altos_list_finish(struct altos_list *list)
-{
- IOObjectRelease (list->iterator);
- 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
-
-
-#ifdef WINDOWS
-
-#include <stdlib.h>
-#include <windows.h>
-#include <setupapi.h>
-
-struct altos_list {
- HDEVINFO dev_info;
- int index;
- int ftdi;
-};
-
-#define USB_BUF_SIZE 64
-
-struct altos_file {
- HANDLE handle;
- unsigned char out_data[USB_BUF_SIZE];
- int out_used;
- unsigned char in_data[USB_BUF_SIZE];
- int in_used;
- int in_read;
- OVERLAPPED ov_read;
- BOOL pend_read;
- OVERLAPPED ov_write;
-};
-
-#include <stdarg.h>
-
-static void
-log_message(char *fmt, ...)
-{
- static FILE *log = NULL;
- va_list a;
-
- if (!log)
- log = fopen("\\temp\\altos.txt", "w");
- if (log) {
- SYSTEMTIME time;
- GetLocalTime(&time);
- fprintf (log, "%4d-%02d-%02d %2d:%02d:%02d. ",
- time.wYear, time.wMonth, time.wDay,
- time.wHour, time.wMinute, time.wSecond);
- va_start(a, fmt);
- vfprintf(log, fmt, a);
- va_end(a);
- fflush(log);
- }
-}
-
-static void
-_altos_set_last_windows_error(char *file, int line)
-{
- DWORD error = GetLastError();
- TCHAR message[1024];
- FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
- 0,
- error,
- 0,
- message,
- sizeof (message) / sizeof (TCHAR),
- NULL);
- if (error != ERROR_SUCCESS)
- log_message ("%s:%d %s\n", file, line, message);
- altos_set_last_error(error, message);
-}
-
-#define altos_set_last_windows_error() _altos_set_last_windows_error(__FILE__, __LINE__)
-
-PUBLIC struct altos_list *
-altos_list_start(void)
-{
- struct altos_list *list = calloc(1, sizeof (struct altos_list));
-
- if (!list)
- return NULL;
- list->dev_info = SetupDiGetClassDevs(NULL, "USB", NULL,
- DIGCF_ALLCLASSES|DIGCF_PRESENT);
- if (list->dev_info == INVALID_HANDLE_VALUE) {
- altos_set_last_windows_error();
- free(list);
- return NULL;
- }
- list->index = 0;
- list->ftdi = 0;
- return list;
-}
-
-PUBLIC struct altos_list *
-altos_ftdi_list_start(void)
-{
- struct altos_list *list = calloc(1, sizeof (struct altos_list));
-
- if (!list)
- return NULL;
- list->dev_info = SetupDiGetClassDevs(NULL, "FTDIBUS", NULL,
- DIGCF_ALLCLASSES|DIGCF_PRESENT);
- if (list->dev_info == INVALID_HANDLE_VALUE) {
- altos_set_last_windows_error();
- free(list);
- return NULL;
- }
- list->index = 0;
- list->ftdi = 1;
- return list;
-}
-
-PUBLIC int
-altos_list_next(struct altos_list *list, struct altos_device *device)
-{
- SP_DEVINFO_DATA dev_info_data;
- BYTE port[128];
- DWORD port_len;
- char friendlyname[256];
- BYTE symbolic[256];
- DWORD symbolic_len;
- HKEY dev_key;
- unsigned int vid, pid;
- int serial;
- HRESULT result;
- DWORD friendlyname_type;
- DWORD friendlyname_len;
- char instanceid[1024];
- DWORD instanceid_len;
-
- dev_info_data.cbSize = sizeof (SP_DEVINFO_DATA);
- while(SetupDiEnumDeviceInfo(list->dev_info, list->index,
- &dev_info_data))
- {
- list->index++;
-
- dev_key = SetupDiOpenDevRegKey(list->dev_info, &dev_info_data,
- DICS_FLAG_GLOBAL, 0, DIREG_DEV,
- KEY_READ);
- if (dev_key == INVALID_HANDLE_VALUE) {
- altos_set_last_windows_error();
- continue;
- }
-
- if (list->ftdi) {
- vid = 0x0403;
- pid = 0x6015;
- serial = 0;
- } else {
- vid = pid = serial = 0;
- /* Fetch symbolic name for this device and parse out
- * the vid/pid/serial info */
- symbolic_len = sizeof(symbolic);
- result = RegQueryValueEx(dev_key, "SymbolicName", NULL, NULL,
- symbolic, &symbolic_len);
- if (result != 0) {
- altos_set_last_windows_error();
- } else {
- sscanf((char *) symbolic + sizeof("\\??\\USB#VID_") - 1,
- "%04X", &vid);
- sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_") - 1,
- "%04X", &pid);
- sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_XXXX#") - 1,
- "%d", &serial);
- }
- if (vid == 0 || pid == 0 || serial == 0) {
- if (SetupDiGetDeviceInstanceId(list->dev_info,
- &dev_info_data,
- instanceid,
- sizeof (instanceid),
- &instanceid_len)) {
- sscanf((char *) instanceid + sizeof("USB\\VID_") - 1,
- "%04X", &vid);
- sscanf((char *) instanceid + sizeof("USB\\VID_XXXX&PID_") - 1,
- "%04X", &pid);
- sscanf((char *) instanceid + sizeof("USB\\VID_XXXX&PID_XXXX\\") - 1,
- "%d", &serial);
- } else {
- altos_set_last_windows_error();
- }
- }
- if (vid == 0 || pid == 0 || serial == 0) {
- RegCloseKey(dev_key);
- continue;
- }
- }
-
- /* Fetch the com port name */
- port_len = sizeof (port);
- result = RegQueryValueEx(dev_key, "PortName", NULL, NULL,
- port, &port_len);
- RegCloseKey(dev_key);
- if (result != 0) {
- altos_set_last_windows_error();
- continue;
- }
-
- /* Fetch the device description which is the device name,
- * with firmware that has unique USB ids */
- friendlyname_len = sizeof (friendlyname);
- if(!SetupDiGetDeviceRegistryProperty(list->dev_info,
- &dev_info_data,
- SPDRP_FRIENDLYNAME,
- &friendlyname_type,
- (BYTE *)friendlyname,
- sizeof(friendlyname),
- &friendlyname_len))
- {
- altos_set_last_windows_error();
- continue;
- }
- device->vendor = vid;
- device->product = pid;
- device->serial = serial;
- strcpy(device->name, friendlyname);
-
- strcpy(device->path, (char *) port);
- return 1;
- }
- result = GetLastError();
- if (result != ERROR_NO_MORE_ITEMS)
- altos_set_last_windows_error();
- return 0;
-}
-
-PUBLIC void
-altos_list_finish(struct altos_list *list)
-{
- SetupDiDestroyDeviceInfoList(list->dev_info);
- free(list);
-}
-
-static int
-altos_queue_read(struct altos_file *file)
-{
- DWORD got;
- if (file->pend_read)
- return LIBALTOS_SUCCESS;
-
- if (!ReadFile(file->handle, file->in_data, USB_BUF_SIZE, &got, &file->ov_read)) {
- if (GetLastError() != ERROR_IO_PENDING) {
- altos_set_last_windows_error();
- return LIBALTOS_ERROR;
- }
- file->pend_read = TRUE;
- } else {
- file->pend_read = FALSE;
- file->in_read = 0;
- file->in_used = got;
- }
- return LIBALTOS_SUCCESS;
-}
-
-static int
-altos_wait_read(struct altos_file *file, int timeout)
-{
- DWORD ret;
- DWORD got;
-
- if (!file->pend_read)
- return LIBALTOS_SUCCESS;
-
- if (!timeout)
- timeout = INFINITE;
-
- ret = WaitForSingleObject(file->ov_read.hEvent, timeout);
- switch (ret) {
- case WAIT_OBJECT_0:
- 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;
- break;
- case WAIT_TIMEOUT:
- return LIBALTOS_TIMEOUT;
- break;
- default:
- altos_set_last_windows_error();
- return LIBALTOS_ERROR;
- }
- return LIBALTOS_SUCCESS;
-}
-
-static int
-altos_fill(struct altos_file *file, int timeout)
-{
- int ret;
-
- if (file->in_read < file->in_used)
- return LIBALTOS_SUCCESS;
-
- file->in_read = file->in_used = 0;
-
- ret = altos_queue_read(file);
- if (ret)
- return ret;
- ret = altos_wait_read(file, timeout);
- if (ret)
- return ret;
-
- return LIBALTOS_SUCCESS;
-}
-
-PUBLIC int
-altos_flush(struct altos_file *file)
-{
- DWORD put;
- unsigned char *data = file->out_data;
- int used = file->out_used;
- DWORD ret;
-
- while (used) {
- if (!WriteFile(file->handle, data, used, &put, &file->ov_write)) {
- 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)) {
- altos_set_last_windows_error();
- return LIBALTOS_ERROR;
- }
- break;
- default:
- altos_set_last_windows_error();
- return LIBALTOS_ERROR;
- }
- }
- data += put;
- used -= put;
- }
- file->out_used = 0;
- return LIBALTOS_SUCCESS;
-}
-
-static HANDLE
-open_serial(char *full_name)
-{
- HANDLE handle;
- DCB dcb;
-
- handle = CreateFile(full_name, GENERIC_READ|GENERIC_WRITE,
- 0, NULL, OPEN_EXISTING,
- FILE_FLAG_OVERLAPPED, NULL);
-
- if (handle == INVALID_HANDLE_VALUE) {
- altos_set_last_windows_error();
- return INVALID_HANDLE_VALUE;
- }
-
- if (!GetCommState(handle, &dcb)) {
- altos_set_last_windows_error();
- CloseHandle(handle);
- return INVALID_HANDLE_VALUE;
- }
- dcb.BaudRate = CBR_9600;
- dcb.fBinary = TRUE;
- dcb.fParity = FALSE;
- dcb.fOutxCtsFlow = FALSE;
- dcb.fOutxDsrFlow = FALSE;
- dcb.fDtrControl = DTR_CONTROL_ENABLE;
- dcb.fDsrSensitivity = FALSE;
- dcb.fTXContinueOnXoff = FALSE;
- dcb.fOutX = FALSE;
- dcb.fInX = FALSE;
- dcb.fErrorChar = FALSE;
- dcb.fNull = FALSE;
- dcb.fRtsControl = RTS_CONTROL_ENABLE;
- dcb.fAbortOnError = FALSE;
- dcb.XonLim = 10;
- dcb.XoffLim = 10;
- dcb.ByteSize = 8;
- dcb.Parity = NOPARITY;
- dcb.StopBits = ONESTOPBIT;
- dcb.XonChar = 17;
- dcb.XoffChar = 19;
-#if 0
- dcb.ErrorChar = 0;
- dcb.EofChar = 0;
- dcb.EvtChar = 0;
-#endif
- if (!SetCommState(handle, &dcb)) {
- altos_set_last_windows_error();
- CloseHandle(handle);
- return INVALID_HANDLE_VALUE;
- }
- return handle;
-}
-
-PUBLIC struct altos_file *
-altos_open(struct altos_device *device)
-{
- struct altos_file *file = calloc (1, sizeof (struct altos_file));
- char full_name[64];
- COMMTIMEOUTS timeouts;
- int i;
-
- if (!file)
- return NULL;
-
- strcpy(full_name, "\\\\.\\");
- strcat(full_name, device->path);
-
- file->handle = INVALID_HANDLE_VALUE;
-
- for (i = 0; i < 5; i++) {
- file->handle = open_serial(full_name);
- if (file->handle != INVALID_HANDLE_VALUE)
- break;
- altos_set_last_windows_error();
- Sleep(100);
- }
-
- if (file->handle == INVALID_HANDLE_VALUE) {
- free(file);
- return NULL;
- }
-
- /* The FTDI driver doesn't appear to work right unless you open it twice */
- if (device->vendor == 0x0403) {
- CloseHandle(file->handle);
- file->handle = open_serial(full_name);
- if (file->handle == INVALID_HANDLE_VALUE) {
- free(file);
- return NULL;
- }
- }
-
- timeouts.ReadIntervalTimeout = MAXDWORD;
- timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
- timeouts.ReadTotalTimeoutConstant = 1 << 30; /* almost forever */
- timeouts.WriteTotalTimeoutMultiplier = 0;
- timeouts.WriteTotalTimeoutConstant = 0;
- SetCommTimeouts(file->handle, &timeouts);
-
- file->ov_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- file->ov_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
-
- return file;
-}
-
-PUBLIC void
-altos_close(struct altos_file *file)
-{
- HANDLE handle = file->handle;
- if (handle != INVALID_HANDLE_VALUE) {
- HANDLE ov_read = file->ov_read.hEvent;
- HANDLE ov_write = file->ov_write.hEvent;
- file->handle = INVALID_HANDLE_VALUE;
- file->ov_read.hEvent = INVALID_HANDLE_VALUE;
- file->ov_write.hEvent = INVALID_HANDLE_VALUE;
- PurgeComm(handle, PURGE_RXABORT|PURGE_RXCLEAR|PURGE_TXABORT|PURGE_TXCLEAR);
- Sleep(100);
- CloseHandle(handle);
- file->handle = INVALID_HANDLE_VALUE;
- CloseHandle(ov_read);
- CloseHandle(ov_write);
- }
-}
-
-PUBLIC void
-altos_free(struct altos_file *file)
-{
- altos_close(file);
- free(file);
-}
-
-PUBLIC int
-altos_putchar(struct altos_file *file, char c)
-{
- int ret;
-
- if (file->out_used == USB_BUF_SIZE) {
- ret = altos_flush(file);
- if (ret)
- return ret;
- }
- file->out_data[file->out_used++] = c;
- if (file->out_used == USB_BUF_SIZE)
- return altos_flush(file);
- return LIBALTOS_SUCCESS;
-}
-
-PUBLIC int
-altos_getchar(struct altos_file *file, int timeout)
-{
- int ret;
- while (file->in_read == file->in_used) {
- if (file->handle == INVALID_HANDLE_VALUE) {
- altos_set_last_windows_error();
- return LIBALTOS_ERROR;
- }
- ret = altos_fill(file, timeout);
- if (ret)
- return ret;
- }
- 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
--- /dev/null
+/*
+ * Copyright © 2016 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 "libaltos_private.h"
+
+PUBLIC int
+altos_init(void)
+{
+ return LIBALTOS_SUCCESS;
+}
+
+PUBLIC void
+altos_fini(void)
+{
+}
+
+struct altos_error altos_last_error;
+
+void
+altos_set_last_error(int code, char *string)
+{
+ altos_last_error.code = code;
+ strncpy(altos_last_error.string, string, sizeof (altos_last_error.string) -1);
+ altos_last_error.string[sizeof(altos_last_error.string)-1] = '\0';
+}
+
+PUBLIC void
+altos_get_last_error(struct altos_error *error)
+{
+ *error = altos_last_error;
+}
+
+PUBLIC int
+altos_getchar(struct altos_file *file, int timeout)
+{
+ int ret;
+ while (file->in_read == file->in_used) {
+ ret = altos_fill(file, timeout);
+ if (ret)
+ return ret;
+ }
+ return file->in_data[file->in_read++];
+}
+
+PUBLIC int
+altos_putchar(struct altos_file *file, char c)
+{
+ int ret;
+
+ if (file->out_used == USB_BUF_SIZE) {
+ ret = altos_flush(file);
+ if (ret) {
+ return ret;
+ }
+ }
+ file->out_data[file->out_used++] = c;
+ ret = 0;
+ if (file->out_used == USB_BUF_SIZE)
+ ret = altos_flush(file);
+ return ret;
+}
+
+
+PUBLIC void
+altos_free(struct altos_file *file)
+{
+ altos_close(file);
+ free(file);
+}
--- /dev/null
+/*
+ * Copyright © 2016 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 "libaltos_private.h"
+#include "libaltos_posix.h"
+
+#include <IOKitLib.h>
+#include <IOKit/usb/USBspec.h>
+#include <IOKit/serial/IOSerialKeys.h>
+#include <usb/IOUSBLib.h>
+#include <usb/USBSpec.h>
+#include <sys/param.h>
+#include <paths.h>
+#include <CFNumber.h>
+#include <IOBSD.h>
+
+/* Mac OS X don't have strndup even if _GNU_SOURCE is defined */
+char *
+altos_strndup (const char *s, size_t n)
+{
+ size_t len = strlen (s);
+ char *ret;
+
+ if (len <= n)
+ return strdup (s);
+ ret = malloc(n + 1);
+ strncpy(ret, s, n);
+ ret[n] = '\0';
+ return ret;
+}
+
+struct altos_list {
+ io_iterator_t iterator;
+ int ftdi;
+};
+
+static char *
+get_cfstring(CFTypeRef string, char result[512])
+{
+ Boolean got_string;
+
+ got_string = CFStringGetCString(string, result, 512, kCFStringEncodingASCII);
+ if (!got_string)
+ strcpy(result, "CFStringGetCString failed");
+ return result;
+}
+
+static int
+get_string(io_object_t object, CFStringRef entry, char *result, int result_len)
+{
+ CFTypeRef entry_as_string;
+ Boolean got_string;
+ char entry_string[512];
+
+ entry_as_string = IORegistryEntrySearchCFProperty (object,
+ kIOServicePlane,
+ entry,
+ kCFAllocatorDefault,
+ kIORegistryIterateRecursively);
+ if (entry_as_string) {
+ got_string = CFStringGetCString(entry_as_string,
+ result, result_len,
+ kCFStringEncodingASCII);
+
+ CFRelease(entry_as_string);
+ if (got_string) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int
+get_number(io_object_t object, CFStringRef entry, int *result)
+{
+ CFTypeRef entry_as_number;
+ Boolean got_number;
+ char entry_string[512];
+
+ entry_as_number = IORegistryEntrySearchCFProperty (object,
+ kIOServicePlane,
+ entry,
+ kCFAllocatorDefault,
+ kIORegistryIterateRecursively);
+ if (entry_as_number) {
+ got_number = CFNumberGetValue(entry_as_number,
+ kCFNumberIntType,
+ result);
+ if (got_number) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+PUBLIC struct altos_list *
+altos_list_start(void)
+{
+ struct altos_list *list = calloc (sizeof (struct altos_list), 1);
+ CFMutableDictionaryRef matching_dictionary;
+ io_iterator_t tdIterator;
+ io_object_t tdObject;
+ kern_return_t ret;
+ int i;
+
+ matching_dictionary = IOServiceMatching(kIOSerialBSDServiceValue);
+ if (matching_dictionary) {
+ CFDictionarySetValue(matching_dictionary,
+ CFSTR(kIOSerialBSDTypeKey),
+ CFSTR(kIOSerialBSDAllTypes));
+ }
+
+ ret = IOServiceGetMatchingServices(kIOMasterPortDefault, matching_dictionary, &list->iterator);
+ if (ret != kIOReturnSuccess) {
+ free(list);
+ return NULL;
+ }
+ list->ftdi = 0;
+ return list;
+}
+
+PUBLIC struct altos_list *
+altos_ftdi_list_start(void)
+{
+ struct altos_list *list = altos_list_start();
+
+ if (list)
+ list->ftdi = 1;
+ return list;
+}
+
+static io_service_t get_usb_object(io_object_t serial_device)
+{
+ io_iterator_t iterator;
+ io_service_t usb_device;
+ io_service_t service;
+ IOReturn status;
+
+ status = IORegistryEntryCreateIterator(serial_device,
+ kIOServicePlane,
+ kIORegistryIterateParents | kIORegistryIterateRecursively,
+ &iterator);
+
+ if (status != kIOReturnSuccess)
+ return 0;
+
+ while((service = IOIteratorNext(iterator))) {
+ io_name_t servicename;
+ status = IORegistryEntryGetNameInPlane(service, kIOServicePlane, servicename);
+
+ if (status == kIOReturnSuccess && IOObjectConformsTo(service, kIOUSBDeviceClassName)) {
+ IOObjectRelease(iterator);
+ return service;
+ }
+ IOObjectRelease(service);
+ }
+ IOObjectRelease(iterator);
+ return 0;
+}
+
+PUBLIC int
+altos_list_next(struct altos_list *list, struct altos_device *device)
+{
+
+ io_object_t object;
+ io_service_t usb_device;
+ char serial_string[128];
+
+ for (;;) {
+ object = IOIteratorNext(list->iterator);
+ if (!object) {
+ return 0;
+ }
+
+ usb_device = get_usb_object(object);
+
+ if (get_number (usb_device, CFSTR(kUSBVendorID), &device->vendor) &&
+ get_number (usb_device, CFSTR(kUSBProductID), &device->product) &&
+ get_string (object, CFSTR(kIOCalloutDeviceKey), device->path, sizeof (device->path)) &&
+ get_string (usb_device, CFSTR(kUSBProductString), device->name, sizeof (device->name)) &&
+ get_string (usb_device, CFSTR(kUSBSerialNumberString), serial_string, sizeof (serial_string))) {
+ device->serial = atoi(serial_string);
+ IOObjectRelease(object);
+ IOObjectRelease(usb_device);
+ return 1;
+ }
+ IOObjectRelease(object);
+ IOObjectRelease(usb_device);
+ }
+}
+
+PUBLIC void
+altos_list_finish(struct altos_list *list)
+{
+ IOObjectRelease (list->iterator);
+ 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;
+}
--- /dev/null
+/*
+ * Copyright © 2016 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.
+ */
+
+#define _GNU_SOURCE
+#include "libaltos_private.h"
+#include "libaltos_posix.h"
+
+#include <ctype.h>
+#include <dirent.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_lib.h>
+#include <bluetooth/rfcomm.h>
+
+static char *
+cc_fullname (char *dir, char *file)
+{
+ char *new;
+ int dlen = strlen (dir);
+ int flen = strlen (file);
+ int slen = 0;
+
+ if (dir[dlen-1] != '/')
+ slen = 1;
+ new = malloc (dlen + slen + flen + 1);
+ if (!new)
+ return 0;
+ strcpy(new, dir);
+ if (slen)
+ strcat (new, "/");
+ strcat(new, file);
+ return new;
+}
+
+static char *
+cc_basename(char *file)
+{
+ char *b;
+
+ b = strrchr(file, '/');
+ if (!b)
+ return file;
+ return b + 1;
+}
+
+static char *
+load_string(char *dir, char *file)
+{
+ char *full = cc_fullname(dir, file);
+ char line[4096];
+ char *r;
+ FILE *f;
+ int rlen;
+
+ f = fopen(full, "r");
+ free(full);
+ if (!f)
+ return NULL;
+ r = fgets(line, sizeof (line), f);
+ fclose(f);
+ if (!r)
+ return NULL;
+ rlen = strlen(r);
+ if (r[rlen-1] == '\n')
+ r[rlen-1] = '\0';
+ return strdup(r);
+}
+
+static int
+load_hex(char *dir, char *file)
+{
+ char *line;
+ char *end;
+ long i;
+
+ line = load_string(dir, file);
+ if (!line)
+ return -1;
+ i = strtol(line, &end, 16);
+ free(line);
+ if (end == line)
+ return -1;
+ return i;
+}
+
+static int
+load_dec(char *dir, char *file)
+{
+ char *line;
+ char *end;
+ long i;
+
+ line = load_string(dir, file);
+ if (!line)
+ return -1;
+ i = strtol(line, &end, 10);
+ free(line);
+ if (end == line)
+ return -1;
+ return i;
+}
+
+static int
+dir_filter_tty_colon(const struct dirent *d)
+{
+ return strncmp(d->d_name, "tty:", 4) == 0;
+}
+
+static int
+dir_filter_tty(const struct dirent *d)
+{
+ return strncmp(d->d_name, "tty", 3) == 0;
+}
+
+struct altos_usbdev {
+ char *sys;
+ char *tty;
+ char *manufacturer;
+ char *product_name;
+ int serial; /* AltOS always uses simple integer serial numbers */
+ int idProduct;
+ int idVendor;
+};
+
+static char *
+usb_tty(char *sys)
+{
+ char *base;
+ int num_configs;
+ int config;
+ struct dirent **namelist;
+ int interface;
+ int num_interfaces;
+ char endpoint_base[20];
+ char *endpoint_full;
+ char *tty_dir;
+ int ntty;
+ char *tty;
+
+ base = cc_basename(sys);
+ num_configs = load_hex(sys, "bNumConfigurations");
+ num_interfaces = load_hex(sys, "bNumInterfaces");
+ for (config = 1; config <= num_configs; config++) {
+ for (interface = 0; interface < num_interfaces; interface++) {
+ sprintf(endpoint_base, "%s:%d.%d",
+ base, config, interface);
+ endpoint_full = cc_fullname(sys, endpoint_base);
+
+
+ /* Check for tty:ttyACMx style names
+ */
+ ntty = scandir(endpoint_full, &namelist,
+ dir_filter_tty_colon,
+ alphasort);
+ if (ntty > 0) {
+ free(endpoint_full);
+ tty = cc_fullname("/dev", namelist[0]->d_name + 4);
+ free(namelist);
+ return tty;
+ }
+
+ /* Check for tty/ttyACMx style names
+ */
+ tty_dir = cc_fullname(endpoint_full, "tty");
+ ntty = scandir(tty_dir, &namelist,
+ dir_filter_tty,
+ alphasort);
+ free (tty_dir);
+ if (ntty > 0) {
+ tty = cc_fullname("/dev", namelist[0]->d_name);
+ free(endpoint_full);
+ free(namelist);
+ return tty;
+ }
+
+ /* Check for ttyACMx style names
+ */
+ ntty = scandir(endpoint_full, &namelist,
+ dir_filter_tty,
+ alphasort);
+ free(endpoint_full);
+ if (ntty > 0) {
+ tty = cc_fullname("/dev", namelist[0]->d_name);
+ free(namelist);
+ return tty;
+ }
+
+ }
+ }
+ return NULL;
+}
+
+static struct altos_usbdev *
+usb_scan_device(char *sys)
+{
+ struct altos_usbdev *usbdev;
+ char *tty;
+
+ tty = usb_tty(sys);
+ if (!tty)
+ return NULL;
+ usbdev = calloc(1, sizeof (struct altos_usbdev));
+ if (!usbdev)
+ return NULL;
+ usbdev->sys = strdup(sys);
+ usbdev->manufacturer = load_string(sys, "manufacturer");
+ usbdev->product_name = load_string(sys, "product");
+ usbdev->serial = load_dec(sys, "serial");
+ usbdev->idProduct = load_hex(sys, "idProduct");
+ usbdev->idVendor = load_hex(sys, "idVendor");
+ usbdev->tty = tty;
+ return usbdev;
+}
+
+static void
+usbdev_free(struct altos_usbdev *usbdev)
+{
+ free(usbdev->sys);
+ free(usbdev->manufacturer);
+ free(usbdev->product_name);
+ /* this can get used as a return value */
+ if (usbdev->tty)
+ free(usbdev->tty);
+ free(usbdev);
+}
+
+#define USB_DEVICES "/sys/bus/usb/devices"
+
+static int
+dir_filter_dev(const struct dirent *d)
+{
+ const char *n = d->d_name;
+ char c;
+
+ while ((c = *n++)) {
+ if (isdigit(c))
+ continue;
+ if (c == '-')
+ continue;
+ if (c == '.' && n != d->d_name + 1)
+ continue;
+ return 0;
+ }
+ return 1;
+}
+
+struct altos_list {
+ struct altos_usbdev **dev;
+ int current;
+ int ndev;
+};
+
+struct altos_list *
+altos_list_start(void)
+{
+ int e;
+ struct dirent **ents;
+ char *dir;
+ struct altos_usbdev *dev;
+ struct altos_list *devs;
+ int n;
+
+ devs = calloc(1, sizeof (struct altos_list));
+ if (!devs)
+ return NULL;
+
+ n = scandir (USB_DEVICES, &ents,
+ dir_filter_dev,
+ alphasort);
+ if (!n)
+ return 0;
+ for (e = 0; e < n; e++) {
+ dir = cc_fullname(USB_DEVICES, ents[e]->d_name);
+ dev = usb_scan_device(dir);
+ if (!dev)
+ continue;
+ free(dir);
+ if (devs->dev)
+ devs->dev = realloc(devs->dev,
+ (devs->ndev + 1) * sizeof (struct usbdev *));
+ else
+ devs->dev = malloc (sizeof (struct usbdev *));
+ devs->dev[devs->ndev++] = dev;
+ }
+ free(ents);
+ devs->current = 0;
+ return devs;
+}
+
+PUBLIC struct altos_list *
+altos_ftdi_list_start(void)
+{
+ return altos_list_start();
+}
+
+int
+altos_list_next(struct altos_list *list, struct altos_device *device)
+{
+ struct altos_usbdev *dev;
+ if (list->current >= list->ndev) {
+ return 0;
+ }
+ dev = list->dev[list->current];
+ strcpy(device->name, dev->product_name);
+ device->vendor = dev->idVendor;
+ device->product = dev->idProduct;
+ strcpy(device->path, dev->tty);
+ device->serial = dev->serial;
+ list->current++;
+ return 1;
+}
+
+void
+altos_list_finish(struct altos_list *usbdevs)
+{
+ int i;
+
+ if (!usbdevs)
+ return;
+ for (i = 0; i < usbdevs->ndev; i++)
+ usbdev_free(usbdevs->dev[i]);
+ free(usbdevs);
+}
+
+#include <dlfcn.h>
+
+static void *libbt;
+static int bt_initialized;
+
+static int init_bt(void) {
+ if (!bt_initialized) {
+ bt_initialized = 1;
+ libbt = dlopen("libbluetooth.so.3", RTLD_LAZY);
+ if (!libbt)
+ printf("failed to find bluetooth library\n");
+ }
+ return libbt != NULL;
+}
+
+#define join(a,b) a ## b
+#define bt_func(name, ret, fail, formals, actuals) \
+ static ret join(altos_, name) formals { \
+ static ret (*name) formals; \
+ if (!init_bt()) return fail; \
+ name = dlsym(libbt, #name); \
+ if (!name) return fail; \
+ return name actuals; \
+ }
+
+bt_func(ba2str, int, -1, (const bdaddr_t *ba, char *str), (ba, str))
+#define ba2str altos_ba2str
+
+bt_func(str2ba, int, -1, (const char *str, bdaddr_t *ba), (str, ba))
+#define str2ba altos_str2ba
+
+bt_func(hci_read_remote_name, int, -1, (int sock, const bdaddr_t *ba, int len, char *name, int timeout), (sock, ba, len, name, timeout))
+#define hci_read_remote_name altos_hci_read_remote_name
+
+bt_func(hci_open_dev, int, -1, (int dev_id), (dev_id))
+#define hci_open_dev altos_hci_open_dev
+
+bt_func(hci_get_route, int, -1, (bdaddr_t *bdaddr), (bdaddr))
+#define hci_get_route altos_hci_get_route
+
+bt_func(hci_inquiry, int, -1, (int adapter_id, int len, int max_rsp, const uint8_t *lap, inquiry_info **devs, long flags), (adapter_id, len, max_rsp, lap, devs, flags))
+#define hci_inquiry altos_hci_inquiry
+
+struct altos_bt_list {
+ inquiry_info *ii;
+ int sock;
+ int dev_id;
+ int rsp;
+ int num_rsp;
+};
+
+#define INQUIRY_MAX_RSP 255
+
+struct altos_bt_list *
+altos_bt_list_start(int inquiry_time)
+{
+ struct altos_bt_list *bt_list;
+
+ bt_list = calloc(1, sizeof (struct altos_bt_list));
+ if (!bt_list)
+ goto no_bt_list;
+
+ bt_list->ii = calloc(INQUIRY_MAX_RSP, sizeof (inquiry_info));
+ if (!bt_list->ii)
+ goto no_ii;
+ bt_list->dev_id = hci_get_route(NULL);
+ if (bt_list->dev_id < 0)
+ goto no_dev_id;
+
+ bt_list->sock = hci_open_dev(bt_list->dev_id);
+ if (bt_list->sock < 0)
+ goto no_sock;
+
+ bt_list->num_rsp = hci_inquiry(bt_list->dev_id,
+ inquiry_time,
+ INQUIRY_MAX_RSP,
+ NULL,
+ &bt_list->ii,
+ IREQ_CACHE_FLUSH);
+ if (bt_list->num_rsp < 0)
+ goto no_rsp;
+
+ bt_list->rsp = 0;
+ return bt_list;
+
+no_rsp:
+ close(bt_list->sock);
+no_sock:
+no_dev_id:
+ free(bt_list->ii);
+no_ii:
+ free(bt_list);
+no_bt_list:
+ return NULL;
+}
+
+int
+altos_bt_list_next(struct altos_bt_list *bt_list,
+ struct altos_bt_device *device)
+{
+ inquiry_info *ii;
+
+ if (bt_list->rsp >= bt_list->num_rsp)
+ return 0;
+
+ ii = &bt_list->ii[bt_list->rsp];
+ if (ba2str(&ii->bdaddr, device->addr) < 0)
+ return 0;
+ memset(&device->name, '\0', sizeof (device->name));
+ if (hci_read_remote_name(bt_list->sock, &ii->bdaddr,
+ sizeof (device->name),
+ device->name, 0) < 0) {
+ strcpy(device->name, "[unknown]");
+ }
+ bt_list->rsp++;
+ return 1;
+}
+
+void
+altos_bt_list_finish(struct altos_bt_list *bt_list)
+{
+ close(bt_list->sock);
+ free(bt_list->ii);
+ free(bt_list);
+}
+
+void
+altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device)
+{
+ strncpy(device->name, name, sizeof (device->name));
+ device->name[sizeof(device->name)-1] = '\0';
+ strncpy(device->addr, addr, sizeof (device->addr));
+ device->addr[sizeof(device->addr)-1] = '\0';
+}
+
+struct altos_file *
+altos_bt_open(struct altos_bt_device *device)
+{
+ struct sockaddr_rc addr = { 0 };
+ int status, i;
+ struct altos_file_posix *file;
+
+ file = calloc(1, sizeof (struct altos_file_posix));
+ if (!file) {
+ errno = ENOMEM;
+ altos_set_last_posix_error();
+ goto no_file;
+ }
+ addr.rc_family = AF_BLUETOOTH;
+ addr.rc_channel = 1;
+ if (str2ba(device->addr, &addr.rc_bdaddr) < 0) {
+ altos_set_last_posix_error();
+ goto no_sock;
+ }
+
+ for (i = 0; i < 5; i++) {
+ file->fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
+ if (file->fd < 0) {
+ altos_set_last_posix_error();
+ goto no_sock;
+ }
+
+ status = connect(file->fd,
+ (struct sockaddr *)&addr,
+ sizeof(addr));
+ if (status >= 0 || errno != EBUSY)
+ break;
+ close(file->fd);
+ usleep(100 * 1000);
+ }
+ if (status < 0) {
+ altos_set_last_posix_error();
+ goto no_link;
+ }
+ usleep(100 * 1000);
+
+#ifdef USE_POLL
+ pipe(file->pipe);
+#else
+ file->out_fd = dup(file->fd);
+#endif
+ return &file->file;
+no_link:
+ close(file->fd);
+no_sock:
+ free(file);
+no_file:
+ return NULL;
+}
+
--- /dev/null
+/*
+ * Copyright © 2016 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 "libaltos_private.h"
+#include "libaltos_posix.h"
+
+void
+altos_set_last_posix_error(void)
+{
+ altos_set_last_error(errno, strerror(errno));
+}
+
+PUBLIC struct altos_file *
+altos_open(struct altos_device *device)
+{
+ struct altos_file_posix *file = calloc (sizeof (struct altos_file_posix), 1);
+ int ret;
+ struct termios term;
+
+ 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) {
+ altos_set_last_posix_error();
+ free(file);
+ return NULL;
+ }
+#ifdef USE_POLL
+ pipe(file->pipe);
+#else
+ file->out_fd = open(device->path, O_RDWR | O_NOCTTY);
+ if (file->out_fd < 0) {
+ altos_set_last_posix_error();
+ close(file->fd);
+ free(file);
+ return NULL;
+ }
+#endif
+ ret = tcgetattr(file->fd, &term);
+ if (ret < 0) {
+ altos_set_last_posix_error();
+ close(file->fd);
+#ifndef USE_POLL
+ close(file->out_fd);
+#endif
+ free(file);
+ return NULL;
+ }
+ cfmakeraw(&term);
+ cfsetospeed(&term, B9600);
+ cfsetispeed(&term, B9600);
+#ifdef USE_POLL
+ term.c_cc[VMIN] = 1;
+ term.c_cc[VTIME] = 0;
+#else
+ term.c_cc[VMIN] = 0;
+ term.c_cc[VTIME] = 1;
+#endif
+ ret = tcsetattr(file->fd, TCSAFLUSH, &term);
+ if (ret < 0) {
+ altos_set_last_posix_error();
+ close(file->fd);
+#ifndef USE_POLL
+ close(file->out_fd);
+#endif
+ free(file);
+ return NULL;
+ }
+ return &file->file;
+}
+
+PUBLIC void
+altos_close(struct altos_file *file_common)
+{
+ struct altos_file_posix *file = (struct altos_file_posix *) file_common;
+
+ if (file->fd != -1) {
+ int fd = file->fd;
+ file->fd = -1;
+#ifdef USE_POLL
+ write(file->pipe[1], "\r", 1);
+#else
+ close(file->out_fd);
+ file->out_fd = -1;
+#endif
+ close(fd);
+ }
+}
+
+PUBLIC int
+altos_flush(struct altos_file *file_common)
+{
+ struct altos_file_posix *file = (struct altos_file_posix *) file_common;
+
+ if (file->file.out_used && 0) {
+ printf ("flush \"");
+ fwrite(file->file.out_data, 1, file->file.out_used, stdout);
+ printf ("\"\n");
+ }
+ while (file->file.out_used) {
+ int ret;
+
+ if (file->fd < 0)
+ return -EBADF;
+#ifdef USE_POLL
+ ret = write (file->fd, file->file.out_data, file->file.out_used);
+#else
+ ret = write (file->out_fd, file->file.out_data, file->file.out_used);
+#endif
+ if (ret < 0) {
+ altos_set_last_posix_error();
+ return -altos_last_error.code;
+ }
+ if (ret) {
+ memmove(file->file.out_data, file->file.out_data + ret,
+ file->file.out_used - ret);
+ file->file.out_used -= ret;
+ }
+ }
+ return 0;
+}
+
+
+#ifdef USE_POLL
+#include <poll.h>
+#endif
+
+int
+altos_fill(struct altos_file *file_common, int timeout)
+{
+ struct altos_file_posix *file = (struct altos_file_posix *) file_common;
+
+ int ret;
+#ifdef USE_POLL
+ struct pollfd fd[2];
+#endif
+ if (timeout == 0)
+ timeout = -1;
+ while (file->file.in_read == file->file.in_used) {
+ if (file->fd < 0)
+ return LIBALTOS_ERROR;
+#ifdef USE_POLL
+ fd[0].fd = file->fd;
+ fd[0].events = POLLIN|POLLERR|POLLHUP|POLLNVAL;
+ fd[1].fd = file->pipe[0];
+ fd[1].events = POLLIN;
+ ret = poll(fd, 2, timeout);
+ if (ret < 0) {
+ altos_set_last_posix_error();
+ return LIBALTOS_ERROR;
+ }
+ if (ret == 0)
+ return LIBALTOS_TIMEOUT;
+
+ if (fd[0].revents & (POLLHUP|POLLERR|POLLNVAL))
+ return LIBALTOS_ERROR;
+ if (fd[0].revents & POLLIN)
+#endif
+ {
+ ret = read(file->fd, file->file.in_data, USB_BUF_SIZE);
+ if (ret < 0) {
+ altos_set_last_posix_error();
+ return LIBALTOS_ERROR;
+ }
+ file->file.in_read = 0;
+ file->file.in_used = ret;
+#ifndef USE_POLL
+ if (ret == 0 && timeout > 0)
+ return LIBALTOS_TIMEOUT;
+#endif
+ }
+ }
+ if (file->file.in_used && 0) {
+ printf ("fill \"");
+ fwrite(file->file.in_data, 1, file->file.in_used, stdout);
+ printf ("\"\n");
+ }
+ return 0;
+}
+
--- /dev/null
+/*
+ * Copyright © 2016 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 _LIBALTOS_POSIX_H_
+#define _LIBALTOS_POSIX_H_
+
+#include <fcntl.h>
+#include <termios.h>
+#include <errno.h>
+#include <unistd.h>
+
+struct altos_file_posix {
+ struct altos_file file;
+
+ int fd;
+#ifdef USE_POLL
+ int pipe[2];
+#else
+ int out_fd;
+#endif
+};
+
+void
+altos_set_last_posix_error(void);
+
+#endif /* _LIBALTOS_POSIX_H_ */
--- /dev/null
+/*
+ * Copyright © 2016 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 _LIBALTOS_PRIVATE_H_
+#define _LIBALTOS_PRIVATE_H_
+
+#include "libaltos.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define BLUETOOTH_PRODUCT_TELEBT "TeleBT"
+
+#define USB_BUF_SIZE 64
+
+struct altos_file {
+ /* Shared data */
+ unsigned char out_data[USB_BUF_SIZE];
+ int out_used;
+ unsigned char in_data[USB_BUF_SIZE];
+ int in_used;
+ int in_read;
+};
+
+#ifdef LINUX
+#define USE_POLL
+#endif
+
+#ifdef DARWIN
+#include <unistd.h>
+
+#define strndup(s,n) altos_strndup(s,n)
+
+char *altos_strndup(const char *s, size_t n);
+
+#endif
+
+void
+altos_set_last_error(int code, char *string);
+
+extern struct altos_error altos_last_error;
+
+PUBLIC int
+altos_flush(struct altos_file *file);
+
+int
+altos_fill(struct altos_file *file, int timeout);
+
+#endif /* _LIBALTOS_PRIVATE_H_ */
--- /dev/null
+/*
+ * Copyright © 2016 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 "libaltos_private.h"
+
+#include <winsock2.h>
+#include <windows.h>
+#include <setupapi.h>
+
+struct altos_list {
+ HDEVINFO dev_info;
+ int index;
+ int ftdi;
+};
+
+#define USB_BUF_SIZE 64
+
+struct altos_file_windows {
+ struct altos_file file;
+
+ BOOL is_winsock;
+ /* Data used by the regular I/O */
+ HANDLE handle;
+ OVERLAPPED ov_read;
+ BOOL pend_read;
+ OVERLAPPED ov_write;
+
+ /* Data used by winsock */
+ SOCKET socket;
+};
+
+#include <stdarg.h>
+
+static void
+log_message(char *fmt, ...)
+{
+ static FILE *log = NULL;
+ va_list a;
+
+ if (!log)
+ log = fopen("\\temp\\altos.txt", "w");
+ if (log) {
+ SYSTEMTIME time;
+ char buffer[4096];
+
+ GetLocalTime(&time);
+ sprintf (buffer, "%4d-%02d-%02d %2d:%02d:%02d. ",
+ time.wYear, time.wMonth, time.wDay,
+ time.wHour, time.wMinute, time.wSecond);
+ va_start(a, fmt);
+
+ vsprintf(buffer + strlen(buffer), fmt, a);
+ va_end(a);
+
+ fputs(buffer, log);
+ fflush(log);
+ fputs(buffer, stdout);
+ fflush(stdout);
+ }
+}
+
+static void
+_altos_set_last_windows_error(char *file, int line, DWORD error)
+{
+ TCHAR message[1024];
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
+ 0,
+ error,
+ 0,
+ message,
+ sizeof (message) / sizeof (TCHAR),
+ NULL);
+ if (error != ERROR_SUCCESS)
+ log_message ("%s:%d (%d) %s\n", file, line, error, message);
+ altos_set_last_error(error, message);
+}
+
+#define altos_set_last_windows_error() _altos_set_last_windows_error(__FILE__, __LINE__, GetLastError())
+#define altos_set_last_winsock_error() _altos_set_last_windows_error(__FILE__, __LINE__, WSAGetLastError())
+
+PUBLIC struct altos_list *
+altos_list_start(void)
+{
+ struct altos_list *list = calloc(1, sizeof (struct altos_list));
+
+ if (!list)
+ return NULL;
+ list->dev_info = SetupDiGetClassDevs(NULL, "USB", NULL,
+ DIGCF_ALLCLASSES|DIGCF_PRESENT);
+ if (list->dev_info == INVALID_HANDLE_VALUE) {
+ altos_set_last_windows_error();
+ free(list);
+ return NULL;
+ }
+ list->index = 0;
+ list->ftdi = 0;
+ return list;
+}
+
+PUBLIC struct altos_list *
+altos_ftdi_list_start(void)
+{
+ struct altos_list *list = calloc(1, sizeof (struct altos_list));
+
+ if (!list)
+ return NULL;
+ list->dev_info = SetupDiGetClassDevs(NULL, "FTDIBUS", NULL,
+ DIGCF_ALLCLASSES|DIGCF_PRESENT);
+ if (list->dev_info == INVALID_HANDLE_VALUE) {
+ altos_set_last_windows_error();
+ free(list);
+ return NULL;
+ }
+ list->index = 0;
+ list->ftdi = 1;
+ return list;
+}
+
+PUBLIC int
+altos_list_next(struct altos_list *list, struct altos_device *device)
+{
+ SP_DEVINFO_DATA dev_info_data;
+ BYTE port[128];
+ DWORD port_len;
+ char friendlyname[256];
+ BYTE symbolic[256];
+ DWORD symbolic_len;
+ HKEY dev_key;
+ unsigned int vid, pid;
+ int serial;
+ HRESULT result;
+ DWORD friendlyname_type;
+ DWORD friendlyname_len;
+ char instanceid[1024];
+ DWORD instanceid_len;
+
+ dev_info_data.cbSize = sizeof (SP_DEVINFO_DATA);
+ while(SetupDiEnumDeviceInfo(list->dev_info, list->index,
+ &dev_info_data))
+ {
+ list->index++;
+
+ dev_key = SetupDiOpenDevRegKey(list->dev_info, &dev_info_data,
+ DICS_FLAG_GLOBAL, 0, DIREG_DEV,
+ KEY_READ);
+ if (dev_key == INVALID_HANDLE_VALUE) {
+ altos_set_last_windows_error();
+ continue;
+ }
+
+ if (list->ftdi) {
+ vid = 0x0403;
+ pid = 0x6015;
+ serial = 0;
+ } else {
+ vid = pid = serial = 0;
+ /* Fetch symbolic name for this device and parse out
+ * the vid/pid/serial info */
+ symbolic_len = sizeof(symbolic);
+ result = RegQueryValueEx(dev_key, "SymbolicName", NULL, NULL,
+ symbolic, &symbolic_len);
+ if (result != 0) {
+ altos_set_last_windows_error();
+ } else {
+ sscanf((char *) symbolic + sizeof("\\??\\USB#VID_") - 1,
+ "%04X", &vid);
+ sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_") - 1,
+ "%04X", &pid);
+ sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_XXXX#") - 1,
+ "%d", &serial);
+ }
+ if (vid == 0 || pid == 0 || serial == 0) {
+ if (SetupDiGetDeviceInstanceId(list->dev_info,
+ &dev_info_data,
+ instanceid,
+ sizeof (instanceid),
+ &instanceid_len)) {
+ sscanf((char *) instanceid + sizeof("USB\\VID_") - 1,
+ "%04X", &vid);
+ sscanf((char *) instanceid + sizeof("USB\\VID_XXXX&PID_") - 1,
+ "%04X", &pid);
+ sscanf((char *) instanceid + sizeof("USB\\VID_XXXX&PID_XXXX\\") - 1,
+ "%d", &serial);
+ } else {
+ altos_set_last_windows_error();
+ }
+ }
+ if (vid == 0 || pid == 0 || serial == 0) {
+ RegCloseKey(dev_key);
+ continue;
+ }
+ }
+
+ /* Fetch the com port name */
+ port_len = sizeof (port);
+ result = RegQueryValueEx(dev_key, "PortName", NULL, NULL,
+ port, &port_len);
+ RegCloseKey(dev_key);
+ if (result != 0) {
+ altos_set_last_windows_error();
+ continue;
+ }
+
+ /* Fetch the device description which is the device name,
+ * with firmware that has unique USB ids */
+ friendlyname_len = sizeof (friendlyname);
+ if(!SetupDiGetDeviceRegistryProperty(list->dev_info,
+ &dev_info_data,
+ SPDRP_FRIENDLYNAME,
+ &friendlyname_type,
+ (BYTE *)friendlyname,
+ sizeof(friendlyname),
+ &friendlyname_len))
+ {
+ altos_set_last_windows_error();
+ continue;
+ }
+ device->vendor = vid;
+ device->product = pid;
+ device->serial = serial;
+ strcpy(device->name, friendlyname);
+
+ strcpy(device->path, (char *) port);
+ return 1;
+ }
+ result = GetLastError();
+ if (result != ERROR_NO_MORE_ITEMS)
+ altos_set_last_windows_error();
+ return 0;
+}
+
+PUBLIC void
+altos_list_finish(struct altos_list *list)
+{
+ SetupDiDestroyDeviceInfoList(list->dev_info);
+ free(list);
+}
+
+static int
+altos_queue_read(struct altos_file_windows *file)
+{
+ DWORD got;
+ if (file->pend_read)
+ return LIBALTOS_SUCCESS;
+
+ if (!ReadFile(file->handle, file->file.in_data, USB_BUF_SIZE, &got, &file->ov_read)) {
+ if (GetLastError() != ERROR_IO_PENDING) {
+ altos_set_last_windows_error();
+ return LIBALTOS_ERROR;
+ }
+ file->pend_read = TRUE;
+ } else {
+ file->pend_read = FALSE;
+ file->file.in_read = 0;
+ file->file.in_used = got;
+ }
+ return LIBALTOS_SUCCESS;
+}
+
+static int
+altos_wait_read(struct altos_file_windows *file, int timeout)
+{
+ DWORD ret;
+ DWORD got;
+
+ if (!file->pend_read)
+ return LIBALTOS_SUCCESS;
+
+ if (!timeout)
+ timeout = INFINITE;
+
+ ret = WaitForSingleObject(file->ov_read.hEvent, timeout);
+ switch (ret) {
+ case WAIT_OBJECT_0:
+ if (!GetOverlappedResult(file->handle, &file->ov_read, &got, FALSE)) {
+ if (GetLastError () != ERROR_OPERATION_ABORTED)
+ altos_set_last_windows_error();
+ return LIBALTOS_ERROR;
+ }
+ file->pend_read = FALSE;
+ file->file.in_read = 0;
+ file->file.in_used = got;
+ break;
+ case WAIT_TIMEOUT:
+ return LIBALTOS_TIMEOUT;
+ break;
+ default:
+ altos_set_last_windows_error();
+ return LIBALTOS_ERROR;
+ }
+ return LIBALTOS_SUCCESS;
+}
+
+int
+altos_fill(struct altos_file *file_common, int timeout)
+{
+ struct altos_file_windows *file = (struct altos_file_windows *) file_common;
+
+ int ret;
+
+ if (file->file.in_read < file->file.in_used)
+ return LIBALTOS_SUCCESS;
+
+ file->file.in_read = file->file.in_used = 0;
+
+ if (file->is_winsock) {
+
+ for (;;) {
+ fd_set readfds;
+ TIMEVAL timeval;
+ int thistimeout;
+
+ /* Check to see if the socket has been closed */
+ if (file->socket == INVALID_SOCKET)
+ return LIBALTOS_ERROR;
+
+#define POLL_TIMEOUT 10000
+
+ /* Poll to see if the socket has been closed
+ * as select doesn't abort when that happens
+ */
+ if (timeout) {
+ thistimeout = timeout;
+ if (thistimeout > POLL_TIMEOUT)
+ thistimeout = POLL_TIMEOUT;
+ } else {
+ thistimeout = POLL_TIMEOUT;
+ }
+
+ timeval.tv_sec = thistimeout / 1000;
+ timeval.tv_usec = (thistimeout % 1000) * 1000;
+
+ FD_ZERO(&readfds);
+ FD_SET(file->socket, &readfds);
+
+ ret = select(1, &readfds, NULL, NULL, &timeval);
+
+ if (ret == 0) {
+ if (timeout) {
+ timeout -= thistimeout;
+ if (timeout == 0)
+ return LIBALTOS_TIMEOUT;
+ }
+ } else {
+ if (ret > 0)
+ break;
+
+ if (ret < 0) {
+ altos_set_last_winsock_error();
+ return LIBALTOS_ERROR;
+ }
+ }
+ }
+
+ if (file->socket == INVALID_SOCKET) {
+ altos_set_last_winsock_error();
+ return LIBALTOS_ERROR;
+ }
+
+ ret = recv(file->socket, (char *) file->file.in_data, USB_BUF_SIZE, 0);
+
+ if (ret <= 0) {
+ altos_set_last_winsock_error();
+ return LIBALTOS_ERROR;
+ }
+ file->file.in_read = 0;
+ file->file.in_used = ret;
+ } else {
+ if (file->handle == INVALID_HANDLE_VALUE) {
+ altos_set_last_windows_error();
+ return LIBALTOS_ERROR;
+ }
+
+ ret = altos_queue_read(file);
+ if (ret)
+ return ret;
+ ret = altos_wait_read(file, timeout);
+ if (ret)
+ return ret;
+ }
+
+ return LIBALTOS_SUCCESS;
+}
+
+PUBLIC int
+altos_flush(struct altos_file *file_common)
+{
+ struct altos_file_windows *file = (struct altos_file_windows *) file_common;
+
+ unsigned char *data = file->file.out_data;
+ int used = file->file.out_used;
+
+ while (used) {
+ if (file->is_winsock) {
+ int put;
+
+ put = send(file->socket, (char *) data, used, 0);
+ if (put <= 0) {
+ altos_set_last_winsock_error();
+ return LIBALTOS_ERROR;
+ }
+ data += put;
+ used -= put;
+ } else {
+ DWORD put;
+ DWORD ret;
+ if (!WriteFile(file->handle, data, used, &put, &file->ov_write)) {
+ 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)) {
+ altos_set_last_windows_error();
+ return LIBALTOS_ERROR;
+ }
+ break;
+ default:
+ altos_set_last_windows_error();
+ return LIBALTOS_ERROR;
+ }
+ }
+ data += put;
+ used -= put;
+ }
+ }
+ file->file.out_used = 0;
+ return LIBALTOS_SUCCESS;
+}
+
+static HANDLE
+open_serial(char *full_name)
+{
+ HANDLE handle;
+ DCB dcb;
+
+ handle = CreateFile(full_name, GENERIC_READ|GENERIC_WRITE,
+ 0, NULL, OPEN_EXISTING,
+ FILE_FLAG_OVERLAPPED, NULL);
+
+ if (handle == INVALID_HANDLE_VALUE) {
+ altos_set_last_windows_error();
+ return INVALID_HANDLE_VALUE;
+ }
+
+ if (!GetCommState(handle, &dcb)) {
+ altos_set_last_windows_error();
+ CloseHandle(handle);
+ return INVALID_HANDLE_VALUE;
+ }
+ dcb.BaudRate = CBR_9600;
+ dcb.fBinary = TRUE;
+ dcb.fParity = FALSE;
+ dcb.fOutxCtsFlow = FALSE;
+ dcb.fOutxDsrFlow = FALSE;
+ dcb.fDtrControl = DTR_CONTROL_ENABLE;
+ dcb.fDsrSensitivity = FALSE;
+ dcb.fTXContinueOnXoff = FALSE;
+ dcb.fOutX = FALSE;
+ dcb.fInX = FALSE;
+ dcb.fErrorChar = FALSE;
+ dcb.fNull = FALSE;
+ dcb.fRtsControl = RTS_CONTROL_ENABLE;
+ dcb.fAbortOnError = FALSE;
+ dcb.XonLim = 10;
+ dcb.XoffLim = 10;
+ dcb.ByteSize = 8;
+ dcb.Parity = NOPARITY;
+ dcb.StopBits = ONESTOPBIT;
+ dcb.XonChar = 17;
+ dcb.XoffChar = 19;
+#if 0
+ dcb.ErrorChar = 0;
+ dcb.EofChar = 0;
+ dcb.EvtChar = 0;
+#endif
+ if (!SetCommState(handle, &dcb)) {
+ altos_set_last_windows_error();
+ CloseHandle(handle);
+ return INVALID_HANDLE_VALUE;
+ }
+ return handle;
+}
+
+PUBLIC struct altos_file *
+altos_open(struct altos_device *device)
+{
+ struct altos_file_windows *file = calloc (1, sizeof (struct altos_file_windows));
+ char full_name[64];
+ COMMTIMEOUTS timeouts;
+ int i;
+
+ if (!file)
+ return NULL;
+
+ strcpy(full_name, "\\\\.\\");
+ strcat(full_name, device->path);
+
+ file->handle = INVALID_HANDLE_VALUE;
+
+ for (i = 0; i < 5; i++) {
+ file->handle = open_serial(full_name);
+ if (file->handle != INVALID_HANDLE_VALUE)
+ break;
+ altos_set_last_windows_error();
+ Sleep(100);
+ }
+
+ if (file->handle == INVALID_HANDLE_VALUE) {
+ free(file);
+ return NULL;
+ }
+
+ /* The FTDI driver doesn't appear to work right unless you open it twice */
+ if (device->vendor == 0x0403) {
+ CloseHandle(file->handle);
+ file->handle = open_serial(full_name);
+ if (file->handle == INVALID_HANDLE_VALUE) {
+ free(file);
+ return NULL;
+ }
+ }
+
+ timeouts.ReadIntervalTimeout = MAXDWORD;
+ timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
+ timeouts.ReadTotalTimeoutConstant = 1 << 30; /* almost forever */
+ timeouts.WriteTotalTimeoutMultiplier = 0;
+ timeouts.WriteTotalTimeoutConstant = 0;
+ SetCommTimeouts(file->handle, &timeouts);
+
+ file->ov_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ file->ov_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ return &file->file;
+}
+
+PUBLIC void
+altos_close(struct altos_file *file_common)
+{
+ struct altos_file_windows *file = (struct altos_file_windows *) file_common;
+
+ if (file->is_winsock) {
+ SOCKET socket = file->socket;
+ if (socket != INVALID_SOCKET) {
+ file->socket = INVALID_SOCKET;
+ closesocket(socket);
+ }
+ } else {
+ HANDLE handle = file->handle;
+ if (handle != INVALID_HANDLE_VALUE) {
+ HANDLE ov_read = file->ov_read.hEvent;
+ HANDLE ov_write = file->ov_write.hEvent;
+ file->handle = INVALID_HANDLE_VALUE;
+ file->ov_read.hEvent = INVALID_HANDLE_VALUE;
+ file->ov_write.hEvent = INVALID_HANDLE_VALUE;
+ PurgeComm(handle, PURGE_RXABORT|PURGE_RXCLEAR|PURGE_TXABORT|PURGE_TXCLEAR);
+ Sleep(100);
+ CloseHandle(handle);
+ file->handle = INVALID_HANDLE_VALUE;
+ CloseHandle(ov_read);
+ CloseHandle(ov_write);
+ }
+ }
+}
+
+#include <ws2bth.h>
+
+#define LUP_SET (LUP_RETURN_NAME| LUP_CONTAINERS | LUP_RETURN_ADDR | LUP_FLUSHCACHE |\
+ LUP_RETURN_TYPE | LUP_RETURN_BLOB | LUP_RES_SERVICE)
+
+struct altos_bt_list {
+ WSADATA WSAData;
+ HANDLE lookup;
+};
+
+struct altos_bt_list *
+altos_bt_list_start(int inquiry_time)
+{
+ struct altos_bt_list *bt_list;
+ WSAQUERYSET query_set;
+ int retCode;
+
+ /* Windows provides no way to set the time */
+ (void) inquiry_time;
+ bt_list = calloc(1, sizeof (struct altos_bt_list));
+ if (!bt_list) {
+ altos_set_last_windows_error();
+ return NULL;
+ }
+
+ if ((retCode = WSAStartup(MAKEWORD(2,2),&bt_list->WSAData)) != 0) {
+ altos_set_last_winsock_error();
+ free(bt_list);
+ return NULL;
+ }
+
+ memset(&query_set, '\0', sizeof (query_set));
+ query_set.dwSize = sizeof(WSAQUERYSET);
+ query_set.dwNameSpace = NS_BTH;
+
+ retCode = WSALookupServiceBegin(&query_set, LUP_SET, &bt_list->lookup);
+
+ if (retCode != 0) {
+ altos_set_last_winsock_error();
+ free(bt_list);
+ return NULL;
+ }
+ return bt_list;
+}
+
+static unsigned char get_byte(BTH_ADDR ba, int shift)
+{
+ return (ba >> ((5 - shift) << 3)) & 0xff;
+}
+
+static BTH_ADDR put_byte(unsigned char c, int shift)
+{
+ return ((BTH_ADDR) c) << ((5 - shift) << 3);
+}
+
+static void
+ba2str(BTH_ADDR ba, char *str)
+{
+
+ sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
+ get_byte(ba, 0),
+ get_byte(ba, 1),
+ get_byte(ba, 2),
+ get_byte(ba, 3),
+ get_byte(ba, 4),
+ get_byte(ba, 5));
+}
+
+static BTH_ADDR
+str2ba(char *str)
+{
+ unsigned int bytes[6];
+
+ sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
+ &bytes[0],
+ &bytes[1],
+ &bytes[2],
+ &bytes[3],
+ &bytes[4],
+ &bytes[5]);
+ return (put_byte(bytes[0], 0) |
+ put_byte(bytes[1], 1) |
+ put_byte(bytes[2], 2) |
+ put_byte(bytes[3], 3) |
+ put_byte(bytes[4], 4) |
+ put_byte(bytes[5], 5));
+}
+
+int
+altos_bt_list_next(struct altos_bt_list *bt_list,
+ struct altos_bt_device *device)
+{
+ for (;;) {
+ BYTE buffer[4096];
+ DWORD length = sizeof (buffer);;
+ WSAQUERYSET *results = (WSAQUERYSET *)buffer;
+ CSADDR_INFO *addr_info;
+ int retCode;
+ SOCKADDR_BTH *sockaddr_bth;
+
+ memset(buffer, '\0', sizeof(buffer));
+
+ retCode = WSALookupServiceNext(bt_list->lookup, LUP_SET, &length, results);
+
+ if (retCode != 0) {
+ int error = WSAGetLastError();
+ if (error != WSAENOMORE && error != WSA_E_NO_MORE)
+ altos_set_last_winsock_error();
+ return 0;
+ }
+
+ if (results->dwNumberOfCsAddrs > 0) {
+
+ addr_info = results->lpcsaBuffer;
+
+ strncpy(device->name, results->lpszServiceInstanceName, sizeof(device->name));
+ device->name[sizeof(device->name)-1] = '\0';
+
+ sockaddr_bth = (SOCKADDR_BTH *) addr_info->RemoteAddr.lpSockaddr;
+
+ ba2str(sockaddr_bth->btAddr, device->addr);
+
+ return 1;
+ }
+ }
+}
+
+void
+altos_bt_list_finish(struct altos_bt_list *bt_list)
+{
+ WSALookupServiceEnd(bt_list->lookup);
+ free(bt_list);
+}
+
+void
+altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device)
+{
+ strncpy(device->name, name, sizeof (device->name));
+ device->name[sizeof(device->name)-1] = '\0';
+ strncpy(device->addr, addr, sizeof (device->addr));
+ device->addr[sizeof(device->addr)-1] = '\0';
+}
+
+struct altos_file *
+altos_bt_open(struct altos_bt_device *device)
+{
+ struct altos_file_windows *file;
+ SOCKADDR_BTH sockaddr_bth;
+ int ret;
+
+ file = calloc(1, sizeof (struct altos_file_windows));
+ if (!file) {
+ return NULL;
+ }
+
+ file->is_winsock = TRUE;
+ file->socket = WSASocket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM, NULL, 0, WSA_FLAG_OVERLAPPED);
+
+ if (file->socket == INVALID_SOCKET) {
+ altos_set_last_winsock_error();
+ free(file);
+ return NULL;
+ }
+
+ memset(&sockaddr_bth, '\0', sizeof (sockaddr_bth));
+ sockaddr_bth.addressFamily = AF_BTH;
+ sockaddr_bth.btAddr = str2ba(device->addr);
+ sockaddr_bth.port = 1;
+
+ ret = connect(file->socket, (SOCKADDR *) &sockaddr_bth, sizeof (sockaddr_bth));
+
+ if (ret != 0) {
+ altos_set_last_winsock_error();
+ closesocket(file->socket);
+ free(file);
+ return NULL;
+ }
+ return &file->file;
+}
+
import java.lang.*;
import java.io.*;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
class MicroIterator implements Iterator<MicroDataPoint> {
int i;
package org.altusmetrum.micropeak;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroDataPoint implements AltosUIDataPoint {
public double time;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroDeviceDialog extends AltosDeviceDialog {
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroDownload extends AltosUIDialog implements Runnable, ActionListener, MicroSerialLog, WindowListener {
MicroPeak owner;
import java.awt.*;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroExport extends JFileChooser {
import java.io.*;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroFile {
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.io.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroFileChooser extends JFileChooser {
JFrame frame;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroFrame extends AltosUIFrame {
static String[] micro_icon_names = {
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroPeak extends MicroFrame implements ActionListener, ItemListener {
import java.awt.*;
import java.io.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroRaw extends JTextArea {
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroSave extends JFileChooser {
import java.util.*;
import java.io.*;
import libaltosJNI.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroSerial extends InputStream {
SWIGTYPE_p_altos_file file;
import java.util.*;
import java.io.*;
import libaltosJNI.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
public interface MicroSerialLog {
package org.altusmetrum.micropeak;
import java.io.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroStats {
double coast_height;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroStatsTable extends JComponent implements AltosFontListener {
GridBagLayout layout;
import java.util.*;
import libaltosJNI.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroUSB extends altos_device implements AltosDevice {
; And the stuff to install
-Section "FTDI USB Driver"
- SetOutPath $INSTDIR
-
- File "CDM_v2.12.00_WHQL_Certified.exe"
-
- StrCpy $2 "$INSTDIR\CDM_v2.12.00_WHQL_Certified.exe"
- ExecWait $2
-SectionEnd
-
Section "Install Driver" InstDriver
InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} AltusMetrumSerial
CreateShortCut "$DESKTOP\${REG_NAME}.lnk" "$INSTDIR\${WIN_APP_EXE}" "" "$INSTDIR\${WIN_APP_ICON}"
SectionEnd
+Section "FTDI USB Driver"
+ SetOutPath $INSTDIR
+
+ File "CDM_v2.12.00_WHQL_Certified.exe"
+
+ StrCpy $2 "$INSTDIR\CDM_v2.12.00_WHQL_Certified.exe"
+ ExecWait $2
+SectionEnd
+
Section "Documentation"
SetOutPath $INSTDIR
telescience-v0.2 telescience-v0.2/flash-loader \
teledongle-v3.0 teledongle-v3.0/flash-loader \
teleballoon-v2.0 \
- telebt-v3.0 telebt-v3.0/flash-loader
+ telebt-v3.0 telebt-v3.0/flash-loader \
+ telelcotwo-v0.1 telelcotwo-v0.1/flash-loader \
+ telefiretwo-v0.1 telefiretwo-v0.1/flash-loader \
ARMM0DIRS=\
easymini-v1.0 easymini-v1.0/flash-loader \
- chaoskey-v0.1 chaoskey-v0.1/flash-loader
+ chaoskey-v0.1 chaoskey-v0.1/flash-loader \
+ chaoskey-v1.0 chaoskey-v1.0/flash-loader
AVRDIRS=\
telescience-v0.1 telescience-pwm micropeak nanopeak-v0.1 microkite
#define ao_enable_output(port,bit,pin,v) cc1111_enable_output(port,token_evaluator(port,DIR), token_evaluator(port,SEL), pin, bit, v)
#define ao_gpio_set(port, bit, pin, v) ((pin) = (v))
#define ao_gpio_get(port, bit, pin) (pin)
-
+#define ao_gpio_get_bits(port) (port)
+#define ao_gpio_set_bits(port, bits) ((port) |= bits)
+#define ao_gpio_clr_bits(port, bits) ((port) &= ~bits)
ao_product.h \
ao_task.h \
ao_adc_fast.h \
+ ao_power.h \
stm32f0.h
#
ao_usb_stm.c \
ao_trng_send.c \
ao_task.c \
+ ao_power.c \
+ ao_gpio.c \
ao_product.c
-PRODUCT=ChaosKey-v0.1
+PRODUCT=ChaosKey-hw-0.3-sw-$(VERSION)
PRODUCT_DEF=-DCHAOSKEY_V_0_1
IDVENDOR=0x1d50
IDPRODUCT=0x60c6
#define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN)
+#define AO_POWER_MANAGEMENT 1
+#define AO_LED_POWER AO_LED_RED
+
#define HAS_BEEP 0
/* 48MHz clock based on USB */
#define AO_APB_PRESCALER 1
#define AO_RCC_CFGR_PPRE_DIV STM_RCC_CFGR_PPRE_DIV_1
-#define HAS_USB 1
-#define AO_USB_DIRECTIO 1
-#define AO_PA11_PA12_RMP 0
-#define AO_USB_INTERFACE_CLASS 0xff
+#define HAS_USB 1
+#define AO_USB_DIRECTIO 1
+#define AO_PA11_PA12_RMP 0
+#define AO_USB_DEVICE_CLASS 0xff
+#define AO_USB_INTERFACE_CLASS_DATA 0xff
+#define AO_USB_HAS_OUT 0
+#define AO_USB_HAS_IN 1
+#define AO_USB_HAS_IN2 1
+#define AO_USB_HAS_INT 0
+#define USE_USB_STDIO 0
+#define AO_USB_SELF_POWER 0
+#define AO_USB_DEVICE_ID_SERIAL 1
#define IS_FLASH_LOADER 0
#define AO_NUM_ADC 1
+/* TRNG enable */
+
+#define AO_TRNG_ENABLE_PORT (&stm_gpioa)
+#define AO_TRNG_ENABLE_BIT 8
+
/* CRC */
#define AO_CRC_WIDTH 32
#define AO_CRC_INIT 0xffffffff
/* TRNG */
-#define AO_LED_TRNG_ACTIVE AO_LED_GREEN
+#define AO_LED_TRNG_COOKED AO_LED_GREEN
+#define AO_LED_TRNG_RAW AO_LED_GREEN
+
+/* Mode pin */
+#define AO_RAW_PORT (&stm_gpioa)
+#define AO_RAW_BIT 15
#endif /* _AO_PINS_H_ */
--- /dev/null
+ao_product.h
+chaoskey-*
--- /dev/null
+#
+# AltOS build
+#
+#
+
+include ../stmf0/Makefile.defs
+
+INC = \
+ ao.h \
+ ao_arch.h \
+ ao_arch_funcs.h \
+ ao_pins.h \
+ ao_product.h \
+ ao_task.h \
+ ao_adc_fast.h \
+ ao_power.h \
+ stm32f0.h
+
+#
+# Common AltOS sources
+#
+ALTOS_SRC = \
+ ao_interrupt.c \
+ ao_timer.c \
+ ao_panic.c \
+ ao_mutex.c \
+ ao_dma_stm.c \
+ ao_adc_fast.c \
+ ao_crc_stm.c \
+ ao_stdio.c \
+ ao_led.c \
+ ao_romconfig.c \
+ ao_boot_chain.c \
+ ao_usb_stm.c \
+ ao_trng_send.c \
+ ao_task.c \
+ ao_power.c \
+ ao_gpio.c \
+ ao_product.c
+
+PRODUCT=ChaosKey-hw-1.0-sw-$(VERSION)
+PRODUCT_DEF=-DCHAOSKEY_V_1_0
+IDVENDOR=0x1d50
+IDPRODUCT=0x60c6
+
+CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -g -Os
+
+PROGNAME=chaoskey-v1.0
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_chaoskey.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+ $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+ao_product.h: ao-make-product.5c ../Version
+ $(call quiet,NICKLE,$<) $< -m altusmetrum.org -V $(IDVENDOR) -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) -o $@
+
+$(OBJ): $(INC)
+
+distclean: clean
+
+clean:
+ rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+ rm -f ao_product.h
+
+install:
+
+uninstall:
--- /dev/null
+/*
+ * Copyright © 2014 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_adc_fast.h>
+#include <ao_crc.h>
+#include <ao_trng_send.h>
+
+void main(void)
+{
+ ao_led_init(LEDS_AVAILABLE);
+ ao_clock_init();
+ ao_task_init();
+ ao_timer_init();
+ ao_dma_init();
+ ao_adc_init();
+ ao_crc_init();
+
+ ao_usb_init();
+
+ ao_trng_send_init();
+
+ ao_start_scheduler();
+}
--- /dev/null
+/*
+ * Copyright © 2015 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_PINS_H_
+#define _AO_PINS_H_
+
+#define LED_PORT_ENABLE STM_RCC_AHBENR_IOPBEN
+#define LED_PORT (&stm_gpiob)
+#define LED_PIN_RED 4
+#define AO_LED_RED (1 << LED_PIN_RED)
+
+#define LEDS_AVAILABLE (AO_LED_RED)
+
+#define AO_POWER_MANAGEMENT 1
+#define AO_LED_POWER AO_LED_RED
+
+#define HAS_BEEP 0
+
+/* 48MHz clock based on USB */
+#define AO_HSI48 1
+
+/* HCLK = 48MHz */
+#define AO_AHB_PRESCALER 1
+#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1
+
+/* APB = 48MHz */
+#define AO_APB_PRESCALER 1
+#define AO_RCC_CFGR_PPRE_DIV STM_RCC_CFGR_PPRE_DIV_1
+
+#define HAS_USB 1
+#define AO_USB_DIRECTIO 1
+#define AO_PA11_PA12_RMP 1
+#define AO_USB_DEVICE_CLASS 0xff
+#define AO_USB_INTERFACE_CLASS_DATA 0xff
+#define AO_USB_HAS_OUT 0
+#define AO_USB_HAS_IN 1
+#define AO_USB_HAS_IN2 1
+#define AO_USB_HAS_INT 0
+#define AO_USB_SELF_POWER 0
+#define AO_USB_DEVICE_ID_SERIAL 1
+#define AO_USB_START_DISABLED 1
+#define USE_USB_STDIO 0
+
+#define IS_FLASH_LOADER 0
+
+/* ADC */
+
+#define AO_ADC_PIN0_PORT (&stm_gpioa)
+#define AO_ADC_PIN0_PIN 0
+#define AO_ADC_PIN0_CH 0
+
+#define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_IOPAEN))
+
+#define AO_NUM_ADC 1
+
+/* TRNG enable */
+
+#define AO_TRNG_ENABLE_PORT (&stm_gpioa)
+#define AO_TRNG_ENABLE_BIT 1
+
+/* CRC */
+#define AO_CRC_WIDTH 32
+#define AO_CRC_INIT 0xffffffff
+
+/* Mode pin */
+#define AO_RAW_PORT (&stm_gpioa)
+#define AO_RAW_BIT 15
+
+#endif /* _AO_PINS_H_ */
--- /dev/null
+ao_product.h
+chaoskey*
--- /dev/null
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=chaoskey-v1.0
+include $(TOPDIR)/stmf0/Makefile-flash.defs
--- /dev/null
+/*
+ * Copyright © 2013 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_PINS_H_
+#define _AO_PINS_H_
+
+#include <ao_flash_stm_pins.h>
+
+/* Pin 5 on debug connector */
+
+#define AO_BOOT_PIN 1
+#define AO_BOOT_APPLICATION_GPIO stm_gpioa
+#define AO_BOOT_APPLICATION_PIN 15
+#define AO_BOOT_APPLICATION_VALUE 1
+#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP
+
+/* USB */
+#define HAS_USB 1
+#define AO_USB_DIRECTIO 0
+#define AO_PA11_PA12_RMP 1
+
+#endif /* _AO_PINS_H_ */
--- /dev/null
+ao_product.h
+detherm-*
--- /dev/null
+#
+# AltOS build
+#
+#
+
+include ../stmf0/Makefile.defs
+
+INC = \
+ ao.h \
+ ao_arch.h \
+ ao_arch_funcs.h \
+ ao_pins.h \
+ ao_product.h \
+ ao_task.h \
+ stm32f0.h
+
+#
+# Common AltOS sources
+#
+ALTOS_SRC = \
+ ao_interrupt.c \
+ ao_timer.c \
+ ao_panic.c \
+ ao_mutex.c \
+ ao_dma_stm.c \
+ ao_usb_stm.c \
+ ao_spi_stm.c \
+ ao_exti_stm.c \
+ ao_stdio.c \
+ ao_led.c \
+ ao_log.c \
+ ao_log_mini.c \
+ ao_sample.c \
+ ao_data.c \
+ ao_kalman.c \
+ ao_flight.c \
+ ao_report.c \
+ ao_storage.c \
+ ao_m25.c \
+ ao_romconfig.c \
+ ao_boot_chain.c \
+ ao_ms5607.c \
+ ao_convert_pa.c \
+ ao_pwm.c \
+ ao_servo.c \
+ ao_task.c \
+ ao_config.c \
+ ao_cmd.c \
+ ao_product.c
+
+PRODUCT=Detherm-v1.0
+PRODUCT_DEF=-DDETHERM_V_1_0
+IDPRODUCT=0x0013
+
+CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -g -Os
+
+PROGNAME=detherm-v1.0
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_detherm.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+ $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+ao_product.h: ao-make-product.5c ../Version
+ $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) -o $@
+
+$(OBJ): $(INC)
+
+distclean: clean
+
+clean:
+ rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+ rm -f ao_product.h
+
+install:
+
+uninstall:
--- /dev/null
+/*
+ * Copyright © 2014 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_exti.h>
+#include <ao_pwm.h>
+#include <ao_servo.h>
+
+void main(void)
+{
+ ao_led_init(LEDS_AVAILABLE);
+
+ ao_led_on(AO_LED_RED);
+
+ ao_clock_init();
+ ao_task_init();
+ ao_timer_init();
+ ao_exti_init();
+
+ ao_dma_init();
+ ao_spi_init();
+ ao_usb_init();
+
+ ao_storage_init();
+ ao_ms5607_init();
+// ao_flight_init();
+ ao_pwm_init();
+ ao_servo_init();
+ ao_log_init();
+ ao_report_init();
+ ao_config_init();
+
+ ao_cmd_init();
+
+ ao_start_scheduler();
+}
--- /dev/null
+/*
+ * Copyright © 2015 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_PINS_H_
+#define _AO_PINS_H_
+
+#define LED_PORT_ENABLE STM_RCC_AHBENR_IOPAEN
+#define LED_PORT (&stm_gpioa)
+#define LED_PIN_RED 3
+#define AO_LED_RED (1 << LED_PIN_RED)
+
+#define LEDS_AVAILABLE (AO_LED_RED)
+
+#define HAS_BEEP 0
+
+/* 48MHz clock based on USB */
+//#define AO_HSI48 1
+#define AO_HSE 16000000
+#define AO_RCC_CFGR_PLLMUL STM_RCC_CFGR_PLLMUL_3
+#define AO_PLLMUL 3
+#define AO_PLLDIV 1
+
+/* HCLK = 48MHz */
+#define AO_AHB_PRESCALER 1
+#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1
+
+/* APB = 48MHz */
+#define AO_APB_PRESCALER 1
+#define AO_RCC_CFGR_PPRE_DIV STM_RCC_CFGR_PPRE_DIV_1
+
+#define HAS_USB 1
+#define AO_USB_DIRECTIO 0
+#define AO_PA11_PA12_RMP 1
+
+#define IS_FLASH_LOADER 0
+
+#define AO_DATA_RING 16
+
+#define HAS_ADC 0
+#define HAS_ACCEL 0
+#define HAS_GPS 0
+#define HAS_RADIO 0
+#define HAS_FLIGHT 1
+#define HAS_EEPROM 1
+#define HAS_LOG 1
+
+#define AO_LOG_FORMAT AO_LOG_FORMAT_DETHERM
+
+#define USE_INTERNAL_FLASH 0
+
+/* SPI */
+#define HAS_SPI_1 1
+#define HAS_SPI_2 0
+#define SPI_1_PA5_PA6_PA7 1
+#define SPI_1_PB3_PB4_PB5 1
+#define SPI_1_OSPEEDR STM_OSPEEDR_HIGH
+
+/* MS5607 */
+#define HAS_MS5607 1
+
+#define AO_MS5607_CS_PORT (&stm_gpioa)
+#define AO_MS5607_CS_PIN 0
+#define AO_MS5607_SPI_INDEX AO_SPI_1_PB3_PB4_PB5
+#define AO_MS5607_MISO_PORT (&stm_gpiob)
+#define AO_MS5607_MISO_PIN 4
+#define AO_MS5607_PRIVATE_PINS 1
+#define AO_MS5607_SPI_SPEED AO_SPI_SPEED_6MHz
+
+/* Flash */
+
+#define M25_MAX_CHIPS 1
+#define AO_M25_SPI_CS_PORT (&stm_gpioa)
+#define AO_M25_SPI_CS_MASK (1 << 4)
+#define AO_M25_SPI_BUS AO_SPI_1_PA5_PA6_PA7
+
+/* PWM */
+
+#define NUM_PWM 1
+#define AO_PWM_TIMER (&stm_tim3)
+#define AO_PWM_0_GPIO (&stm_gpiob)
+#define AO_PWM_0_PIN 1
+#define AO_PWM_0_CH 4
+#define PWM_MAX 20000
+#define AO_PWM_TIMER_ENABLE STM_RCC_APB1ENR_TIM3EN
+#define AO_PWM_TIMER_SCALE 32
+
+/* Servo */
+
+#define AO_SERVO_DIR_PORT (&stm_gpiob)
+#define AO_SERVO_DIR_BIT 0
+#define AO_SERVO_SPEED_PWM 0
+
+/* limit 2 */
+#define AO_SERVO_LIMIT_FORE_PORT (&stm_gpiob)
+#define AO_SERVO_LIMIT_FORE_BIT 6
+
+/* limit 1 */
+#define AO_SERVO_LIMIT_BACK_PORT (&stm_gpiob)
+#define AO_SERVO_LIMIT_BACK_BIT 7
+
+#endif /* _AO_PINS_H_ */
--- /dev/null
+ao_product.h
+detherm*
--- /dev/null
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=detherm-v1.0
+include $(TOPDIR)/stmf0/Makefile-flash.defs
--- /dev/null
+/*
+ * Copyright © 2013 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_PINS_H_
+#define _AO_PINS_H_
+
+#include <ao_flash_stm_pins.h>
+
+/* Pin 5 on debug connector */
+
+#define AO_BOOT_PIN 1
+#define AO_BOOT_APPLICATION_GPIO stm_gpioa
+#define AO_BOOT_APPLICATION_PIN 15
+#define AO_BOOT_APPLICATION_VALUE 1
+#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP
+
+/* USB */
+#define HAS_USB 1
+#define AO_USB_DIRECTIO 0
+#define AO_PA11_PA12_RMP 1
+
+#endif /* _AO_PINS_H_ */
#include <ao.h>
#include <ao_button.h>
#include <ao_exti.h>
-#include <ao_debounce.h>
#if AO_EVENT
#include <ao_event.h>
#define ao_button_queue(b,v) ao_event_put_isr(AO_EVENT_BUTTON, b, v)
#define ao_button_queue(b,v)
#endif
-#define AO_BUTTON_DEBOUNCE_HOLD 10
+#define AO_BUTTON_DEBOUNCE_INTERVAL AO_MS_TO_TICKS(50)
-static struct ao_debounce ao_button_debounce[AO_BUTTON_COUNT];
+struct ao_button_state {
+ AO_TICK_TYPE time;
+ uint8_t value;
+};
+
+static struct ao_button_state ao_button_state[AO_BUTTON_COUNT];
#define port(q) AO_BUTTON_ ## q ## _PORT
#define bit(q) AO_BUTTON_ ## q
#define ao_button_value(b) !ao_gpio_get(port(b), bit(b), pin(b))
static uint8_t
-_ao_button_get(struct ao_debounce *debounce)
+_ao_button_get(uint8_t b)
{
- uint8_t b = debounce - ao_button_debounce;
-
switch (b) {
#if AO_BUTTON_COUNT > 0
case 0: return ao_button_value(0);
}
static void
-_ao_button_set(struct ao_debounce *debounce, uint8_t value)
+_ao_button_check(uint8_t b)
{
- uint8_t b = debounce - ao_button_debounce;
-
- ao_button_queue(b, value);
-}
+ uint8_t value = _ao_button_get(b);
+ if (value != ao_button_state[b].value) {
+ AO_TICK_TYPE now = ao_time();
-#define ao_button_update(b) ao_button_do(b, ao_gpio_get(port(b), bit(b), pin(b)))
+ if ((now - ao_button_state[b].time) >= AO_BUTTON_DEBOUNCE_INTERVAL) {
+ ao_button_state[b].value = value;
+ ao_button_queue(b, value);
+ }
+ ao_button_state[b].time = now;
+ }
+}
static void
-ao_button_debounce_init(struct ao_debounce *debounce) {
- ao_debounce_config(debounce,
- _ao_button_get,
- _ao_button_set,
- AO_BUTTON_DEBOUNCE_HOLD);
+_ao_button_init(uint8_t b)
+{
+ uint8_t m = ao_arch_irqsave();
+ uint8_t value = _ao_button_get(b);
+ ao_button_state[b].value = value;
+ ao_button_state[b].time = ao_time();
+ ao_button_queue(b, value);
+ ao_arch_irqrestore(m);
+
}
static void
uint8_t b;
for (b = 0; b < AO_BUTTON_COUNT; b++)
- _ao_debounce_start(&ao_button_debounce[b]);
+ _ao_button_check(b);
}
#define init(b) do { \
- ao_button_debounce_init(&ao_button_debounce[b]); \
ao_enable_port(port(b)); \
\
ao_exti_setup(port(b), bit(b), \
AO_BUTTON_MODE|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, \
- ao_button_isr); \
+ ao_button_isr); \
ao_exti_enable(port(b), bit(b)); \
+ _ao_button_init(b); \
} while (0)
void
#if AO_BUTTON_COUNT > 4
init(4);
#endif
- ao_debounce_init();
}
#include <ao_exti.h>
#include <ao_fec.h>
#include <ao_packet.h>
+#if HAS_PAD
+#include <ao_pad.h>
+#endif
static uint8_t ao_radio_mutex;
#endif
#if PACKET_HAS_SLAVE
ao_packet_slave_stop();
+#endif
+#if HAS_PAD
+ ao_pad_disable();
#endif
ao_radio_get(0xff);
ao_radio_set_mode(AO_RADIO_MODE_TEST);
radio_on = 0;
#if HAS_MONITOR
ao_monitor_enable();
+#endif
+#if HAS_PAD
+ ao_pad_enable();
#endif
}
}
);
}
+uint8_t
+ao_event_get_for(struct ao_event *ev, uint16_t timeout)
+{
+ uint8_t empty = 1;
+ ao_arch_critical(
+ while ((empty = ao_event_queue_empty()))
+ if (ao_sleep_for(&ao_event_queue, timeout))
+ break;
+ if (!empty) {
+ *ev = ao_event_queue[ao_event_queue_remove];
+ ao_event_queue_remove = ao_event_queue_next(ao_event_queue_remove);
+ }
+ );
+ return empty;
+}
+
/* called with interrupts disabled */
void
ao_event_put_isr(uint8_t type, uint8_t unit, int32_t value)
void
ao_event_get(struct ao_event *ev);
+uint8_t
+ao_event_get_for(struct ao_event *ev, uint16_t timeout);
+
void
ao_event_put_isr(uint8_t type, uint8_t unit, int32_t value);
--- /dev/null
+/*
+ * Copyright © 2012 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_lco.h>
+#include <ao_event.h>
+#include <ao_lco_func.h>
+#include <ao_radio_cmac.h>
+
+#define DEBUG 1
+
+#if DEBUG
+static uint8_t ao_lco_debug;
+#define DEBUG_EVENT 1
+#define DEBUG_STATUS 2
+#define PRINTD(l, ...) do { if (!(ao_lco_debug & l)) break; printf ("\r%5u %s: ", ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } while(0)
+#else
+#define PRINTD(l,...)
+#endif
+
+#define AO_LCO_VALID_LAST 1
+#define AO_LCO_VALID_EVER 2
+
+static uint8_t ao_lco_suspended;
+static uint8_t ao_lco_selected;
+static uint8_t ao_lco_valid;
+static uint8_t ao_lco_channels;
+static uint16_t ao_lco_tick_offset;
+
+/* UI values */
+static uint8_t ao_lco_armed;
+static uint8_t ao_lco_firing;
+
+#define ao_lco_box (ao_config.pad_box)
+
+static struct ao_pad_query ao_pad_query;
+
+#define MASK_SIZE(n) (((n) + 7) >> 3)
+#define MASK_ID(n) ((n) >> 3)
+#define MASK_SHIFT(n) ((n) & 7)
+
+static void
+ao_lco_set_armed(int pad, int armed)
+{
+ uint8_t bit = (1 << pad);
+
+ if (armed) {
+ ao_lco_selected |= bit;
+ ao_lco_armed |= bit;
+ } else {
+ ao_lco_selected &= ~bit;
+ ao_lco_armed &= ~bit;
+ }
+ PRINTD(DEBUG_EVENT, "pad %d bit 0x%x armed %d ao_lco_selected 0x%x ao_lco_armed 0x%x\n",
+ pad, bit, armed, ao_lco_selected, ao_lco_armed);
+ ao_wakeup(&ao_lco_armed);
+}
+
+static void
+ao_lco_suspend(void)
+{
+ if (!ao_lco_suspended) {
+ PRINTD(DEBUG_EVENT, "suspend\n");
+ ao_lco_suspended = 1;
+ ao_lco_selected = 0;
+ ao_lco_armed = 0;
+ ao_wakeup(&ao_pad_query);
+ }
+}
+
+static void
+ao_lco_wakeup(void)
+{
+ if (ao_lco_suspended) {
+ ao_lco_suspended = 0;
+ ao_wakeup(&ao_lco_suspended);
+ }
+}
+
+static void
+ao_lco_input(void)
+{
+ static struct ao_event event;
+ uint8_t timeout;
+
+ ao_config_get();
+ for (;;) {
+ if (ao_config.pad_idle && !ao_lco_suspended) {
+ timeout = ao_event_get_for(&event, AO_SEC_TO_TICKS(ao_config.pad_idle));
+ if (timeout) {
+ ao_lco_suspend();
+ continue;
+ }
+ } else {
+ ao_event_get(&event);
+ }
+ ao_lco_wakeup();
+ PRINTD(DEBUG_EVENT, "event type %d unit %d value %d\n",
+ event.type, event.unit, event.value);
+ switch (event.type) {
+ case AO_EVENT_BUTTON:
+ switch (event.unit) {
+ case AO_BUTTON_ARM_0:
+ ao_lco_set_armed(0, event.value);
+ break;
+#if AO_BUTTON_ARM_NUM > 1
+ case AO_BUTTON_ARM_1:
+ ao_lco_set_armed(1, event.value);
+ break;
+#endif
+ case AO_BUTTON_FIRE:
+ if (ao_lco_armed) {
+ ao_lco_firing = event.value;
+ PRINTD(DEBUG_EVENT, "Firing %d\n", ao_lco_firing);
+ ao_wakeup(&ao_lco_armed);
+ }
+ break;
+ }
+ break;
+ }
+ }
+}
+
+static AO_LED_TYPE continuity_led[AO_LED_CONTINUITY_NUM] = {
+#ifdef AO_LED_CONTINUITY_0
+ AO_LED_CONTINUITY_0,
+#endif
+#ifdef AO_LED_CONTINUITY_1
+ AO_LED_CONTINUITY_1,
+#endif
+#ifdef AO_LED_CONTINUITY_2
+ AO_LED_CONTINUITY_2,
+#endif
+#ifdef AO_LED_CONTINUITY_3
+ AO_LED_CONTINUITY_3,
+#endif
+#ifdef AO_LED_CONTINUITY_4
+ AO_LED_CONTINUITY_4,
+#endif
+#ifdef AO_LED_CONTINUITY_5
+ AO_LED_CONTINUITY_5,
+#endif
+#ifdef AO_LED_CONTINUITY_6
+ AO_LED_CONTINUITY_6,
+#endif
+#ifdef AO_LED_CONTINUITY_7
+ AO_LED_CONTINUITY_7,
+#endif
+};
+
+static uint8_t
+ao_lco_get_channels(void)
+{
+ int8_t r;
+
+ r = ao_lco_query(ao_lco_box, &ao_pad_query, &ao_lco_tick_offset);
+ if (r == AO_RADIO_CMAC_OK) {
+ ao_lco_channels = ao_pad_query.channels;
+ ao_lco_valid = AO_LCO_VALID_LAST | AO_LCO_VALID_EVER;
+ } else
+ ao_lco_valid &= ~AO_LCO_VALID_LAST;
+ PRINTD(DEBUG_STATUS, "ao_lco_get_channels() rssi %d valid %d ret %d offset %d\n", ao_radio_cmac_rssi, ao_lco_valid, r, ao_lco_tick_offset);
+ ao_wakeup(&ao_pad_query);
+ return ao_lco_valid;
+}
+
+static void
+ao_lco_igniter_status(void)
+{
+ uint8_t c;
+ uint8_t t = 0;
+
+ for (;;) {
+ ao_sleep(&ao_pad_query);
+ while (ao_lco_suspended) {
+ ao_led_off(AO_LED_GREEN|AO_LED_AMBER|AO_LED_RED|AO_LED_REMOTE_ARM);
+ for (c = 0; c < AO_LED_CONTINUITY_NUM; c++)
+ ao_led_off(continuity_led[c]);
+ ao_sleep(&ao_lco_suspended);
+ }
+ PRINTD(DEBUG_STATUS, "RSSI %d VALID %d\n", ao_radio_cmac_rssi, ao_lco_valid);
+ if (!(ao_lco_valid & AO_LCO_VALID_LAST)) {
+ ao_led_on(AO_LED_RED);
+ ao_led_off(AO_LED_GREEN|AO_LED_AMBER);
+ continue;
+ }
+ if (ao_radio_cmac_rssi < -90) {
+ ao_led_on(AO_LED_AMBER);
+ ao_led_off(AO_LED_RED|AO_LED_GREEN);
+ } else {
+ ao_led_on(AO_LED_GREEN);
+ ao_led_off(AO_LED_RED|AO_LED_AMBER);
+ }
+ if (ao_pad_query.arm_status)
+ ao_led_on(AO_LED_REMOTE_ARM);
+ else
+ ao_led_off(AO_LED_REMOTE_ARM);
+
+ for (c = 0; c < AO_LED_CONTINUITY_NUM; c++) {
+ uint8_t status;
+
+ if (ao_pad_query.channels & (1 << c))
+ status = ao_pad_query.igniter_status[c];
+ else
+ status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN;
+ PRINTD(DEBUG_STATUS, "\tchannel %d status %d\n", c, status);
+ if (status == AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN)
+ ao_led_on(continuity_led[c]);
+ else
+ ao_led_off(continuity_led[c]);
+ }
+ t = 1-t;
+ }
+}
+
+static void
+ao_lco_arm_warn(void)
+{
+ int i;
+ for (;;) {
+ while (ao_lco_suspended)
+ ao_sleep(&ao_lco_suspended);
+ while (!ao_lco_armed)
+ ao_sleep(&ao_lco_armed);
+ for (i = 0; i < ao_lco_armed; i++) {
+ ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(100));
+ ao_delay(AO_MS_TO_TICKS(100));
+ }
+ ao_delay(AO_MS_TO_TICKS(300));
+ }
+}
+
+static struct ao_task ao_lco_input_task;
+static struct ao_task ao_lco_monitor_task;
+static struct ao_task ao_lco_arm_warn_task;
+static struct ao_task ao_lco_igniter_status_task;
+
+static void
+ao_lco_monitor(void)
+{
+ uint16_t delay;
+
+ ao_add_task(&ao_lco_input_task, ao_lco_input, "lco input");
+ ao_add_task(&ao_lco_arm_warn_task, ao_lco_arm_warn, "lco arm warn");
+ ao_add_task(&ao_lco_igniter_status_task, ao_lco_igniter_status, "lco igniter status");
+ ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200));
+ for (;;) {
+ while (ao_lco_suspended)
+ ao_sleep(&ao_lco_suspended);
+
+ PRINTD(DEBUG_STATUS, "monitor armed %d firing %d\n",
+ ao_lco_armed, ao_lco_firing);
+
+ if (ao_lco_armed && ao_lco_firing) {
+ ao_lco_ignite();
+ } else {
+ ao_lco_get_channels();
+ if (ao_lco_armed) {
+ if (ao_lco_selected) {
+ PRINTD(DEBUG_STATUS, "Arming pads %x\n",
+ ao_lco_selected);
+ if (ao_lco_valid & AO_LCO_VALID_EVER) {
+ ao_lco_arm(ao_lco_box, ao_lco_selected, ao_lco_tick_offset);
+ ao_delay(AO_MS_TO_TICKS(10));
+ }
+ }
+ }
+ }
+ if (ao_lco_armed && ao_lco_firing)
+ delay = AO_MS_TO_TICKS(100);
+ else {
+ delay = AO_SEC_TO_TICKS(1);
+ }
+ ao_sleep_for(&ao_lco_armed, delay);
+ }
+}
+
+#if DEBUG
+void
+ao_lco_set_debug(void)
+{
+ ao_cmd_decimal();
+ if (ao_cmd_status == ao_cmd_success)
+ ao_lco_debug = ao_cmd_lex_i;
+}
+
+__code struct ao_cmds ao_lco_cmds[] = {
+ { ao_lco_set_debug, "D <0 off, 1 on>\0Debug" },
+ { 0, NULL }
+};
+#endif
+
+void
+ao_lco_init(void)
+{
+ ao_add_task(&ao_lco_monitor_task, ao_lco_monitor, "lco monitor");
+#if DEBUG
+ ao_cmd_register(&ao_lco_cmds[0]);
+#endif
+}
__xdata struct ao_ms5607_prom ao_ms5607_prom;
static __xdata uint8_t ms5607_configured;
+#ifndef AO_MS5607_SPI_SPEED
+#define AO_MS5607_SPI_SPEED AO_SPI_SPEED_FAST
+#endif
+
static void
ao_ms5607_start(void) {
- ao_spi_get_bit(AO_MS5607_CS_PORT, AO_MS5607_CS_PIN, AO_MS5607_CS, AO_MS5607_SPI_INDEX, AO_SPI_SPEED_FAST);
+ ao_spi_get_bit(AO_MS5607_CS_PORT, AO_MS5607_CS_PIN, AO_MS5607_CS, AO_MS5607_SPI_INDEX, AO_MS5607_SPI_SPEED);
}
static void
{
char c;
ao_packet_enable = 1;
+ ao_packet_tx_used = 0;
ao_cmd_white();
flush();
#ifdef AO_SIREN
ao_gpio_set(AO_SIREN_PORT, AO_SIREN_PIN, AO_SIREN, v);
#else
+#if HAS_BEEP
ao_beep(v ? AO_BEEP_MID : 0);
+#else
+ (void) v;
+#endif
#endif
}
{
#ifdef AO_STROBE
ao_gpio_set(AO_STROBE_PORT, AO_STROBE_PIN, AO_STROBE, v);
+#else
+ (void) v;
#endif
}
static void
ao_pad_run(void)
{
- uint8_t pins;
+ AO_PORT_TYPE pins;
for (;;) {
while (!ao_pad_ignite)
if (ao_pad_ignite & (1 << 3))
pins |= (1 << AO_PAD_PIN_3);
#endif
- AO_PAD_PORT = (AO_PAD_PORT & (~AO_PAD_ALL_PINS)) | pins;
+ PRINTD("ignite pins 0x%x\n", pins);
+ ao_gpio_set_bits(AO_PAD_PORT, pins);
while (ao_pad_ignite) {
ao_pad_ignite = 0;
ao_delay(AO_PAD_FIRE_TIME);
}
- AO_PAD_PORT &= ~(AO_PAD_ALL_PINS);
+ ao_gpio_clr_bits(AO_PAD_PORT, pins);
+ PRINTD("turn off pins 0x%x\n", pins);
}
}
#define AO_PAD_ARM_SIREN_INTERVAL 200
+#ifndef AO_PYRO_R_PYRO_SENSE
+#define AO_PYRO_R_PYRO_SENSE 100
+#define AO_PYRO_R_SENSE_GND 27
+#define AO_FIRE_R_POWER_FET 100
+#define AO_FIRE_R_FET_SENSE 100
+#define AO_FIRE_R_SENSE_GND 27
+#endif
+
static void
ao_pad_monitor(void)
{
uint8_t sample;
__pdata uint8_t prev = 0, cur = 0;
__pdata uint8_t beeping = 0;
- __xdata struct ao_data *packet;
+ __xdata volatile struct ao_data *packet;
__pdata uint16_t arm_beep_time = 0;
sample = ao_data_head;
ao_sleep((void *) DATA_TO_XDATA(&ao_data_head));
);
+
packet = &ao_data_ring[sample];
sample = ao_data_ring_next(sample);
pyro = packet->adc.pyro;
-#define VOLTS_TO_PYRO(x) ((int16_t) ((x) * 27.0 / 127.0 / 3.3 * 32767.0))
+#define VOLTS_TO_PYRO(x) ((int16_t) ((x) * ((1.0 * AO_PYRO_R_SENSE_GND) / \
+ (1.0 * (AO_PYRO_R_SENSE_GND + AO_PYRO_R_PYRO_SENSE)) / 3.3 * AO_ADC_MAX)))
+
+
+#define VOLTS_TO_FIRE(x) ((int16_t) ((x) * ((1.0 * AO_FIRE_R_SENSE_GND) / \
+ (1.0 * (AO_FIRE_R_SENSE_GND + AO_FIRE_R_FET_SENSE)) / 3.3 * AO_ADC_MAX)))
/* convert ADC value to voltage in tenths, then add .2 for the diode drop */
query.battery = (packet->adc.batt + 96) / 192 + 2;
if (pyro > VOLTS_TO_PYRO(10)) {
query.arm_status = AO_PAD_ARM_STATUS_ARMED;
cur |= AO_LED_ARMED;
- } else if (pyro < VOLTS_TO_PYRO(5)) {
- query.arm_status = AO_PAD_ARM_STATUS_DISARMED;
- arm_beep_time = 0;
- } else {
+#if AO_FIRE_R_POWER_FET
+ } else if (pyro > VOLTS_TO_PYRO(5)) {
if ((ao_time() % 100) < 50)
cur |= AO_LED_ARMED;
query.arm_status = AO_PAD_ARM_STATUS_UNKNOWN;
arm_beep_time = 0;
+#endif
+ } else {
+ query.arm_status = AO_PAD_ARM_STATUS_DISARMED;
+ arm_beep_time = 0;
}
if ((ao_time() - ao_pad_packet_time) > AO_SEC_TO_TICKS(2))
cur |= AO_LED_RED;
* 27k /
* gnd ---
*
+ * v_pyro \
+ * 200k igniter
+ * output /
+ * 200k \
+ * sense relay
+ * 22k /
+ * gnd ---
+ *
* If the relay is closed, then sense will be 0
* If no igniter is present, then sense will be v_pyro * 27k/227k = pyro * 127 / 227 ~= pyro/2
* If igniter is present, then sense will be v_pyro * 27k/127k ~= v_pyro / 20 = pyro
*/
+#if AO_FIRE_R_POWER_FET
if (sense <= pyro / 8) {
status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED;
if ((ao_time() % 100) < 50)
cur |= AO_LED_CONTINUITY(c);
- }
- else if (pyro / 8 * 3 <= sense && sense <= pyro / 8 * 5)
+ } else
+ if (pyro / 8 * 3 <= sense && sense <= pyro / 8 * 5)
status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN;
else if (pyro / 8 * 7 <= sense) {
status = AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN;
cur |= AO_LED_CONTINUITY(c);
}
+#else
+ if (sense >= pyro / 8 * 5) {
+ status = AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN;
+ cur |= AO_LED_CONTINUITY(c);
+ } else {
+ status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN;
+ }
+#endif
query.igniter_status[c] = status;
}
if (cur != prev) {
l = byte & 0xf;
return h * 10 + l;
}
-#else
-#define ao_pad_read_box() 0
+#endif
+
+#if HAS_FIXED_PAD_BOX
+#define ao_pad_read_box() ao_config.pad_box
+#endif
+
+#ifdef PAD_BOX
+#define ao_pad_read_box() PAD_BOX
#endif
static void
--- /dev/null
+/*
+ * Copyright © 2016 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_servo.h"
+#include "ao_pwm.h"
+#include "ao_exti.h"
+
+static uint8_t limit_wakeup;
+
+static void
+ao_limit_isr(void)
+{
+ ao_wakeup(&limit_wakeup);
+}
+
+static void
+ao_limit_enable(uint8_t dir)
+{
+ if (dir == AO_SERVO_FORE)
+ ao_exti_enable(AO_SERVO_LIMIT_FORE_PORT, AO_SERVO_LIMIT_FORE_BIT);
+ else
+ ao_exti_enable(AO_SERVO_LIMIT_BACK_PORT, AO_SERVO_LIMIT_BACK_BIT);
+}
+
+static void
+ao_limit_disable(uint8_t dir)
+{
+ if (dir == AO_SERVO_FORE)
+ ao_exti_disable(AO_SERVO_LIMIT_FORE_PORT, AO_SERVO_LIMIT_FORE_BIT);
+ else
+ ao_exti_disable(AO_SERVO_LIMIT_BACK_PORT, AO_SERVO_LIMIT_BACK_BIT);
+}
+
+static uint8_t
+ao_limit_get(uint8_t dir)
+{
+ if (dir == AO_SERVO_FORE)
+ return !ao_gpio_get(AO_SERVO_LIMIT_FORE_PORT, AO_SERVO_LIMIT_FORE_BIT, PIN);
+ else
+ return !ao_gpio_get(AO_SERVO_LIMIT_BACK_PORT, AO_SERVO_LIMIT_BACK_BIT, PIN);
+}
+
+void
+ao_servo_run(uint16_t speed, uint8_t dir, uint16_t timeout)
+{
+ printf ("speed %d dir %d\n", speed, dir);
+
+ /* Turn on the motor */
+ ao_gpio_set(AO_SERVO_DIR_PORT, AO_SERVO_DIR_BIT, AO_SERVO_DIR_PIN, dir);
+ ao_pwm_set(AO_SERVO_SPEED_PWM, speed);
+
+ /* Wait until the limit sensor is triggered */
+ ao_arch_block_interrupts();
+ ao_limit_enable(dir);
+ while (!ao_limit_get(dir))
+ if (ao_sleep_for(&limit_wakeup, timeout))
+ break;
+ ao_limit_disable(dir);
+ ao_arch_release_interrupts();
+
+ /* Turn off the motor */
+ ao_pwm_set(AO_SERVO_SPEED_PWM, 0);
+}
+
+#define init_limit(p,b) do { \
+ ao_enable_port(p); \
+ ao_exti_setup(p, b, \
+ AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED, \
+ ao_limit_isr); \
+ } while (0)
+
+
+static void
+ao_servo_cmd(void)
+{
+ uint8_t dir;
+ uint16_t speed;
+
+ ao_cmd_decimal();
+ dir = ao_cmd_lex_u32;
+ ao_cmd_decimal();
+ speed = ao_cmd_lex_u32;
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+
+ printf("Run servo %d\n", dir);
+ ao_servo_run(speed, dir, AO_MS_TO_TICKS(200));
+}
+
+static const struct ao_cmds ao_servo_cmds[] = {
+ { ao_servo_cmd, "S <dir> <speed>\0Run servo in indicated direction" },
+ { 0, NULL },
+};
+
+
+void
+ao_servo_init(void)
+{
+ init_limit(AO_SERVO_LIMIT_FORE_PORT, AO_SERVO_LIMIT_FORE_BIT);
+ init_limit(AO_SERVO_LIMIT_BACK_PORT, AO_SERVO_LIMIT_BACK_BIT);
+ ao_enable_output(AO_SERVO_DIR_PORT, AO_SERVO_DIR_BIT, AO_SERVO_DIR_PIN, 0);
+ ao_cmd_register(&ao_servo_cmds[0]);
+}
--- /dev/null
+/*
+ * Copyright © 2016 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_SERVO_H_
+#define _AO_SERVO_H_
+
+void
+ao_servo_run(uint16_t speed, uint8_t dir, uint16_t timeout);
+
+void
+ao_servo_init(void);
+
+#define AO_SERVO_FORE 0
+#define AO_SERVO_BACK 1
+
+/* To configure the servo:
+ *
+ * #define AO_SERVO_PWM <pwm index>
+ * #define AO_SERVO_DIR_PORT <gpio>
+ * #define AO_SERVO_DIR_PIN <pin>
+ * #define AO_SERVO_LIMIT_FORE_PORT <gpio>
+ * #define AO_SERVO_LIMIT_FORE_PIN <pin>
+ * #define AO_SERVO_LIMIT_BACK_PORT <gpio>
+ * #define AO_SERVO_LIMIT_BACK_PIN <pin>
+ */
+
+#endif /* _AO_SERVO_H_ */
#include <ao_adc_fast.h>
#include <ao_crc.h>
#include <ao_trng_send.h>
+#include <ao_exti.h>
+#include <ao_power.h>
+
+static struct ao_task ao_trng_send_task, ao_trng_send_raw_task;
+static uint8_t trng_running;
+static AO_TICK_TYPE trng_power_time;
+
+#define TRNG_ENABLE_DELAY AO_MS_TO_TICKS(100)
+
+static uint8_t random_mutex;
static void
-ao_trng_send(void)
+ao_trng_get_raw(uint16_t *buf)
+{
+ uint16_t i;
+ uint16_t t;
+ uint16_t v;
+
+ t = ao_adc_get(AO_USB_IN_SIZE>>1); /* one 16-bit value per two output bytes */
+ for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) {
+ v = ao_adc_ring[t];
+ *buf++ = v;
+ t = (t + 1) & (AO_ADC_RING_SIZE - 1);
+ }
+ ao_adc_ack(AO_USB_IN_SIZE>>1);
+}
+
+static void
+ao_trng_send_raw(void)
{
static uint16_t *buffer[2];
int usb_buf_id;
+
+ if (!buffer[0]) {
+ buffer[0] = ao_usb_alloc();
+ buffer[1] = ao_usb_alloc();
+ if (!buffer[0])
+ ao_exit();
+ }
+
+ usb_buf_id = 0;
+
+ for (;;) {
+ ao_mutex_get(&random_mutex);
+ if (!trng_running) {
+ AO_TICK_TYPE delay;
+
+ delay = trng_power_time + TRNG_ENABLE_DELAY - ao_time();
+ if (delay > TRNG_ENABLE_DELAY)
+ delay = TRNG_ENABLE_DELAY;
+
+ /* Delay long enough for the HV power supply
+ * to stabilize so that the first bits we read
+ * aren't of poor quality
+ */
+ ao_delay(delay);
+ trng_running = TRUE;
+ }
+#ifdef AO_LED_TRNG_RAW
+ ao_led_on(AO_LED_TRNG_RAW);
+#endif
+ ao_trng_get_raw(buffer[usb_buf_id]);
+#ifdef AO_LED_TRNG_RAW
+ ao_led_off(AO_LED_TRNG_RAW);
+#endif
+ ao_mutex_put(&random_mutex);
+ ao_usb_write2(buffer[usb_buf_id], AO_USB_IN_SIZE);
+ usb_buf_id = 1-usb_buf_id;
+ }
+}
+
+/* Make sure there's at least 8 bits of variance in the samples */
+#define MIN_VARIANCE (128 * 128)
+
+/* Make sure the signal is spread around a bit */
+#define MAX_VARIANCE (512 * 512)
+
+#define ADD_STATS(value) do { \
+ sum += (value); \
+ sum2 += (value) * (value); \
+ } while(0)
+
+#define VARIANCE(n) ((sum2 - (sum / (n) * sum)) / (n))
+
+static int
+ao_trng_get_cooked(uint16_t *buf)
+{
uint16_t i;
- uint16_t *buf;
uint16_t t;
uint32_t *rnd = (uint32_t *) ao_adc_ring;
+ int32_t sum, sum2, var;
+
+ sum = sum2 = 0;
+ t = ao_adc_get(AO_USB_IN_SIZE) >> 1; /* one 16-bit value per output byte */
+ for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) {
+ uint32_t v;
+ uint16_t v1, v2;
+
+ /* Fetch two values in one operation */
+ v = rnd[t];
+ t = (t + 1) & ((AO_ADC_RING_SIZE >> 1) - 1);
+
+ *buf++ = ao_crc_in_32_out_16(v);
+
+ v1 = v;
+ v2 = v >> 16;
+
+ ADD_STATS(v1);
+ ADD_STATS(v2);
+ }
+ ao_adc_ack(AO_USB_IN_SIZE);
+ var = VARIANCE(2 * AO_USB_IN_SIZE / sizeof (uint16_t));
+ return var >= MIN_VARIANCE && var <= MAX_VARIANCE;
+}
+
+#define AO_TRNG_START_WAIT 1024
+#define AO_TRNG_START_CHECK 32
+
+static void
+ao_trng_send(void)
+{
+ static uint16_t *buffer[2];
+ int usb_buf_id;
+ int good_bits;
+ int failed;
+ int s;
if (!buffer[0]) {
buffer[0] = ao_usb_alloc();
buffer[1] = ao_usb_alloc();
if (!buffer[0])
- return;
+ ao_exit();
}
usb_buf_id = 0;
+#ifdef AO_TRNG_ENABLE_PORT
+ ao_gpio_set(AO_TRNG_ENABLE_PORT, AO_TRNG_ENABLE_BIT, AO_TRNG_ENABLE_PIN, 1);
+#endif
+ trng_power_time = ao_time();
+
ao_crc_reset();
+ ao_delay(TRNG_ENABLE_DELAY);
+
+ for (s = 0; s < AO_TRNG_START_WAIT; s++) {
+ if (ao_trng_get_cooked(buffer[0]))
+ break;
+ ao_delay(AO_MS_TO_TICKS(10));
+ }
+
+ /* Validate the hardware before enabling USB */
+ failed = 0;
+ for (s = 0; s < AO_TRNG_START_CHECK; s++) {
+ if (!ao_trng_get_cooked(buffer[0])) {
+ failed++;
+ ao_delay(AO_MS_TO_TICKS(10));
+ }
+ }
+ if (failed > AO_TRNG_START_CHECK / 4)
+ ao_panic(AO_PANIC_DMA);
+
+ ao_add_task(&ao_trng_send_raw_task, ao_trng_send_raw, "trng_send_raw");
+
+#ifdef AO_USB_START_DISABLED
+ ao_usb_enable();
+#endif
+
for (;;) {
- ao_led_on(AO_LED_TRNG_ACTIVE);
- t = ao_adc_get(AO_USB_IN_SIZE) >> 1; /* one 16-bit value per output byte */
- buf = buffer[usb_buf_id];
- for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) {
- *buf++ = ao_crc_in_32_out_16(rnd[t]);
- t = (t + 1) & ((AO_ADC_RING_SIZE>>1) - 1);
+ ao_mutex_get(&random_mutex);
+ if (!trng_running) {
+ AO_TICK_TYPE delay;
+
+ delay = trng_power_time + TRNG_ENABLE_DELAY - ao_time();
+ if (delay > TRNG_ENABLE_DELAY)
+ delay = TRNG_ENABLE_DELAY;
+
+ /* Delay long enough for the HV power supply
+ * to stabilize so that the first bits we read
+ * aren't of poor quality
+ */
+ ao_delay(delay);
+ trng_running = TRUE;
+ }
+#ifdef AO_LED_TRNG_COOKED
+ ao_led_on(AO_LED_TRNG_COOKED);
+#endif
+ good_bits = ao_trng_get_cooked(buffer[usb_buf_id]);
+#ifdef AO_LED_TRNG_COOKED
+ ao_led_off(AO_LED_TRNG_COOKED);
+#endif
+ ao_mutex_put(&random_mutex);
+ if (good_bits) {
+ ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE);
+ usb_buf_id = 1-usb_buf_id;
+ failed = 0;
+ } else {
+ failed++;
+ ao_delay(AO_MS_TO_TICKS(10));
+ if (failed > 10) {
+ ao_usb_disable();
+ ao_panic(AO_PANIC_DMA);
+ }
}
- ao_adc_ack(AO_USB_IN_SIZE);
- ao_led_off(AO_LED_TRNG_ACTIVE);
- ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE);
- usb_buf_id = 1-usb_buf_id;
}
}
-static struct ao_task ao_trng_send_task;
+#if AO_POWER_MANAGEMENT
+
+static void ao_trng_suspend(void *arg)
+{
+ (void) arg;
+#ifdef AO_TRNG_ENABLE_PORT
+ ao_gpio_set(AO_TRNG_ENABLE_PORT, AO_TRNG_ENABLE_BIT, AO_TRNG_ENABLE_PIN, 0);
+#endif
+ trng_running = FALSE;
+}
+
+static void ao_trng_resume(void *arg)
+{
+ (void) arg;
+#ifdef AO_TRNG_ENABLE_PORT
+ ao_gpio_set(AO_TRNG_ENABLE_PORT, AO_TRNG_ENABLE_BIT, AO_TRNG_ENABLE_PIN, 1);
+#endif
+ trng_power_time = ao_time();
+}
+
+static struct ao_power ao_trng_power = {
+ .suspend = ao_trng_suspend,
+ .resume = ao_trng_resume
+};
+
+#endif
void
ao_trng_send_init(void)
{
+#ifdef AO_TRNG_ENABLE_PORT
+ ao_enable_output(AO_TRNG_ENABLE_PORT, AO_TRNG_ENABLE_BIT, AO_TRNG_ENABLE_PIN, 0);
+ ao_power_register(&ao_trng_power);
+#endif
+ ao_enable_input(AO_RAW_PORT, AO_RAW_BIT, AO_EXTI_MODE_PULL_UP);
ao_add_task(&ao_trng_send_task, ao_trng_send, "trng_send");
}
*/
#define HAS_MMA655X 1
+#define AO_MMA655X_INVERT 0
#define AO_MMA655X_SPI_INDEX AO_SPI_1_PB3_PB4_PB5
#define AO_MMA655X_CS_PORT (&stm_gpioc)
#define AO_MMA655X_CS_PIN 12
void
ao_clock_init(void);
+#if AO_POWER_MANAGEMENT
+/* Go to low power clock */
+void
+ao_clock_suspend(void);
+
+/* Restart full-speed clock */
+void
+ao_clock_resume(void);
+#endif
+
/*
* ao_mutex.c
*/
} while(0)
#define ao_fifo_full(f) ((((f).insert + 1) & (AO_FIFO_SIZE-1)) == (f).remove)
+#define ao_fifo_mostly(f) ((((f).insert - (f).remove) & (AO_FIFO_SIZE-1)) >= (AO_FIFO_SIZE * 3 / 4))
+#define ao_fifo_barely(f) ((((f).insert - (f).remove) & (AO_FIFO_SIZE-1)) >= (AO_FIFO_SIZE * 1 / 4))
#define ao_fifo_empty(f) ((f).insert == (f).remove)
#if PACKET_HAS_MASTER || PACKET_HAS_SLAVE
#if HAS_APRS
if (minor < 22)
ao_config.aprs_format = AO_CONFIG_DEFAULT_APRS_FORMAT;
+#endif
+#if HAS_FIXED_PAD_BOX
+ if (minor < 22)
+ ao_config.pad_box = 1;
+ if (minor < 23)
+ ao_config.pad_idle = 120;
#endif
ao_config.minor = AO_CONFIG_MINOR;
ao_config_dirty = 1;
}
#endif /* HAS_APRS */
+#if HAS_FIXED_PAD_BOX
+void
+ao_config_pad_box_show(void)
+{
+ printf ("Pad box: %d\n", ao_config.pad_box);
+}
+
+void
+ao_config_pad_box_set(void)
+{
+ ao_cmd_decimal();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ _ao_config_edit_start();
+ ao_config.pad_box = ao_cmd_lex_i;
+ _ao_config_edit_finish();
+}
+
+void
+ao_config_pad_idle_show(void)
+{
+ printf ("Idle timeout: %d\n", ao_config.pad_idle);
+}
+
+void
+ao_config_pad_idle_set(void)
+{
+ ao_cmd_decimal();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ _ao_config_edit_start();
+ ao_config.pad_idle = ao_cmd_lex_i;
+ _ao_config_edit_finish();
+}
+#endif
+
struct ao_config_var {
__code char *str;
void (*set)(void) __reentrant;
ao_config_aprs_ssid_set, ao_config_aprs_ssid_show },
{ "C <0 compressed, 1 uncompressed>\0APRS format",
ao_config_aprs_format_set, ao_config_aprs_format_show },
+#endif
+#if HAS_FIXED_PAD_BOX
+ { "B <box>\0Set pad box (1-99)",
+ ao_config_pad_box_set, ao_config_pad_box_show },
+ { "i <seconds>\0Set idle timeout (0 disable)",
+ ao_config_pad_idle_set, ao_config_pad_idle_show },
#endif
{ "s\0Show",
ao_config_show, 0 },
#endif
#define AO_CONFIG_MAJOR 1
-#define AO_CONFIG_MINOR 22
+#define AO_CONFIG_MINOR 23
#define AO_AES_LEN 16
#if HAS_APRS
uint8_t aprs_format; /* minor version 22 */
#endif
+#if HAS_FIXED_PAD_BOX
+ uint8_t pad_box; /* minor version 22 */
+ uint8_t pad_idle; /* minor version 23 */
+#endif
};
#define AO_APRS_FORMAT_COMPRESSED 0
#define AO_ACCEL_INVERT 4095
+#ifndef AO_MMA655X_INVERT
+#error AO_MMA655X_INVERT not defined
+#endif
+
#define ao_data_accel(packet) ((packet)->mma655x)
#if AO_MMA655X_INVERT
#define ao_data_accel_cook(packet) (AO_ACCEL_INVERT - (packet)->mma655x)
--- /dev/null
+/*
+ * Copyright © 2013 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_FAST_TIMER_H_
+#define _AO_FAST_TIMER_H_
+
+void
+ao_fast_timer_init(void);
+
+#ifndef AO_FAST_TIMER_MAX
+#define AO_FAST_TIMER_MAX 2
+#endif
+
+void
+ao_fast_timer_on(void (*callback)(void));
+
+void
+ao_fast_timer_off(void (*callback)(void));
+
+#endif /* _AO_FAST_TIMER_H_ */
{
ao_flight_state = ao_flight_landed;
+#if HAS_ADC
/* turn off the ADC capture */
ao_timer_set_adc_interval(0);
+#endif
ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
}
#define AO_LOG_FORMAT_TELEMINI 8 /* 16-byte MS5607 baro only, 3.3V supply */
#define AO_LOG_FORMAT_TELEGPS 9 /* 32 byte telegps records */
#define AO_LOG_FORMAT_TELEMEGA 10 /* 32 byte typed telemega records with 32 bit gyro cal */
+#define AO_LOG_FORMAT_DETHERM 11 /* 16-byte MS5607 baro only, no ADC */
#define AO_LOG_FORMAT_NONE 127 /* No log at all */
extern __code uint8_t ao_log_format;
ao_data_ring[ao_log_data_pos].ms5607_raw.pres);
ao_log_pack24(log.u.sensor.temp,
ao_data_ring[ao_log_data_pos].ms5607_raw.temp);
+#if AO_LOG_FORMAT != AO_LOG_FORMAT_DETHERM
log.u.sensor.sense_a = ao_data_ring[ao_log_data_pos].adc.sense_a;
log.u.sensor.sense_m = ao_data_ring[ao_log_data_pos].adc.sense_m;
log.u.sensor.v_batt = ao_data_ring[ao_log_data_pos].adc.v_batt;
+#endif
ao_log_mini(&log);
if (ao_log_state <= ao_flight_coast)
next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT;
{
uint8_t i = 0, j = 0;
- while (n--)
+ while (n--) {
+#ifdef AO_PANIC_DELAY_SCALE
+ uint8_t s = AO_PANIC_DELAY_SCALE;
+ while (s--)
+#endif
while (--j)
while (--i)
ao_arch_nop();
+ }
}
void
ao_arch_block_interrupts();
for (;;) {
ao_panic_delay(20);
+#if HAS_BEEP
for (n = 0; n < 5; n++) {
- ao_led_on(AO_LED_PANIC);
ao_beep(AO_BEEP_HIGH);
ao_panic_delay(1);
- ao_led_off(AO_LED_PANIC);
ao_beep(AO_BEEP_LOW);
ao_panic_delay(1);
}
ao_beep(AO_BEEP_OFF);
ao_panic_delay(2);
+#endif
#ifdef SDCC
#pragma disable_warning 126
--- /dev/null
+/*
+ * Copyright © 2016 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_power.h>
+
+static struct ao_power *head, *tail;
+
+void
+ao_power_register(struct ao_power *power)
+{
+ if (power->registered)
+ return;
+ power->registered = TRUE;
+ if (tail) {
+ tail->next = power;
+ power->prev = tail;
+ tail = power;
+ } else {
+ head = tail = power;
+ }
+#ifdef AO_LED_POWER
+ ao_led_on(AO_LED_POWER);
+#endif
+}
+
+void
+ao_power_unregister(struct ao_power *power)
+{
+ if (!power->registered)
+ return;
+ power->registered = FALSE;
+ if (power->prev)
+ power->prev->next = power->next;
+ else
+ head = power->next;
+ if (power->next)
+ power->next->prev = power->prev;
+ else
+ tail = power->prev;
+}
+
+void
+ao_power_suspend(void)
+{
+ struct ao_power *p;
+
+#ifdef AO_LED_POWER
+ ao_led_off(AO_LED_POWER);
+#endif
+ for (p = tail; p; p = p->prev)
+ p->suspend(p->arg);
+}
+
+void
+ao_power_resume(void)
+{
+ struct ao_power *p;
+
+ for (p = head; p; p = p->next)
+ p->resume(p->arg);
+#ifdef AO_LED_POWER
+ ao_led_on(AO_LED_POWER);
+#endif
+}
+
--- /dev/null
+/*
+ * Copyright © 2016 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_POWER_H_
+#define _AO_POWER_H_
+
+#if AO_POWER_MANAGEMENT
+
+struct ao_power {
+ struct ao_power *prev, *next;
+
+ void (*suspend)(void *arg);
+ void (*resume)(void *arg);
+ void *arg;
+ uint8_t registered;
+};
+
+void
+ao_power_register(struct ao_power *power);
+
+void
+ao_power_unregister(struct ao_power *power);
+
+void
+ao_power_suspend(void);
+
+void
+ao_power_resume(void);
+
+#else /* AO_POWER_MANAGEMENT */
+
+#define ao_power_register(power)
+#define ao_power_unregister(power)
+#define ao_power_suspend()
+#define ao_power_resume()
+
+#endif /* else AO_POWER_MANAGEMENT */
+
+#endif /* _AO_POWER_H_ */
#define AO_USB_MAX_POWER 100
#endif
-#ifndef AO_USB_INTERFACE_CLASS
-#define AO_USB_INTERFACE_CLASS 0x02
+#ifndef AO_USB_SELF_POWER
+#define AO_USB_SELF_POWER 1
+#endif
+
+#define AO_USB_DEVICE_CLASS_COMMUNICATION 0x02
+#define AO_USB_INTERFACE_CLASS_CONTROL_CDC 0x02
+#define AO_USB_INTERFACE_CLASS_DATA_CDC 0x0A
+
+#ifndef AO_USB_DEVICE_CLASS
+#define AO_USB_DEVICE_CLASS AO_USB_DEVICE_CLASS_COMMUNICATION
+#endif
+
+#ifndef AO_USB_INTERFACE_CLASS_DATA
+#define AO_USB_INTERFACE_CLASS_CONTROL AO_USB_INTERFACE_CLASS_CONTROL_CDC
+#define AO_USB_INTERFACE_CLASS_DATA AO_USB_INTERFACE_CLASS_DATA_CDC
#endif
#include "ao_usb.h"
+
+#define HEADER_LEN 9
+#define CONTROL_CLASS_LEN 35
+#define DATA_LEN (9 + 7 * AO_USB_HAS_OUT + 7 * AO_USB_HAS_IN + 7 * AO_USB_HAS_IN2)
+
+#define TOTAL_LENGTH (HEADER_LEN + AO_USB_HAS_INT * CONTROL_CLASS_LEN + DATA_LEN)
+#define NUM_INTERFACES (AO_USB_HAS_INT + 1)
+
/* USB descriptors in one giant block of bytes */
AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] =
{
0x12,
AO_USB_DESC_DEVICE,
LE_WORD(0x0110), /* bcdUSB */
- 0x02, /* bDeviceClass */
+ AO_USB_DEVICE_CLASS, /* bDeviceClass */
0x00, /* bDeviceSubClass */
0x00, /* bDeviceProtocol */
AO_USB_CONTROL_SIZE, /* bMaxPacketSize */
/* Configuration descriptor */
0x09,
AO_USB_DESC_CONFIGURATION,
- LE_WORD(67), /* wTotalLength */
- 0x02, /* bNumInterfaces */
+ LE_WORD(TOTAL_LENGTH), /* wTotalLength */
+ NUM_INTERFACES, /* bNumInterfaces */
0x01, /* bConfigurationValue */
0x00, /* iConfiguration */
- 0xC0, /* bmAttributes */
+ 0x80 | (AO_USB_SELF_POWER << 6), /* bmAttributes */
AO_USB_MAX_POWER >> 1, /* bMaxPower, 2mA units */
+#if AO_USB_HAS_INT
/* Control class interface */
0x09,
AO_USB_DESC_INTERFACE,
0x00, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x01, /* bNumEndPoints */
- AO_USB_INTERFACE_CLASS, /* bInterfaceClass */
+ AO_USB_INTERFACE_CLASS_CONTROL, /* bInterfaceClass */
0x02, /* bInterfaceSubClass */
0x01, /* bInterfaceProtocol, linux requires value of 1 for the cdc_acm module */
0x00, /* iInterface */
0x03, /* bmAttributes = intr */
LE_WORD(8), /* wMaxPacketSize */
0xff, /* bInterval */
+#endif
/* Data class interface descriptor */
0x09,
AO_USB_DESC_INTERFACE,
- 0x01, /* bInterfaceNumber */
- 0x00, /* bAlternateSetting */
- 0x02, /* bNumEndPoints */
- 0x0A, /* bInterfaceClass = data */
- 0x00, /* bInterfaceSubClass */
- 0x00, /* bInterfaceProtocol */
- 0x00, /* iInterface */
-
+ AO_USB_HAS_INT, /* bInterfaceNumber */
+ 0x00, /* bAlternateSetting */
+ AO_USB_HAS_OUT + AO_USB_HAS_IN + AO_USB_HAS_IN2, /* bNumEndPoints */
+ AO_USB_INTERFACE_CLASS_DATA, /* bInterfaceClass = data */
+ 0x00, /* bInterfaceSubClass */
+ 0x00, /* bInterfaceProtocol */
+ 0x00, /* iInterface */
+
+#if AO_USB_HAS_OUT
/* Data EP OUT */
0x07,
AO_USB_DESC_ENDPOINT,
0x02, /* bmAttributes = bulk */
LE_WORD(AO_USB_OUT_SIZE),/* wMaxPacketSize */
0x00, /* bInterval */
+#endif
+#if AO_USB_HAS_IN
/* Data EP in */
0x07,
AO_USB_DESC_ENDPOINT,
0x02, /* bmAttributes = bulk */
LE_WORD(AO_USB_IN_SIZE),/* wMaxPacketSize */
0x00, /* bInterval */
+#endif
+
+#if AO_USB_HAS_IN2
+ /* Data EP in 2 */
+ 0x07,
+ AO_USB_DESC_ENDPOINT,
+ AO_USB_IN2_EP|0x80, /* bEndpointAddress */
+ 0x02, /* bmAttributes = bulk */
+ LE_WORD(AO_USB_IN_SIZE),/* wMaxPacketSize */
+ 0x00, /* bInterval */
+#endif
/* String descriptors */
0x04,
*/
if (ao_cur_task->wchan == NULL)
ao_task_to_run_queue(ao_cur_task);
- ao_cur_task = NULL;
for (;;) {
ao_arch_memory_barrier();
if (!ao_list_is_empty(&run_queue))
void
ao_wakeup(__xdata void *wchan) __reentrant
{
+ ao_validate_cur_stack();
#if HAS_TASK_QUEUE
struct ao_task *sleep, *next;
struct ao_list *sleep_queue;
}
ao_arch_irqrestore(flags);
#else
+ {
uint8_t i;
for (i = 0; i < ao_num_tasks; i++)
if (ao_tasks[i]->wchan == wchan)
ao_tasks[i]->wchan = NULL;
+ }
#endif
ao_check_stack();
}
extern __xdata struct ao_task *__data ao_cur_task;
extern __data uint8_t ao_task_minimize_latency; /* Reduce IRQ latency */
+#ifndef HAS_ARCH_VALIDATE_CUR_STACK
+#define ao_validate_cur_stack()
+#endif
+
/*
ao_task.c
*/
#ifndef AO_USB_OUT_EP
#define AO_USB_OUT_EP 4
#define AO_USB_IN_EP 5
+#define AO_USB_IN2_EP 6
+#endif
+
+#ifndef AO_USB_HAS_OUT
+#define AO_USB_HAS_OUT 1
+#endif
+
+#ifndef AO_USB_HAS_IN
+#define AO_USB_HAS_IN 1
+#endif
+
+#ifndef AO_USB_HAS_INT
+#define AO_USB_HAS_INT 1
+#endif
+
+#ifndef AO_USB_HAS_IN2
+#define AO_USB_HAS_IN2 0
#endif
/*
void
ao_spi_init(void);
+static inline void
+ao_spi_send_sync(const void *block, uint16_t len, uint8_t spi_index)
+{
+ ao_spi_send(block, len, spi_index);
+}
+
+static inline void ao_spi_send_byte(uint8_t byte, uint8_t spi_index)
+{
+ struct lpc_ssp *lpc_ssp;
+ switch (spi_index) {
+ case 0:
+ lpc_ssp = &lpc_ssp0;
+ break;
+ case 1:
+ lpc_ssp = &lpc_ssp1;
+ break;
+ }
+ lpc_ssp->dr = byte;
+ while ((lpc_ssp->sr & (1 << LPC_SSP_SR_RNE)) == 0);
+ (void) lpc_ssp->dr;
+}
+
#define ao_spi_init_cs(port, mask) do { \
uint8_t __bit__; \
for (__bit__ = 0; __bit__ < 32; __bit__++) { \
--- /dev/null
+/*
+ * Copyright © 2016 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_fast_timer.h>
+
+static void (*ao_fast_timer_callback[AO_FAST_TIMER_MAX])(void);
+static uint8_t ao_fast_timer_count;
+static uint8_t ao_fast_timer_users;
+
+static void
+ao_fast_timer_enable(void)
+{
+ lpc_ct16b0.tcr = ((1 << LPC_CT16B_TCR_CEN) |
+ (1 << LPC_CT16B_TCR_CRST));
+}
+
+static void
+ao_fast_timer_disable(void)
+{
+ lpc_ct16b0.tcr = ((0 << LPC_CT16B_TCR_CEN) |
+ (0 << LPC_CT16B_TCR_CRST));
+}
+
+void
+ao_fast_timer_on(void (*callback)(void))
+{
+ ao_fast_timer_callback[ao_fast_timer_count] = callback;
+ if (!ao_fast_timer_count++)
+ ao_fast_timer_enable();
+}
+
+void
+ao_fast_timer_off(void (*callback)(void))
+{
+ uint8_t n;
+
+ for (n = 0; n < ao_fast_timer_count; n++)
+ if (ao_fast_timer_callback[n] == callback) {
+ for (; n < ao_fast_timer_count-1; n++) {
+ ao_fast_timer_callback[n] = ao_fast_timer_callback[n+1];
+ }
+ if (!--ao_fast_timer_count)
+ ao_fast_timer_disable();
+ break;
+ }
+}
+
+void lpc_ct16b0_isr(void)
+{
+ uint32_t v = lpc_ct16b0.ir;
+ int i;
+
+ lpc_ct16b0.ir = v;
+ if (v & (1 << LPC_CT16B_IR_MR0INT)) {
+ for (i = 0; i < ao_fast_timer_count; i++)
+ (*ao_fast_timer_callback[i])();
+ }
+}
+
+#ifndef FAST_TIMER_FREQ
+#define FAST_TIMER_FREQ 10000
+#endif
+
+#define TIMER_FAST (AO_LPC_SYSCLK / FAST_TIMER_FREQ)
+
+void
+ao_fast_timer_init(void)
+{
+ if (!ao_fast_timer_users) {
+
+ lpc_nvic_set_enable(LPC_ISR_CT16B0_POS);
+ lpc_nvic_set_priority(LPC_ISR_CT16B0_POS, AO_LPC_NVIC_CLOCK_PRIORITY);
+ /* Turn on 16-bit timer CT16B0 */
+
+ lpc_scb.sysahbclkctrl |= 1 << LPC_SCB_SYSAHBCLKCTRL_CT16B0;
+
+ /* Disable timer */
+ lpc_ct16b0.tcr = 0;
+
+ /* scale factor 1 */
+ lpc_ct16b0.pr = 0;
+ lpc_ct16b0.pc = 0;
+
+ lpc_ct16b0.mcr = ((1 << LPC_CT16B_MCR_MR0I) |
+ (1 << LPC_CT16B_MCR_MR0R));
+
+ lpc_ct16b0.mr[0] = TIMER_FAST;
+
+ ao_fast_timer_disable();
+ }
+ if (ao_fast_timer_users == AO_FAST_TIMER_MAX)
+ ao_panic(AO_PANIC_FAST_TIMER);
+ ao_fast_timer_users++;
+}
+
(1 << LPC_SCB_SYSAHBCLKCTRL_FLASHARRAY) |
(1 << LPC_SCB_SYSAHBCLKCTRL_GPIO) |
(1 << LPC_SCB_SYSAHBCLKCTRL_IOCON));
-
+
/* Enable the brown-out detection at the highest voltage to
* make sure the flash part remains happy
*/
/* Turn the IRC clock back on */
lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_IRC_PD);
ao_clock_delay();
-
+
/* Switch to the IRC clock */
lpc_scb.mainclksel = LPC_SCB_MAINCLKSEL_SEL_IRC << LPC_SCB_MAINCLKSEL_SEL;
lpc_scb.mainclkuen = (0 << LPC_SCB_MAINCLKUEN_ENA);
lpc_scb.mainclkuen = (1 << LPC_SCB_MAINCLKUEN_ENA);
while (!(lpc_scb.mainclkuen & (1 << LPC_SCB_MAINCLKUEN_ENA)))
;
-
+
/* Switch USB to the main clock */
lpc_scb.usbclksel = (LPC_SCB_USBCLKSEL_SEL_MAIN_CLOCK << LPC_SCB_USBCLKSEL_SEL);
lpc_scb.usbclkuen = (0 << LPC_SCB_USBCLKUEN_ENA);
lpc_scb.usbclkuen = (1 << LPC_SCB_USBCLKUEN_ENA);
while (!(lpc_scb.usbclkuen & (1 << LPC_SCB_USBCLKUEN_ENA)))
;
-
+
/* Find a PLL post divider ratio that gets the FCCO in range */
for (p = 0; p < 4; p++)
if (AO_LPC_CLKOUT << (1 + p) >= AO_LPC_FCCO_MIN)
lpc_scb.syspllclkuen = (1 << LPC_SCB_SYSPLLCLKUEN_ENA);
while (!(lpc_scb.syspllclkuen & (1 << LPC_SCB_SYSPLLCLKUEN_ENA)))
;
-
+
/* Turn on the PLL */
lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_SYSPLL_PD);
/* Wait for it to lock */
-
+
for (i = 0; i < 20000; i++)
if (lpc_scb.syspllstat & (1 << LPC_SCB_SYSPLLSTAT_LOCK))
break;
lpc_scb.usbpllclkuen = (1 << LPC_SCB_USBPLLCLKUEN_ENA);
while (!(lpc_scb.usbpllclkuen & (1 << LPC_SCB_USBPLLCLKUEN_ENA)))
;
-
+
/* Power down everything we don't need */
lpc_scb.pdruncfg = ((1 << LPC_SCB_PDRUNCFG_IRCOUT_PD) |
(1 << LPC_SCB_PDRUNCFG_IRC_PD) |
vuint32_t mainclksel; /* 0x70 */
vuint32_t mainclkuen;
vuint32_t sysahbclkdiv;
- uint32_t r7c;
+ uint32_t r7c;
vuint32_t sysahbclkctrl; /* 0x80 */
uint32_t r84[3];
uint32_t rcc;
uint32_t rd0[4];
-
+
vuint32_t clkoutsel; /* 0xe0 */
vuint32_t clkoutuen;
vuint32_t clkoutdiv;
uint32_t rec;
-
+
uint32_t rf0[4]; /* 0xf0 */
-
+
vuint32_t pioporcap0; /* 0x100 */
vuint32_t pioporcap1;
uint32_t r102[2];
uint32_t r120[4]; /* 0x120 */
uint32_t r130[4]; /* 0x130 */
uint32_t r140[4]; /* 0x140 */
-
+
vuint32_t bodctrl; /* 0x150 */
vuint32_t systckcal;
uint32_t r158[2];
uint32_t r240[12 * 4]; /* 0x240 */
uint32_t r300[15 * 4]; /* 0x300 */
-
+
uint32_t r3f0; /* 0x3f0 */
vuint32_t device_id;
};
vuint32_t word[0x40]; /* 0x1000 */
uint8_t r1100[0x2000 - 0x1100];
-
+
vuint32_t dir[2]; /* 0x2000 */
uint8_t r2008[0x2080 - 0x2008];
return (lpc_nvic.iser >> irq) & 1;
}
-
+
static inline void
lpc_nvic_set_pending(int irq) {
lpc_nvic.ispr = (1 << irq);
#define LPC_ADC_STAT_OVERRUN 8
#define LPC_ADC_STAT_ADINT 16
+struct lpc_ct16b {
+ vuint32_t ir; /* 0x00 */
+ vuint32_t tcr;
+ vuint32_t tc;
+ vuint32_t pr;
+
+ vuint32_t pc; /* 0x10 */
+ vuint32_t mcr;
+ vuint32_t mr[4]; /* 0x18 */
+ vuint32_t ccr; /* 0x28 */
+ vuint32_t cr0;
+
+ vuint32_t cr1_0; /* 0x30 (only for ct16b0 */
+ vuint32_t cr1_1; /* 0x34 (only for ct16b1 */
+ uint32_t r38;
+ vuint32_t emr;
+
+ uint8_t r40[0x70 - 0x40];
+
+ vuint32_t ctcr; /* 0x70 */
+ vuint32_t pwmc;
+};
+
+extern struct lpc_ct16b lpc_ct16b0, lpc_ct16b1;
+
+#define lpc_ct16b0 (*(struct lpc_ct16b *) 0x4000c000)
+#define lpc_ct16b1 (*(struct lpc_ct16b *) 0x40010000)
+
+#define LPC_CT16B_IR_MR0INT 0
+#define LPC_CT16B_IR_MR1INT 1
+#define LPC_CT16B_IR_MR2INT 2
+#define LPC_CT16B_IR_MR3INT 3
+#define LPC_CT16B_IR_CR0INT 4
+#define LPC_CT16B0_IR_CR1INT 6
+#define LPC_CT16B1_IR_CR1INT 5
+
+#define LPC_CT16B_TCR_CEN 0
+#define LPC_CT16B_TCR_CRST 1
+
+#define LPC_CT16B_MCR_MR0I 0
+#define LPC_CT16B_MCR_MR0R 1
+#define LPC_CT16B_MCR_MR0S 2
+#define LPC_CT16B_MCR_MR1I 3
+#define LPC_CT16B_MCR_MR1R 4
+#define LPC_CT16B_MCR_MR1S 5
+#define LPC_CT16B_MCR_MR2I 6
+#define LPC_CT16B_MCR_MR2R 7
+#define LPC_CT16B_MCR_MR2S 8
+#define LPC_CT16B_MCR_MR3I 9
+#define LPC_CT16B_MCR_MR3R 10
+#define LPC_CT16B_MCR_MR3S 11
+
+#define LPC_CT16B_CCR_CAP0RE 0
+#define LPC_CT16B_CCR_CAP0FE 1
+#define LPC_CT16B_CCR_CAP0I 2
+#define LPC_CT16B0_CCR_CAP1RE 6
+#define LPC_CT16B0_CCR_CAP1FE 7
+#define LPC_CT16B0_CCR_CAP1I 8
+#define LPC_CT16B1_CCR_CAP1RE 3
+#define LPC_CT16B1_CCR_CAP1FE 4
+#define LPC_CT16B1_CCR_CAP1I 5
+
+#define LPC_CT16B_EMR_EM0 0
+#define LPC_CT16B_EMR_EM1 1
+#define LPC_CT16B_EMR_EM2 2
+#define LPC_CT16B_EMR_EM3 3
+#define LPC_CT16B_EMR_EMC0 4
+#define LPC_CT16B_EMR_EMC1 6
+#define LPC_CT16B_EMR_EMC2 8
+#define LPC_CT16B_EMR_EMC3 10
+
+#define LPC_CT16B_EMR_EMC_NOTHING 0
+#define LPC_CT16B_EMR_EMC_CLEAR 1
+#define LPC_CT16B_EMR_EMC_SET 2
+#define LPC_CT16B_EMR_EMC_TOGGLE 3
+
+#define LPC_CT16B_CCR_CTM 0
+#define LPC_CT16B_CCR_CTM_TIMER 0
+#define LPC_CT16B_CCR_CTM_COUNTER_RISING 1
+#define LPC_CT16B_CCR_CTM_COUNTER_FALLING 2
+#define LPC_CT16B_CCR_CTM_COUNTER_BOTH 3
+#define LPC_CT16B_CCR_CIS 2
+#define LPC_CT16B_CCR_CIS_CAP0 0
+#define LPC_CT16B0_CCR_CIS_CAP1 2
+#define LPC_CT16B1_CCR_CIS_CAP1 1
+#define LPC_CT16B_CCR_ENCC 4
+#define LPC_CT16B_CCR_SELCC 5
+#define LPC_CT16B_CCR_SELCC_RISING_CAP0 0
+#define LPC_CT16B_CCR_SELCC_FALLING_CAP0 1
+#define LPC_CT16B0_CCR_SELCC_RISING_CAP1 4
+#define LPC_CT16B0_CCR_SELCC_FALLING_CAP1 5
+#define LPC_CT16B1_CCR_SELCC_RISING_CAP1 2
+#define LPC_CT16B1_CCR_SELCC_FALLING_CAP1 3
+#define LPC_CT16B_CCR_
+
+#define LPC_CT16B_PWMC_PWMEN0 0
+#define LPC_CT16B_PWMC_PWMEN1 1
+#define LPC_CT16B_PWMC_PWMEN2 2
+#define LPC_CT16B_PWMC_PWMEN3 3
+
struct lpc_ct32b {
vuint32_t ir; /* 0x00 */
vuint32_t tcr;
vuint32_t tc;
vuint32_t pr;
-
+
vuint32_t pc; /* 0x10 */
vuint32_t mcr;
vuint32_t mr[4]; /* 0x18 */
vuint32_t ccr; /* 0x28 */
vuint32_t cr0;
-
+
vuint32_t cr1_0; /* 0x30 (only for ct32b0 */
vuint32_t cr1_1; /* 0x34 (only for ct32b1 */
uint32_t r38;
lpc_usb_sram = 0x20004000;
lpc_usb_endpoint = 0x20004700;
lpc_usart = 0x40008000;
+lpc_ct16b0 = 0x4000c000;
+lpc_ct16b1 = 0x40010000;
lpc_ct32b0 = 0x40014000;
lpc_ct32b1 = 0x40018000;
lpc_adc = 0x4001c000;
* STM32L definitions and code fragments for AltOS
*/
+#ifndef AO_STACK_SIZE
#define AO_STACK_SIZE 512
+#endif
#define AO_LED_TYPE uint16_t
void
ao_spi_send_sync(void *block, uint16_t len, uint8_t spi_index);
+static inline void
+ao_spi_send_byte(uint8_t byte, uint8_t spi_index)
+{
+ struct stm_spi *stm_spi;
+
+ switch (AO_SPI_INDEX(spi_index)) {
+ case 0:
+ stm_spi = &stm_spi1;
+ break;
+ case 1:
+ stm_spi = &stm_spi2;
+ break;
+ }
+
+ stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
+ (0 << STM_SPI_CR2_RXNEIE) |
+ (0 << STM_SPI_CR2_ERRIE) |
+ (0 << STM_SPI_CR2_SSOE) |
+ (0 << STM_SPI_CR2_TXDMAEN) |
+ (0 << STM_SPI_CR2_RXDMAEN));
+
+ /* Clear RXNE */
+ (void) stm_spi->dr;
+
+ while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE)));
+ stm_spi->dr = byte;
+}
+
void
ao_spi_recv(void *block, uint16_t len, uint8_t spi_index);
#define ao_gpio_get(port, bit, pin) stm_gpio_get(port, bit)
+#define ao_gpio_set_bits(port, bits) stm_gpio_set_bits(port, bits)
+
+#define ao_gpio_clr_bits(port, bits) stm_gpio_clr_bits(port, bits);
+
+
#define ao_enable_output(port,bit,pin,v) do { \
ao_enable_port(port); \
ao_gpio_set(port, bit, pin, v); \
void
ao_i2c_init(void);
+#if USE_SERIAL_1_SW_FLOW || USE_SERIAL_2_SW_FLOW || USE_SERIAL_3_SW_FLOW
+#define HAS_SERIAL_SW_FLOW 1
+#else
+#define HAS_SERIAL_SW_FLOW 0
+#endif
+
+#if USE_SERIAL_1_FLOW && !USE_SERIAL_1_SW_FLOW || USE_SERIAL_2_FLOW && !USE_SERIAL_2_SW_FLOW || USE_SERIAL_3_FLOW && !USE_SERIAL_3_SW_FLOW
+#define HAS_SERIAL_HW_FLOW 1
+#else
+#define HAS_SERIAL_HW_FLOW 0
+#endif
+
/* ao_serial_stm.c */
struct ao_stm_usart {
struct ao_fifo rx_fifo;
struct ao_fifo tx_fifo;
struct stm_usart *reg;
- uint8_t tx_started;
+ uint8_t tx_running;
+ uint8_t draining;
+#if HAS_SERIAL_SW_FLOW
+ /* RTS - 0 if we have FIFO space, 1 if not
+ * CTS - 0 if we can send, 0 if not
+ */
+ struct stm_gpio *gpio_rts;
+ struct stm_gpio *gpio_cts;
+ uint8_t pin_rts;
+ uint8_t pin_cts;
+ uint8_t rts;
+#endif
};
#if HAS_SERIAL_1
#define HAS_SAMPLE_PROFILE 0
#endif
+#if DEBUG
+#define HAS_ARCH_VALIDATE_CUR_STACK 1
+
+static inline void
+ao_validate_cur_stack(void)
+{
+ uint8_t *psp;
+
+ asm("mrs %0,psp" : "=&r" (psp));
+ if (ao_cur_task &&
+ psp <= ao_cur_task->stack &&
+ psp >= ao_cur_task->stack - 256)
+ ao_panic(AO_PANIC_STACK);
+}
+#endif
+
#if !HAS_SAMPLE_PROFILE
#define HAS_ARCH_START_SCHEDULER 1
+++ /dev/null
-/*
- * Copyright © 2013 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_FAST_TIMER_H_
-#define _AO_FAST_TIMER_H_
-
-void
-ao_fast_timer_init(void);
-
-#ifndef AO_FAST_TIMER_MAX
-#define AO_FAST_TIMER_MAX 2
-#endif
-
-void
-ao_fast_timer_on(void (*callback)(void));
-
-void
-ao_fast_timer_off(void (*callback)(void));
-
-#endif /* _AO_FAST_TIMER_H_ */
*/
#include <ao.h>
+#include <ao_exti.h>
void
ao_debug_out(char c)
stm_usart1.dr = c;
}
-static void
+static int
_ao_usart_tx_start(struct ao_stm_usart *usart)
{
- if (!ao_fifo_empty(usart->tx_fifo) && !usart->tx_started)
- {
- usart->tx_started = 1;
- ao_fifo_remove(usart->tx_fifo, usart->reg->dr);
+ if (!ao_fifo_empty(usart->tx_fifo)) {
+#if HAS_SERIAL_SW_FLOW
+ if (usart->gpio_cts && ao_gpio_get(usart->gpio_cts, usart->pin_cts, foo) == 1) {
+ ao_exti_enable(usart->gpio_cts, usart->pin_cts);
+ return 0;
+ }
+#endif
+ if (usart->reg->sr & (1 << STM_USART_SR_TXE))
+ {
+ usart->tx_running = 1;
+ usart->reg->cr1 |= (1 << STM_USART_CR1_TXEIE) | (1 << STM_USART_CR1_TCIE);
+ ao_fifo_remove(usart->tx_fifo, usart->reg->dr);
+ ao_wakeup(&usart->tx_fifo);
+ return 1;
+ }
}
+ return 0;
}
+#if HAS_SERIAL_SW_FLOW
static void
-ao_usart_isr(struct ao_stm_usart *usart, int stdin)
+_ao_usart_cts(struct ao_stm_usart *usart)
{
- uint32_t sr;
-
- sr = usart->reg->sr;
- usart->reg->sr = 0;
+ if (_ao_usart_tx_start(usart))
+ ao_exti_disable(usart->gpio_cts, usart->pin_cts);
+}
+#endif
- if (sr & (1 << STM_USART_SR_RXNE)) {
- char c = usart->reg->dr;
- if (!ao_fifo_full(usart->rx_fifo))
- ao_fifo_insert(usart->rx_fifo, c);
- ao_wakeup(&usart->rx_fifo);
- if (stdin)
- ao_wakeup(&ao_stdin_ready);
+static void
+_ao_usart_rx(struct ao_stm_usart *usart, int stdin)
+{
+ if (usart->reg->sr & (1 << STM_USART_SR_RXNE)) {
+ if (!ao_fifo_full(usart->rx_fifo)) {
+ ao_fifo_insert(usart->rx_fifo, usart->reg->dr);
+ ao_wakeup(&usart->rx_fifo);
+ if (stdin)
+ ao_wakeup(&ao_stdin_ready);
+#if HAS_SERIAL_SW_FLOW
+ /* If the fifo is nearly full, turn off RTS and wait
+ * for it to drain a bunch
+ */
+ if (usart->gpio_rts && ao_fifo_mostly(usart->rx_fifo)) {
+ ao_gpio_set(usart->gpio_rts, usart->pin_rts, usart->pin_rts, 1);
+ usart->rts = 0;
+ }
+#endif
+ } else {
+ usart->reg->cr1 &= ~(1 << STM_USART_CR1_RXNEIE);
+ }
}
- if (sr & (1 << STM_USART_SR_TC)) {
- usart->tx_started = 0;
- _ao_usart_tx_start(usart);
- ao_wakeup(&usart->tx_fifo);
+}
+
+static void
+ao_usart_isr(struct ao_stm_usart *usart, int stdin)
+{
+ _ao_usart_rx(usart, stdin);
+
+ if (!_ao_usart_tx_start(usart))
+ usart->reg->cr1 &= ~(1<< STM_USART_CR1_TXEIE);
+
+ if (usart->reg->sr & (1 << STM_USART_SR_TC)) {
+ usart->tx_running = 0;
+ usart->reg->cr1 &= ~(1 << STM_USART_CR1_TCIE);
+ if (usart->draining) {
+ usart->draining = 0;
+ ao_wakeup(&usart->tx_fifo);
+ }
}
}
-int
+static int
_ao_usart_pollchar(struct ao_stm_usart *usart)
{
int c;
else {
uint8_t u;
ao_fifo_remove(usart->rx_fifo,u);
+ if ((usart->reg->cr1 & (1 << STM_USART_CR1_RXNEIE)) == 0) {
+ if (ao_fifo_barely(usart->rx_fifo))
+ usart->reg->cr1 |= (1 << STM_USART_CR1_RXNEIE);
+ }
+#if HAS_SERIAL_SW_FLOW
+ /* If we've cleared RTS, check if there's space now and turn it back on */
+ if (usart->gpio_rts && usart->rts == 0 && ao_fifo_barely(usart->rx_fifo)) {
+ ao_gpio_set(usart->gpio_rts, usart->pin_rts, foo, 0);
+ usart->rts = 1;
+ }
+#endif
c = u;
}
return c;
}
-char
+static char
ao_usart_getchar(struct ao_stm_usart *usart)
{
int c;
return ao_sleep_for(&usart->rx_fifo, timeout);
}
-void
+static void
ao_usart_putchar(struct ao_stm_usart *usart, char c)
{
ao_arch_block_interrupts();
ao_arch_release_interrupts();
}
-void
+static void
ao_usart_drain(struct ao_stm_usart *usart)
{
ao_arch_block_interrupts();
- while (!ao_fifo_empty(usart->tx_fifo))
+ while (!ao_fifo_empty(usart->tx_fifo) || usart->tx_running) {
+ usart->draining = 1;
ao_sleep(&usart->tx_fifo);
+ }
ao_arch_release_interrupts();
}
},
};
-void
+static void
ao_usart_set_speed(struct ao_stm_usart *usart, uint8_t speed)
{
if (speed > AO_SERIAL_SPEED_115200)
usart->reg->brr = ao_usart_speeds[speed].brr;
}
-void
+static void
ao_usart_init(struct ao_stm_usart *usart)
{
usart->reg->cr1 = ((0 << STM_USART_CR1_OVER8) |
(0 << STM_USART_CR1_PS) |
(0 << STM_USART_CR1_PEIE) |
(0 << STM_USART_CR1_TXEIE) |
- (1 << STM_USART_CR1_TCIE) |
+ (0 << STM_USART_CR1_TCIE) |
(1 << STM_USART_CR1_RXNEIE) |
(0 << STM_USART_CR1_IDLEIE) |
(1 << STM_USART_CR1_TE) |
ao_usart_set_speed(usart, AO_SERIAL_SPEED_9600);
}
-void
+#if HAS_SERIAL_HW_FLOW
+static void
ao_usart_set_flow(struct ao_stm_usart *usart)
{
usart->reg->cr3 |= ((1 << STM_USART_CR3_CTSE) |
(1 << STM_USART_CR3_RTSE));
}
+#endif
#if HAS_SERIAL_1
void
ao_serial1_set_speed(uint8_t speed)
{
+ ao_usart_drain(&ao_stm_usart1);
ao_usart_set_speed(&ao_stm_usart1, speed);
}
#endif /* HAS_SERIAL_1 */
void
ao_serial2_set_speed(uint8_t speed)
{
+ ao_usart_drain(&ao_stm_usart2);
ao_usart_set_speed(&ao_stm_usart2, speed);
}
+
+#if HAS_SERIAL_SW_FLOW
+void
+ao_serial2_cts(void)
+{
+ _ao_usart_cts(&ao_stm_usart2);
+}
+#endif
+
#endif /* HAS_SERIAL_2 */
#if HAS_SERIAL_3
struct ao_stm_usart ao_stm_usart3;
-void stm_usart3_isr(void) { ao_usart_isr(&ao_stm_usart3, USE_SERIAL_2_STDIN); }
+void stm_usart3_isr(void) { ao_usart_isr(&ao_stm_usart3, USE_SERIAL_3_STDIN); }
char
ao_serial3_getchar(void)
void
ao_serial3_set_speed(uint8_t speed)
{
+ ao_usart_drain(&ao_stm_usart3);
ao_usart_set_speed(&ao_stm_usart3, speed);
}
+
+void
+ao_serial3_drain(void)
+{
+ ao_usart_drain(&ao_stm_usart3);
+}
#endif /* HAS_SERIAL_3 */
+#if HAS_SERIAL_SW_FLOW
+static void
+ao_serial_set_sw_rts_cts(struct ao_stm_usart *usart,
+ void (*isr)(void),
+ struct stm_gpio *port_rts,
+ int pin_rts,
+ struct stm_gpio *port_cts,
+ int pin_cts)
+{
+ /* Pull RTS low to note that there's space in the FIFO
+ */
+ ao_enable_output(port_rts, pin_rts, foo, 0);
+ usart->gpio_rts = port_rts;
+ usart->pin_rts = pin_rts;
+ usart->rts = 1;
+
+ ao_exti_setup(port_cts, pin_cts, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED, isr);
+ usart->gpio_cts = port_cts;
+ usart->pin_cts = pin_cts;
+}
+#endif
+
void
ao_serial_init(void)
{
stm_afr_set(&stm_gpioa, 2, STM_AFR_AF7);
stm_afr_set(&stm_gpioa, 3, STM_AFR_AF7);
-#if USE_SERIAL_2_FLOW
+# if USE_SERIAL_2_FLOW
+# if USE_SERIAL_2_SW_FLOW
+ ao_serial_set_sw_rts_cts(&ao_stm_usart2,
+ ao_serial2_cts,
+ SERIAL_2_PORT_RTS,
+ SERIAL_2_PIN_RTS,
+ SERIAL_2_PORT_CTS,
+ SERIAL_2_PIN_CTS);
+# else
stm_afr_set(&stm_gpioa, 0, STM_AFR_AF7);
stm_afr_set(&stm_gpioa, 1, STM_AFR_AF7);
-#endif
+# endif
+# endif
#else
#if SERIAL_2_PD5_PD6
stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN);
ao_stm_usart2.reg = &stm_usart2;
ao_usart_init(&ao_stm_usart2);
-#if USE_SERIAL_2_FLOW
+#if USE_SERIAL_2_FLOW && !USE_SERIAL_2_SW_FLOW
ao_usart_set_flow(&ao_stm_usart2);
#endif
void stm_systick_isr(void)
{
+ ao_validate_cur_stack();
if (stm_systick.csr & (1 << STM_SYSTICK_CSR_COUNTFLAG)) {
++ao_tick_count;
#if HAS_TASK_QUEUE
gpio->bsrr = ((uint32_t) (value ^ 1) << (pin + 16)) | ((uint32_t) value << pin);
}
+static inline void
+stm_gpio_set_bits(struct stm_gpio *gpio, uint16_t bits) {
+ gpio->bsrr = bits;
+}
+
+static inline void
+stm_gpio_clr_bits(struct stm_gpio *gpio, uint16_t bits) {
+ gpio->bsrr = ((uint32_t) bits) << 16;
+}
+
static inline uint8_t
stm_gpio_get(struct stm_gpio *gpio, int pin) {
return (gpio->idr >> pin) & 1;
PROGNAME=altos-flash
PROG=$(HARDWARE)-$(PROGNAME)-$(VERSION).elf
+BIN=$(HARDWARE)-$(PROGNAME)-$(VERSION).bin
+
+MAKEBIN=$(TOPDIR)/../ao-tools/ao-makebin/ao-makebin
+FLASH_ADDR=0x08000000
+
+all: $(PROG) $(BIN)
$(PROG): Makefile $(OBJ) altos-loader.ld
$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+$(BIN): $(PROG)
+ $(MAKEBIN) --output=$@ --base=$(FLASH_ADDR) $(PROG)
+
ao_product.h: ao-make-product.5c $(TOPDIR)/Version
$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
$(OBJ): $(INC)
-all: $(PROG)
-
distclean: clean
clean:
(1 << STM_DMA_CCR_MINC) |
(0 << STM_DMA_CCR_PINC) |
(0 << STM_DMA_CCR_CIRC) |
- (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR));
+ (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR) |
+ (1 << STM_DMA_CCR_TCIE));
+
ao_dma_set_isr(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1), ao_adc_dma_done);
ao_dma_start(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1));
ao_adc_init(void)
{
uint32_t chselr;
- int i;
/* Reset ADC */
stm_rcc.apb2rstr |= (1 << STM_RCC_APB2RSTR_ADCRST);
/* Shortest sample time */
stm_adc.smpr = STM_ADC_SMPR_SMP_1_5 << STM_ADC_SMPR_SMP;
+ /* Turn off enable and start */
+ stm_adc.cr &= ~((1 << STM_ADC_CR_ADEN) | (1 << STM_ADC_CR_ADSTART));
+
/* Calibrate */
stm_adc.cr |= (1 << STM_ADC_CR_ADCAL);
- for (i = 0; i < 0xf000; i++) {
- if ((stm_adc.cr & (1 << STM_ADC_CR_ADCAL)) == 0)
- break;
- }
+ while ((stm_adc.cr & (1 << STM_ADC_CR_ADCAL)) != 0)
+ ;
/* Enable */
stm_adc.cr |= (1 << STM_ADC_CR_ADEN);
* STM32F0 definitions and code fragments for AltOS
*/
+#ifndef AO_STACK_SIZE
#define AO_STACK_SIZE 512
+#endif
#define AO_LED_TYPE uint16_t
#define AO_PCLK1 (AO_HCLK / AO_APB1_PRESCALER)
#define AO_PCLK2 (AO_HCLK / AO_APB2_PRESCALER)
#define AO_SYSTICK (AO_HCLK)
+#define AO_PANIC_DELAY_SCALE (AO_SYSCLK / 12000000)
#if AO_APB1_PRESCALER == 1
#define AO_TIM23467_CLK AO_PCLK1
#define AO_TIM91011_CLK (2 * AO_PCLK2)
#endif
-#define AO_STM_NVIC_HIGH_PRIORITY 4
-#define AO_STM_NVIC_CLOCK_PRIORITY 6
-#define AO_STM_NVIC_MED_PRIORITY 8
-#define AO_STM_NVIC_LOW_PRIORITY 10
+#define AO_STM_NVIC_HIGH_PRIORITY (0 << 6)
+#define AO_STM_NVIC_CLOCK_PRIORITY (1 << 6)
+#define AO_STM_NVIC_MED_PRIORITY (2 << 6)
+#define AO_STM_NVIC_LOW_PRIORITY (3 << 6)
void ao_lcd_stm_init(void);
#ifndef _AO_ARCH_FUNCS_H_
#define _AO_ARCH_FUNCS_H_
+#include <ao_power.h>
+
/* ao_spi_stm.c
*/
-/* PCLK is set to 16MHz (HCLK 32MHz, APB prescaler 2) */
+/* PCLK is set to 48MHz (HCLK 48MHz, HPRE 1, PPRE 1) */
-#define AO_SPI_SPEED_8MHz STM_SPI_CR1_BR_PCLK_2
-#define AO_SPI_SPEED_4MHz STM_SPI_CR1_BR_PCLK_4
-#define AO_SPI_SPEED_2MHz STM_SPI_CR1_BR_PCLK_8
-#define AO_SPI_SPEED_1MHz STM_SPI_CR1_BR_PCLK_16
-#define AO_SPI_SPEED_500kHz STM_SPI_CR1_BR_PCLK_32
-#define AO_SPI_SPEED_250kHz STM_SPI_CR1_BR_PCLK_64
-#define AO_SPI_SPEED_125kHz STM_SPI_CR1_BR_PCLK_128
-#define AO_SPI_SPEED_62500Hz STM_SPI_CR1_BR_PCLK_256
+#define AO_SPI_SPEED_24MHz STM_SPI_CR1_BR_PCLK_2
+#define AO_SPI_SPEED_12MHz STM_SPI_CR1_BR_PCLK_4
+#define AO_SPI_SPEED_6MHz STM_SPI_CR1_BR_PCLK_8
+#define AO_SPI_SPEED_3MHz STM_SPI_CR1_BR_PCLK_16
+#define AO_SPI_SPEED_1500kHz STM_SPI_CR1_BR_PCLK_32
+#define AO_SPI_SPEED_750kHz STM_SPI_CR1_BR_PCLK_64
+#define AO_SPI_SPEED_375kHz STM_SPI_CR1_BR_PCLK_128
+#define AO_SPI_SPEED_187500Hz STM_SPI_CR1_BR_PCLK_256
-#define AO_SPI_SPEED_FAST AO_SPI_SPEED_8MHz
+#define AO_SPI_SPEED_FAST AO_SPI_SPEED_24MHz
/* Companion bus wants something no faster than 200kHz */
-#define AO_SPI_SPEED_200kHz AO_SPI_SPEED_125kHz
+#define AO_SPI_SPEED_200kHz AO_SPI_SPEED_187500Hz
#define AO_SPI_CONFIG_1 0x00
#define AO_SPI_1_CONFIG_PA5_PA6_PA7 AO_SPI_CONFIG_1
#define ao_spi_get_bit(reg,bit,pin,bus,speed) ao_spi_get_mask(reg,(1<<bit),bus,speed)
#define ao_spi_put_bit(reg,bit,pin,bus) ao_spi_put_mask(reg,(1<<bit),bus)
-#define ao_enable_port(port) do { \
- if ((port) == &stm_gpioa) \
- stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN); \
- else if ((port) == &stm_gpiob) \
- stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN); \
- else if ((port) == &stm_gpioc) \
- stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPCEN); \
- else if ((port) == &stm_gpiof) \
- stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPFEN); \
- } while (0)
+extern struct ao_power ao_power_gpioa;
+extern struct ao_power ao_power_gpiob;
+extern struct ao_power ao_power_gpioc;
+extern struct ao_power ao_power_gpiof;
-#define ao_disable_port(port) do { \
- if ((port) == &stm_gpioa) \
- stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPAEN); \
- else if ((port) == &stm_gpiob) \
- stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPBEN); \
- else if ((port) == &stm_gpioc) \
- stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPCEN); \
- else if ((port) == &stm_gpiof) \
- stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPFEN); \
- } while (0)
+static inline void ao_enable_port(struct stm_gpio *port)
+{
+ if ((port) == &stm_gpioa) {
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN);
+ ao_power_register(&ao_power_gpioa);
+ } else if ((port) == &stm_gpiob) {
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN);
+ ao_power_register(&ao_power_gpiob);
+ } else if ((port) == &stm_gpioc) {
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPCEN);
+ ao_power_register(&ao_power_gpioc);
+ } else if ((port) == &stm_gpiof) {
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPFEN);
+ ao_power_register(&ao_power_gpiof);
+ }
+}
+
+static inline void ao_disable_port(struct stm_gpio *port)
+{
+ if ((port) == &stm_gpioa) {
+ stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPAEN);
+ ao_power_unregister(&ao_power_gpioa);
+ } else if ((port) == &stm_gpiob) {
+ stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPBEN);
+ ao_power_unregister(&ao_power_gpiob);
+ } else if ((port) == &stm_gpioc) {
+ stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPCEN);
+ ao_power_unregister(&ao_power_gpioc);
+ } else if ((port) == &stm_gpiof) {
+ stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPFEN);
+ ao_power_unregister(&ao_power_gpiof);
+ }
+}
#define ao_gpio_set(port, bit, pin, v) stm_gpio_set(port, bit, v)
} while (0)
#define ao_enable_cs(port,bit) do { \
- stm_gpio_set((port), bit, 1); \
- stm_moder_set((port), bit, STM_MODER_OUTPUT); \
+ ao_enable_output(port, bit, pin, 1); \
} while (0)
#define ao_spi_init_cs(port, mask) do { \
void
ao_usb_write(uint16_t *buffer, uint16_t len);
+
+void
+ao_usb_write2(uint16_t *buffer, uint16_t len);
#endif /* AO_USB_DIRECTIO */
#endif /* _AO_ARCH_FUNCS_H_ */
static uint8_t ao_dma_mutex[STM_NUM_DMA];
static uint8_t ao_dma_active;
-#define id(ch) STM_DMA_INDEX(ch)
-#define id_mask(id) (STM_DMA_ISR_MASK << (id))
-#define ch_mask(ch) id_mask(id(ch))
+#define ch_mask(id) (STM_DMA_ISR_MASK << STM_DMA_ISR(id))
static void
ao_dma_isr(uint8_t low_index, uint8_t high_index, uint32_t mask) {
/* Ack them */
stm_dma.ifcr = isr;
for (index = low_index; index <= high_index; index++) {
- if (isr & id_mask(index)) {
+ if (isr & ch_mask(index)) {
if (ao_dma_config[index].isr)
(*ao_dma_config[index].isr)(index);
else {
}
}
-void stm_dma_ch1_isr(void) { ao_dma_isr(id(1), id(1), ch_mask(1)); }
-void stm_dma_ch2_3_isr(void) { ao_dma_isr(id(2), id(3), ch_mask(2) | ch_mask(3)); }
-void stm_dma1_ch4_5_6_isr(void) { ao_dma_isr(id(4), id(6), ch_mask(4) | ch_mask(5) | ch_mask(6)); }
+void stm_dma_ch1_isr(void) {
+ ao_dma_isr(STM_DMA_INDEX(1),
+ STM_DMA_INDEX(1),
+ ch_mask(STM_DMA_INDEX(1)));
+}
+
+void stm_dma_ch2_3_isr(void) {
+ ao_dma_isr(STM_DMA_INDEX(2),
+ STM_DMA_INDEX(3),
+ ch_mask(STM_DMA_INDEX(2)) |
+ ch_mask(STM_DMA_INDEX(3)));
+}
+
+void stm_dma1_ch4_5_6_isr(void) {
+ ao_dma_isr(STM_DMA_INDEX(4), STM_DMA_INDEX(6),
+ ch_mask(STM_DMA_INDEX(4)) |
+ ch_mask(STM_DMA_INDEX(5)) |
+ ch_mask(STM_DMA_INDEX(6)));
+}
void
ao_dma_set_transfer(uint8_t index,
if (ao_dma_active++ == 0)
stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMAEN);
);
- stm_dma.channel[index].ccr = ccr | (1 << STM_DMA_CCR_TCIE);
+ ao_dma_config[index].isr = NULL;
+ ao_dma_done[index] = 0;
stm_dma.channel[index].cndtr = count;
stm_dma.channel[index].cpar = peripheral;
stm_dma.channel[index].cmar = memory;
- ao_dma_config[index].isr = NULL;
+ stm_dma.channel[index].ccr = ccr;
}
void
void
ao_dma_start(uint8_t index)
{
- ao_dma_done[index] = 0;
stm_dma.channel[index].ccr |= (1 << STM_DMA_CCR_EN);
}
#define AO_EXTI_PIN_NOCONFIGURE 64
void
-ao_exti_setup(struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)());
+ao_exti_setup(struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)(void));
void
ao_exti_set_mode(struct stm_gpio *gpio, uint8_t pin, uint8_t mode);
--- /dev/null
+/*
+ * Copyright © 2016 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_exti.h>
+
+static void (*ao_exti_callback[16])(void);
+
+uint32_t ao_last_exti;
+
+static void ao_exti_range_isr(uint8_t first, uint8_t last, uint16_t mask) {
+ uint16_t pending = (ao_last_exti = stm_exti.pr) & mask;
+ uint8_t pin;
+ static uint16_t last_mask;
+ static uint8_t last_pin;
+
+ if (pending == last_mask) {
+ stm_exti.pr = last_mask;
+ (*ao_exti_callback[last_pin])();
+ return;
+ }
+ stm_exti.pr = pending;
+ for (pin = first; pin <= last; pin++)
+ if ((pending & ((uint32_t) 1 << pin)) && ao_exti_callback[pin]) {
+ last_mask = (1 << pin);
+ last_pin = pin;
+ (*ao_exti_callback[pin])();
+ }
+}
+
+void stm_exti0_1_isr(void) { ao_exti_range_isr(0, 1, 0x0003); }
+void stm_exti2_3_isr(void) { ao_exti_range_isr(2, 3, 0x000c); }
+void stm_exti4_15_isr(void) { ao_exti_range_isr(4, 15, 0xfff0); }
+
+void
+ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)(void)) {
+ uint32_t mask = 1 << pin;
+ uint32_t pupdr;
+ uint8_t irq;
+ uint8_t prio;
+
+ ao_exti_callback[pin] = callback;
+
+ /* configure gpio to interrupt routing */
+ stm_exticr_set(gpio, pin);
+
+ if (!(mode & AO_EXTI_PIN_NOCONFIGURE)) {
+ /* configure pin as input, setting selected pull-up/down mode */
+ stm_moder_set(gpio, pin, STM_MODER_INPUT);
+ switch (mode & (AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_PULL_DOWN)) {
+ case 0:
+ default:
+ pupdr = STM_PUPDR_NONE;
+ break;
+ case AO_EXTI_MODE_PULL_UP:
+ pupdr = STM_PUPDR_PULL_UP;
+ break;
+ case AO_EXTI_MODE_PULL_DOWN:
+ pupdr = STM_PUPDR_PULL_DOWN;
+ break;
+ }
+ stm_pupdr_set(gpio, pin, pupdr);
+ }
+
+ /* Set interrupt mask and rising/falling mode */
+ stm_exti.imr &= ~mask;
+ if (mode & AO_EXTI_MODE_RISING)
+ stm_exti.rtsr |= mask;
+ else
+ stm_exti.rtsr &= ~mask;
+ if (mode & AO_EXTI_MODE_FALLING)
+ stm_exti.ftsr |= mask;
+ else
+ stm_exti.ftsr &= ~mask;
+
+ if (pin <= 1)
+ irq = STM_ISR_EXTI0_1_POS;
+ else if (pin <= 3)
+ irq = STM_ISR_EXTI2_3_POS;
+ else
+ irq = STM_ISR_EXTI4_15_POS;
+
+ /* Set priority */
+ prio = AO_STM_NVIC_MED_PRIORITY;
+ if (mode & AO_EXTI_PRIORITY_LOW)
+ prio = AO_STM_NVIC_LOW_PRIORITY;
+ else if (mode & AO_EXTI_PRIORITY_HIGH)
+ prio = AO_STM_NVIC_HIGH_PRIORITY;
+
+ stm_nvic_set_priority(irq, prio);
+ stm_nvic_set_enable(irq);
+}
+
+void
+ao_exti_set_mode(struct stm_gpio *gpio, uint8_t pin, uint8_t mode) {
+ (void) gpio;
+
+ uint32_t mask = 1 << pin;
+
+ if (mode & AO_EXTI_MODE_RISING)
+ stm_exti.rtsr |= mask;
+ else
+ stm_exti.rtsr &= ~mask;
+ if (mode & AO_EXTI_MODE_FALLING)
+ stm_exti.ftsr |= mask;
+ else
+ stm_exti.ftsr &= ~mask;
+}
+
+void
+ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)()) {
+ (void) gpio;
+ ao_exti_callback[pin] = callback;
+}
+
+void
+ao_exti_enable(struct stm_gpio *gpio, uint8_t pin) {
+ uint32_t mask = (1 << pin);
+ (void) gpio;
+ stm_exti.pr = mask;
+ stm_exti.imr |= (1 << pin);
+}
+
+void
+ao_exti_disable(struct stm_gpio *gpio, uint8_t pin) {
+ uint32_t mask = (1 << pin);
+ (void) gpio;
+ stm_exti.imr &= ~mask;
+ stm_exti.pr = mask;
+}
+
+void
+ao_exti_init(void)
+{
+}
--- /dev/null
+/*
+ * Copyright © 2016 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>
+
+static void
+ao_gpio_suspend(void *arg)
+{
+ struct stm_gpio *port = arg;
+ if (port == &stm_gpioa)
+ stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPAEN);
+ else if ((port) == &stm_gpiob)
+ stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPBEN);
+ else if ((port) == &stm_gpioc)
+ stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPCEN);
+ else if ((port) == &stm_gpiof)
+ stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPFEN);
+}
+
+static void
+ao_gpio_resume(void *arg)
+{
+ struct stm_gpio *port = arg;
+ if (port == &stm_gpioa)
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN);
+ else if ((port) == &stm_gpiob)
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN);
+ else if ((port) == &stm_gpioc)
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPCEN);
+ else if ((port) == &stm_gpiof)
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPFEN);
+}
+
+struct ao_power ao_power_gpioa = {
+ .suspend = ao_gpio_suspend,
+ .resume = ao_gpio_resume,
+ .arg = &stm_gpioa
+};
+
+struct ao_power ao_power_gpiob = {
+ .suspend = ao_gpio_suspend,
+ .resume = ao_gpio_resume,
+ .arg = &stm_gpiob
+};
+
+struct ao_power ao_power_gpioc = {
+ .suspend = ao_gpio_suspend,
+ .resume = ao_gpio_resume,
+ .arg = &stm_gpioc
+};
+
+struct ao_power ao_power_gpiof = {
+ .suspend = ao_gpio_suspend,
+ .resume = ao_gpio_resume,
+ .arg = &stm_gpiof
+};
+
--- /dev/null
+/*
+ * Copyright © 2016 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_pwm.h"
+
+static uint8_t pwm_running;
+
+static uint16_t pwm_value[NUM_PWM];
+
+static void
+ao_pwm_up(void)
+{
+ if (pwm_running++ == 0) {
+ struct stm_tim23 *tim = AO_PWM_TIMER;
+
+ tim->ccr1 = 0;
+ tim->ccr2 = 0;
+ tim->ccr3 = 0;
+ tim->ccr4 = 0;
+ tim->arr = PWM_MAX - 1; /* turn on the timer */
+ tim->cr1 = ((STM_TIM23_CR1_CKD_1 << STM_TIM23_CR1_CKD) |
+ (0 << STM_TIM23_CR1_ARPE) |
+ (STM_TIM23_CR1_CMS_EDGE << STM_TIM23_CR1_CMS) |
+ (STM_TIM23_CR1_DIR_UP << STM_TIM23_CR1_DIR) |
+ (0 << STM_TIM23_CR1_OPM) |
+ (0 << STM_TIM23_CR1_URS) |
+ (0 << STM_TIM23_CR1_UDIS) |
+ (1 << STM_TIM23_CR1_CEN));
+
+ /* Set the timer running */
+ tim->egr = (1 << STM_TIM23_EGR_UG);
+ }
+}
+
+static void
+ao_pwm_down(void)
+{
+ if (--pwm_running == 0) {
+ struct stm_tim23 *tim = AO_PWM_TIMER;
+
+ tim->arr = 0;
+ tim->cr1 = ((STM_TIM23_CR1_CKD_1 << STM_TIM23_CR1_CKD) |
+ (0 << STM_TIM23_CR1_ARPE) |
+ (STM_TIM23_CR1_CMS_EDGE << STM_TIM23_CR1_CMS) |
+ (STM_TIM23_CR1_DIR_UP << STM_TIM23_CR1_DIR) |
+ (0 << STM_TIM23_CR1_OPM) |
+ (0 << STM_TIM23_CR1_URS) |
+ (0 << STM_TIM23_CR1_UDIS) |
+ (0 << STM_TIM23_CR1_CEN));
+
+ /* Stop the timer */
+ tim->egr = (1 << STM_TIM23_EGR_UG);
+ }
+}
+
+void
+ao_pwm_set(uint8_t pwm, uint16_t value)
+{
+ struct stm_tim23 *tim = AO_PWM_TIMER;
+ uint8_t ch = AO_PWM_0_CH;
+
+ if (value > PWM_MAX)
+ value = PWM_MAX;
+ if (value != 0) {
+ if (pwm_value[pwm] == 0)
+ ao_pwm_up();
+ }
+#if NUM_PWM > 1
+ switch (pwm) {
+ case 0:
+ ch = AO_PWM_0_CH;
+ break;
+ case 1:
+ ch = AO_PWM_0_CH;
+ break;
+#if NUM_PWM > 2
+ case 2:
+ ch = AO_PWM_0_CH;
+ break;
+#endif
+#if NUM_PWM > 3
+ case 3:
+ ch = AO_PWM_0_CH;
+ break;
+#endif
+ }
+#endif
+
+ switch (ch) {
+ case 1:
+ tim->ccr1 = value;
+ break;
+ case 2:
+ tim->ccr2 = value;
+ break;
+ case 3:
+ tim->ccr3 = value;
+ break;
+ case 4:
+ tim->ccr4 = value;
+ break;
+ }
+ if (value == 0) {
+ if (pwm_value[pwm] != 0)
+ ao_pwm_down();
+ }
+ pwm_value[pwm] = value;
+}
+
+static void
+ao_pwm_cmd(void)
+{
+ uint8_t ch;
+ uint16_t val;
+
+ ao_cmd_decimal();
+ ch = ao_cmd_lex_u32;
+ ao_cmd_decimal();
+ val = ao_cmd_lex_u32;
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+
+ printf("Set channel %d to %d\n", ch, val);
+ ao_pwm_set(ch, val);
+}
+
+static const struct ao_cmds ao_pwm_cmds[] = {
+ { ao_pwm_cmd, "P <ch> <val>\0Set PWM ch to val" },
+ { 0, NULL },
+};
+
+void
+ao_pwm_init(void)
+{
+ struct stm_tim23 *tim = AO_PWM_TIMER;
+
+ stm_rcc.apb1enr |= (1 << AO_PWM_TIMER_ENABLE);
+
+ tim->cr1 = 0;
+ tim->psc = AO_PWM_TIMER_SCALE - 1;
+ tim->cnt = 0;
+ tim->ccer = ((1 << STM_TIM23_CCER_CC1E) |
+ (0 << STM_TIM23_CCER_CC1P) |
+ (1 << STM_TIM23_CCER_CC2E) |
+ (0 << STM_TIM23_CCER_CC2P) |
+ (1 << STM_TIM23_CCER_CC3E) |
+ (0 << STM_TIM23_CCER_CC3P) |
+ (1 << STM_TIM23_CCER_CC4E) |
+ (0 << STM_TIM23_CCER_CC4P));
+
+ tim->ccmr1 = ((0 << STM_TIM23_CCMR1_OC2CE) |
+ (STM_TIM23_CCMR1_OC2M_PWM_MODE_1 << STM_TIM23_CCMR1_OC2M) |
+ (0 << STM_TIM23_CCMR1_OC2PE) |
+ (0 << STM_TIM23_CCMR1_OC2FE) |
+ (STM_TIM23_CCMR1_CC2S_OUTPUT << STM_TIM23_CCMR1_CC2S) |
+
+ (0 << STM_TIM23_CCMR1_OC1CE) |
+ (STM_TIM23_CCMR1_OC1M_PWM_MODE_1 << STM_TIM23_CCMR1_OC1M) |
+ (0 << STM_TIM23_CCMR1_OC1PE) |
+ (0 << STM_TIM23_CCMR1_OC1FE) |
+ (STM_TIM23_CCMR1_CC1S_OUTPUT << STM_TIM23_CCMR1_CC1S));
+
+
+ tim->ccmr2 = ((0 << STM_TIM23_CCMR2_OC4CE) |
+ (STM_TIM23_CCMR2_OC4M_PWM_MODE_1 << STM_TIM23_CCMR2_OC4M) |
+ (0 << STM_TIM23_CCMR2_OC4PE) |
+ (0 << STM_TIM23_CCMR2_OC4FE) |
+ (STM_TIM23_CCMR2_CC4S_OUTPUT << STM_TIM23_CCMR2_CC4S) |
+
+ (0 << STM_TIM23_CCMR2_OC3CE) |
+ (STM_TIM23_CCMR2_OC3M_PWM_MODE_1 << STM_TIM23_CCMR2_OC3M) |
+ (0 << STM_TIM23_CCMR2_OC3PE) |
+ (0 << STM_TIM23_CCMR2_OC3FE) |
+ (STM_TIM23_CCMR2_CC3S_OUTPUT << STM_TIM23_CCMR2_CC3S));
+ tim->egr = 0;
+
+ tim->sr = 0;
+ tim->dier = 0;
+ tim->smcr = 0;
+ tim->cr2 = ((0 << STM_TIM23_CR2_TI1S) |
+ (STM_TIM23_CR2_MMS_RESET<< STM_TIM23_CR2_MMS) |
+ (0 << STM_TIM23_CR2_CCDS));
+
+ stm_afr_set(AO_PWM_0_GPIO, AO_PWM_0_PIN, STM_AFR_AF1);
+ stm_ospeedr_set(AO_PWM_0_GPIO, AO_PWM_0_PIN, STM_OSPEEDR_MEDIUM);
+#if NUM_PWM > 1
+ stm_afr_set(AO_PWM_1_GPIO, AO_PWM_1_PIN, STM_AFR_AF1);
+ stm_ospeedr_set(AO_PWM_1_GPIO, AO_PWM_1_PIN, STM_OSPEEDR_MEDIUM);
+#endif
+#if NUM_PWM > 2
+ stm_afr_set(AO_PWM_2_GPIO, AO_PWM_2_PIN, STM_AFR_AF1);
+ stm_ospeedr_set(AO_PWM_2_GPIO, AO_PWM_2_PIN, STM_OSPEEDR_MEDIUM);
+#endif
+#if NUM_PWM > 3
+ stm_afr_set(AO_PWM_3_GPIO, AO_PWM_3_PIN, STM_AFR_AF1);
+ stm_ospeedr_set(AO_PWM_3_GPIO, AO_PWM_3_PIN, STM_OSPEEDR_MEDIUM);
+#endif
+ ao_cmd_register(&ao_pwm_cmds[0]);
+}
--- /dev/null
+/*
+ * Copyright © 2016 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>
+
+struct ao_spi_stm_info {
+ uint8_t miso_dma_index;
+ uint8_t mosi_dma_index;
+ struct stm_spi *stm_spi;
+};
+
+static uint8_t ao_spi_mutex[STM_NUM_SPI];
+static uint8_t ao_spi_index[STM_NUM_SPI];
+
+static const struct ao_spi_stm_info ao_spi_stm_info[STM_NUM_SPI] = {
+ {
+ .miso_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI1_RX),
+ .mosi_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI1_TX),
+ &stm_spi1
+ },
+ {
+ .miso_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI2_RX),
+ .mosi_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI2_TX),
+ &stm_spi2
+ }
+};
+
+static uint8_t spi_dev_null;
+
+
+
+#define SPI_CR2 ((0 << STM_SPI_CR2_LDMA_TX) | \
+ (0 << STM_SPI_CR2_LDMA_RX) | \
+ (1 << STM_SPI_CR2_FRXTH) | \
+ (STM_SPI_CR2_DS_8 << STM_SPI_CR2_DS) | \
+ (0 << STM_SPI_CR2_TXEIE) | \
+ (0 << STM_SPI_CR2_RXNEIE) | \
+ (0 << STM_SPI_CR2_ERRIE) | \
+ (STM_SPI_CR2_FRF_MOTOROLA << STM_SPI_CR2_FRF) | \
+ (0 << STM_SPI_CR2_NSSP) | \
+ (0 << STM_SPI_CR2_SSOE))
+
+#define SPI_CR2_DMA (SPI_CR2 | \
+ (1 << STM_SPI_CR2_TXDMAEN) | \
+ (1 << STM_SPI_CR2_RXDMAEN))
+
+#define SPI_CR2_SYNC (SPI_CR2 | \
+ (0 << STM_SPI_CR2_TXDMAEN) | \
+ (0 << STM_SPI_CR2_RXDMAEN))
+
+void
+ao_spi_send(const void *block, uint16_t len, uint8_t spi_index)
+{
+ struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
+ uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index;
+ uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index;
+
+ /* Set up the transmit DMA to deliver data */
+ ao_dma_set_transfer(mosi_dma_index,
+ &stm_spi->dr,
+ (void *) block,
+ len,
+ (0 << STM_DMA_CCR_MEM2MEM) |
+ (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+ (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+ (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+ (1 << STM_DMA_CCR_MINC) |
+ (0 << STM_DMA_CCR_PINC) |
+ (0 << STM_DMA_CCR_CIRC) |
+ (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR) |
+ (0 << STM_DMA_CCR_TCIE));
+
+ /* Clear RXNE */
+ (void) stm_spi->dr;
+
+ /* Set up the receive DMA -- when this is done, we know the SPI unit
+ * is idle. Without this, we'd have to poll waiting for the BSY bit to
+ * be cleared
+ */
+ ao_dma_set_transfer(miso_dma_index,
+ &stm_spi->dr,
+ &spi_dev_null,
+ len,
+ (0 << STM_DMA_CCR_MEM2MEM) |
+ (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+ (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+ (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+ (0 << STM_DMA_CCR_MINC) |
+ (0 << STM_DMA_CCR_PINC) |
+ (0 << STM_DMA_CCR_CIRC) |
+ (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR) |
+ (1 << STM_DMA_CCR_TCIE));
+
+ stm_spi->cr2 = SPI_CR2_DMA;
+
+ ao_dma_start(miso_dma_index);
+ ao_dma_start(mosi_dma_index);
+ ao_arch_critical(
+ while (!ao_dma_done[miso_dma_index])
+ ao_sleep(&ao_dma_done[miso_dma_index]);
+ );
+ ao_dma_done_transfer(mosi_dma_index);
+ ao_dma_done_transfer(miso_dma_index);
+}
+
+void
+ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index)
+{
+ struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
+ uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index;
+ uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index;
+
+ /* Set up the transmit DMA to deliver data */
+ ao_dma_set_transfer(mosi_dma_index,
+ &stm_spi->dr,
+ &value,
+ len,
+ (0 << STM_DMA_CCR_MEM2MEM) |
+ (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+ (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+ (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+ (0 << STM_DMA_CCR_MINC) |
+ (0 << STM_DMA_CCR_PINC) |
+ (0 << STM_DMA_CCR_CIRC) |
+ (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR) |
+ (0 << STM_DMA_CCR_TCIE));
+
+ /* Clear RXNE */
+ (void) stm_spi->dr;
+
+ /* Set up the receive DMA -- when this is done, we know the SPI unit
+ * is idle. Without this, we'd have to poll waiting for the BSY bit to
+ * be cleared
+ */
+ ao_dma_set_transfer(miso_dma_index,
+ &stm_spi->dr,
+ &spi_dev_null,
+ len,
+ (0 << STM_DMA_CCR_MEM2MEM) |
+ (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+ (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+ (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+ (0 << STM_DMA_CCR_MINC) |
+ (0 << STM_DMA_CCR_PINC) |
+ (0 << STM_DMA_CCR_CIRC) |
+ (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR) |
+ (1 << STM_DMA_CCR_TCIE));
+
+ stm_spi->cr2 = SPI_CR2_DMA;
+ ao_dma_start(miso_dma_index);
+ ao_dma_start(mosi_dma_index);
+ ao_arch_critical(
+ while (!ao_dma_done[miso_dma_index])
+ ao_sleep(&ao_dma_done[miso_dma_index]);
+ );
+ ao_dma_done_transfer(mosi_dma_index);
+ ao_dma_done_transfer(miso_dma_index);
+}
+
+void
+ao_spi_send_sync(void *block, uint16_t len, uint8_t spi_index)
+{
+ uint8_t *b = block;
+ struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
+
+ stm_spi->cr2 = SPI_CR2_SYNC;
+
+ /* Clear RXNE */
+ (void) stm_spi->dr;
+
+ while (len--) {
+ while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE)));
+ stm_spi->dr = *b++;
+ }
+}
+
+void
+ao_spi_recv(void *block, uint16_t len, uint8_t spi_index)
+{
+ struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
+ uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index;
+ uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index;
+
+ spi_dev_null = 0xff;
+
+ /* Set up transmit DMA to make the SPI hardware actually run */
+ ao_dma_set_transfer(mosi_dma_index,
+ &stm_spi->dr,
+ &spi_dev_null,
+ len,
+ (0 << STM_DMA_CCR_MEM2MEM) |
+ (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+ (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+ (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+ (0 << STM_DMA_CCR_MINC) |
+ (0 << STM_DMA_CCR_PINC) |
+ (0 << STM_DMA_CCR_CIRC) |
+ (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR) |
+ (0 << STM_DMA_CCR_TCIE));
+
+ /* Clear RXNE */
+ (void) stm_spi->dr;
+
+ /* Set up the receive DMA to capture data */
+ ao_dma_set_transfer(miso_dma_index,
+ &stm_spi->dr,
+ block,
+ len,
+ (0 << STM_DMA_CCR_MEM2MEM) |
+ (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+ (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+ (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+ (1 << STM_DMA_CCR_MINC) |
+ (0 << STM_DMA_CCR_PINC) |
+ (0 << STM_DMA_CCR_CIRC) |
+ (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR) |
+ (1 << STM_DMA_CCR_TCIE));
+
+ stm_spi->cr2 = SPI_CR2_DMA;
+ ao_dma_start(miso_dma_index);
+ ao_dma_start(mosi_dma_index);
+
+ /* Wait until the SPI unit is done */
+ ao_arch_critical(
+ while (!ao_dma_done[miso_dma_index])
+ ao_sleep(&ao_dma_done[miso_dma_index]);
+ );
+
+ ao_dma_done_transfer(mosi_dma_index);
+ ao_dma_done_transfer(miso_dma_index);
+}
+
+void
+ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index)
+{
+ struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
+ uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index;
+ uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index;
+
+ /* Set up transmit DMA to send data */
+ ao_dma_set_transfer(mosi_dma_index,
+ &stm_spi->dr,
+ out,
+ len,
+ (0 << STM_DMA_CCR_MEM2MEM) |
+ (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+ (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+ (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+ (1 << STM_DMA_CCR_MINC) |
+ (0 << STM_DMA_CCR_PINC) |
+ (0 << STM_DMA_CCR_CIRC) |
+ (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR) |
+ (0 << STM_DMA_CCR_TCIE));
+
+ /* Clear RXNE */
+ (void) stm_spi->dr;
+
+ /* Set up the receive DMA to capture data */
+ ao_dma_set_transfer(miso_dma_index,
+ &stm_spi->dr,
+ in,
+ len,
+ (0 << STM_DMA_CCR_MEM2MEM) |
+ (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+ (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+ (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+ (1 << STM_DMA_CCR_MINC) |
+ (0 << STM_DMA_CCR_PINC) |
+ (0 << STM_DMA_CCR_CIRC) |
+ (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR) |
+ (1 << STM_DMA_CCR_TCIE));
+
+ stm_spi->cr2 = SPI_CR2_DMA;
+ ao_dma_start(miso_dma_index);
+ ao_dma_start(mosi_dma_index);
+
+ /* Wait until the SPI unit is done */
+ ao_arch_critical(
+ while (!ao_dma_done[miso_dma_index])
+ ao_sleep(&ao_dma_done[miso_dma_index]);
+ );
+
+ ao_dma_done_transfer(mosi_dma_index);
+ ao_dma_done_transfer(miso_dma_index);
+}
+
+static void
+ao_spi_disable_index(uint8_t spi_index)
+{
+ /* Disable current config
+ */
+ switch (AO_SPI_INDEX(spi_index)) {
+ case STM_SPI_INDEX(1):
+ switch (spi_index) {
+ case AO_SPI_1_PA5_PA6_PA7:
+ stm_gpio_set(&stm_gpioa, 5, 1);
+ stm_moder_set(&stm_gpioa, 5, STM_MODER_OUTPUT);
+ stm_moder_set(&stm_gpioa, 6, STM_MODER_INPUT);
+ stm_moder_set(&stm_gpioa, 7, STM_MODER_OUTPUT);
+ break;
+ case AO_SPI_1_PB3_PB4_PB5:
+ stm_gpio_set(&stm_gpiob, 3, 1);
+ stm_moder_set(&stm_gpiob, 3, STM_MODER_OUTPUT);
+ stm_moder_set(&stm_gpiob, 4, STM_MODER_INPUT);
+ stm_moder_set(&stm_gpiob, 5, STM_MODER_OUTPUT);
+ break;
+ }
+ break;
+ case STM_SPI_INDEX(2):
+ switch (spi_index) {
+ case AO_SPI_2_PB13_PB14_PB15:
+ stm_gpio_set(&stm_gpiob, 13, 1);
+ stm_moder_set(&stm_gpiob, 13, STM_MODER_OUTPUT);
+ stm_moder_set(&stm_gpiob, 14, STM_MODER_INPUT);
+ stm_moder_set(&stm_gpiob, 15, STM_MODER_OUTPUT);
+ break;
+ }
+ break;
+ }
+}
+
+static void
+ao_spi_enable_index(uint8_t spi_index)
+{
+ switch (AO_SPI_INDEX(spi_index)) {
+ case STM_SPI_INDEX(1):
+ switch (spi_index) {
+ case AO_SPI_1_PA5_PA6_PA7:
+ stm_afr_set(&stm_gpioa, 5, STM_AFR_AF0);
+ stm_afr_set(&stm_gpioa, 6, STM_AFR_AF0);
+ stm_afr_set(&stm_gpioa, 7, STM_AFR_AF0);
+ break;
+ case AO_SPI_1_PB3_PB4_PB5:
+ stm_afr_set(&stm_gpiob, 3, STM_AFR_AF0);
+ stm_afr_set(&stm_gpiob, 4, STM_AFR_AF0);
+ stm_afr_set(&stm_gpiob, 5, STM_AFR_AF0);
+ break;
+ }
+ break;
+ case STM_SPI_INDEX(2):
+ switch (spi_index) {
+ case AO_SPI_2_PB13_PB14_PB15:
+ stm_afr_set(&stm_gpiob, 13, STM_AFR_AF0);
+ stm_afr_set(&stm_gpiob, 14, STM_AFR_AF0);
+ stm_afr_set(&stm_gpiob, 15, STM_AFR_AF0);
+ break;
+ }
+ break;
+ }
+}
+
+static void
+ao_spi_config(uint8_t spi_index, uint32_t speed)
+{
+ uint8_t id = AO_SPI_INDEX(spi_index);
+ struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi;
+
+ stm_spi->cr2 = SPI_CR2;
+ stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) | /* Three wire mode */
+ (0 << STM_SPI_CR1_BIDIOE) |
+ (0 << STM_SPI_CR1_CRCEN) | /* CRC disabled */
+ (0 << STM_SPI_CR1_CRCNEXT) |
+ (0 << STM_SPI_CR1_CRCL) |
+ (0 << STM_SPI_CR1_RXONLY) |
+ (1 << STM_SPI_CR1_SSM) | /* Software SS handling */
+ (1 << STM_SPI_CR1_SSI) | /* ... */
+ (0 << STM_SPI_CR1_LSBFIRST) | /* Big endian */
+ (1 << STM_SPI_CR1_SPE) | /* Enable SPI unit */
+ (speed << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */
+ (1 << STM_SPI_CR1_MSTR) |
+ (0 << STM_SPI_CR1_CPOL) | /* Format 0 */
+ (0 << STM_SPI_CR1_CPHA));
+
+ if (spi_index != ao_spi_index[id]) {
+
+ /* Disable old config
+ */
+ ao_spi_disable_index(ao_spi_index[id]);
+
+ /* Enable new config
+ */
+ ao_spi_enable_index(spi_index);
+
+ /* Remember current config
+ */
+ ao_spi_index[id] = spi_index;
+ }
+}
+
+uint8_t
+ao_spi_try_get(uint8_t spi_index, uint32_t speed, uint8_t task_id)
+{
+ uint8_t id = AO_SPI_INDEX(spi_index);
+
+ if (!ao_mutex_try(&ao_spi_mutex[id], task_id))
+ return 0;
+ ao_spi_config(spi_index, speed);
+ return 1;
+}
+
+void
+ao_spi_get(uint8_t spi_index, uint32_t speed)
+{
+ uint8_t id = AO_SPI_INDEX(spi_index);
+ ao_mutex_get(&ao_spi_mutex[id]);
+ ao_spi_config(spi_index, speed);
+}
+
+void
+ao_spi_put(uint8_t spi_index)
+{
+ uint8_t id = AO_SPI_INDEX(spi_index);
+ struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi;
+
+ stm_spi->cr1 = 0;
+ ao_mutex_put(&ao_spi_mutex[id]);
+}
+
+static void
+ao_spi_channel_init(uint8_t spi_index)
+{
+ uint8_t id = AO_SPI_INDEX(spi_index);
+ struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi;
+
+ ao_spi_disable_index(spi_index);
+
+ stm_spi->cr1 = 0;
+ (void) stm_spi->sr;
+ stm_spi->cr2 = SPI_CR2_SYNC;
+}
+
+void
+ao_spi_init(void)
+{
+#if HAS_SPI_1
+# if SPI_1_PA5_PA6_PA7
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN);
+ stm_ospeedr_set(&stm_gpioa, 5, SPI_1_OSPEEDR);
+ stm_ospeedr_set(&stm_gpioa, 6, SPI_1_OSPEEDR);
+ stm_ospeedr_set(&stm_gpioa, 7, SPI_1_OSPEEDR);
+# endif
+# if SPI_1_PB3_PB4_PB5
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN);
+ stm_ospeedr_set(&stm_gpiob, 3, SPI_1_OSPEEDR);
+ stm_ospeedr_set(&stm_gpiob, 4, SPI_1_OSPEEDR);
+ stm_ospeedr_set(&stm_gpiob, 5, SPI_1_OSPEEDR);
+# endif
+ stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SPI1EN);
+ ao_spi_index[0] = AO_SPI_CONFIG_NONE;
+ ao_spi_channel_init(STM_SPI_INDEX(1));
+#endif
+
+#if HAS_SPI_2
+# if SPI_2_PB10_PB13_PB14
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN);
+ stm_ospeedr_set(&stm_gpiob, 13, SPI_2_OSPEEDR);
+ stm_ospeedr_set(&stm_gpiob, 14, SPI_2_OSPEEDR);
+ stm_ospeedr_set(&stm_gpiob, 15, SPI_2_OSPEEDR);
+# endif
+ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_SPI2EN);
+ ao_spi_index[1] = AO_SPI_CONFIG_NONE;
+ ao_spi_channel_init(STM_SPI_INDEX(2));
+#endif
+}
#if AO_DATA_ALL
if (++ao_data_count == ao_data_interval) {
ao_data_count = 0;
+#if HAS_ADC
#if HAS_FAKE_FLIGHT
if (ao_fake_flight_active)
ao_fake_flight_poll();
else
#endif
ao_adc_poll();
+#endif
#if (AO_DATA_ALL & ~(AO_DATA_ADC))
ao_wakeup((void *) &ao_data_count);
#endif
#endif
+#if AO_HSI48
static void
ao_clock_enable_crs(void)
{
(0 << STM_CRS_CR_ERRIE) |
(0 << STM_CRS_CR_SYNCWARNIE) |
(0 << STM_CRS_CR_SYNCOKIE));
-
}
+#endif
-void
-ao_clock_init(void)
+static void
+ao_clock_hsi(void)
{
- uint32_t cfgr;
-
- /* Switch to HSI while messing about */
stm_rcc.cr |= (1 << STM_RCC_CR_HSION);
while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY)))
ao_arch_nop();
/* reset PLLON, CSSON, HSEBYP, HSEON */
stm_rcc.cr &= 0x0000ffff;
+}
- /* Disable all interrupts */
- stm_rcc.cir = 0;
-
+static void
+ao_clock_normal_start(void)
+{
#if AO_HSE
-#define STM_RCC_CFGR_SWS_TARGET_CLOCK STM_RCC_CFGR_SWS_HSE
-#define STM_RCC_CFGR_SW_TARGET_CLOCK STM_RCC_CFGR_SW_HSE
+ uint32_t cfgr;
+#define STM_RCC_CFGR_SWS_TARGET_CLOCK STM_RCC_CFGR_SWS_PLL
+#define STM_RCC_CFGR_SW_TARGET_CLOCK STM_RCC_CFGR_SW_PLL
#define STM_PLLSRC AO_HSE
-#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK 1
+#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK STM_RCC_CFGR_PLLSRC_HSE
#if AO_HSE_BYPASS
stm_rcc.cr |= (1 << STM_RCC_CR_HSEBYP);
stm_rcc.cr |= (1 << STM_RCC_CR_HSEON);
while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSERDY)))
asm("nop");
+
+#ifdef STM_PLLSRC
+ /* Disable the PLL */
+ stm_rcc.cr &= ~(1 << STM_RCC_CR_PLLON);
+ while (stm_rcc.cr & (1 << STM_RCC_CR_PLLRDY))
+ asm("nop");
+
+ /* PLLVCO to 48MHz (for USB) -> PLLMUL = 3 */
+ cfgr = stm_rcc.cfgr;
+ cfgr &= ~(STM_RCC_CFGR_PLLMUL_MASK << STM_RCC_CFGR_PLLMUL);
+ cfgr |= (AO_RCC_CFGR_PLLMUL << STM_RCC_CFGR_PLLMUL);
+
+ /* PLL source */
+ cfgr &= ~(1 << STM_RCC_CFGR_PLLSRC);
+ cfgr |= (STM_RCC_CFGR_PLLSRC_TARGET_CLOCK << STM_RCC_CFGR_PLLSRC);
+ stm_rcc.cfgr = cfgr;
+
+ /* Disable pre divider */
+ stm_rcc.cfgr2 = (STM_RCC_CFGR2_PREDIV_1 << STM_RCC_CFGR2_PREDIV);
+
+ /* Enable the PLL and wait for it */
+ stm_rcc.cr |= (1 << STM_RCC_CR_PLLON);
+ while (!(stm_rcc.cr & (1 << STM_RCC_CR_PLLRDY)))
+ asm("nop");
+
+#endif
+
#endif
#define STM_PLLSRC STM_HSI
#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK 0
#endif
+}
+
+static void
+ao_clock_normal_switch(void)
+{
+ uint32_t cfgr;
+ cfgr = stm_rcc.cfgr;
+ cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW);
+ cfgr |= (STM_RCC_CFGR_SW_TARGET_CLOCK << STM_RCC_CFGR_SW);
+ stm_rcc.cfgr = cfgr;
+ for (;;) {
+ uint32_t c, part, mask, val;
+
+ c = stm_rcc.cfgr;
+ mask = (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS);
+ val = (STM_RCC_CFGR_SWS_TARGET_CLOCK << STM_RCC_CFGR_SWS);
+ part = c & mask;
+ if (part == val)
+ break;
+ }
+#if !AO_HSI && !AO_NEED_HSI
+ /* Turn off the HSI clock */
+ stm_rcc.cr &= ~(1 << STM_RCC_CR_HSION);
+#endif
#ifdef STM_PLLSRC
-#error No code for PLL initialization yet
+ /* USB PLL source */
+ stm_rcc.cfgr3 |= (1 << STM_RCC_CFGR3_USBSW);
#endif
+}
+
+void
+ao_clock_init(void)
+{
+ uint32_t cfgr;
+
+ /* Switch to HSI while messing about */
+ ao_clock_hsi();
+
+ /* Disable all interrupts */
+ stm_rcc.cir = 0;
+
+ /* Start high speed clock */
+ ao_clock_normal_start();
/* Set flash latency to tolerate 48MHz SYSCLK -> 1 wait state */
stm_rcc.cfgr = cfgr;
/* Switch to the desired system clock */
-
- cfgr = stm_rcc.cfgr;
- cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW);
- cfgr |= (STM_RCC_CFGR_SW_TARGET_CLOCK << STM_RCC_CFGR_SW);
- stm_rcc.cfgr = cfgr;
- for (;;) {
- uint32_t c, part, mask, val;
-
- c = stm_rcc.cfgr;
- mask = (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS);
- val = (STM_RCC_CFGR_SWS_TARGET_CLOCK << STM_RCC_CFGR_SWS);
- part = c & mask;
- if (part == val)
- break;
- }
+ ao_clock_normal_switch();
/* Clear reset flags */
stm_rcc.csr |= (1 << STM_RCC_CSR_RMVF);
-#if !AO_HSI && !AO_NEED_HSI
- /* Turn off the HSI clock */
- stm_rcc.cr &= ~(1 << STM_RCC_CR_HSION);
-#endif
#if DEBUG_THE_CLOCK
/* Output SYSCLK on PA8 for measurments */
stm_rcc.cfgr |= (STM_RCC_CFGR_MCOSEL_HSE << STM_RCC_CFGR_MCOSEL);
#endif
}
+
+#if AO_POWER_MANAGEMENT
+void
+ao_clock_suspend(void)
+{
+ ao_clock_hsi();
+}
+
+void
+ao_clock_resume(void)
+{
+ ao_clock_normal_start();
+ ao_clock_normal_switch();
+}
+#endif
#include "ao.h"
#include "ao_usb.h"
#include "ao_product.h"
+#include "ao_power.h"
#define USB_DEBUG 0
+#define USB_STATUS 0
#define USB_DEBUG_DATA 0
#define USB_ECHO 0
#error "must define AO_PA11_PA12_RMP"
#endif
+#ifndef AO_POWER_MANAGEMENT
+#define AO_POWER_MANAGEMENT 0
+#endif
+
#ifndef USE_USB_STDIO
#define USE_USB_STDIO 1
#endif
static uint16_t *ao_usb_ep0_tx_buffer;
static uint16_t *ao_usb_ep0_rx_buffer;
+#if AO_USB_HAS_INT
/* Pointer to interrupt buffer in USB memory */
static uint16_t ao_usb_int_tx_offset;
+#endif
/* Pointer to bulk data tx/rx buffers in USB memory */
+#if AO_USB_HAS_IN
static uint16_t ao_usb_in_tx_offset;
static uint16_t *ao_usb_in_tx_buffer;
-static uint16_t ao_usb_out_rx_offset;
-static uint16_t *ao_usb_out_rx_buffer;
/* System ram shadow of USB buffer; writing individual bytes is
* too much of a pain (sigh) */
static uint8_t ao_usb_tx_buffer[AO_USB_IN_SIZE];
static uint8_t ao_usb_tx_count;
+#endif
+#if AO_USB_HAS_OUT
+static uint16_t ao_usb_out_rx_offset;
+static uint16_t *ao_usb_out_rx_buffer;
+
+/* System ram shadow of USB buffer; writing individual bytes is
+ * too much of a pain (sigh) */
static uint8_t ao_usb_rx_buffer[AO_USB_OUT_SIZE];
static uint8_t ao_usb_rx_count, ao_usb_rx_pos;
+#endif
+#if AO_USB_HAS_IN2
+static uint16_t ao_usb_in2_tx_offset;
+static uint16_t *ao_usb_in2_tx_buffer;
+
+/* System ram shadow of USB buffer; writing individual bytes is
+ * too much of a pain (sigh) */
+static uint8_t ao_usb_tx2_buffer[AO_USB_IN_SIZE];
+static uint8_t ao_usb_tx2_count;
+#endif
+
/*
* End point register indices
*/
#define AO_USB_INT_EPR 1
#define AO_USB_OUT_EPR 2
#define AO_USB_IN_EPR 3
+#define AO_USB_IN2_EPR 4
/* Marks when we don't need to send an IN packet.
* This happens only when the last IN packet is not full,
*/
static uint8_t ao_usb_in_pending;
+#if AO_USB_HAS_IN2
+/* Marks when we have delivered an IN packet to the hardware
+ * and it has not been received yet. ao_sleep on this address
+ * to wait for it to be delivered.
+ */
+static uint8_t ao_usb_in2_pending;
+static uint16_t in2_count;
+static uint8_t ao_usb_in2_flushed;
+#endif
+
/* Marks when an OUT packet has been received by the hardware
* but not pulled to the shadow buffer.
*/
uint8_t ao_usb_running;
static uint8_t ao_usb_configuration;
-#define AO_USB_EP0_GOT_RESET 1
-#define AO_USB_EP0_GOT_SETUP 2
-#define AO_USB_EP0_GOT_RX_DATA 4
-#define AO_USB_EP0_GOT_TX_ACK 8
+#define AO_USB_EP0_GOT_SETUP 1
+#define AO_USB_EP0_GOT_RX_DATA 2
+#define AO_USB_EP0_GOT_TX_ACK 4
static uint8_t ao_usb_ep0_receive;
static uint8_t ao_usb_address;
ao_usb_ep0_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr);
ao_usb_sram_addr += AO_USB_CONTROL_SIZE;
+
+#if AO_USB_HAS_INT
ao_usb_int_tx_offset = ao_usb_sram_addr;
ao_usb_sram_addr += AO_USB_INT_SIZE;
+#endif
+#if AO_USB_HAS_OUT
ao_usb_out_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr);
ao_usb_out_rx_offset = ao_usb_sram_addr;
ao_usb_sram_addr += AO_USB_OUT_SIZE;
+#endif
+#if AO_USB_HAS_IN
ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr);
ao_usb_in_tx_offset = ao_usb_sram_addr;
ao_usb_sram_addr += AO_USB_IN_SIZE;
+#endif
+
+#if AO_USB_HAS_IN2
+ ao_usb_in2_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr);
+ ao_usb_in2_tx_offset = ao_usb_sram_addr;
+ ao_usb_sram_addr += AO_USB_IN_SIZE;
+#endif
}
static void
{
debug ("ao_usb_set_configuration\n");
+#if AO_USB_HAS_INT
/* Set up the INT end point */
ao_usb_bdt[AO_USB_INT_EPR].single.addr_tx = ao_usb_int_tx_offset;
ao_usb_bdt[AO_USB_INT_EPR].single.count_tx = 0;
STM_USB_EPR_EP_TYPE_INTERRUPT,
STM_USB_EPR_STAT_RX_DISABLED,
STM_USB_EPR_STAT_TX_NAK);
+#endif
+#if AO_USB_HAS_OUT
/* Set up the OUT end point */
ao_usb_bdt[AO_USB_OUT_EPR].single.addr_rx = ao_usb_out_rx_offset;
ao_usb_bdt[AO_USB_OUT_EPR].single.count_rx = ((1 << STM_USB_BDT_COUNT_RX_BL_SIZE) |
STM_USB_EPR_EP_TYPE_BULK,
STM_USB_EPR_STAT_RX_VALID,
STM_USB_EPR_STAT_TX_DISABLED);
+#endif
+#if AO_USB_HAS_IN
/* Set up the IN end point */
ao_usb_bdt[AO_USB_IN_EPR].single.addr_tx = ao_usb_in_tx_offset;
ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = 0;
STM_USB_EPR_EP_TYPE_BULK,
STM_USB_EPR_STAT_RX_DISABLED,
STM_USB_EPR_STAT_TX_NAK);
+#endif
+
+#if AO_USB_HAS_IN2
+ /* Set up the IN2 end point */
+ ao_usb_bdt[AO_USB_IN2_EPR].single.addr_tx = ao_usb_in2_tx_offset;
+ ao_usb_bdt[AO_USB_IN2_EPR].single.count_tx = 0;
+
+ ao_usb_init_ep(AO_USB_IN2_EPR,
+ AO_USB_IN2_EP,
+ STM_USB_EPR_EP_TYPE_BULK,
+ STM_USB_EPR_STAT_RX_DISABLED,
+ STM_USB_EPR_STAT_TX_NAK);
+#endif
ao_usb_running = 1;
#if AO_USB_DIRECTIO
static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8};
+#if AO_USB_DEVICE_ID_SERIAL
+static uint8_t ao_usb_serial[2 + 48];
+
+/* Convert a 32-bit value to 8 hexidecimal UCS2 characters */
+static void
+hex_to_ucs2(uint32_t in, uint8_t *out)
+{
+ int i;
+
+ for (i = 28; i >= 0; i -= 4) {
+ uint8_t bits = (in >> i) & 0xf;
+ *out++ = ((bits < 10) ? '0' : ('a' - 10)) + bits;
+ *out++ = 0;
+ }
+}
+
+/* Encode the device ID (96 bits) in hexidecimal to use as a device
+ * serial number
+ */
+static void
+ao_usb_serial_init(void)
+{
+ ao_usb_serial[0] = 50; /* length */
+ ao_usb_serial[1] = AO_USB_DESC_STRING;
+ hex_to_ucs2(stm_device_id.u_id0, ao_usb_serial + 2 + 0);
+ hex_to_ucs2(stm_device_id.u_id1, ao_usb_serial + 2 + 16);
+ hex_to_ucs2(stm_device_id.u_id2, ao_usb_serial + 2 + 32);
+}
+#endif
+
/* Walk through the list of descriptors and find a match
*/
static void
len = descriptor[2];
else
len = descriptor[0];
+#if AO_USB_DEVICE_ID_SERIAL
+ /* Slightly hacky - the serial number is string 3 */
+ if (type == AO_USB_DESC_STRING && (value & 0xff) == 3) {
+ descriptor = ao_usb_serial;
+ len = sizeof (ao_usb_serial);
+ }
+#endif
ao_usb_ep0_in_set(descriptor, len);
break;
}
ao_usb_ep0_handle(uint8_t receive)
{
ao_usb_ep0_receive = 0;
- if (receive & AO_USB_EP0_GOT_RESET) {
- debug ("\treset\n");
- ao_usb_set_ep0();
- return;
- }
if (receive & AO_USB_EP0_GOT_SETUP) {
debug ("\tsetup\n");
ao_usb_ep0_setup();
}
}
+#if AO_POWER_MANAGEMENT
+void
+ao_usb_suspend(void)
+{
+ stm_usb.cntr |= (1 << STM_USB_CNTR_FSUSP);
+ ao_power_suspend();
+ stm_usb.cntr |= (1 << STM_USB_CNTR_LP_MODE);
+ ao_clock_suspend();
+}
+
+void
+ao_usb_wakeup(void)
+{
+ ao_clock_resume();
+ stm_usb.cntr &= ~(1 << STM_USB_CNTR_FSUSP);
+ ao_power_resume();
+}
+#endif
+
void
stm_usb_isr(void)
{
ao_wakeup(&ao_usb_in_pending);
}
break;
+#if AO_USB_HAS_IN2
+ case AO_USB_IN2_EPR:
+ ++in2_count;
+ _tx_dbg1("TX2 ISR", epr);
+ if (ao_usb_epr_ctr_tx(epr)) {
+ ao_usb_in2_pending = 0;
+ ao_wakeup(&ao_usb_in2_pending);
+ }
+ break;
+#endif
case AO_USB_INT_EPR:
++int_count;
if (ao_usb_epr_ctr_tx(epr))
if (istr & (1 << STM_USB_ISTR_RESET)) {
++reset_count;
- ao_usb_ep0_receive |= AO_USB_EP0_GOT_RESET;
- ao_usb_ep0_handle(ao_usb_ep0_receive);
+ debug ("\treset\n");
+ ao_usb_set_ep0();
}
-
+#if AO_POWER_MANAGEMENT
+ if (istr & (1 << STM_USB_ISTR_SUSP)) {
+ debug ("\tsuspend\n");
+ ao_usb_suspend();
+ }
+ if (istr & (1 << STM_USB_ISTR_WKUP)) {
+ debug ("\twakeup\n");
+ ao_usb_wakeup();
+ }
+#endif
}
+#if AO_USB_HAS_IN
/* Queue the current IN buffer for transmission */
static void
_ao_usb_in_send(void)
}
ao_arch_release_interrupts();
}
+#endif
+
+#if AO_USB_HAS_IN2
+/* Queue the current IN buffer for transmission */
+static void
+_ao_usb_in2_send(void)
+{
+ _tx_dbg0("in2_send start");
+ debug ("send2 %d\n", ao_usb_tx_count);
+ while (ao_usb_in2_pending)
+ ao_sleep(&ao_usb_in2_pending);
+ ao_usb_in2_pending = 1;
+ if (ao_usb_tx2_count != AO_USB_IN_SIZE)
+ ao_usb_in2_flushed = 1;
+ ao_usb_copy_tx(ao_usb_tx2_buffer, ao_usb_in2_tx_buffer, ao_usb_tx2_count);
+ ao_usb_bdt[AO_USB_IN2_EPR].single.addr_tx = ao_usb_in_tx_offset;
+ ao_usb_bdt[AO_USB_IN2_EPR].single.count_tx = ao_usb_tx_count;
+ ao_usb_tx2_count = 0;
+ _ao_usb_set_stat_tx(AO_USB_IN2_EPR, STM_USB_EPR_STAT_TX_VALID);
+ _tx_dbg0("in2_send end");
+}
+
+/* Wait for a free IN buffer. Interrupts are blocked */
+static void
+_ao_usb_in2_wait(void)
+{
+ for (;;) {
+ /* Check if the current buffer is writable */
+ if (ao_usb_tx2_count < AO_USB_IN_SIZE)
+ break;
+
+ _tx_dbg0("in2_wait top");
+ /* Wait for an IN buffer to be ready */
+ while (ao_usb_in2_pending)
+ ao_sleep(&ao_usb_in2_pending);
+ _tx_dbg0("in_wait bottom");
+ }
+}
+
+void
+ao_usb_flush2(void)
+{
+ if (!ao_usb_running)
+ return;
+
+ /* Anytime we've sent a character since
+ * the last time we flushed, we'll need
+ * to send a packet -- the only other time
+ * we would send a packet is when that
+ * packet was full, in which case we now
+ * want to send an empty packet
+ */
+ ao_arch_block_interrupts();
+ while (!ao_usb_in2_flushed) {
+ _tx_dbg0("flush2 top");
+ _ao_usb_in2_send();
+ _tx_dbg0("flush2 end");
+ }
+ ao_arch_release_interrupts();
+}
+
+void
+ao_usb_putchar2(char c)
+{
+ if (!ao_usb_running)
+ return;
+
+ ao_arch_block_interrupts();
+ _ao_usb_in2_wait();
+ ao_usb_in2_flushed = 0;
+ ao_usb_tx2_buffer[ao_usb_tx2_count++] = (uint8_t) c;
+
+ /* Send the packet when full */
+ if (ao_usb_tx2_count == AO_USB_IN_SIZE) {
+ _tx_dbg0("putchar2 full");
+ _ao_usb_in2_send();
+ _tx_dbg0("putchar2 flushed");
+ }
+ ao_arch_release_interrupts();
+}
+#endif
+
+#if AO_USB_HAS_OUT
static void
_ao_usb_out_recv(void)
{
ao_arch_release_interrupts();
return c;
}
+#endif
#if AO_USB_DIRECTIO
uint16_t *
_ao_usb_set_stat_tx(AO_USB_IN_EPR, STM_USB_EPR_STAT_TX_VALID);
ao_arch_release_interrupts();
}
+
+#if AO_USB_HAS_IN2
+void
+ao_usb_write2(uint16_t *buffer, uint16_t len)
+{
+ ao_arch_block_interrupts();
+
+ /* Wait for everything to be ready at the same time */
+ for (;;) {
+ /* Make sure USB is connected */
+ if (!ao_usb_running) {
+ ao_sleep(&ao_usb_running);
+ continue;
+ }
+
+ /* Flush any pending regular I/O */
+ if (ao_usb_tx2_count) {
+ _ao_usb_in2_send();
+ continue;
+ }
+
+ /* Wait for an idle IN buffer */
+ if (ao_usb_in2_pending) {
+ ao_sleep(&ao_usb_in2_pending);
+ continue;
+ }
+ break;
+ }
+
+ ao_usb_in2_pending = 1;
+ ao_usb_in2_flushed = (len != AO_USB_IN_SIZE);
+ ao_usb_bdt[AO_USB_IN2_EPR].single.addr_tx = ao_usb_packet_buffer_offset(buffer);
+ ao_usb_bdt[AO_USB_IN2_EPR].single.count_tx = len;
+ _ao_usb_set_stat_tx(AO_USB_IN2_EPR, STM_USB_EPR_STAT_TX_VALID);
+ ao_arch_release_interrupts();
+}
+#endif
#endif
void
stm_usb.cntr = ((1 << STM_USB_CNTR_CTRM) |
(0 << STM_USB_CNTR_PMAOVRM) |
(0 << STM_USB_CNTR_ERRM) |
- (0 << STM_USB_CNTR_WKUPM) |
- (0 << STM_USB_CNTR_SUSPM) |
+ (AO_POWER_MANAGEMENT << STM_USB_CNTR_WKUPM) |
+ (AO_POWER_MANAGEMENT << STM_USB_CNTR_SUSPM) |
(1 << STM_USB_CNTR_RESETM) |
(0 << STM_USB_CNTR_SOFM) |
(0 << STM_USB_CNTR_ESOFM) |
}
#endif
-#if USB_DEBUG
+#if USB_STATUS
static void
ao_usb_irq(void)
{
/* Set PA11/PA12 remapping bit */
stm_syscfg.cfgr1 |= (AO_PA11_PA12_RMP << STM_SYSCFG_CFGR1_PA11_PA12_RMP);
+#ifndef AO_USB_START_DISABLED
ao_usb_enable();
+#endif
+
+#if AO_USB_DEVICE_ID_SERIAL
+ ao_usb_serial_init();
+#endif
debug ("ao_usb_init\n");
ao_usb_ep0_state = AO_USB_EP0_IDLE;
#if USB_ECHO
ao_add_task(&ao_usb_echo_task, ao_usb_echo, "usb echo");
#endif
-#if USB_DEBUG
+#if USB_STATUS
ao_cmd_register(&ao_usb_cmds[0]);
#endif
#if !USB_ECHO
/* calibration data in system memory */
stm_cal = 0x1ffff7b8;
stm_flash_size_04x = 0x1ffff7cc;
-stm_device_id = 0x1ff80050;
+stm_device_id = 0x1ffff7ac;
#define STM_RCC_CR2_HSI14RDY 1
#define STM_RCC_CR2_HSI14ON 0
+#define STM_RCC_CFGR2_PREDIV 0
+#define STM_RCC_CFGR2_PREDIV_1 0x0
+#define STM_RCC_CFGR2_PREDIV_2 0x1
+#define STM_RCC_CFGR2_PREDIV_3 0x2
+#define STM_RCC_CFGR2_PREDIV_4 0x3
+#define STM_RCC_CFGR2_PREDIV_5 0x4
+#define STM_RCC_CFGR2_PREDIV_6 0x5
+#define STM_RCC_CFGR2_PREDIV_7 0x6
+#define STM_RCC_CFGR2_PREDIV_8 0x7
+#define STM_RCC_CFGR2_PREDIV_9 0x8
+#define STM_RCC_CFGR2_PREDIV_10 0x9
+#define STM_RCC_CFGR2_PREDIV_11 0xa
+#define STM_RCC_CFGR2_PREDIV_12 0xb
+#define STM_RCC_CFGR2_PREDIV_13 0xc
+#define STM_RCC_CFGR2_PREDIV_14 0xd
+#define STM_RCC_CFGR2_PREDIV_15 0xe
+#define STM_RCC_CFGR2_PREDIV_16 0xf
+
#define STM_RCC_CFGR3_USART3SW 18
#define STM_RCC_CFGR3_USART2SW 16
#define STM_RCC_CFGR3_ADCSW 8
#define STM_ISR_TSC_POS 8
#define STM_ISR_DMA_CH1_POS 9
#define STM_ISR_DMA_CH2_3_DMA2_CH1_2_POS 10
-#define STM_ISR_DMA_CH44_5_6_7_DMA2_CH3_4_5_POS 11
+#define STM_ISR_DMA_CH4_5_6_7_DMA2_CH3_4_5_POS 11
#define STM_ISR_ADC_COMP_POS 12
#define STM_ISR_TIM1_BRK_UP_TRG_COM_POS 13
#define STM_ISR_TIM1_CC_POS 14
struct stm_syscfg {
vuint32_t cfgr1;
+ uint32_t reserved_04;
vuint32_t exticr[4];
vuint32_t cfgr2;
+ uint8_t reserved_1c[0x80-0x1c];
+ vuint32_t itline[31];
};
extern struct stm_syscfg stm_syscfg;
#define STM_SYSCFG_CFGR1_MEM_MODE_SRAM 3
#define STM_SYSCFG_CFGR1_MEM_MODE_MASK 3
-#if 0
+#define STM_SYSCFG_EXTICR_PA 0
+#define STM_SYSCFG_EXTICR_PB 1
+#define STM_SYSCFG_EXTICR_PC 2
+#define STM_SYSCFG_EXTICR_PD 3
+#define STM_SYSCFG_EXTICR_PE 4
+#define STM_SYSCFG_EXTICR_PF 5
+
static inline void
stm_exticr_set(struct stm_gpio *gpio, int pin) {
uint8_t reg = pin >> 2;
stm_syscfg.exticr[reg] = (stm_syscfg.exticr[reg] & ~(0xf << shift)) | val << shift;
}
-#endif
-
struct stm_dma_channel {
vuint32_t ccr;
vuint32_t reserved;
};
-#define STM_NUM_DMA 6
+#define STM_NUM_DMA 5
struct stm_dma {
vuint32_t isr;
extern struct stm_dma stm_dma;
-/* DMA channels go from 1 to 6, instead of 0 to 5 (sigh)
+/* DMA channels go from 1 to 5, instead of 0 to 4 (sigh)
*/
#define STM_DMA_INDEX(channel) ((channel) - 1)
#define STM_SPI_CR1_BIDIOE 14
#define STM_SPI_CR1_CRCEN 13
#define STM_SPI_CR1_CRCNEXT 12
-#define STM_SPI_CR1_DFF 11
+#define STM_SPI_CR1_CRCL 11
#define STM_SPI_CR1_RXONLY 10
#define STM_SPI_CR1_SSM 9
#define STM_SPI_CR1_SSI 8
#define STM_SPI_CR1_CPOL 1
#define STM_SPI_CR1_CPHA 0
+#define STM_SPI_CR2_LDMA_TX 14
+#define STM_SPI_CR2_LDMA_RX 13
+#define STM_SPI_CR2_FRXTH 12
+#define STM_SPI_CR2_DS 8
+#define STM_SPI_CR2_DS_4 0x3
+#define STM_SPI_CR2_DS_5 0x4
+#define STM_SPI_CR2_DS_6 0x5
+#define STM_SPI_CR2_DS_7 0x6
+#define STM_SPI_CR2_DS_8 0x7
+#define STM_SPI_CR2_DS_9 0x8
+#define STM_SPI_CR2_DS_10 0x9
+#define STM_SPI_CR2_DS_11 0xa
+#define STM_SPI_CR2_DS_12 0xb
+#define STM_SPI_CR2_DS_13 0xc
+#define STM_SPI_CR2_DS_14 0xd
+#define STM_SPI_CR2_DS_15 0xe
+#define STM_SPI_CR2_DS_16 0xf
#define STM_SPI_CR2_TXEIE 7
#define STM_SPI_CR2_RXNEIE 6
#define STM_SPI_CR2_ERRIE 5
+#define STM_SPI_CR2_FRF 4
+# define STM_SPI_CR2_FRF_MOTOROLA 0
+# define STM_SPI_CR2_FRF_TI 1
+#define STM_SPI_CR2_NSSP 3
#define STM_SPI_CR2_SSOE 2
#define STM_SPI_CR2_TXDMAEN 1
#define STM_SPI_CR2_RXDMAEN 0
+#define STM_SPI_SR_FTLVL 11
+#define STM_SPI_SR_FRLVL 9
+#define STM_SPI_SR_FRE 8
#define STM_SPI_SR_BSY 7
#define STM_SPI_SR_OVR 6
#define STM_SPI_SR_MODF 5
#define STM_SPI_SR_CRCERR 4
+#define STM_SPI_SR_UDR 3
+#define STM_SPI_SR_CHSIDE 2
#define STM_SPI_SR_TXE 1
#define STM_SPI_SR_RXNE 0
#define STM_I2C_CCR_CCR 0
#define STM_I2C_CCR_MASK 0x7ff
-struct stm_tim234 {
+struct stm_tim23 {
vuint32_t cr1;
vuint32_t cr2;
vuint32_t smcr;
uint32_t reserved_44;
vuint32_t dcr;
vuint32_t dmar;
-
- uint32_t reserved_50;
};
-extern struct stm_tim234 stm_tim2, stm_tim3, stm_tim4;
-
-#define STM_TIM234_CR1_CKD 8
-#define STM_TIM234_CR1_CKD_1 0
-#define STM_TIM234_CR1_CKD_2 1
-#define STM_TIM234_CR1_CKD_4 2
-#define STM_TIM234_CR1_CKD_MASK 3
-#define STM_TIM234_CR1_ARPE 7
-#define STM_TIM234_CR1_CMS 5
-#define STM_TIM234_CR1_CMS_EDGE 0
-#define STM_TIM234_CR1_CMS_CENTER_1 1
-#define STM_TIM234_CR1_CMS_CENTER_2 2
-#define STM_TIM234_CR1_CMS_CENTER_3 3
-#define STM_TIM234_CR1_CMS_MASK 3
-#define STM_TIM234_CR1_DIR 4
-#define STM_TIM234_CR1_DIR_UP 0
-#define STM_TIM234_CR1_DIR_DOWN 1
-#define STM_TIM234_CR1_OPM 3
-#define STM_TIM234_CR1_URS 2
-#define STM_TIM234_CR1_UDIS 1
-#define STM_TIM234_CR1_CEN 0
-
-#define STM_TIM234_CR2_TI1S 7
-#define STM_TIM234_CR2_MMS 4
-#define STM_TIM234_CR2_MMS_RESET 0
-#define STM_TIM234_CR2_MMS_ENABLE 1
-#define STM_TIM234_CR2_MMS_UPDATE 2
-#define STM_TIM234_CR2_MMS_COMPARE_PULSE 3
-#define STM_TIM234_CR2_MMS_COMPARE_OC1REF 4
-#define STM_TIM234_CR2_MMS_COMPARE_OC2REF 5
-#define STM_TIM234_CR2_MMS_COMPARE_OC3REF 6
-#define STM_TIM234_CR2_MMS_COMPARE_OC4REF 7
-#define STM_TIM234_CR2_MMS_MASK 7
-#define STM_TIM234_CR2_CCDS 3
-
-#define STM_TIM234_SMCR_ETP 15
-#define STM_TIM234_SMCR_ECE 14
-#define STM_TIM234_SMCR_ETPS 12
-#define STM_TIM234_SMCR_ETPS_OFF 0
-#define STM_TIM234_SMCR_ETPS_DIV_2 1
-#define STM_TIM234_SMCR_ETPS_DIV_4 2
-#define STM_TIM234_SMCR_ETPS_DIV_8 3
-#define STM_TIM234_SMCR_ETPS_MASK 3
-#define STM_TIM234_SMCR_ETF 8
-#define STM_TIM234_SMCR_ETF_NONE 0
-#define STM_TIM234_SMCR_ETF_INT_N_2 1
-#define STM_TIM234_SMCR_ETF_INT_N_4 2
-#define STM_TIM234_SMCR_ETF_INT_N_8 3
-#define STM_TIM234_SMCR_ETF_DTS_2_N_6 4
-#define STM_TIM234_SMCR_ETF_DTS_2_N_8 5
-#define STM_TIM234_SMCR_ETF_DTS_4_N_6 6
-#define STM_TIM234_SMCR_ETF_DTS_4_N_8 7
-#define STM_TIM234_SMCR_ETF_DTS_8_N_6 8
-#define STM_TIM234_SMCR_ETF_DTS_8_N_8 9
-#define STM_TIM234_SMCR_ETF_DTS_16_N_5 10
-#define STM_TIM234_SMCR_ETF_DTS_16_N_6 11
-#define STM_TIM234_SMCR_ETF_DTS_16_N_8 12
-#define STM_TIM234_SMCR_ETF_DTS_32_N_5 13
-#define STM_TIM234_SMCR_ETF_DTS_32_N_6 14
-#define STM_TIM234_SMCR_ETF_DTS_32_N_8 15
-#define STM_TIM234_SMCR_ETF_MASK 15
-#define STM_TIM234_SMCR_MSM 7
-#define STM_TIM234_SMCR_TS 4
-#define STM_TIM234_SMCR_TS_ITR0 0
-#define STM_TIM234_SMCR_TS_ITR1 1
-#define STM_TIM234_SMCR_TS_ITR2 2
-#define STM_TIM234_SMCR_TS_ITR3 3
-#define STM_TIM234_SMCR_TS_TI1F_ED 4
-#define STM_TIM234_SMCR_TS_TI1FP1 5
-#define STM_TIM234_SMCR_TS_TI2FP2 6
-#define STM_TIM234_SMCR_TS_ETRF 7
-#define STM_TIM234_SMCR_TS_MASK 7
-#define STM_TIM234_SMCR_OCCS 3
-#define STM_TIM234_SMCR_SMS 0
-#define STM_TIM234_SMCR_SMS_DISABLE 0
-#define STM_TIM234_SMCR_SMS_ENCODER_MODE_1 1
-#define STM_TIM234_SMCR_SMS_ENCODER_MODE_2 2
-#define STM_TIM234_SMCR_SMS_ENCODER_MODE_3 3
-#define STM_TIM234_SMCR_SMS_RESET_MODE 4
-#define STM_TIM234_SMCR_SMS_GATED_MODE 5
-#define STM_TIM234_SMCR_SMS_TRIGGER_MODE 6
-#define STM_TIM234_SMCR_SMS_EXTERNAL_CLOCK 7
-#define STM_TIM234_SMCR_SMS_MASK 7
-
-#define STM_TIM234_SR_CC4OF 12
-#define STM_TIM234_SR_CC3OF 11
-#define STM_TIM234_SR_CC2OF 10
-#define STM_TIM234_SR_CC1OF 9
-#define STM_TIM234_SR_TIF 6
-#define STM_TIM234_SR_CC4IF 4
-#define STM_TIM234_SR_CC3IF 3
-#define STM_TIM234_SR_CC2IF 2
-#define STM_TIM234_SR_CC1IF 1
-#define STM_TIM234_SR_UIF 0
-
-#define STM_TIM234_EGR_TG 6
-#define STM_TIM234_EGR_CC4G 4
-#define STM_TIM234_EGR_CC3G 3
-#define STM_TIM234_EGR_CC2G 2
-#define STM_TIM234_EGR_CC1G 1
-#define STM_TIM234_EGR_UG 0
-
-#define STM_TIM234_CCMR1_OC2CE 15
-#define STM_TIM234_CCMR1_OC2M 12
-#define STM_TIM234_CCMR1_OC2M_FROZEN 0
-#define STM_TIM234_CCMR1_OC2M_SET_HIGH_ON_MATCH 1
-#define STM_TIM234_CCMR1_OC2M_SET_LOW_ON_MATCH 2
-#define STM_TIM234_CCMR1_OC2M_TOGGLE 3
-#define STM_TIM234_CCMR1_OC2M_FORCE_LOW 4
-#define STM_TIM234_CCMR1_OC2M_FORCE_HIGH 5
-#define STM_TIM234_CCMR1_OC2M_PWM_MODE_1 6
-#define STM_TIM234_CCMR1_OC2M_PWM_MODE_2 7
-#define STM_TIM234_CCMR1_OC2M_MASK 7
-#define STM_TIM234_CCMR1_OC2PE 11
-#define STM_TIM234_CCMR1_OC2FE 10
-#define STM_TIM234_CCMR1_CC2S 8
-#define STM_TIM234_CCMR1_CC2S_OUTPUT 0
-#define STM_TIM234_CCMR1_CC2S_INPUT_TI2 1
-#define STM_TIM234_CCMR1_CC2S_INPUT_TI1 2
-#define STM_TIM234_CCMR1_CC2S_INPUT_TRC 3
-#define STM_TIM234_CCMR1_CC2S_MASK 3
-
-#define STM_TIM234_CCMR1_OC1CE 7
-#define STM_TIM234_CCMR1_OC1M 4
-#define STM_TIM234_CCMR1_OC1M_FROZEN 0
-#define STM_TIM234_CCMR1_OC1M_SET_HIGH_ON_MATCH 1
-#define STM_TIM234_CCMR1_OC1M_SET_LOW_ON_MATCH 2
-#define STM_TIM234_CCMR1_OC1M_TOGGLE 3
-#define STM_TIM234_CCMR1_OC1M_FORCE_LOW 4
-#define STM_TIM234_CCMR1_OC1M_FORCE_HIGH 5
-#define STM_TIM234_CCMR1_OC1M_PWM_MODE_1 6
-#define STM_TIM234_CCMR1_OC1M_PWM_MODE_2 7
-#define STM_TIM234_CCMR1_OC1M_MASK 7
-#define STM_TIM234_CCMR1_OC1PE 11
-#define STM_TIM234_CCMR1_OC1FE 2
-#define STM_TIM234_CCMR1_CC1S 0
-#define STM_TIM234_CCMR1_CC1S_OUTPUT 0
-#define STM_TIM234_CCMR1_CC1S_INPUT_TI1 1
-#define STM_TIM234_CCMR1_CC1S_INPUT_TI2 2
-#define STM_TIM234_CCMR1_CC1S_INPUT_TRC 3
-#define STM_TIM234_CCMR1_CC1S_MASK 3
-
-#define STM_TIM234_CCMR2_OC4CE 15
-#define STM_TIM234_CCMR2_OC4M 12
-#define STM_TIM234_CCMR2_OC4M_FROZEN 0
-#define STM_TIM234_CCMR2_OC4M_SET_HIGH_ON_MATCH 1
-#define STM_TIM234_CCMR2_OC4M_SET_LOW_ON_MATCH 2
-#define STM_TIM234_CCMR2_OC4M_TOGGLE 3
-#define STM_TIM234_CCMR2_OC4M_FORCE_LOW 4
-#define STM_TIM234_CCMR2_OC4M_FORCE_HIGH 5
-#define STM_TIM234_CCMR2_OC4M_PWM_MODE_1 6
-#define STM_TIM234_CCMR2_OC4M_PWM_MODE_2 7
-#define STM_TIM234_CCMR2_OC4M_MASK 7
-#define STM_TIM234_CCMR2_OC4PE 11
-#define STM_TIM234_CCMR2_OC4FE 10
-#define STM_TIM234_CCMR2_CC4S 8
-#define STM_TIM234_CCMR2_CC4S_OUTPUT 0
-#define STM_TIM234_CCMR2_CC4S_INPUT_TI4 1
-#define STM_TIM234_CCMR2_CC4S_INPUT_TI3 2
-#define STM_TIM234_CCMR2_CC4S_INPUT_TRC 3
-#define STM_TIM234_CCMR2_CC4S_MASK 3
-
-#define STM_TIM234_CCMR2_OC3CE 7
-#define STM_TIM234_CCMR2_OC3M 4
-#define STM_TIM234_CCMR2_OC3M_FROZEN 0
-#define STM_TIM234_CCMR2_OC3M_SET_HIGH_ON_MATCH 1
-#define STM_TIM234_CCMR2_OC3M_SET_LOW_ON_MATCH 2
-#define STM_TIM234_CCMR2_OC3M_TOGGLE 3
-#define STM_TIM234_CCMR2_OC3M_FORCE_LOW 4
-#define STM_TIM234_CCMR2_OC3M_FORCE_HIGH 5
-#define STM_TIM234_CCMR2_OC3M_PWM_MODE_1 6
-#define STM_TIM234_CCMR2_OC3M_PWM_MODE_2 7
-#define STM_TIM234_CCMR2_OC3M_MASK 7
-#define STM_TIM234_CCMR2_OC3PE 11
-#define STM_TIM234_CCMR2_OC3FE 2
-#define STM_TIM234_CCMR2_CC3S 0
-#define STM_TIM234_CCMR2_CC3S_OUTPUT 0
-#define STM_TIM234_CCMR2_CC3S_INPUT_TI3 1
-#define STM_TIM234_CCMR2_CC3S_INPUT_TI4 2
-#define STM_TIM234_CCMR2_CC3S_INPUT_TRC 3
-#define STM_TIM234_CCMR2_CC3S_MASK 3
-
-#define STM_TIM234_CCER_CC4NP 15
-#define STM_TIM234_CCER_CC4P 13
-#define STM_TIM234_CCER_CC4E 12
-#define STM_TIM234_CCER_CC3NP 11
-#define STM_TIM234_CCER_CC3P 9
-#define STM_TIM234_CCER_CC3E 8
-#define STM_TIM234_CCER_CC2NP 7
-#define STM_TIM234_CCER_CC2P 5
-#define STM_TIM234_CCER_CC2E 4
-#define STM_TIM234_CCER_CC1NP 3
-#define STM_TIM234_CCER_CC1P 1
-#define STM_TIM234_CCER_CC1E 0
+extern struct stm_tim23 stm_tim2, stm_tim3;
+
+#define stm_tim3 (*(struct stm_tim23 *) 0x40000400)
+#define stm_tim2 (*(struct stm_tim23 *) 0x40000000)
+
+#define STM_TIM23_CR1_CKD 8
+#define STM_TIM23_CR1_CKD_1 0
+#define STM_TIM23_CR1_CKD_2 1
+#define STM_TIM23_CR1_CKD_4 2
+#define STM_TIM23_CR1_CKD_MASK 3
+#define STM_TIM23_CR1_ARPE 7
+#define STM_TIM23_CR1_CMS 5
+#define STM_TIM23_CR1_CMS_EDGE 0
+#define STM_TIM23_CR1_CMS_CENTER_1 1
+#define STM_TIM23_CR1_CMS_CENTER_2 2
+#define STM_TIM23_CR1_CMS_CENTER_3 3
+#define STM_TIM23_CR1_CMS_MASK 3
+#define STM_TIM23_CR1_DIR 4
+#define STM_TIM23_CR1_DIR_UP 0
+#define STM_TIM23_CR1_DIR_DOWN 1
+#define STM_TIM23_CR1_OPM 3
+#define STM_TIM23_CR1_URS 2
+#define STM_TIM23_CR1_UDIS 1
+#define STM_TIM23_CR1_CEN 0
+
+#define STM_TIM23_CR2_TI1S 7
+#define STM_TIM23_CR2_MMS 4
+#define STM_TIM23_CR2_MMS_RESET 0
+#define STM_TIM23_CR2_MMS_ENABLE 1
+#define STM_TIM23_CR2_MMS_UPDATE 2
+#define STM_TIM23_CR2_MMS_COMPARE_PULSE 3
+#define STM_TIM23_CR2_MMS_COMPARE_OC1REF 4
+#define STM_TIM23_CR2_MMS_COMPARE_OC2REF 5
+#define STM_TIM23_CR2_MMS_COMPARE_OC3REF 6
+#define STM_TIM23_CR2_MMS_COMPARE_OC4REF 7
+#define STM_TIM23_CR2_MMS_MASK 7
+#define STM_TIM23_CR2_CCDS 3
+
+#define STM_TIM23_SMCR_ETP 15
+#define STM_TIM23_SMCR_ECE 14
+#define STM_TIM23_SMCR_ETPS 12
+#define STM_TIM23_SMCR_ETPS_OFF 0
+#define STM_TIM23_SMCR_ETPS_DIV_2 1
+#define STM_TIM23_SMCR_ETPS_DIV_4 2
+#define STM_TIM23_SMCR_ETPS_DIV_8 3
+#define STM_TIM23_SMCR_ETPS_MASK 3
+#define STM_TIM23_SMCR_ETF 8
+#define STM_TIM23_SMCR_ETF_NONE 0
+#define STM_TIM23_SMCR_ETF_INT_N_2 1
+#define STM_TIM23_SMCR_ETF_INT_N_4 2
+#define STM_TIM23_SMCR_ETF_INT_N_8 3
+#define STM_TIM23_SMCR_ETF_DTS_2_N_6 4
+#define STM_TIM23_SMCR_ETF_DTS_2_N_8 5
+#define STM_TIM23_SMCR_ETF_DTS_4_N_6 6
+#define STM_TIM23_SMCR_ETF_DTS_4_N_8 7
+#define STM_TIM23_SMCR_ETF_DTS_8_N_6 8
+#define STM_TIM23_SMCR_ETF_DTS_8_N_8 9
+#define STM_TIM23_SMCR_ETF_DTS_16_N_5 10
+#define STM_TIM23_SMCR_ETF_DTS_16_N_6 11
+#define STM_TIM23_SMCR_ETF_DTS_16_N_8 12
+#define STM_TIM23_SMCR_ETF_DTS_32_N_5 13
+#define STM_TIM23_SMCR_ETF_DTS_32_N_6 14
+#define STM_TIM23_SMCR_ETF_DTS_32_N_8 15
+#define STM_TIM23_SMCR_ETF_MASK 15
+#define STM_TIM23_SMCR_MSM 7
+#define STM_TIM23_SMCR_TS 4
+#define STM_TIM23_SMCR_TS_ITR0 0
+#define STM_TIM23_SMCR_TS_ITR1 1
+#define STM_TIM23_SMCR_TS_ITR2 2
+#define STM_TIM23_SMCR_TS_ITR3 3
+#define STM_TIM23_SMCR_TS_TI1F_ED 4
+#define STM_TIM23_SMCR_TS_TI1FP1 5
+#define STM_TIM23_SMCR_TS_TI2FP2 6
+#define STM_TIM23_SMCR_TS_ETRF 7
+#define STM_TIM23_SMCR_TS_MASK 7
+#define STM_TIM23_SMCR_OCCS 3
+#define STM_TIM23_SMCR_SMS 0
+#define STM_TIM23_SMCR_SMS_DISABLE 0
+#define STM_TIM23_SMCR_SMS_ENCODER_MODE_1 1
+#define STM_TIM23_SMCR_SMS_ENCODER_MODE_2 2
+#define STM_TIM23_SMCR_SMS_ENCODER_MODE_3 3
+#define STM_TIM23_SMCR_SMS_RESET_MODE 4
+#define STM_TIM23_SMCR_SMS_GATED_MODE 5
+#define STM_TIM23_SMCR_SMS_TRIGGER_MODE 6
+#define STM_TIM23_SMCR_SMS_EXTERNAL_CLOCK 7
+#define STM_TIM23_SMCR_SMS_MASK 7
+
+#define STM_TIM23_SR_CC4OF 12
+#define STM_TIM23_SR_CC3OF 11
+#define STM_TIM23_SR_CC2OF 10
+#define STM_TIM23_SR_CC1OF 9
+#define STM_TIM23_SR_TIF 6
+#define STM_TIM23_SR_CC4IF 4
+#define STM_TIM23_SR_CC3IF 3
+#define STM_TIM23_SR_CC2IF 2
+#define STM_TIM23_SR_CC1IF 1
+#define STM_TIM23_SR_UIF 0
+
+#define STM_TIM23_EGR_TG 6
+#define STM_TIM23_EGR_CC4G 4
+#define STM_TIM23_EGR_CC3G 3
+#define STM_TIM23_EGR_CC2G 2
+#define STM_TIM23_EGR_CC1G 1
+#define STM_TIM23_EGR_UG 0
+
+#define STM_TIM23_CCMR1_OC2CE 15
+#define STM_TIM23_CCMR1_OC2M 12
+#define STM_TIM23_CCMR1_OC2M_FROZEN 0
+#define STM_TIM23_CCMR1_OC2M_SET_HIGH_ON_MATCH 1
+#define STM_TIM23_CCMR1_OC2M_SET_LOW_ON_MATCH 2
+#define STM_TIM23_CCMR1_OC2M_TOGGLE 3
+#define STM_TIM23_CCMR1_OC2M_FORCE_LOW 4
+#define STM_TIM23_CCMR1_OC2M_FORCE_HIGH 5
+#define STM_TIM23_CCMR1_OC2M_PWM_MODE_1 6
+#define STM_TIM23_CCMR1_OC2M_PWM_MODE_2 7
+#define STM_TIM23_CCMR1_OC2M_MASK 7
+#define STM_TIM23_CCMR1_OC2PE 11
+#define STM_TIM23_CCMR1_OC2FE 10
+#define STM_TIM23_CCMR1_CC2S 8
+#define STM_TIM23_CCMR1_CC2S_OUTPUT 0
+#define STM_TIM23_CCMR1_CC2S_INPUT_TI2 1
+#define STM_TIM23_CCMR1_CC2S_INPUT_TI1 2
+#define STM_TIM23_CCMR1_CC2S_INPUT_TRC 3
+#define STM_TIM23_CCMR1_CC2S_MASK 3
+
+#define STM_TIM23_CCMR1_OC1CE 7
+#define STM_TIM23_CCMR1_OC1M 4
+#define STM_TIM23_CCMR1_OC1M_FROZEN 0
+#define STM_TIM23_CCMR1_OC1M_SET_HIGH_ON_MATCH 1
+#define STM_TIM23_CCMR1_OC1M_SET_LOW_ON_MATCH 2
+#define STM_TIM23_CCMR1_OC1M_TOGGLE 3
+#define STM_TIM23_CCMR1_OC1M_FORCE_LOW 4
+#define STM_TIM23_CCMR1_OC1M_FORCE_HIGH 5
+#define STM_TIM23_CCMR1_OC1M_PWM_MODE_1 6
+#define STM_TIM23_CCMR1_OC1M_PWM_MODE_2 7
+#define STM_TIM23_CCMR1_OC1M_MASK 7
+#define STM_TIM23_CCMR1_OC1PE 11
+#define STM_TIM23_CCMR1_OC1FE 2
+#define STM_TIM23_CCMR1_CC1S 0
+#define STM_TIM23_CCMR1_CC1S_OUTPUT 0
+#define STM_TIM23_CCMR1_CC1S_INPUT_TI1 1
+#define STM_TIM23_CCMR1_CC1S_INPUT_TI2 2
+#define STM_TIM23_CCMR1_CC1S_INPUT_TRC 3
+#define STM_TIM23_CCMR1_CC1S_MASK 3
+
+#define STM_TIM23_CCMR2_OC4CE 15
+#define STM_TIM23_CCMR2_OC4M 12
+#define STM_TIM23_CCMR2_OC4M_FROZEN 0
+#define STM_TIM23_CCMR2_OC4M_SET_HIGH_ON_MATCH 1
+#define STM_TIM23_CCMR2_OC4M_SET_LOW_ON_MATCH 2
+#define STM_TIM23_CCMR2_OC4M_TOGGLE 3
+#define STM_TIM23_CCMR2_OC4M_FORCE_LOW 4
+#define STM_TIM23_CCMR2_OC4M_FORCE_HIGH 5
+#define STM_TIM23_CCMR2_OC4M_PWM_MODE_1 6
+#define STM_TIM23_CCMR2_OC4M_PWM_MODE_2 7
+#define STM_TIM23_CCMR2_OC4M_MASK 7
+#define STM_TIM23_CCMR2_OC4PE 11
+#define STM_TIM23_CCMR2_OC4FE 10
+#define STM_TIM23_CCMR2_CC4S 8
+#define STM_TIM23_CCMR2_CC4S_OUTPUT 0
+#define STM_TIM23_CCMR2_CC4S_INPUT_TI4 1
+#define STM_TIM23_CCMR2_CC4S_INPUT_TI3 2
+#define STM_TIM23_CCMR2_CC4S_INPUT_TRC 3
+#define STM_TIM23_CCMR2_CC4S_MASK 3
+
+#define STM_TIM23_CCMR2_OC3CE 7
+#define STM_TIM23_CCMR2_OC3M 4
+#define STM_TIM23_CCMR2_OC3M_FROZEN 0
+#define STM_TIM23_CCMR2_OC3M_SET_HIGH_ON_MATCH 1
+#define STM_TIM23_CCMR2_OC3M_SET_LOW_ON_MATCH 2
+#define STM_TIM23_CCMR2_OC3M_TOGGLE 3
+#define STM_TIM23_CCMR2_OC3M_FORCE_LOW 4
+#define STM_TIM23_CCMR2_OC3M_FORCE_HIGH 5
+#define STM_TIM23_CCMR2_OC3M_PWM_MODE_1 6
+#define STM_TIM23_CCMR2_OC3M_PWM_MODE_2 7
+#define STM_TIM23_CCMR2_OC3M_MASK 7
+#define STM_TIM23_CCMR2_OC3PE 11
+#define STM_TIM23_CCMR2_OC3FE 2
+#define STM_TIM23_CCMR2_CC3S 0
+#define STM_TIM23_CCMR2_CC3S_OUTPUT 0
+#define STM_TIM23_CCMR2_CC3S_INPUT_TI3 1
+#define STM_TIM23_CCMR2_CC3S_INPUT_TI4 2
+#define STM_TIM23_CCMR2_CC3S_INPUT_TRC 3
+#define STM_TIM23_CCMR2_CC3S_MASK 3
+
+#define STM_TIM23_CCER_CC4NP 15
+#define STM_TIM23_CCER_CC4P 13
+#define STM_TIM23_CCER_CC4E 12
+#define STM_TIM23_CCER_CC3NP 11
+#define STM_TIM23_CCER_CC3P 9
+#define STM_TIM23_CCER_CC3E 8
+#define STM_TIM23_CCER_CC2NP 7
+#define STM_TIM23_CCER_CC2P 5
+#define STM_TIM23_CCER_CC2E 4
+#define STM_TIM23_CCER_CC1NP 3
+#define STM_TIM23_CCER_CC1P 1
+#define STM_TIM23_CCER_CC1E 0
struct stm_usb {
struct {
#define USE_SERIAL_2_STDIN 1
#define DELAY_SERIAL_2_STDIN 1
#define USE_SERIAL_2_FLOW 1
+#define USE_SERIAL_2_SW_FLOW 1
#define SERIAL_2_PA2_PA3 1
#define SERIAL_2_PD5_PD6 0
+#define SERIAL_2_PORT_RTS (&stm_gpioa)
+#define SERIAL_2_PIN_RTS 0
+#define SERIAL_2_PORT_CTS (&stm_gpioa)
+#define SERIAL_2_PIN_CTS 1
#define HAS_SERIAL_3 0
#define USE_SERIAL_3_STDIN 0
ao_clock_init();
ao_task_init();
- ao_serial_init();
ao_led_init(LEDS_AVAILABLE);
ao_led_on(AO_LED_RED);
ao_timer_init();
#define PACKET_HAS_MASTER 0
#define PACKET_HAS_SLAVE 0
+#define PAD_BOX 0
+
#define AO_LED_CONTINUITY(c) (1 << ((c) + 2))
#define AO_LED_CONTINUITY_MASK (0xc)
#define AO_LED_ARMED 0x10
--- /dev/null
+telefiretwo-*
+ao_product.h
--- /dev/null
+#
+# TeleFire build file
+#
+
+include ../stm/Makefile.defs
+
+INC = \
+ ao.h \
+ ao_pins.h \
+ ao_arch.h \
+ ao_arch_funcs.h \
+ ao_pad.h \
+ ao_product.h \
+ ao_radio_spi.h \
+ ao_radio_cmac.h \
+ ao_cc1200_CC1200.h \
+ ao_cc1200.h \
+ stm32l.h
+#
+# Common AltOS sources
+#
+
+#PROFILE=ao_profile.c
+#PROFILE_DEF=-DAO_PROFILE=1
+
+ALTOS_SRC = \
+ ao_boot_chain.c \
+ ao_interrupt.c \
+ ao_product.c \
+ ao_romconfig.c \
+ ao_cmd.c \
+ ao_adc_stm.c \
+ ao_data.c \
+ ao_config.c \
+ ao_task.c \
+ ao_led.c \
+ ao_stdio.c \
+ ao_panic.c \
+ ao_timer.c \
+ ao_mutex.c \
+ ao_freq.c \
+ ao_dma_stm.c \
+ ao_spi_stm.c \
+ ao_eeprom_stm.c \
+ ao_usb_stm.c \
+ ao_exti_stm.c \
+ ao_cc1200.c \
+ ao_radio_cmac.c \
+ ao_aes.c \
+ ao_aes_tables.c \
+ ao_pad.c \
+ ao_radio_cmac_cmd.c
+
+PRODUCT_SRC = \
+ ao_telefiretwo.c
+
+PRODUCT=TeleFire-v0.1
+PRODUCT_DEF=-DTELEFIRETWO_V_0_1
+IDPRODUCT=0x000f
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g
+
+PROGNAME = telefiretwo-v0.1
+PROG = $(PROGNAME)-$(VERSION).elf
+HEX = $(PROGNAME)-$(VERSION).ihx
+
+SRC = $(ALTOS_SRC) $(PRODUCT_SRC)
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+ $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+$(OBJ): $(INC)
+
+ao_product.h: ao-make-product.5c ../Version
+ $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+distclean: clean
+
+clean:
+ rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+ rm -f ao_product.h
+
+install:
+
+uninstall:
+
--- /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.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define HAS_RADIO 1
+#define HAS_RADIO_RATE 1
+#define HAS_TELEMETRY 0
+
+#define HAS_FLIGHT 0
+#define HAS_USB 1
+#define HAS_BEEP 0
+#define HAS_GPS 0
+#define HAS_SERIAL_1 0
+#define HAS_ADC 1
+#define HAS_DBG 0
+#define HAS_EEPROM 1
+#define HAS_LOG 0
+#define HAS_PAD 1
+#define USE_INTERNAL_FLASH 1
+#define IGNITE_ON_P0 0
+#define PACKET_HAS_MASTER 0
+#define PACKET_HAS_SLAVE 0
+#define AO_DATA_RING 32
+#define HAS_FIXED_PAD_BOX 1
+
+/* 8MHz High speed external crystal */
+#define AO_HSE 8000000
+
+/* PLLVCO = 96MHz (so that USB will work) */
+#define AO_PLLMUL 12
+#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12)
+
+#define AO_CC1200_FOSC 40000000
+
+/* SYSCLK = 32MHz (no need to go faster than CPU) */
+#define AO_PLLDIV 3
+#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_3)
+
+/* HCLK = 32MHz (CPU clock) */
+#define AO_AHB_PRESCALER 1
+#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1
+
+/* Run APB1 at 16MHz (HCLK/2) */
+#define AO_APB1_PRESCALER 2
+#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2
+
+/* Run APB2 at 16MHz (HCLK/2) */
+#define AO_APB2_PRESCALER 2
+#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2
+
+#define HAS_EEPROM 1
+#define USE_INTERNAL_FLASH 1
+#define USE_EEPROM_CONFIG 1
+#define USE_STORAGE_CONFIG 0
+#define HAS_USB 1
+#define HAS_BEEP 0
+#define HAS_RADIO 1
+#define HAS_RADIO_RATE 1
+#define HAS_TELEMETRY 0
+#define HAS_AES 1
+
+#define HAS_SPI_1 0
+#define SPI_1_PA5_PA6_PA7 0
+#define SPI_1_PB3_PB4_PB5 0
+#define SPI_1_PE13_PE14_PE15 0
+
+#define HAS_SPI_2 1 /* CC1200 */
+#define SPI_2_PB13_PB14_PB15 1
+#define SPI_2_PD1_PD3_PD4 0
+#define SPI_2_GPIO (&stm_gpiob)
+#define SPI_2_SCK 13
+#define SPI_2_MISO 14
+#define SPI_2_MOSI 15
+#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz
+
+#define HAS_I2C_1 0
+
+#define HAS_I2C_2 0
+
+#define PACKET_HAS_SLAVE 0
+#define PACKET_HAS_MASTER 0
+
+#define FAST_TIMER_FREQ 10000 /* .1ms for debouncing */
+
+/*
+ * Radio is a cc1200 connected via SPI
+ */
+
+#define AO_RADIO_CAL_DEFAULT 5695733
+
+#define AO_FEC_DEBUG 0
+#define AO_CC1200_SPI_CS_PORT (&stm_gpioa)
+#define AO_CC1200_SPI_CS_PIN 7
+#define AO_CC1200_SPI_BUS AO_SPI_2_PB13_PB14_PB15
+#define AO_CC1200_SPI stm_spi2
+
+#define AO_CC1200_INT_PORT (&stm_gpiob)
+#define AO_CC1200_INT_PIN (11)
+
+#define AO_CC1200_INT_GPIO 2
+#define AO_CC1200_INT_GPIO_IOCFG CC1200_IOCFG2
+
+#define LED_PORT_0 (&stm_gpioa)
+#define LED_PORT_1 (&stm_gpiob)
+
+#define LED_PORT_0_ENABLE STM_RCC_AHBENR_GPIOAEN
+#define LED_PORT_1_ENABLE STM_RCC_AHBENR_GPIOBEN
+
+/* Port A, pins 4-6 */
+#define LED_PORT_0_SHIFT 4
+#define LED_PORT_0_MASK 0x7
+#define LED_PIN_GREEN 0
+#define LED_PIN_AMBER 1
+#define LED_PIN_RED 2
+#define AO_LED_RED (1 << LED_PIN_RED)
+#define AO_LED_AMBER (1 << LED_PIN_AMBER)
+#define AO_LED_GREEN (1 << LED_PIN_GREEN)
+
+/* Port B, pins 3-5 */
+#define LED_PORT_1_SHIFT 0
+#define LED_PORT_1_MASK (0x7 << 3)
+#define LED_PIN_CONT_1 3
+#define LED_PIN_CONT_0 4
+#define LED_PIN_ARMED 5
+
+#define AO_LED_ARMED (1 << LED_PIN_ARMED)
+#define AO_LED_CONTINUITY(c) (1 << (4 - (c)))
+#define AO_LED_CONTINUITY_MASK (0x3 << 3)
+
+#define LEDS_AVAILABLE (LED_PORT_0_MASK|LED_PORT_1_MASK)
+
+#define SPI_CS_PORT P1
+#define SPI_CS_SEL P1SEL
+#define SPI_CS_DIR P1DIR
+
+#define SPI_CONST 0x00
+
+#define AO_PAD_NUM 2
+#define AO_PAD_PORT (&stm_gpiob)
+
+#define AO_PAD_PIN_0 9
+#define AO_PAD_ADC_0 0
+
+#define AO_PAD_PIN_1 8
+#define AO_PAD_ADC_1 1
+
+#define AO_PAD_ALL_PINS ((1 << AO_PAD_PIN_0) | (1 << AO_PAD_PIN_1))
+#define AO_PAD_ALL_CHANNELS ((1 << 0) | (1 << 1))
+
+/* test these values with real igniters */
+#define AO_PAD_RELAY_CLOSED 3524
+#define AO_PAD_NO_IGNITER 16904
+#define AO_PAD_GOOD_IGNITER 22514
+
+#define AO_PAD_ADC_PYRO 8
+#define AO_PAD_ADC_BATT 2
+
+#define AO_ADC_FIRST_PIN 0
+
+#define AO_NUM_ADC 4
+
+#define AO_ADC_SQ1 AO_PAD_ADC_0
+#define AO_ADC_SQ2 AO_PAD_ADC_1
+#define AO_ADC_SQ3 AO_PAD_ADC_PYRO
+#define AO_ADC_SQ4 AO_PAD_ADC_BATT
+
+#define AO_PYRO_R_PYRO_SENSE 200
+#define AO_PYRO_R_SENSE_GND 22
+
+#define AO_FIRE_R_POWER_FET 0
+#define AO_FIRE_R_FET_SENSE 200
+#define AO_FIRE_R_SENSE_GND 22
+
+#define HAS_ADC_TEMP 0
+
+struct ao_adc {
+ int16_t sense[AO_PAD_NUM];
+ int16_t pyro;
+ int16_t batt;
+};
+
+#define AO_ADC_DUMP(p) \
+ printf ("tick: %5u 0: %5d 1: %5d pyro: %5d batt %5d\n", \
+ (p)->tick, \
+ (p)->adc.sense[0], \
+ (p)->adc.sense[1], \
+ (p)->adc.pyro, \
+ (p)->adc.batt)
+
+#define AO_ADC_PINS ((1 << AO_PAD_ADC_0) | \
+ (1 << AO_PAD_ADC_1) | \
+ (1 << AO_PAD_ADC_PYRO) | \
+ (1 << AO_PAD_ADC_BATT))
+
+#endif /* _AO_PINS_H_ */
--- /dev/null
+/*
+ * Copyright © 2012 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_pad.h>
+#include <ao_exti.h>
+#include <ao_radio_cmac_cmd.h>
+
+void
+main(void)
+{
+ ao_clock_init();
+
+ ao_led_init(LEDS_AVAILABLE);
+
+ ao_task_init();
+
+ ao_timer_init();
+ ao_spi_init();
+ ao_dma_init();
+ ao_exti_init();
+
+ ao_cmd_init();
+
+ ao_adc_init();
+
+ ao_eeprom_init();
+
+ ao_radio_init();
+
+ ao_usb_init();
+
+ ao_config_init();
+
+ ao_pad_init();
+
+// ao_radio_cmac_cmd_init();
+
+ ao_start_scheduler();
+}
--- /dev/null
+*.elf
+*.ihx
--- /dev/null
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=telefiretwo-v0.1
+include $(TOPDIR)/stm/Makefile-flash.defs
--- /dev/null
+/*
+ * Copyright © 2013 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_PINS_H_
+#define _AO_PINS_H_
+
+/* External crystal at 8MHz */
+#define AO_HSE 8000000
+
+#include <ao_flash_stm_pins.h>
+
+#define AO_BOOT_PIN 1
+#define AO_BOOT_APPLICATION_GPIO stm_gpiob
+#define AO_BOOT_APPLICATION_PIN 6
+#define AO_BOOT_APPLICATION_VALUE 1
+#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP
+
+#endif /* _AO_PINS_H_ */
--- /dev/null
+telefiretwo-*
+ao_product.h
--- /dev/null
+#
+# TeleFire build file
+#
+
+include ../stm/Makefile.defs
+
+INC = \
+ ao.h \
+ ao_pins.h \
+ ao_arch.h \
+ ao_arch_funcs.h \
+ ao_pad.h \
+ ao_product.h \
+ ao_radio_spi.h \
+ ao_radio_cmac.h \
+ ao_cc1200_CC1200.h \
+ ao_cc1200.h \
+ stm32l.h
+#
+# Common AltOS sources
+#
+
+#PROFILE=ao_profile.c
+#PROFILE_DEF=-DAO_PROFILE=1
+
+ALTOS_SRC = \
+ ao_boot_chain.c \
+ ao_interrupt.c \
+ ao_product.c \
+ ao_romconfig.c \
+ ao_cmd.c \
+ ao_adc_stm.c \
+ ao_data.c \
+ ao_config.c \
+ ao_task.c \
+ ao_led.c \
+ ao_stdio.c \
+ ao_panic.c \
+ ao_timer.c \
+ ao_mutex.c \
+ ao_freq.c \
+ ao_dma_stm.c \
+ ao_spi_stm.c \
+ ao_beep_stm.c \
+ ao_eeprom_stm.c \
+ ao_usb_stm.c \
+ ao_exti_stm.c \
+ ao_cc1200.c \
+ ao_radio_cmac.c \
+ ao_aes.c \
+ ao_aes_tables.c \
+ ao_pad.c \
+ ao_radio_cmac_cmd.c
+
+PRODUCT_SRC = \
+ ao_telefiretwo.c
+
+PRODUCT=TeleFire-v0.2
+PRODUCT_DEF=-DTELEFIRETWO_V_0_2
+IDPRODUCT=0x000f
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g
+
+PROGNAME = telefiretwo-v0.2
+PROG = $(PROGNAME)-$(VERSION).elf
+HEX = $(PROGNAME)-$(VERSION).ihx
+
+SRC = $(ALTOS_SRC) $(PRODUCT_SRC)
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+ $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+$(OBJ): $(INC)
+
+ao_product.h: ao-make-product.5c ../Version
+ $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+distclean: clean
+
+clean:
+ rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+ rm -f ao_product.h
+
+install:
+
+uninstall:
+
--- /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.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define HAS_RADIO 1
+#define HAS_RADIO_RATE 1
+#define HAS_TELEMETRY 0
+
+#define HAS_FLIGHT 0
+#define HAS_USB 1
+#define HAS_BEEP 1
+#define BEEPER_CHANNEL 4
+#define HAS_GPS 0
+#define HAS_SERIAL_1 0
+#define HAS_ADC 1
+#define HAS_DBG 0
+#define HAS_EEPROM 1
+#define HAS_LOG 0
+#define HAS_PAD 1
+#define USE_INTERNAL_FLASH 1
+#define IGNITE_ON_P0 0
+#define PACKET_HAS_MASTER 0
+#define PACKET_HAS_SLAVE 0
+#define AO_DATA_RING 32
+#define HAS_FIXED_PAD_BOX 1
+
+/* 8MHz High speed external crystal */
+#define AO_HSE 8000000
+
+/* PLLVCO = 96MHz (so that USB will work) */
+#define AO_PLLMUL 12
+#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12)
+
+#define AO_CC1200_FOSC 40000000
+
+/* SYSCLK = 32MHz (no need to go faster than CPU) */
+#define AO_PLLDIV 3
+#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_3)
+
+/* HCLK = 32MHz (CPU clock) */
+#define AO_AHB_PRESCALER 1
+#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1
+
+/* Run APB1 at 16MHz (HCLK/2) */
+#define AO_APB1_PRESCALER 2
+#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2
+
+/* Run APB2 at 16MHz (HCLK/2) */
+#define AO_APB2_PRESCALER 2
+#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2
+
+#define HAS_EEPROM 1
+#define USE_INTERNAL_FLASH 1
+#define USE_EEPROM_CONFIG 1
+#define USE_STORAGE_CONFIG 0
+#define HAS_USB 1
+#define HAS_RADIO 1
+#define HAS_RADIO_RATE 1
+#define HAS_TELEMETRY 0
+#define HAS_AES 1
+
+#define HAS_SPI_1 0
+#define SPI_1_PA5_PA6_PA7 0
+#define SPI_1_PB3_PB4_PB5 0
+#define SPI_1_PE13_PE14_PE15 0
+
+#define HAS_SPI_2 1 /* CC1200 */
+#define SPI_2_PB13_PB14_PB15 1
+#define SPI_2_PD1_PD3_PD4 0
+#define SPI_2_GPIO (&stm_gpiob)
+#define SPI_2_SCK 13
+#define SPI_2_MISO 14
+#define SPI_2_MOSI 15
+#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz
+
+#define HAS_I2C_1 0
+
+#define HAS_I2C_2 0
+
+#define PACKET_HAS_SLAVE 0
+#define PACKET_HAS_MASTER 0
+
+#define FAST_TIMER_FREQ 10000 /* .1ms for debouncing */
+
+/*
+ * Radio is a cc1200 connected via SPI
+ */
+
+#define AO_RADIO_CAL_DEFAULT 5695733
+
+#define AO_FEC_DEBUG 0
+#define AO_CC1200_SPI_CS_PORT (&stm_gpioa)
+#define AO_CC1200_SPI_CS_PIN 7
+#define AO_CC1200_SPI_BUS AO_SPI_2_PB13_PB14_PB15
+#define AO_CC1200_SPI stm_spi2
+
+#define AO_CC1200_INT_PORT (&stm_gpiob)
+#define AO_CC1200_INT_PIN (11)
+
+#define AO_CC1200_INT_GPIO 2
+#define AO_CC1200_INT_GPIO_IOCFG CC1200_IOCFG2
+
+#define LED_PORT_0 (&stm_gpioa)
+#define LED_PORT_1 (&stm_gpiob)
+
+#define LED_PORT_0_ENABLE STM_RCC_AHBENR_GPIOAEN
+#define LED_PORT_1_ENABLE STM_RCC_AHBENR_GPIOBEN
+
+/* Port A, pins 4-6 */
+#define LED_PORT_0_SHIFT 4
+#define LED_PORT_0_MASK 0x7
+#define LED_PIN_GREEN 0
+#define LED_PIN_AMBER 1
+#define LED_PIN_RED 2
+#define AO_LED_RED (1 << LED_PIN_RED)
+#define AO_LED_AMBER (1 << LED_PIN_AMBER)
+#define AO_LED_GREEN (1 << LED_PIN_GREEN)
+
+/* Port B, pins 4-5 */
+#define LED_PORT_1_SHIFT 0
+#define LED_PORT_1_MASK (0x3 << 4)
+#define LED_PIN_CONT_0 4
+#define LED_PIN_ARMED 5
+
+#define AO_LED_ARMED (1 << LED_PIN_ARMED)
+#define AO_LED_CONTINUITY(c) (1 << (4 - (c)))
+#define AO_LED_CONTINUITY_MASK (0x1 << 4)
+
+#define LEDS_AVAILABLE (LED_PORT_0_MASK|LED_PORT_1_MASK)
+
+/* Alarm A */
+#define AO_SIREN
+#define AO_SIREN_PORT (&stm_gpiob)
+#define AO_SIREN_PIN 8
+
+/* Alarm B */
+#define AO_STROBE
+#define AO_STROBE_PORT (&stm_gpiob)
+#define AO_STROBE_PIN 9
+
+#define SPI_CONST 0x00
+
+#define AO_PAD_NUM 1
+#define AO_PAD_PORT (&stm_gpioa)
+
+#define AO_PAD_PIN_0 1
+#define AO_PAD_ADC_0 0
+
+#define AO_PAD_ALL_PINS ((1 << AO_PAD_PIN_0))
+#define AO_PAD_ALL_CHANNELS ((1 << 0))
+
+/* test these values with real igniters */
+#define AO_PAD_RELAY_CLOSED 3524
+#define AO_PAD_NO_IGNITER 16904
+#define AO_PAD_GOOD_IGNITER 22514
+
+#define AO_PAD_ADC_PYRO 2
+#define AO_PAD_ADC_BATT 8
+
+#define AO_ADC_FIRST_PIN 0
+
+#define AO_NUM_ADC 3
+
+#define AO_ADC_SQ1 AO_PAD_ADC_0
+#define AO_ADC_SQ2 AO_PAD_ADC_PYRO
+#define AO_ADC_SQ3 AO_PAD_ADC_BATT
+
+#define AO_PYRO_R_PYRO_SENSE 200
+#define AO_PYRO_R_SENSE_GND 22
+
+#define AO_FIRE_R_POWER_FET 0
+#define AO_FIRE_R_FET_SENSE 200
+#define AO_FIRE_R_SENSE_GND 22
+
+#define HAS_ADC_TEMP 0
+
+struct ao_adc {
+ int16_t sense[AO_PAD_NUM];
+ int16_t pyro;
+ int16_t batt;
+};
+
+#define AO_ADC_DUMP(p) \
+ printf ("tick: %5u 0: %5d pyro: %5d batt %5d\n", \
+ (p)->tick, \
+ (p)->adc.sense[0], \
+ (p)->adc.pyro, \
+ (p)->adc.batt)
+
+#define AO_ADC_PINS ((1 << AO_PAD_ADC_0) | \
+ (1 << AO_PAD_ADC_PYRO) | \
+ (1 << AO_PAD_ADC_BATT))
+
+#endif /* _AO_PINS_H_ */
--- /dev/null
+/*
+ * Copyright © 2012 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_pad.h>
+#include <ao_exti.h>
+#include <ao_radio_cmac_cmd.h>
+
+void
+main(void)
+{
+ ao_clock_init();
+
+ ao_led_init(LEDS_AVAILABLE);
+
+ ao_task_init();
+
+ ao_timer_init();
+ ao_spi_init();
+ ao_dma_init();
+ ao_exti_init();
+
+ ao_cmd_init();
+
+ ao_adc_init();
+
+ ao_eeprom_init();
+
+ ao_radio_init();
+
+ ao_usb_init();
+
+ ao_config_init();
+
+ ao_pad_init();
+
+// ao_radio_cmac_cmd_init();
+
+ ao_start_scheduler();
+}
--- /dev/null
+*.elf
+*.ihx
--- /dev/null
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=telefiretwo-v0.2
+include $(TOPDIR)/stm/Makefile-flash.defs
--- /dev/null
+/*
+ * Copyright © 2013 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_PINS_H_
+#define _AO_PINS_H_
+
+/* External crystal at 8MHz */
+#define AO_HSE 8000000
+
+#include <ao_flash_stm_pins.h>
+
+#define AO_BOOT_PIN 1
+#define AO_BOOT_APPLICATION_GPIO stm_gpiob
+#define AO_BOOT_APPLICATION_PIN 6
+#define AO_BOOT_APPLICATION_VALUE 1
+#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP
+
+#endif /* _AO_PINS_H_ */
ao_radio_spi.h \
ao_radio_cmac.h \
ao_cc1120_CC1120.h \
- ao_debounce.h \
stm32l.h
#
ao_fec_tx.c \
ao_fec_rx.c \
ao_seven_segment.c \
- ao_debounce.c \
ao_quadrature.c \
ao_button.c \
ao_event.c \
ao_radio_cmac.h \
ao_cc1200_CC1200.h \
ao_cc1200.h \
- ao_debounce.h \
stm32l.h
#
ao_fec_tx.c \
ao_fec_rx.c \
ao_seven_segment.c \
- ao_debounce.c \
ao_quadrature.c \
ao_button.c \
ao_event.c \
--- /dev/null
+ao_product.h
+telelco*.elf
--- /dev/null
+#
+# AltOS build for TeleLCO
+#
+#
+
+include ../stm/Makefile.defs
+
+INC = \
+ ao.h \
+ ao_arch.h \
+ ao_arch_funcs.h \
+ ao_boot.h \
+ ao_companion.h \
+ ao_data.h \
+ ao_sample.h \
+ ao_pins.h \
+ ao_product.h \
+ ao_radio_spi.h \
+ ao_radio_cmac.h \
+ ao_cc1200_CC1200.h \
+ ao_cc1200.h \
+ stm32l.h
+
+#
+# Common AltOS sources
+#
+
+#PROFILE=ao_profile.c
+#PROFILE_DEF=-DAO_PROFILE=1
+
+ALTOS_SRC = \
+ ao_boot_chain.c \
+ ao_interrupt.c \
+ ao_product.c \
+ ao_romconfig.c \
+ ao_cmd.c \
+ ao_config.c \
+ ao_task.c \
+ ao_led.c \
+ ao_stdio.c \
+ ao_panic.c \
+ ao_timer.c \
+ ao_mutex.c \
+ ao_freq.c \
+ ao_dma_stm.c \
+ ao_spi_stm.c \
+ ao_beep_stm.c \
+ ao_eeprom_stm.c \
+ ao_fast_timer.c \
+ ao_usb_stm.c \
+ ao_exti_stm.c \
+ ao_cc1200.c \
+ ao_radio_cmac.c \
+ ao_aes.c \
+ ao_aes_tables.c \
+ ao_fec_tx.c \
+ ao_fec_rx.c \
+ ao_button.c \
+ ao_event.c \
+ ao_lco_two.c \
+ ao_lco_func.c \
+ ao_lco_cmd.c \
+ ao_radio_cmac_cmd.c
+
+PRODUCT=TeleLCOTwo-v0.1
+PRODUCT_DEF=-DTELELCOTWO
+IDPRODUCT=0x0023
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g
+
+PROGNAME=telelcotwo-v0.1
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_telelcotwo.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+ $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+$(OBJ): $(INC)
+
+ao_product.h: ao-make-product.5c ../Version
+ $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+distclean: clean
+
+clean:
+ rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+ rm -f ao_product.h
+
+install:
+
+uninstall:
--- /dev/null
+/*
+ * Copyright © 2012 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_PINS_H_
+#define _AO_PINS_H_
+
+/* 8MHz High speed external crystal */
+#define AO_HSE 8000000
+
+/* PLLVCO = 96MHz (so that USB will work) */
+#define AO_PLLMUL 12
+#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12)
+
+#define AO_CC1200_FOSC 40000000
+
+/* SYSCLK = 32MHz (no need to go faster than CPU) */
+#define AO_PLLDIV 3
+#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_3)
+
+/* HCLK = 32MHz (CPU clock) */
+#define AO_AHB_PRESCALER 1
+#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1
+
+/* Run APB1 at 16MHz (HCLK/2) */
+#define AO_APB1_PRESCALER 2
+#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2
+
+/* Run APB2 at 16MHz (HCLK/2) */
+#define AO_APB2_PRESCALER 2
+#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2
+
+#define HAS_EEPROM 1
+#define USE_INTERNAL_FLASH 1
+#define USE_EEPROM_CONFIG 1
+#define USE_STORAGE_CONFIG 0
+#define HAS_USB 1
+#define HAS_BEEP 1
+#define BEEPER_CHANNEL 4
+#define HAS_RADIO 1
+#define HAS_RADIO_RATE 1
+#define HAS_TELEMETRY 0
+#define HAS_AES 1
+#define HAS_FIXED_PAD_BOX 1
+
+#define HAS_SPI_1 0
+#define SPI_1_PA5_PA6_PA7 0
+#define SPI_1_PB3_PB4_PB5 0
+#define SPI_1_PE13_PE14_PE15 0
+
+#define HAS_SPI_2 1 /* CC1200 */
+#define SPI_2_PB13_PB14_PB15 1
+#define SPI_2_PD1_PD3_PD4 0
+#define SPI_2_GPIO (&stm_gpiod)
+#define SPI_2_SCK 13
+#define SPI_2_MISO 14
+#define SPI_2_MOSI 15
+#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz
+
+#define HAS_I2C_1 0
+
+#define HAS_I2C_2 0
+
+#define PACKET_HAS_SLAVE 0
+#define PACKET_HAS_MASTER 0
+
+#define FAST_TIMER_FREQ 10000 /* .1ms for debouncing */
+
+/*
+ * Radio is a cc1200 connected via SPI
+ */
+
+#define AO_RADIO_CAL_DEFAULT 5695733
+
+#define AO_FEC_DEBUG 0
+#define AO_CC1200_SPI_CS_PORT (&stm_gpioa)
+#define AO_CC1200_SPI_CS_PIN 7
+#define AO_CC1200_SPI_BUS AO_SPI_2_PB13_PB14_PB15
+#define AO_CC1200_SPI stm_spi2
+
+#define AO_CC1200_INT_PORT (&stm_gpiob)
+#define AO_CC1200_INT_PIN (11)
+
+#define AO_CC1200_INT_GPIO 2
+#define AO_CC1200_INT_GPIO_IOCFG CC1200_IOCFG2
+
+#define LOW_LEVEL_DEBUG 0
+
+#define LED_PORT_0 (&stm_gpioa)
+#define LED_PORT_1 (&stm_gpiob)
+
+#define LED_PORT_0_ENABLE STM_RCC_AHBENR_GPIOAEN
+#define LED_PORT_1_ENABLE STM_RCC_AHBENR_GPIOBEN
+
+/* Port A, pins 4-6 */
+#define LED_PORT_0_SHIFT 4
+#define LED_PORT_0_MASK 0x7
+
+#define LED_PIN_GREEN 0
+#define LED_PIN_AMBER 1
+#define LED_PIN_RED 2
+
+#define AO_LED_RED (1 << LED_PIN_RED)
+#define AO_LED_AMBER (1 << LED_PIN_AMBER)
+#define AO_LED_GREEN (1 << LED_PIN_GREEN)
+
+/* Port B, pins 3-5 */
+#define LED_PORT_1_SHIFT 0
+#define LED_PORT_1_MASK (0x7 << 3)
+
+#define LED_PIN_CONTINUITY_1 3
+#define LED_PIN_CONTINUITY_0 4
+#define LED_PIN_REMOTE_ARM 5
+
+#define AO_LED_CONTINUITY_1 (1 << LED_PIN_CONTINUITY_1)
+#define AO_LED_CONTINUITY_0 (1 << LED_PIN_CONTINUITY_0)
+
+#define AO_LED_CONTINUITY_NUM 2
+
+#define AO_LED_REMOTE_ARM (1 << LED_PIN_REMOTE_ARM)
+
+#define LEDS_AVAILABLE (AO_LED_RED | \
+ AO_LED_AMBER | \
+ AO_LED_GREEN | \
+ AO_LED_CONTINUITY_1 | \
+ AO_LED_CONTINUITY_0 | \
+ AO_LED_REMOTE_ARM)
+
+/*
+ * Use event queue for input devices
+ */
+
+#define AO_EVENT 1
+
+/*
+ * Buttons
+ */
+
+#define AO_BUTTON_COUNT 3
+#define AO_BUTTON_MODE AO_EXTI_MODE_PULL_UP
+
+#define AO_BUTTON_0_PORT &stm_gpioa
+#define AO_BUTTON_0 0
+
+#define AO_BUTTON_ARM_0 0
+
+#define AO_BUTTON_1_PORT &stm_gpioa
+#define AO_BUTTON_1 1
+
+#define AO_BUTTON_ARM_1 1
+
+#define AO_BUTTON_ARM_NUM 2
+
+#define AO_BUTTON_2_PORT &stm_gpioa
+#define AO_BUTTON_2 2
+
+#define AO_BUTTON_FIRE 2
+
+#endif /* _AO_PINS_H_ */
--- /dev/null
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_exti.h>
+#include <ao_packet.h>
+#include <ao_companion.h>
+#include <ao_profile.h>
+#include <ao_pyro.h>
+#include <ao_aes.h>
+#include <ao_button.h>
+#include <ao_lco.h>
+#include <ao_lco_cmd.h>
+#include <ao_radio_cmac_cmd.h>
+#include <ao_eeprom.h>
+
+int
+main(void)
+{
+ ao_clock_init();
+
+ ao_led_init(LEDS_AVAILABLE);
+ ao_led_on(AO_LED_GREEN);
+ ao_beep_init();
+ ao_task_init();
+
+ ao_timer_init();
+
+ ao_spi_init();
+ ao_dma_init();
+ ao_exti_init();
+
+ ao_cmd_init();
+
+ ao_button_init();
+
+ ao_eeprom_init();
+
+ ao_radio_init();
+
+ ao_usb_init();
+
+ ao_config_init();
+
+ ao_lco_init();
+ ao_lco_cmd_init();
+// ao_radio_cmac_cmd_init();
+
+ ao_start_scheduler();
+ return 0;
+}
--- /dev/null
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=telelcotwo-v0.1
+include $(TOPDIR)/stm/Makefile-flash.defs
--- /dev/null
+/*
+ * Copyright © 2013 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_PINS_H_
+#define _AO_PINS_H_
+
+/* External crystal at 8MHz */
+#define AO_HSE 8000000
+
+#include <ao_flash_stm_pins.h>
+
+/* Fire switch. Press at power on to get boot loader */
+
+#define AO_BOOT_PIN 1
+#define AO_BOOT_APPLICATION_GPIO stm_gpioa
+#define AO_BOOT_APPLICATION_PIN 2
+#define AO_BOOT_APPLICATION_VALUE 1
+#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP
+
+#endif /* _AO_PINS_H_ */
*/
#define HAS_MMA655X 1
+#define AO_MMA655X_INVERT 0
#define AO_MMA655X_SPI_INDEX AO_SPI_1_PE13_PE14_PE15
#define AO_MMA655X_CS_PORT (&stm_gpiod)
#define AO_MMA655X_CS_PIN 4
*/
#define HAS_MMA655X 1
+#define AO_MMA655X_INVERT 0
#define AO_MMA655X_SPI_INDEX AO_SPI_1_PE13_PE14_PE15
#define AO_MMA655X_CS_PORT (&stm_gpiod)
#define AO_MMA655X_CS_PIN 4
*/
#define HAS_MMA655X 1
+#define AO_MMA655X_INVERT 0
#define AO_MMA655X_SPI_INDEX AO_SPI_1_PE13_PE14_PE15
#define AO_MMA655X_CS_PORT (&stm_gpiod)
#define AO_MMA655X_CS_PIN 4
--- /dev/null
+gnuplot -persist << EOF
+set ylabel "altitude (m)"
+set y2label "error"
+set xlabel "time (s)"
+set xtics border out nomirror
+set ytics border out nomirror
+set y2tics border out nomirror
+plot "$1" using 1:3 with lines axes x1y1 title "raw height",\
+"$1" using 1:21 with lines axes x1y2 title "error"
+EOF
import java.util.concurrent.*;
import java.util.*;
import java.text.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class TeleGPS
extends AltosUIFrame
import java.io.*;
import java.util.concurrent.*;
import java.text.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class TeleGPSConfig implements ActionListener {
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class TeleGPSConfigUI
extends AltosUIDialog
JLabel version_value;
JLabel serial_value;
AltosUIFreqList radio_frequency_value;
- JTextField radio_calibration_value;
+ JLabel radio_calibration_value;
JRadioButton radio_enable_value;
AltosUIRateList rate_value;
JComboBox<String> aprs_interval_value;
return product != null && product.startsWith("TeleGPS");
}
- void set_radio_calibration_tool_tip() {
- if (radio_calibration_value.isEnabled())
- radio_calibration_value.setToolTipText("Tune radio output to match desired frequency");
- else
- radio_calibration_value.setToolTipText("Cannot tune radio while connected over packet mode");
- }
-
void set_radio_enable_tool_tip() {
if (radio_enable_value.isEnabled())
radio_enable_value.setToolTipText("Enable/Disable telemetry and RDF transmissions");
c.anchor = GridBagConstraints.LINE_START;
c.insets = ir;
c.ipady = 5;
- radio_calibration_value = new JTextField(String.format("%d", 1186611));
- radio_calibration_value.getDocument().addDocumentListener(this);
+ radio_calibration_value = new JLabel(String.format("%d", 1186611));
pane.add(radio_calibration_value, c);
- set_radio_calibration_tool_tip();
row++;
/* Radio Enable */
}
}
- public int radio_calibration() throws AltosConfigDataException {
- return parse_int("radio calibration", radio_calibration_value.getText(), false);
- }
-
public void set_radio_enable(int new_radio_enable) {
if (new_radio_enable >= 0) {
radio_enable_value.setSelected(new_radio_enable > 0);
import javax.swing.*;
import java.io.*;
import java.text.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class TeleGPSDisplayThread extends Thread {
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class TeleGPSInfo extends AltosUIFlightTab {
import java.beans.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
public class TeleGPSPreferences
extends AltosUIConfigure
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class TeleGPSState extends AltosUIFlightTab {
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class TeleGPSStatus extends JComponent implements AltosFlightDisplay {
GridBagLayout layout;
package org.altusmetrum.telegps;
import java.awt.event.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class TeleGPSStatusUpdate implements ActionListener {