cd micropeak && $(MAKE) fat-install
endif
-fat:
- cd src && $(MAKE) all
- cd doc && $(MAKE) all
+fat: all-recursive
cd libaltos && $(MAKE) fat
cd altoslib && $(MAKE) all
- cd altosuilib && $(MAKE) all
cd icon && $(MAKE) fat
cd altosui && $(MAKE) fat
cd micropeak && $(MAKE) fat
fat_altos = \
src/easymega-v1.0/easymega-v1.0-$(VERSION).ihx \
src/easymega-v2.0/easymega-v2.0-$(VERSION).ihx \
+ src/easymega-v3.0/easymega-v3.0-$(VERSION).ihx \
src/easymini-v1.0/easymini-v1.0-$(VERSION).ihx \
src/easymini-v2.0/easymini-v2.0-$(VERSION).ihx \
src/easymini-v3.0/easymini-v3.0-$(VERSION).ihx \
src/easymotor-v3/easymotor-v3-$(VERSION).ihx \
src/easytimer-v1/easytimer-v1-$(VERSION).ihx \
+ src/easytimer-v2/easytimer-v2-$(VERSION).ihx \
src/telebt-v3.0/telebt-v3.0-$(VERSION).ihx \
src/telebt-v4.0/telebt-v4.0-$(VERSION).ihx \
src/teledongle-v3.0/teledongle-v3.0-$(VERSION).ihx \
src/telegps-v1.0/telegps-v1.0-$(VERSION).ihx \
src/telegps-v2.0/telegps-v2.0-$(VERSION).ihx \
+ src/telegps-v3.0/telegps-v3.0-$(VERSION).ihx \
+ src/telegps-v4.0/telegps-v4.0-$(VERSION).ihx \
src/telemega-v1.0/telemega-v1.0-$(VERSION).ihx \
src/telemega-v2.0/telemega-v2.0-$(VERSION).ihx \
src/telemega-v3.0/telemega-v3.0-$(VERSION).ihx \
src/telemega-v4.0/telemega-v4.0-$(VERSION).ihx \
src/telemega-v5.0/telemega-v5.0-$(VERSION).ihx \
src/telemega-v6.0/telemega-v6.0-$(VERSION).ihx \
+ src/telemega-v7.0/telemega-v7.0-$(VERSION).ihx \
src/telemetrum-v2.0/telemetrum-v2.0-$(VERSION).ihx \
src/telemetrum-v3.0/telemetrum-v3.0-$(VERSION).ihx \
src/telemetrum-v4.0/telemetrum-v4.0-$(VERSION).ihx \
Add the firmware to Releasing
+ Add new product specs to doc/specs.inc
+
These are Keith's notes on how to do a release
- update the version and date in configure.ac if Bdale hasn't already
installers for Windows and Mac OS X
sudo apt update
- sudo apt install genisoimage nsis \
+ sudo apt install genisoimage nsis gcc-avr avr-libc \
gcc-i686-linux-gnu gcc-aarch64-linux-gnu \
gcc-arm-linux-gnueabi gcc-arm-linux-gnueabihf \
gcc-mingw-w64-i686-posix gcc-mingw-w64-x86-64-win32
git commit -n debian/changelog -m "update changelog for Debian build"
+ - review debian/patches, all should be obsoleted by a new release, so
+ take care of any that are there and commit the changes
+
- if this is a -1 release, then
gbp buildpackage --git-no-pristine-tar \
--git-upstream-branch=branch-<version> \ # eg 1.3
- store a stable copy of ARM binaries for production use
cp src/chaoskey-v1.0/{*.elf,*.ihx,*.bin,*.map} \
- src/easymega-v[1-2].0/{*.elf,*.ihx,*.map} \
+ src/easymega-v[1-3].0/{*.elf,*.ihx,*.map} \
src/easymini-v[1-3].0/{*.elf,*.ihx,*.map} \
src/easymotor-v3/{*.elf,*.ihx,*.map} \
- src/easytimer-v1/{*.elf,*.ihx,*.map} \
+ src/easytimer-v[1-2]/{*.elf,*.ihx,*.map} \
src/telebt-v[3-4].0/{*.elf,*.ihx,*.map} \
src/teledongle-v3.0/{*.elf,*.ihx,*.map} \
- src/telegps-v[1-3].0/{*.elf,*.ihx,*.map} \
- src/telemega-v[1-6].0/{*.elf,*.ihx,*.map} \
+ src/telegps-v[1-4].0/{*.elf,*.ihx,*.map} \
+ src/telemega-v[1-7].0/{*.elf,*.ihx,*.map} \
src/telemetrum-v[2-4].0/{*.elf,*.ihx,*.map} \
src/telemini-v3.0/{*.elf,*.ihx,*.map} \
- src/telelco-v2.0/{*.elf,*.ihx,*.map} \
+ src/telelco-v[2-3].0/{*.elf,*.ihx,*.map} \
src/telefireeight-v[1-2].0/{*.elf,*.ihx,*.map} \
~/altusmetrumllc/Binaries/
cp src/chaoskey-v1.0/flash-loader/{*.elf,*.bin,*.map} \
- src/easymega-v[1-2].0/flash-loader/*.elf \
+ src/easymega-v[1-3].0/flash-loader/*.elf \
src/easymini-v[1-3].0/flash-loader/*.elf \
src/easymotor-v3/flash-loader/*.elf \
- src/easytimer-v1/flash-loader/*.elf \
+ src/easytimer-v[1-2]/flash-loader/*.elf \
src/telebt-v[3-4].0/flash-loader/{*.elf,*.bin,*.map} \
src/teledongle-v3.0/flash-loader/*.elf \
- src/telegps-v[1-3].0/flash-loader/{*.elf,*.bin,*.map} \
- src/telemega-v[1-6].0/flash-loader/*.elf \
+ src/telegps-v[1-4].0/flash-loader/{*.elf,*.bin,*.map} \
+ src/telemega-v[1-7].0/flash-loader/*.elf \
src/telemetrum-v[2-4].0/flash-loader/*.elf \
src/telemini-v3.0/flash-loader/{*.elf,*.bin,*.map} \
- src/telelco-v2.0/flash-loader/*.elf \
+ src/telelco-v[2-3].0/flash-loader/*.elf \
src/telefireeight-v[1-2].0/flash-loader/*.elf \
~/altusmetrumllc/Binaries/loaders/
(cd ~/altusmetrumllc ; git add Binaries ; git commit -a)
switch (telemetry_state.connect) {
case TelemetryState.CONNECT_CONNECTED:
if (telemetry_state.config != null) {
- String str = String.format("S/N %d %6.3f MHz%s", telemetry_state.config.serial,
+ String str = String.format(Locale.getDefault(), "S/N %d %6.3f MHz%s", telemetry_state.config.serial,
telemetry_state.frequency, telemetry_state.idle_mode ? " (idle)" : "");
if (telemetry_state.telemetry_rate != AltosLib.ao_telemetry_rate_38400)
- str = str.concat(String.format(" %d bps",
+ str = str.concat(String.format(Locale.getDefault(), " %d bps",
AltosLib.ao_telemetry_rate_values[telemetry_state.telemetry_rate]));
setTitle(str);
} else {
break;
case TelemetryState.CONNECT_CONNECTING:
if (telemetry_state.address != null)
- setTitle(String.format("Connecting to %s...", telemetry_state.address.name));
+ setTitle(String.format(Locale.getDefault(), "Connecting to %s...", telemetry_state.address.name));
else
setTitle("Connecting to something...");
break;
static String age_string(int age) {
String text;
if (age < 60)
- text = String.format("%ds", age);
+ text = String.format(Locale.getDefault(), "%ds", age);
else if (age < 60 * 60)
- text = String.format("%dm", age / 60);
+ text = String.format(Locale.getDefault(), "%dm", age / 60);
else if (age < 60 * 60 * 24)
- text = String.format("%dh", age / (60 * 60));
+ text = String.format(Locale.getDefault(), "%dh", age / (60 * 60));
else
- text = String.format("%dd", age / (24 * 60 * 60));
+ text = String.format(Locale.getDefault(), "%dd", age / (24 * 60 * 60));
return text;
}
if (state.cal_data().serial == AltosLib.MISSING)
mSerialView.setText("");
else
- mSerialView.setText(String.format("%d", state.cal_data().serial));
+ mSerialView.setText(String.format(Locale.getDefault(), "%d", state.cal_data().serial));
}
if (saved_state == null || state.cal_data().flight != saved_state.flight) {
if (state.cal_data().flight == AltosLib.MISSING)
mFlightView.setText("");
else
- mFlightView.setText(String.format("%d", state.cal_data().flight));
+ mFlightView.setText(String.format(Locale.getDefault(), "%d", state.cal_data().flight));
}
if (saved_state == null || state.state() != saved_state.state) {
if (state.state() == AltosLib.ao_flight_stateless) {
if (state.rssi == AltosLib.MISSING)
mRSSIView.setText("");
else
- mRSSIView.setText(String.format("%d", state.rssi));
+ mRSSIView.setText(String.format(Locale.getDefault(), "%d", state.rssi));
}
saved_state = new SavedState(state);
}
}
int deg = (int) Math.floor(p);
double min = (p - Math.floor(p)) * 60.0;
- return String.format("%d° %7.4f\" %s", deg, min, h);
+ return String.format(Locale.getDefault(), "%d° %7.4f\" %s", deg, min, h);
}
static String number(String format, double value) {
if (value == AltosLib.MISSING)
return "";
- return String.format(format, value);
+ return String.format(Locale.getDefault(), format, value);
}
static String integer(String format, int value) {
if (value == AltosLib.MISSING)
return "";
- return String.format(format, value);
+ return String.format(Locale.getDefault(), format, value);
}
private View create_tab_view(String label) {
try {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, this);
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
- } catch (Exception e) {
+ } catch (SecurityException e) {
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 1, this);
location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
}
else if (iheading < -179 || 179 < iheading)
return "backwards";
else if (iheading < 0)
- return String.format("left %d°", -iheading);
+ return String.format(Locale.getDefault(), "left %d°", -iheading);
else
- return String.format("right %d°", iheading);
+ return String.format(Locale.getDefault(), "right %d°", iheading);
}
public void onLocationChanged(Location location) {
public final static String NAME = "org.altusmetrum.AltosDroid";
private Context context = null;
private SharedPreferences prefs = null;
- private SharedPreferences.Editor editor = null;
public AltosDroidPreferencesBackend(Context in_context) {
this(in_context, NAME);
public AltosDroidPreferencesBackend(Context in_context, String in_prefs) {
context = in_context;
prefs = context.getSharedPreferences(in_prefs, 0);
- editor = prefs.edit();
}
public String[] keys() {
}
public void putBoolean(String key, boolean value) {
+ SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean(key, value);
+ editor.apply();
}
public void putDouble(String key, double value) {
+ SharedPreferences.Editor editor = prefs.edit();
editor.putFloat(key, (float)value);
+ editor.apply();
}
public void putInt(String key, int value) {
+ SharedPreferences.Editor editor = prefs.edit();
editor.putInt(key, value);
+ editor.apply();
}
public void putString(String key, String value) {
+ SharedPreferences.Editor editor = prefs.edit();
// AltosDebug.debug("AltosDroidPreferencesBackend put string %s:\n", key);
// String[] lines = value.split("\n");
// for (String l : lines)
// AltosDebug.debug(" %s\n", l);
editor.putString(key, value);
+ editor.apply();
}
public void putBytes(String key, byte[] bytes) {
+ SharedPreferences.Editor editor = prefs.edit();
String save = Base64.encodeToString(bytes, Base64.DEFAULT);
editor.putString(key, save);
+ editor.apply();
}
public void remove(String key) {
+ SharedPreferences.Editor editor = prefs.edit();
AltosDebug.debug("remove preference %s\n", key);
editor.remove(key);
+ editor.apply();
}
public void flush() {
- editor.apply();
}
public File homeDirectory() {
Rocket(int serial, AltosMapOffline map_offline) {
this.serial = serial;
- this.name = String.format("%d", serial);
+ this.name = String.format(Locale.ROOT, "%d", serial);
this.map_offline = map_offline;
}
}
RocketOnline(Context context, int serial, GoogleMap map, double lat, double lon, long last_packet) {
this.serial = serial;
- String name = String.format("%d", serial);
+ String name = String.format(Locale.ROOT, "%d", serial);
this.marker = map.addMarker(new MarkerOptions()
.icon(BitmapDescriptorFactory.fromBitmap(rocket_bitmap(context, name)))
.position(new LatLng(lat, lon))
void
position_permission() {
- if (mMap != null)
- mMap.setMyLocationEnabled(true);
+ if (mMap != null) {
+ try {
+ mMap.setMyLocationEnabled(true);
+ } catch (SecurityException e) {
+ }
+ }
}
@Override
if (mMap != null) {
map_type_changed(map_type);
if (altos_droid.have_location_permission)
- mMap.setMyLocationEnabled(true);
+ position_permission();
else
altos_droid.tell_map_permission(this);
mMap.getUiSettings().setTiltGesturesEnabled(false);
package org.altusmetrum.AltosDroid;
+import java.util.*;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
import android.location.Location;
}
public synchronized void speak(String format, Object ... arguments) {
- speak(String.format(format, arguments));
+ speak(String.format(Locale.getDefault(), format, arguments));
}
public synchronized boolean is_speaking() {
String direction = AltosDroid.direction(from_receiver, receiver);
if (direction == null)
- direction = String.format("Bearing %d", (int) (from_receiver.bearing + 0.5));
+ direction = String.format(Locale.getDefault(), "Bearing %d", (int) (from_receiver.bearing + 0.5));
speak("%s, distance %s.", direction,
AltosConvert.distance.say_units(from_receiver.distance));
package org.altusmetrum.AltosDroid;
+import java.util.*;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
frequency = getIntent().getDoubleExtra(AltosDroid.EXTRA_FREQUENCY, 0.0);
frequencyView = (TextView) findViewById(R.id.frequency);
- frequencyView.setText(String.format("Frequency: %7.3f MHz", frequency));
+ frequencyView.setText(String.format(Locale.getDefault(), "Frequency: %7.3f MHz", frequency));
connect = (Button) findViewById(R.id.connect_idle);
connect.setOnClickListener(new OnClickListener() {
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);
+ String name = String.format(Locale.getDefault(), "%d", extra);
+ String pretty = String.format(Locale.getDefault(), "%c", 'A' + extra);
if (!set_igniter(status, name, pretty))
break;
}
}
private void arm_set_text() {
- String text = String.format("Armed %d", arm_remaining);
+ String text = String.format(Locale.getDefault(), "Armed %d", arm_remaining);
if (arm.isChecked())
arm.setText(text);
if (selected_item != null)
known_sites_spinner.setSelection(known_sites_adapter.getPosition(selected_item));
else {
- latitude.setText(new StringBuffer(String.format("%12.6f", current_location_site.latitude)));
- longitude.setText(new StringBuffer(String.format("%12.6f", current_location_site.longitude)));
+ latitude.setText(new StringBuffer(String.format(Locale.getDefault(), "%12.6f", current_location_site.latitude)));
+ longitude.setText(new StringBuffer(String.format(Locale.getDefault(), "%12.6f", current_location_site.longitude)));
}
} else {
current_location_site.latitude = location.getLatitude();
class SiteListListener implements OnItemSelectedListener {
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
AltosLaunchSite site = (AltosLaunchSite) parent.getItemAtPosition(pos);
- latitude.setText(new StringBuffer(String.format("%12.6f", site.latitude)));
- longitude.setText(new StringBuffer(String.format("%12.6f", site.longitude)));
+ latitude.setText(new StringBuffer(String.format(Locale.getDefault(), "%12.6f", site.latitude)));
+ longitude.setText(new StringBuffer(String.format(Locale.getDefault(), "%12.6f", site.longitude)));
}
public void onNothingSelected(AdapterView<?> parent) {
}
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
try {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, this);
- } catch (Exception e) {
- locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 1, this);
+ } catch (SecurityException e) {
+ try {
+ locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 1, this);
+ } catch (SecurityException se) {
+ }
}
new AltosLaunchSites(this);
if (tracker.serial == 0)
((TextView) row.findViewById(R.id.serial_view)).setText("");
else
- ((TextView) row.findViewById(R.id.serial_view)).setText(String.format("%d", tracker.serial));
+ ((TextView) row.findViewById(R.id.serial_view)).setText(String.format(Locale.getDefault(), "%d", tracker.serial));
if (tracker.frequency == 0.0)
((TextView) row.findViewById(R.id.frequency_view)).setText("");
else if (tracker.frequency == AltosLib.MISSING)
((TextView) row.findViewById(R.id.frequency_view)).setText("");
else
- ((TextView) row.findViewById(R.id.frequency_view)).setText(String.format("%7.3f", tracker.frequency));
+ ((TextView) row.findViewById(R.id.frequency_view)).setText(String.format(Locale.getDefault(), "%7.3f", tracker.frequency));
if (tracker.received_time != 0) {
int age = (int) ((start_time - tracker.received_time + 500) / 1000);
((TextView) row.findViewById(R.id.age_view)).setText(AltosDroid.age_string(age));
package org.altusmetrum.AltosDroid;
+import java.util.*;
+
import org.altusmetrum.altoslib_14.*;
import android.app.Activity;
mBearingView.setText(direction);
} else {
mBearingLabel.setText("Bearing");
- mBearingView.setText(String.format("%3.0f°", from_receiver.bearing));
+ mBearingView.setText(String.format(Locale.getDefault(), "%3.0f°", from_receiver.bearing));
}
set_value(mDistanceView, AltosConvert.distance, 6, from_receiver.distance);
} else {
package org.altusmetrum.AltosDroid;
+import java.util.*;
+
import org.altusmetrum.altoslib_14.*;
import android.os.Bundle;
if (state.gps != null) {
int soln = state.gps.nsat;
int nsat = state.gps.cc_gps_sat != null ? state.gps.cc_gps_sat.length : 0;
- gps_locked_view.setText(String.format("%d in soln, %d in view", soln, nsat));
+ gps_locked_view.setText(String.format(Locale.getDefault(), "%d in soln, %d in view", soln, nsat));
gps_locked_lights.set(state.gps.locked && state.gps.nsat >= 4, false);
if (state.gps_ready)
gps_ready_view.setText("Ready");
package org.altusmetrum.AltosDroid;
+import java.util.*;
import org.altusmetrum.altoslib_14.*;
import android.os.Bundle;
public void show(TelemetryState telem_state, AltosState state, AltosGreatCircle from_receiver, Location receiver) {
if (from_receiver != null) {
- mBearingView.setText(String.format("%1.0f°", from_receiver.bearing));
+ mBearingView.setText(String.format(Locale.getDefault(), "%1.0f°", from_receiver.bearing));
set_value(mDistanceView, AltosConvert.distance, 1, from_receiver.distance);
String direction = AltosDroid.direction(from_receiver, receiver);
if (direction == null)
if (frequency == 0.0)
display = "Auto";
else if (frequency == AltosLib.MISSING) {
- display = String.format("%-8.8s %6d", call, serial);
+ display = String.format(Locale.getDefault(), "%-8.8s %6d", call, serial);
} else {
- display = String.format("%-8.8s %7.3f %6d", call, frequency, serial);
+ display = String.format(Locale.getDefault(), "%-8.8s %7.3f %6d", call, frequency, serial);
}
}
android:layout_weight="1"
android:hint="@string/frequency"
android:inputType="number|numberDecimal"/>
- />
<TextView
android:id="@+id/mhz"
android:layout_width="wrap_content"
public void set_tick(int tick) {
if (tick != AltosLib.MISSING) {
if (prev_tick != AltosLib.MISSING) {
- while (tick < prev_tick - 1000) {
+ while (tick < prev_tick - 32767) {
tick += 65536;
}
+ while (tick > prev_tick + 32767) {
+ tick -= 65536;
+ }
}
if (first_tick == AltosLib.MISSING)
first_tick = tick;
public int report_feet;
+ /* HAS_GPS_MOSAIC */
+ public int gps_receiver;
+
/* Storage info replies */
public int storage_size;
public int storage_erase_unit;
case AltosLib.AO_LOG_FORMAT_TELEMEGA_4:
case AltosLib.AO_LOG_FORMAT_TELEMEGA_5:
case AltosLib.AO_LOG_FORMAT_TELEMEGA_6:
+ case AltosLib.AO_LOG_FORMAT_TELEMEGA_7:
case AltosLib.AO_LOG_FORMAT_EASYMEGA_2:
case AltosLib.AO_LOG_FORMAT_EASYMEGA_3:
case AltosLib.AO_LOG_FORMAT_EASYMOTOR:
return false;
}
+ public boolean has_radio() {
+ return product.startsWith("Tele");
+ }
+
int[] parse_version(String v) {
String[] parts = v.split("\\.");
int r[] = new int[parts.length];
report_feet = AltosLib.MISSING;
+ gps_receiver = AltosLib.MISSING;
+
tracker_motion = AltosLib.MISSING;
tracker_interval = AltosLib.MISSING;
try { report_feet = get_int(line, "Report in feet:"); } catch (Exception e) {}
+ try { gps_receiver = get_int(line, "GPS receiver:"); } catch (Exception e) {}
+
/* HAS_TRACKER */
try {
int[] values = get_values(line, "Tracker setting:");
return true;
if (product.startsWith("TeleMega-v6"))
return true;
+ if (product.startsWith("TeleMega-v7"))
+ return true;
if (product.startsWith("EasyMotor-v2"))
return true;
if (product.startsWith("EasyMotor-v3"))
return AltosAdxl375.X_AXIS;
if (product.startsWith("TeleMega-v6"))
return AltosAdxl375.X_AXIS;
+ if (product.startsWith("TeleMega-v7"))
+ return AltosAdxl375.X_AXIS;
if (product.startsWith("EasyMotor-v2"))
return AltosAdxl375.X_AXIS;
if (product.startsWith("EasyMotor-v3"))
if (report_feet != AltosLib.MISSING)
report_feet = source.report_feet();
+ if (gps_receiver != AltosLib.MISSING)
+ gps_receiver = source.gps_receiver();
+
/* HAS_TRACKER */
if (tracker_motion != AltosLib.MISSING)
tracker_motion = source.tracker_motion();
dest.set_beep(beep);
dest.set_radio_10mw(radio_10mw);
dest.set_report_feet(report_feet);
+ dest.set_gps_receiver(gps_receiver);
dest.set_tracker_motion(tracker_motion);
dest.set_tracker_interval(tracker_interval);
}
if (radio_10mw != AltosLib.MISSING)
link.printf("c p %d\n", radio_10mw);
- /* HAS_RADIO_10MW */
if (report_feet != AltosLib.MISSING)
link.printf("c u %d\n", report_feet);
+ /* HAS_GPS_MOSAIC */
+ if (gps_receiver != AltosLib.MISSING)
+ link.printf("c g %d\n", gps_receiver);
+
/* HAS_TRACKER */
if (tracker_motion != AltosLib.MISSING && tracker_interval != AltosLib.MISSING)
link.printf("c t %d %d\n", tracker_motion, tracker_interval);
public abstract int report_feet() throws AltosConfigDataException;
- public abstract void set_report_feet(int radio_10mw);
+ public abstract void set_report_feet(int report_feet);
+
+ public abstract int gps_receiver() throws AltosConfigDataException;
+
+ public abstract void set_gps_receiver(int gps_receiver);
}
private static final double GRAVITATIONAL_ACCELERATION = -gravity;
private static final double AIR_GAS_CONSTANT = 287.053;
- private static final double NUMBER_OF_LAYERS = 7;
- private static final double MAXIMUM_ALTITUDE = 84852.0;
- private static final double MINIMUM_PRESSURE = 0.3734;
+ private static final double MAXIMUM_ALTITUDE = 100000.0;
+ private static final double MINIMUM_PRESSURE = 0.023439;
private static final double LAYER0_BASE_TEMPERATURE = 288.15;
private static final double LAYER0_BASE_PRESSURE = 101325;
/* lapse rate and base altitude for each layer in the atmosphere */
private static final double[] lapse_rate = {
- -0.0065, 0.0, 0.001, 0.0028, 0.0, -0.0028, -0.002
+ -0.0065, 0.0, 0.001, 0.0028, 0.0, -0.0028, -0.002, 0,
};
- private static final int[] base_altitude = {
- 0, 11000, 20000, 32000, 47000, 51000, 71000
+ private static final double[] base_altitude = {
+ 0, 11000, 20000, 32000, 47000, 51000, 71000, 84852,
};
+ private static final int NUMBER_OF_LAYERS = base_altitude.length;
/* outputs atmospheric pressure associated with the given altitude.
* altitudes are measured with respect to the mean sea level
*/
double next_base_pressure = LAYER0_BASE_PRESSURE;
double altitude;
- double base_pressure;
- double base_temperature;
+ double base_pressure = 0;
+ double base_temperature = 0;
double base; /* base for function to determine base pressure of next layer */
double exponent; /* exponent for function to determine base pressure
of next layer */
double coefficient;
int layer_number; /* identifies layer in the atmosphere */
- int delta_z; /* difference between two altitudes */
+ double delta_z; /* difference between two altitudes */
- if (pressure < 0) /* illegal pressure */
- return -1;
if (pressure < MINIMUM_PRESSURE) /* FIX ME: use sensor data to improve model */
- return MAXIMUM_ALTITUDE;
+ pressure = MINIMUM_PRESSURE;
/* calculate the base temperature and pressure for the atmospheric layer
associated with the inputted pressure. */
- layer_number = -1;
- do {
- layer_number++;
+ for (layer_number = 0; layer_number < NUMBER_OF_LAYERS - 1; layer_number++) {
base_pressure = next_base_pressure;
base_temperature = next_base_temperature;
delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number];
next_base_pressure *= Math.pow(base, exponent);
}
next_base_temperature += delta_z * lapse_rate[layer_number];
+ if (pressure >= next_base_pressure)
+ break;
}
- while(layer_number < NUMBER_OF_LAYERS - 1 && pressure < next_base_pressure);
/* calculate the altitude associated with the inputted pressure */
if (lapse_rate[layer_number] == 0.0) {
+ coefficient * (Math.pow(base, exponent) - 1);
}
+ if (altitude > MAXIMUM_ALTITUDE)
+ altitude = MAXIMUM_ALTITUDE;
+
return altitude;
}
return raw / 4095.0;
}
+ static double stm_adc(int raw) {
+ return raw / 4095.0;
+ }
+
+ static public double easy_timer_battery_voltage(int v_batt) {
+ if (v_batt != AltosLib.MISSING)
+ return 3.3 * stm_adc(v_batt) * (5.6 + 10.0) / 10.0;
+ return AltosLib.MISSING;
+ }
+
+ static double easy_timer_pyro_voltage_15v(int raw) {
+ if (raw != AltosLib.MISSING)
+ return 3.3 * stm_adc(raw) * (100.0 + 27.0) / 27.0;
+ return AltosLib.MISSING;
+ }
+
+ static public double metrum_battery_voltage(int v_batt) {
+ if (v_batt != AltosLib.MISSING)
+ return 3.3 * stm_adc(v_batt) * (5.6 + 10.0) / 10.0;
+ return AltosLib.MISSING;
+ }
+
+ static double metrum_pyro_voltage(int raw) {
+ if (raw != AltosLib.MISSING)
+ return 3.3 * stm_adc(raw) * (100.0 + 27.0) / 27.0;
+ return AltosLib.MISSING;
+ }
+
static public double mega_battery_voltage(int v_batt) {
if (v_batt != AltosLib.MISSING)
- return 3.3 * mega_adc(v_batt) * (5.6 + 10.0) / 10.0;
+ return 3.3 * stm_adc(v_batt) * (5.6 + 10.0) / 10.0;
return AltosLib.MISSING;
}
- static double mega_pyro_voltage(int raw) {
+ static double mega_pyro_voltage_15v(int raw) {
if (raw != AltosLib.MISSING)
- return 3.3 * mega_adc(raw) * (100.0 + 27.0) / 27.0;
+ return 3.3 * stm_adc(raw) * (100.0 + 27.0) / 27.0;
+ return AltosLib.MISSING;
+ }
+
+ static double mega_pyro_voltage_30v(int raw) {
+ if (raw != AltosLib.MISSING)
+ return 3.3 * stm_adc(raw) * (100.0 + 12.0) / 12.0;
return AltosLib.MISSING;
}
return sensor / 32767.0 * supply * (5.6 + 10.0) / 10.0;
}
+ /* STM32F042 */
+ static double tele_gps_4_voltage(int sensor) {
+ double supply = 3.3;
+
+ return sensor / 4095.0 * supply * (5.6 + 10.0) / 10.0;
+ }
+
static double tele_bt_3_battery(int raw) {
if (raw == AltosLib.MISSING)
return AltosLib.MISSING;
public static int beep_freq_to_value(double freq) {
if (freq == 0)
- return 94;
+ return 0;
return (int) Math.floor (1.0/2.0 * (24.0e6/32.0) / freq + 0.5);
}
return cal_data;
}
+ public AltosConfigData config_data() {
+ return null;
+ }
+
public void set_time(double time) {
if (time != AltosLib.MISSING)
this.time = time;
case AltosLib.AO_LOG_FORMAT_TELEMEGA_4:
case AltosLib.AO_LOG_FORMAT_TELEMEGA_5:
case AltosLib.AO_LOG_FORMAT_TELEMEGA_6:
+ case AltosLib.AO_LOG_FORMAT_TELEMEGA_7:
return data32(16);
case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
return data16(14);
case AltosLib.AO_LOG_FORMAT_TELEMEGA_4:
case AltosLib.AO_LOG_FORMAT_TELEMEGA_5:
case AltosLib.AO_LOG_FORMAT_TELEMEGA_6:
+ case AltosLib.AO_LOG_FORMAT_TELEMEGA_7:
return data32(20);
case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
return data16(16);
case AltosLib.AO_LOG_FORMAT_TELEMEGA_4:
case AltosLib.AO_LOG_FORMAT_TELEMEGA_5:
case AltosLib.AO_LOG_FORMAT_TELEMEGA_6:
+ case AltosLib.AO_LOG_FORMAT_TELEMEGA_7:
return data32(24);
case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
return data16(18);
case AltosLib.AO_LOG_FORMAT_TELEMEGA_5:
return AltosLib.model_mpu6000;
case AltosLib.AO_LOG_FORMAT_TELEMEGA_6:
+ case AltosLib.AO_LOG_FORMAT_TELEMEGA_7:
return AltosLib.model_bmi088;
}
return AltosLib.MISSING;
switch (log_format) {
case AltosLib.AO_LOG_FORMAT_TELEMEGA_5:
case AltosLib.AO_LOG_FORMAT_TELEMEGA_6:
+ case AltosLib.AO_LOG_FORMAT_TELEMEGA_7:
return true;
}
return false;
switch (log_format) {
case AltosLib.AO_LOG_FORMAT_TELEMEGA_5:
case AltosLib.AO_LOG_FORMAT_TELEMEGA_6:
+ case AltosLib.AO_LOG_FORMAT_TELEMEGA_7:
return AltosLib.model_mmc5983;
}
return AltosLib.MISSING;
private int sense(int i) { return data16(6 + i * 2); }
private int pyro() { return data16(26); }
+ private double pyro_voltage(int sense) {
+ switch (log_format) {
+ case AltosLib.AO_LOG_FORMAT_TELEMEGA_7:
+ return AltosConvert.mega_pyro_voltage_30v(sense);
+ default:
+ return AltosConvert.mega_pyro_voltage_15v(sense);
+ }
+ }
+
/* AO_LOG_GPS_TIME elements */
private int latitude() { return data32(0); }
private int longitude() { return data32(4); }
break;
case AltosLib.AO_LOG_TEMP_VOLT:
listener.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt()));
- listener.set_pyro_voltage(AltosConvert.mega_pyro_voltage(v_pbatt()));
+ listener.set_pyro_voltage(pyro_voltage(v_pbatt()));
int nsense = nsense();
- listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense(nsense-2)));
- listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sense(nsense-1)));
+ listener.set_apogee_voltage(pyro_voltage(sense(nsense-2)));
+ listener.set_main_voltage(pyro_voltage(sense(nsense-1)));
double voltages[] = new double[nsense-2];
for (int i = 0; i < nsense-2; i++)
- voltages[i] = AltosConvert.mega_pyro_voltage(sense(i));
+ voltages[i] = pyro_voltage(sense(i));
listener.set_igniter_voltage(voltages);
listener.set_pyro_fired(pyro());
listener.set_acceleration(cal_data.acceleration(accel()));
break;
case AltosLib.AO_LOG_TEMP_VOLT:
- listener.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt()));
- listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense_a()));
- listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sense_m()));
+ listener.set_battery_voltage(AltosConvert.metrum_battery_voltage(v_batt()));
+ listener.set_apogee_voltage(AltosConvert.metrum_pyro_voltage(sense_a()));
+ listener.set_main_voltage(AltosConvert.metrum_pyro_voltage(sense_m()));
break;
case AltosLib.AO_LOG_GPS_POS:
gps = listener.make_temp_gps(false);
case AltosLib.AO_LOG_FORMAT_TELEMEGA_5:
case AltosLib.AO_LOG_FORMAT_TELEMEGA_6:
case AltosLib.AO_LOG_FORMAT_EASYMEGA_3:
+ case AltosLib.AO_LOG_FORMAT_TELEMEGA_7:
record = new AltosEepromRecordMega(eeprom);
break;
case AltosLib.AO_LOG_FORMAT_TELEMETRUM:
} else {
while (t < tick - 32767)
t += 65536;
+ while (t > tick + 32767)
+ t -= 65536;
tick = t;
}
record.wide_tick = tick;
listener.set_acceleration(cal_data.acceleration(accel()));
- listener.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt()));
- listener.set_pyro_voltage(AltosConvert.mega_pyro_voltage(v_pbatt()));
+ listener.set_battery_voltage(AltosConvert.easy_timer_battery_voltage(v_batt()));
+ listener.set_pyro_voltage(AltosConvert.easy_timer_pyro_voltage_15v(v_pbatt()));
int nsense = nsense();
- listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense(nsense-2)));
- listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sense(nsense-1)));
+ listener.set_apogee_voltage(AltosConvert.easy_timer_pyro_voltage_15v(sense(nsense-2)));
+ listener.set_main_voltage(AltosConvert.easy_timer_pyro_voltage_15v(sense(nsense-1)));
double voltages[] = new double[nsense-2];
for (int i = 0; i < nsense-2; i++)
- voltages[i] = AltosConvert.mega_pyro_voltage(sense(i));
+ voltages[i] = AltosConvert.easy_timer_pyro_voltage_15v(sense(i));
listener.set_igniter_voltage(voltages);
listener.set_pyro_fired(pyro());
static final int idle_sensor_emini3 = 112;
static final int idle_sensor_etimer2 = 113;
static final int idle_sensor_emega3 = 114;
+ static final int idle_sensor_tgps4 = 115;
public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException, TimeoutException, AltosUnknownProduct {
for (int idler : idlers) {
case idle_sensor_tgps3:
AltosSensorTGPS3.provide_data(listener, link);
break;
+ case idle_sensor_tgps4:
+ AltosSensorTGPS4.provide_data(listener, link);
+ break;
case idle_sensor_tmini3:
AltosSensorTMini3.provide_data(listener, link);
break;
AltosIdler.idle_ms5607,
AltosIdler.idle_imu, AltosIdler.idle_mag,
AltosIdler.idle_sensor_mega),
+ new AltosIdler("TeleMega-v7",
+ AltosIdler.idle_gps,
+ AltosIdler.idle_adxl375,
+ AltosIdler.idle_ms5607,
+ AltosIdler.idle_imu, AltosIdler.idle_mag,
+ AltosIdler.idle_sensor_mega),
new AltosIdler("EasyMega-v1",
AltosIdler.idle_mma655x,
AltosIdler.idle_ms5607,
new AltosIdler("TeleGPS-v3",
AltosIdler.idle_gps,
AltosIdler.idle_sensor_tgps3),
+ new AltosIdler("TeleGPS-v4",
+ AltosIdler.idle_gps,
+ AltosIdler.idle_sensor_tgps4),
new AltosIdler("EasyTimer-v1",
AltosIdler.idle_imu_et_v1,
AltosIdler.idle_sensor_easytimer1),
public final static int product_basestation = 0x10000 + 1;
public final static int product_altimeter = 0x10000 + 2;
+ public final static int gps_builtin = 0;
+ public final static int gps_mosaic = 1;
+
+ public final static String[] gps_receiver_names = {
+ "Builtin", "Mosaic-X5"
+ };
+
private static class Product {
final String name;
final int product;
"Compressed", "Uncompressed"
};
+ public static final String[] ignite_mode_values = {
+ "Dual Deploy",
+ "Redundant Apogee",
+ "Redundant Main",
+ "Separation & Apogee",
+ };
+
+ public static final String[] pad_orientation_values_radio = {
+ "Antenna Up",
+ "Antenna Down",
+ };
+
+ public static final String[] pad_orientation_values_no_radio = {
+ "Beeper Up",
+ "Beeper Down",
+ };
+
+ public static String[] pad_orientation_values(boolean radio) {
+ if (radio)
+ return pad_orientation_values_radio;
+ else
+ return pad_orientation_values_no_radio;
+ }
+
public static final String launch_sites_url = "https://maps.altusmetrum.org/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_LOG_FORMAT_TELEMEGA_6 = 22;
public static final int AO_LOG_FORMAT_EASYTIMER_2 = 23;
public static final int AO_LOG_FORMAT_EASYMEGA_3 = 24;
+ public static final int AO_LOG_FORMAT_TELEMEGA_7 = 25;
public static final int AO_LOG_FORMAT_NONE = 127;
public static final int model_mpu6000 = 0;
return product_telemega;
case AO_LOG_FORMAT_TELEMEGA_6:
return product_telemega;
+ case AO_LOG_FORMAT_TELEMEGA_7:
+ return product_telemega;
case AO_LOG_FORMAT_NONE:
return product_altusmetrum;
default:
}
InputStream in = new BufferedInputStream(uc.getInputStream());
int bytesRead = 0;
- int offset = 0;
- data = new byte[contentLength];
- while (offset < contentLength) {
- bytesRead = in.read(data, offset, data.length - offset);
- if (bytesRead == -1)
- break;
- offset += bytesRead;
+ byte[] buffer = new byte[4096];
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ while ((bytesRead = in.read(buffer)) != -1) {
+ baos.write(buffer, 0, bytesRead);
}
in.close();
+ data = baos.toByteArray();
- if (offset == contentLength)
- status = AltosMapTile.fetched;
- else
- status = AltosMapTile.failed;
+ status = AltosMapTile.fetched;
} catch (IOException e) {
status = AltosMapTile.failed;
public interface AltosRecordSet {
public AltosCalData cal_data();
+ public AltosConfigData config_data();
public void capture_series(AltosDataListener listener);
public boolean valid();
}
import java.util.concurrent.TimeoutException;
class AltosSensorMega {
+ int log_format;
int tick;
int[] sense;
int v_batt;
public AltosSensorMega(AltosLink link) throws InterruptedException, TimeoutException {
this();
+ log_format = link.config_data().log_format;
String[] items = link.adc();
for (int i = 0; i < items.length;) {
if (items[i].equals("tick:")) {
}
}
+ double pyro_voltage(int sense) {
+ switch (log_format) {
+ case AltosLib.AO_LOG_FORMAT_TELEMEGA_7:
+ return AltosConvert.mega_pyro_voltage_30v(sense);
+ default:
+ return AltosConvert.mega_pyro_voltage_15v(sense);
+ }
+ }
+
+ double battery_voltage(int sense) {
+ return AltosConvert.mega_battery_voltage(sense);
+ }
+
static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException {
try {
AltosSensorMega sensor_mega = new AltosSensorMega(link);
- listener.set_battery_voltage(AltosConvert.mega_battery_voltage(sensor_mega.v_batt));
- listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sensor_mega.sense[4]));
- listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sensor_mega.sense[5]));
+ listener.set_battery_voltage(sensor_mega.battery_voltage(sensor_mega.v_batt));
+ listener.set_apogee_voltage(sensor_mega.pyro_voltage(sensor_mega.sense[4]));
+ listener.set_main_voltage(sensor_mega.pyro_voltage(sensor_mega.sense[5]));
double[] igniter_voltage = new double[4];
for (int i = 0; i < 4; i++)
- igniter_voltage[i] = AltosConvert.mega_pyro_voltage(sensor_mega.sense[i]);
+ igniter_voltage[i] = sensor_mega.pyro_voltage(sensor_mega.sense[i]);
listener.set_igniter_voltage(igniter_voltage);
} catch (TimeoutException te) {
static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException {
try {
AltosSensorMetrum sensor_metrum = new AltosSensorMetrum(link);
- listener.set_battery_voltage(AltosConvert.mega_battery_voltage(sensor_metrum.v_batt));
- listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sensor_metrum.sense_a));
- listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sensor_metrum.sense_m));
+ listener.set_battery_voltage(AltosConvert.metrum_battery_voltage(sensor_metrum.v_batt));
+ listener.set_apogee_voltage(AltosConvert.metrum_pyro_voltage(sensor_metrum.sense_a));
+ listener.set_main_voltage(AltosConvert.metrum_pyro_voltage(sensor_metrum.sense_m));
} catch (TimeoutException te) {
}
}
--- /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; 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.
+ */
+
+package org.altusmetrum.altoslib_14;
+
+import java.util.concurrent.TimeoutException;
+
+public class AltosSensorTGPS4 {
+ public int tick;
+ public int batt;
+
+ static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException {
+ try {
+ AltosSensorTGPS4 sensor_tgps = new AltosSensorTGPS4(link);
+
+ if (sensor_tgps == null)
+ return;
+ listener.set_battery_voltage(AltosConvert.tele_gps_4_voltage(sensor_tgps.batt));
+
+ } catch (TimeoutException te) {
+ }
+ }
+
+ public AltosSensorTGPS4(AltosLink link) throws InterruptedException, TimeoutException {
+ String[] items = link.adc();
+ for (int i = 0; i < items.length - 1;) {
+ if (items[i].equals("tick:")) {
+ tick = Integer.parseInt(items[i+1]);
+ i += 2;
+ continue;
+ }
+ if (items[i].equals("batt:")) {
+ batt = Integer.parseInt(items[i+1]);
+ i += 2;
+ continue;
+ }
+ i++;
+ }
+ }
+}
+
final static int packet_type_satellite = 0x06;
final static int packet_type_companion = 0x07;
final static int packet_type_mega_sensor_mpu = 0x08;
- final static int packet_type_mega_data = 0x09;
+ final static int packet_type_mega_data_15v = 0x09;
final static int packet_type_metrum_sensor = 0x0a;
final static int packet_type_metrum_data = 0x0b;
final static int packet_type_mini2 = 0x10;
final static int packet_type_mega_sensor_bmx160 = 0x12;
final static int packet_type_mega_norm_mpu6000_mmc5983 = 0x13;
final static int packet_type_mega_norm_bmi088_mmc5983 = 0x14;
+ final static int packet_type_mega_data_30v = 0x15;
static AltosTelemetry parse_hex(String hex) throws ParseException, AltosCRCException {
AltosTelemetry telem = null;
listener.finish();
}
+ public AltosConfigData config_data() {
+ return null;
+ }
+
public AltosTelemetryFile(FileInputStream input) throws IOException {
telems = new AltosTelemetryIterable(input);
}
super(bytes);
}
+ double pyro_voltage(int sense) {
+ switch (type()) {
+ case AltosTelemetry.packet_type_mega_data_30v:
+ return AltosConvert.mega_pyro_voltage_30v(sense);
+ default:
+ return AltosConvert.mega_pyro_voltage_15v(sense);
+ }
+ }
+
public void provide_data(AltosDataListener listener) {
super.provide_data(listener);
listener.set_state(state());
listener.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt()));
- listener.set_pyro_voltage(AltosConvert.mega_pyro_voltage(v_pyro()));
+ listener.set_pyro_voltage(pyro_voltage(v_pyro()));
- listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense(4)));
- listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sense(5)));
+ listener.set_apogee_voltage(pyro_voltage(sense(4)));
+ listener.set_main_voltage(pyro_voltage(sense(5)));
double voltages[] = new double[4];
for (int i = 0; i < 4; i++)
- voltages[i] = AltosConvert.mega_pyro_voltage(sense(i));
+ voltages[i] = pyro_voltage(sense(i));
listener.set_igniter_voltage(voltages);
listener.set_kalman(height_16(), speed()/16.0, acceleration()/16.0);
- listener.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt()));
+ listener.set_battery_voltage(AltosConvert.metrum_battery_voltage(v_batt()));
- listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense_a()));
- listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sense_m()));
+ listener.set_apogee_voltage(AltosConvert.metrum_pyro_voltage(sense_a()));
+ listener.set_main_voltage(AltosConvert.metrum_pyro_voltage(sense_m()));
}
}
case packet_type_mega_sensor_bmx160:
telem = new AltosTelemetryMegaSensor(bytes, AltosIMU.imu_type_telemega_v4);
break;
- case packet_type_mega_data:
+ case packet_type_mega_data_15v:
+ case packet_type_mega_data_30v:
telem = new AltosTelemetryMegaData(bytes);
break;
case packet_type_metrum_sensor:
AltosSensorTGPS1.java \
AltosSensorTGPS2.java \
AltosSensorTGPS3.java \
+ AltosSensorTGPS4.java \
AltosSensorEasyMotor2.java \
AltosState.java \
AltosStateName.java \
JLabel radio_enable_label;
JLabel radio_10mw_label;
JLabel report_feet_label;
+ JLabel gps_receiver_label;
JLabel rate_label;
JLabel aprs_interval_label;
JLabel aprs_ssid_label;
JRadioButton radio_enable_value;
JRadioButton radio_10mw_value;
JComboBox<String> report_feet_value;
+ JComboBox<String> gps_receiver_value;
AltosUIRateList rate_value;
JComboBox<String> aprs_interval_value;
JComboBox<Integer> aprs_ssid_value;
"0", "5", "10", "15", "20"
};
- static String[] ignite_mode_values = {
- "Dual Deploy",
- "Redundant Apogee",
- "Redundant Main",
- "Separation & Apogee",
- };
-
static String[] aprs_interval_values = {
"Disabled",
"2",
"4250",
};
- static String[] pad_orientation_values_radio = {
- "Antenna Up",
- "Antenna Down",
- };
-
- static String[] pad_orientation_values_no_radio = {
- "Beeper Up",
- "Beeper Down",
- };
-
String[] pad_orientation_values;
static String[] tracker_motion_values_m = {
}
void set_pad_orientation_values() {
- String [] new_values;
- if (has_radio())
- new_values = pad_orientation_values_radio;
- else
- new_values = pad_orientation_values_no_radio;
+ String [] new_values = AltosLib.pad_orientation_values(has_radio());
if (new_values != pad_orientation_values) {
int id = pad_orientation_value.getSelectedIndex();
pad_orientation_value.removeAllItems();
void set_beep_tool_tip() {
if (beep_value.isVisible())
- beep_value.setToolTipText("What frequency the beeper will sound at");
+ beep_value.setToolTipText("What frequency the beeper will sound at (0 for off)");
else
beep_value.setToolTipText("Older firmware could not select beeper frequency");
}
report_feet_value.setToolTipText("Older firmware always beeps max height in meters");
}
+ void set_gps_receiver_tool_tip() {
+ if (gps_receiver_value.isVisible())
+ gps_receiver_value.setToolTipText("GPS receiver selection");
+ else
+ gps_receiver_value.setToolTipText("Only TeleMega with new firmware supports alternate GPS receivers");
+ }
+
/* Build the UI using a grid bag */
public AltosConfigFCUI(JFrame in_owner, boolean remote) {
super (in_owner, title, false);
set_report_feet_tool_tip();
row++;
+ /* GPS Receiver */
+ c = new GridBagConstraints();
+ c.gridx = 0; c.gridy = row;
+ c.gridwidth = 4;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = il;
+ c.ipady = 5;
+ gps_receiver_label = new JLabel("GPS Receiver:");
+ pane.add(gps_receiver_label, c);
+
+ c = new GridBagConstraints();
+ c.gridx = 4; c.gridy = row;
+ c.gridwidth = 4;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.weightx = 1;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = ir;
+ c.ipady = 5;
+ gps_receiver_value = new JComboBox<String>(AltosLib.gps_receiver_names);
+ gps_receiver_value.setEditable(false);
+ gps_receiver_value.addItemListener(this);
+ pane.add(gps_receiver_value, c);
+ set_gps_receiver_tool_tip();
+ row++;
+
/* Telemetry Rate */
c = new GridBagConstraints();
c.gridx = 0; c.gridy = row;
c.anchor = GridBagConstraints.LINE_START;
c.insets = ir;
c.ipady = 5;
- ignite_mode_value = new JComboBox<String>(ignite_mode_values);
+ ignite_mode_value = new JComboBox<String>(AltosLib.ignite_mode_values);
ignite_mode_value.setEditable(false);
ignite_mode_value.addItemListener(this);
pane.add(ignite_mode_value, c);
c.anchor = GridBagConstraints.LINE_START;
c.insets = ir;
c.ipady = 5;
- pad_orientation_values = pad_orientation_values_no_radio;
+ pad_orientation_values = AltosLib.pad_orientation_values(false);
pad_orientation_value = new JComboBox<String>(pad_orientation_values);
pad_orientation_value.setEditable(false);
public void set_ignite_mode(int new_ignite_mode) {
if (new_ignite_mode != AltosLib.MISSING) {
- if (new_ignite_mode >= ignite_mode_values.length)
+ if (new_ignite_mode >= AltosLib.ignite_mode_values.length)
new_ignite_mode = 0;
if (new_ignite_mode < 0) {
ignite_mode_value.setEnabled(false);
return AltosLib.MISSING;
}
+ public void set_gps_receiver(int new_gps_receiver) {
+ System.out.printf("set_gps_receiver %d\n", new_gps_receiver);
+ if (new_gps_receiver != AltosLib.MISSING) {
+ if (new_gps_receiver >= AltosLib.gps_receiver_names.length)
+ new_gps_receiver = 0;
+ if (new_gps_receiver < 0) {
+ gps_receiver_value.setEnabled(false);
+ new_gps_receiver = 0;
+ } else {
+ gps_receiver_value.setEnabled(true);
+ }
+ gps_receiver_value.setSelectedIndex(new_gps_receiver);
+ }
+ gps_receiver_value.setVisible(new_gps_receiver != AltosLib.MISSING);
+ gps_receiver_label.setVisible(new_gps_receiver != AltosLib.MISSING);
+
+ set_gps_receiver_tool_tip();
+ }
+
+ public int gps_receiver() {
+ if (gps_receiver_value.isVisible())
+ return gps_receiver_value.getSelectedIndex();
+ else
+ return AltosLib.MISSING;
+ }
+
String[] tracker_motion_values() {
if (AltosConvert.imperial_units)
return tracker_motion_values_ft;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
-import org.jfree.ui.RefineryUtilities;
+import org.jfree.chart.ui.UIUtils;
public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, AltosUnitsListener, AltosFilterListener
{
AltosUIMap map;
AltosFlightStats stats;
AltosFlightStatsTable statsTable;
+ AltosFlightConfigTable configTable;
+ AltosFlightPyroTable pyroTable;
AltosGPS gps;
boolean has_gps;
map.font_size_changed(font_size);
if (statsTable != null)
statsTable.font_size_changed(font_size);
+ if (configTable != null)
+ configTable.font_size_changed(font_size);
+ if (pyroTable != null)
+ pyroTable.font_size_changed(font_size);
}
public void units_changed(boolean imperial_units) {
map.units_changed(imperial_units);
if (enable != null)
enable.units_changed(imperial_units);
+ if (configTable != null)
+ configTable.units_changed(imperial_units);
+ if (pyroTable != null)
+ pyroTable.units_changed(imperial_units);
}
AltosUIFlightSeries flight_series;
AltosGraphUI(AltosRecordSet set, File file) throws InterruptedException, IOException {
super(file.getName());
AltosCalData cal_data = set.cal_data();
-
+ AltosConfigData config_data = set.config_data();
pane = new JTabbedPane();
pane.add("Flight Graph", graph.panel);
pane.add("Configure Graph", enable);
pane.add("Flight Statistics", statsTable);
+ if (config_data != null) {
+ configTable = new AltosFlightConfigTable(config_data);
+ pane.add("Configuration", configTable);
+ if (config_data.npyro > 0 && config_data.npyro != AltosLib.MISSING) {
+ pyroTable = new AltosFlightPyroTable(config_data.pyros, config_data.npyro);
+ pane.add("Pyros", pyroTable);
+ }
+ }
has_gps = false;
fill_map(flight_series);
FIRMWARE_TMEGA_4_0=$(top_srcdir)/src/telemega-v4.0/telemega-v4.0-$(VERSION).ihx
FIRMWARE_TMEGA_5_0=$(top_srcdir)/src/telemega-v5.0/telemega-v5.0-$(VERSION).ihx
FIRMWARE_TMEGA_6_0=$(top_srcdir)/src/telemega-v6.0/telemega-v6.0-$(VERSION).ihx
-FIRMWARE_TMEGA=$(FIRMWARE_TMEGA_1_0) $(FIRMWARE_TMEGA_2_0) $(FIRMWARE_TMEGA_3_0) $(FIRMWARE_TMEGA_4_0) $(FIRMWARE_TMEGA_5_0) $(FIRMWARE_TMEGA_6_0)
+FIRMWARE_TMEGA_7_0=$(top_srcdir)/src/telemega-v7.0/telemega-v7.0-$(VERSION).ihx
+FIRMWARE_TMEGA=$(FIRMWARE_TMEGA_1_0) $(FIRMWARE_TMEGA_2_0) $(FIRMWARE_TMEGA_3_0) $(FIRMWARE_TMEGA_4_0) $(FIRMWARE_TMEGA_5_0) $(FIRMWARE_TMEGA_6_0) $(FIRMWARE_TMEGA_7_0)
FIRMWARE_EMINI_1_0=$(top_srcdir)/src/easymini-v1.0/easymini-v1.0-$(VERSION).ihx
FIRMWARE_EMINI_2_0=$(top_srcdir)/src/easymini-v2.0/easymini-v2.0-$(VERSION).ihx
FIRMWARE_EMEGA_1_0=$(top_srcdir)/src/easymega-v1.0/easymega-v1.0-$(VERSION).ihx
FIRMWARE_EMEGA_2_0=$(top_srcdir)/src/easymega-v2.0/easymega-v2.0-$(VERSION).ihx
-FIRMWARE_EMEGA=$(FIRMWARE_EMEGA_1_0) $(FIRMWARE_EMEGA_2_0)
+FIRMWARE_EMEGA_3_0=$(top_srcdir)/src/easymega-v3.0/easymega-v3.0-$(VERSION).ihx
+FIRMWARE_EMEGA=$(FIRMWARE_EMEGA_1_0) $(FIRMWARE_EMEGA_2_0) $(FIRMWARE_EMEGA_3_0)
FIRMWARE_EMOTOR_3=$(top_srcdir)/src/easymotor-v3/easymotor-v3-$(VERSION).ihx
FIRMWARE_EMOTOR=$(FIRMWARE_EMOTOR_3)
FIRMWARE_ETIMER_1=$(top_srcdir)/src/easytimer-v1/easytimer-v1-$(VERSION).ihx
-FIRMWARE_ETIMER=$(FIRMWARE_ETIMER_1)
+FIRMWARE_ETIMER_2=$(top_srcdir)/src/easytimer-v2/easytimer-v2-$(VERSION).ihx
+FIRMWARE_ETIMER=$(FIRMWARE_ETIMER_1) $(FIRMWARE_ETIMER_2)
FIRMWARE_TGPS_1_0=$(top_srcdir)/src/telegps-v1.0/telegps-v1.0-$(VERSION).ihx
FIRMWARE_TGPS_2_0=$(top_srcdir)/src/telegps-v2.0/telegps-v2.0-$(VERSION).ihx
FIRMWARE_TGPS_3_0=$(top_srcdir)/src/telegps-v3.0/telegps-v3.0-$(VERSION).ihx
-FIRMWARE_TGPS=$(FIRMWARE_TGPS_1_0) $(FIRMWARE_TGPS_2_0) $(FIRMWARE_TGPS_3_0)
+FIRMWARE_TGPS_4_0=$(top_srcdir)/src/telegps-v4.0/telegps-v4.0-$(VERSION).ihx
+FIRMWARE_TGPS=$(FIRMWARE_TGPS_1_0) $(FIRMWARE_TGPS_2_0) $(FIRMWARE_TGPS_3_0) $(FIRMWARE_TGPS_4_0)
FIRMWARE_TLCO_2_0=$(top_srcdir)/src/telelco-v2.0/telelco-v2.0-$(VERSION).ihx
FIRMWARE_TLCO=$(FIRMWARE_TLCO_2_0)
File "../src/telegps-v1.0/telegps-v1.0-${VERSION}.ihx"
File "../src/telegps-v2.0/telegps-v2.0-${VERSION}.ihx"
File "../src/telegps-v3.0/telegps-v3.0-${VERSION}.ihx"
+ File "../src/telegps-v4.0/telegps-v4.0-${VERSION}.ihx"
File "../src/teledongle-v3.0/teledongle-v3.0-${VERSION}.ihx"
File "../src/telebt-v3.0/telebt-v3.0-${VERSION}.ihx"
File "../src/telebt-v4.0/telebt-v4.0-${VERSION}.ihx"
File "../src/telemega-v4.0/telemega-v4.0-${VERSION}.ihx"
File "../src/telemega-v5.0/telemega-v5.0-${VERSION}.ihx"
File "../src/telemega-v6.0/telemega-v6.0-${VERSION}.ihx"
+ File "../src/telemega-v7.0/telemega-v7.0-${VERSION}.ihx"
File "../src/easymini-v1.0/easymini-v1.0-${VERSION}.ihx"
File "../src/easymini-v2.0/easymini-v2.0-${VERSION}.ihx"
File "../src/easymini-v3.0/easymini-v3.0-${VERSION}.ihx"
File "../src/easymega-v1.0/easymega-v1.0-${VERSION}.ihx"
File "../src/easymega-v2.0/easymega-v2.0-${VERSION}.ihx"
+ File "../src/easymega-v3.0/easymega-v3.0-${VERSION}.ihx"
File "../src/easymotor-v3/easymotor-v3-${VERSION}.ihx"
File "../src/easytimer-v1/easytimer-v1-${VERSION}.ihx"
+ File "../src/easytimer-v2/easytimer-v2-${VERSION}.ihx"
File "../src/telelco-v2.0/telelco-v2.0-${VERSION}.ihx"
File "../src/telefireeight-v1.0/telefireeight-v1.0-${VERSION}.ihx"
File "../src/telefireeight-v2.0/telefireeight-v2.0-${VERSION}.ihx"
--- /dev/null
+/*
+ * Copyright © 2024 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.
+ */
+
+package org.altusmetrum.altosuilib_14;
+
+import java.awt.*;
+import javax.swing.*;
+import java.util.*;
+import org.altusmetrum.altoslib_14.*;
+
+public class AltosFlightConfigTable extends JComponent
+ implements AltosFontListener, AltosUnitsListener
+{
+ GridBagLayout layout;
+
+ FlightConfig[] flight_configs;
+ AltosConfigData config_data;
+
+ class FlightConfig implements AltosFontListener {
+ JLabel label;
+ JLabel[] value;
+
+ public void font_size_changed(int font_size) {
+ label.setFont(AltosUILib.label_font);
+ for (int i = 0; i < value.length; i++)
+ value[i].setFont(AltosUILib.value_font);
+ }
+
+ public void set(String l, String[] values) {
+ label.setText(l);
+ for (int j = 0; j < values.length; j++)
+ value[j].setText(values[j]);
+ }
+
+ public FlightConfig(GridBagLayout layout, int y, String label_text, String ... values) {
+ GridBagConstraints c = new GridBagConstraints();
+ c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad);
+ c.weighty = 1;
+
+ label = new JLabel(label_text);
+ label.setFont(AltosUILib.label_font);
+ label.setHorizontalAlignment(SwingConstants.LEFT);
+ c.gridx = 0; c.gridy = y;
+ c.anchor = GridBagConstraints.WEST;
+ c.fill = GridBagConstraints.VERTICAL;
+ c.weightx = 0;
+ layout.setConstraints(label, c);
+ add(label);
+
+ value = new JLabel[values.length];
+ for (int j = 0; j < values.length; j++) {
+ value[j] = new JLabel(values[j]);
+ value[j].setFont(AltosUILib.value_font);
+ c.gridx = j+1; c.gridy = y;
+ c.anchor = GridBagConstraints.CENTER;
+ c.fill = GridBagConstraints.BOTH;
+ c.weightx = 1;
+ layout.setConstraints(value[j], c);
+ add(value[j]);
+ }
+ flight_configs[y] = this;
+ }
+
+ }
+
+ private FlightConfig set_config(int y, String label, String ... values) {
+ if (flight_configs[y] == null)
+ flight_configs[y] = new FlightConfig(layout, y, label, values);
+ else
+ flight_configs[y].set(label, values);
+ return flight_configs[y];
+ }
+
+ public void font_size_changed(int font_size) {
+ for (int y = 0; flight_configs[y] != null; y++)
+ flight_configs[y].font_size_changed(font_size);
+ }
+
+ private String main_deploy_label() {
+ return String.format("Main Deploy Altitude(%s)", AltosConvert.height.parse_units());
+ }
+
+ private String main_deploy_value() {
+ return String.format("%-6.1f", AltosConvert.height.value(config_data.main_deploy, AltosConvert.imperial_units));
+ }
+
+ public void set_config() {
+ int y = 0;
+ if (config_data.serial != AltosLib.MISSING) {
+ if (config_data.product != null && config_data.version != null)
+ set_config(y++, "Device",
+ config_data.product,
+ String.format("version %s", config_data.version),
+ String.format("serial %d", config_data.serial));
+ else
+ set_config(y++, "Serial", String.format("%d", config_data.serial));
+ }
+ if (config_data.flight != AltosLib.MISSING)
+ set_config(y++, "Flight", String.format("%d", config_data.flight));
+ if (config_data.main_deploy != AltosLib.MISSING)
+ set_config(y++, main_deploy_label(), main_deploy_value());
+ if (config_data.apogee_delay != AltosLib.MISSING)
+ set_config(y++, "Apogee Delay(s)", String.format("%d", config_data.apogee_delay));
+ if (config_data.apogee_lockout != AltosLib.MISSING)
+ set_config(y++, "Apogee Lockout(s)", String.format("%d", config_data.apogee_lockout));
+ if (config_data.radio_frequency != AltosLib.MISSING)
+ set_config(y++, "Radio Frequency (MHz)", String.format("%-7.3f", config_data.radio_frequency / 1000.0));
+ if (config_data.radio_calibration != AltosLib.MISSING)
+ set_config(y++, "Radio Calibration", String.format("%d", config_data.radio_calibration));
+ if (config_data.radio_enable != AltosLib.MISSING)
+ set_config(y++, "Radio Enable", String.format("%b", config_data.radio_enable != 0));
+ if (config_data.radio_10mw != AltosLib.MISSING)
+ set_config(y++, "Limit transmit to 10mW", String.format("%b", config_data.radio_10mw != 0));
+ if (config_data.report_feet != AltosLib.MISSING)
+ set_config(y++, "Beep max height in", config_data.report_feet == 0 ? "Meters" : "Feet");
+ if (config_data.gps_receiver != AltosLib.MISSING)
+ set_config(y++, "GPS Receiver", AltosLib.gps_receiver_names[config_data.gps_receiver]);
+ if (config_data.telemetry_rate != AltosLib.MISSING)
+ set_config(y++, "Telemetry baud rate", String.format("%d", AltosLib.ao_telemetry_rate_values[config_data.telemetry_rate]));
+ if (config_data.aprs_interval != AltosLib.MISSING)
+ set_config(y++, "APRS Interval(s)", String.format("%d", config_data.aprs_interval));
+ if (config_data.aprs_ssid != AltosLib.MISSING)
+ set_config(y++, "APRS SSID", String.format("%d", config_data.aprs_ssid));
+ if (config_data.aprs_format != AltosLib.MISSING)
+ set_config(y++, "APRS Format", AltosLib.ao_aprs_format_name[config_data.aprs_format]);
+ if (config_data.callsign != null)
+ set_config(y++, "Callsign", config_data.callsign);
+ if (config_data.flight_log_max != AltosLib.MISSING)
+ set_config(y++, "Maximum Flight Log Size(kB)", String.format("%d", config_data.flight_log_max));
+ if (config_data.ignite_mode != AltosLib.MISSING)
+ set_config(y++, "Igniter Firing Mode", AltosLib.ignite_mode_values[config_data.ignite_mode]);
+ if (config_data.pad_orientation != AltosLib.MISSING)
+ set_config(y++, "Pad Orientation", AltosLib.pad_orientation_values(config_data.has_radio())[config_data.pad_orientation]);
+ if (config_data.accel_cal_plus != AltosLib.MISSING)
+ set_config(y++, "Accel Calibration",
+ String.format("Plus %d", config_data.accel_cal_plus),
+ String.format("Minus %d", config_data.accel_cal_minus));
+ if (config_data.beep != AltosLib.MISSING)
+ set_config(y++, "Beeper(Hz)",
+ config_data.beep == 0 ? "Disabled" :
+ String.format("%-7.1f", AltosConvert.beep_value_to_freq(config_data.beep)));
+ if (config_data.tracker_motion != AltosLib.MISSING)
+ set_config(y++,
+ String.format("Logging Trigger Motion (%s):", AltosConvert.height.parse_units()),
+ String.format("%-6.1f",
+ AltosConvert.height.value(config_data.tracker_motion, AltosConvert.imperial_units)));
+ if (config_data.tracker_interval != AltosLib.MISSING)
+ set_config(y++, "Position Reporting Interval(s)",
+ String.format("%d", config_data.tracker_interval));
+ }
+
+ public void units_changed(boolean imperial_units) {
+ set_config();
+ }
+
+ public void tell_closing() {
+ AltosUIPreferences.unregister_font_listener(this);
+ }
+
+ public AltosFlightConfigTable() {
+ layout = new GridBagLayout();
+
+ setLayout(layout);
+
+ AltosUIPreferences.register_font_listener(this);
+ }
+
+ public AltosFlightConfigTable(AltosConfigData config_data) {
+ this();
+ this.config_data = config_data;
+ flight_configs = new FlightConfig[30];
+ set_config();
+ }
+}
--- /dev/null
+/*
+ * Copyright © 2024 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.
+ */
+
+package org.altusmetrum.altosuilib_14;
+
+import java.awt.*;
+import javax.swing.*;
+import java.util.*;
+import org.altusmetrum.altoslib_14.*;
+
+public class AltosFlightPyroTable extends JComponent
+ implements AltosFontListener, AltosUnitsListener
+{
+ GridBagLayout layout;
+ AltosPyro[] pyros;
+ int npyro;
+ FlightPyro[] flight_pyros;
+
+ class FlightPyro implements AltosFontListener {
+ JLabel label;
+ JTextField[] text_fields;
+
+ public void font_size_changed(int font_size) {
+ label.setFont(AltosUILib.label_font);
+ for (int i = 0; i < text_fields.length; i++)
+ text_fields[i].setFont(AltosUILib.value_font);
+ }
+
+ public void set_value(int y, int p, String value) {
+ GridBagConstraints c = new GridBagConstraints();
+ c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad);
+ c.weighty = 1;
+ JTextField text_field;
+
+ if (text_fields[p] == null) {
+ text_field = new JTextField(value);
+ text_field.setEditable(false);
+ text_field.setFont(AltosUILib.value_font);
+ text_field.setHorizontalAlignment(SwingConstants.RIGHT);
+ c.gridx = p+1; c.gridy = y;
+ c.anchor = GridBagConstraints.EAST;
+ c.fill = GridBagConstraints.BOTH;
+ c.weightx = 1;
+ layout.setConstraints(text_field, c);
+ add(text_field);
+ text_fields[p] = text_field;
+ } else {
+ text_fields[p].setText(value);
+ }
+ }
+
+ public void set_label(String text) {
+ label.setText(text);
+ }
+
+ public FlightPyro(GridBagLayout layout, int y, String label_text, int npyro) {
+ GridBagConstraints c = new GridBagConstraints();
+ c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad);
+ c.weighty = 1;
+
+ if (label_text != null) {
+ label = new JLabel(label_text);
+ label.setFont(AltosUILib.label_font);
+ label.setHorizontalAlignment(SwingConstants.LEFT);
+ c.gridx = 0; c.gridy = y;
+ c.anchor = GridBagConstraints.WEST;
+ c.fill = GridBagConstraints.VERTICAL;
+ c.weightx = 0;
+ layout.setConstraints(label, c);
+ add(label);
+ }
+
+ text_fields = new JTextField[npyro];
+ }
+ }
+
+ public void font_size_changed(int font_size) {
+ for (int i = 0; i < flight_pyros.length; i++)
+ flight_pyros[i].font_size_changed(font_size);
+ }
+
+ public void set_pyros() {
+ int nrow = 1;
+ for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1) {
+ if ((AltosPyro.pyro_all_useful & flag) != 0) {
+ for (int p = 0; p < npyro; p++) {
+ if ((pyros[p].flags & flag) != 0) {
+ String text;
+ double value = pyros[p].get_value(flag);
+ if ((flag & AltosPyro.pyro_state_value) != 0) {
+ text = AltosLib.state_name_capital((int) value);
+ } else {
+ double scale = AltosPyro.pyro_to_scale(flag);
+ double unit_value = value;
+ AltosUnits units = AltosPyro.pyro_to_units(flag);
+ if (units != null)
+ unit_value = units.parse_value(value);
+ String format;
+ if (scale >= 100)
+ format = "%6.2f";
+ else if (scale >= 10)
+ format = "%6.1f";
+ else
+ format = "%6.0f";
+ text = String.format(format, unit_value);
+ }
+ flight_pyros[nrow].set_value(nrow, p, text);
+ }
+ }
+ nrow++;
+ }
+ }
+ }
+
+ public void units_changed(boolean imperial_units) {
+ System.out.printf("units changed\n");
+ int nrow = 1;
+ for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1) {
+ if ((AltosPyro.pyro_all_useful & flag) != 0) {
+ String name = AltosPyro.pyro_to_name(flag);
+ flight_pyros[nrow].set_label(name);
+ }
+ }
+ set_pyros();
+ }
+
+ public void tell_closing() {
+ AltosUIPreferences.unregister_font_listener(this);
+ }
+
+ public AltosFlightPyroTable(AltosPyro[] pyros, int npyro) {
+ layout = new GridBagLayout();
+
+ int nrow = 0;
+
+ for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1) {
+ if ((AltosPyro.pyro_all_useful & flag) != 0) {
+ nrow++;
+ }
+ }
+
+ flight_pyros = new FlightPyro[nrow + 1];
+
+ nrow = 0;
+
+ flight_pyros[0] = new FlightPyro(layout, 0, null, npyro);
+
+ for (int p = 0; p < npyro; p++) {
+ flight_pyros[0].set_value(0, p, String.format("Channel %c", 'A' + p));
+ }
+ nrow++;
+ for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1) {
+ if ((AltosPyro.pyro_all_useful & flag) != 0) {
+ String name = AltosPyro.pyro_to_name(flag);
+ flight_pyros[nrow] = new FlightPyro(layout, nrow, name, npyro);
+ nrow++;
+ }
+ }
+
+
+ this.pyros = pyros;
+ this.npyro = npyro;
+
+ set_pyros();
+
+ setLayout(layout);
+ AltosUIPreferences.register_font_listener(this);
+ }
+}
import javax.swing.*;
import org.altusmetrum.altoslib_14.*;
-import org.jfree.ui.*;
+import org.jfree.chart.ui.*;
import org.jfree.chart.*;
import org.jfree.chart.plot.*;
import org.jfree.chart.axis.*;
import javax.swing.*;
import org.altusmetrum.altoslib_14.*;
-import org.jfree.ui.*;
+import org.jfree.chart.ui.*;
import org.jfree.chart.*;
import org.jfree.chart.plot.*;
import org.jfree.chart.axis.*;
import java.util.*;
import org.altusmetrum.altoslib_14.*;
-import org.jfree.ui.*;
+import org.jfree.chart.ui.*;
import org.jfree.chart.*;
import org.jfree.chart.plot.*;
import org.jfree.chart.axis.*;
import javax.swing.*;
import org.altusmetrum.altoslib_14.*;
-import org.jfree.ui.*;
+import org.jfree.chart.ui.*;
import org.jfree.chart.*;
import org.jfree.chart.plot.*;
import org.jfree.chart.axis.*;
import javax.swing.*;
import org.altusmetrum.altoslib_14.*;
-import org.jfree.ui.*;
+import org.jfree.chart.ui.*;
import org.jfree.chart.*;
import org.jfree.chart.plot.*;
import org.jfree.chart.axis.*;
chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT,
plot, true);
- ChartUtilities.applyCurrentTheme(chart);
+ ChartUtils.applyCurrentTheme(chart);
plot.setDomainGridlinePaint(gridline_color);
plot.setRangeGridlinePaint(gridline_color);
import javax.swing.*;
import org.altusmetrum.altoslib_14.*;
-import org.jfree.ui.*;
+import org.jfree.chart.ui.*;
import org.jfree.chart.*;
import org.jfree.chart.plot.*;
import org.jfree.chart.axis.*;
import javax.swing.*;
import org.altusmetrum.altoslib_14.*;
-import org.jfree.ui.*;
+import org.jfree.chart.ui.*;
import org.jfree.chart.*;
import org.jfree.chart.plot.*;
import org.jfree.chart.axis.*;
import javax.swing.*;
import org.altusmetrum.altoslib_14.*;
-import org.jfree.ui.*;
+import org.jfree.chart.ui.*;
import org.jfree.chart.*;
import org.jfree.chart.plot.*;
import org.jfree.chart.axis.*;
import javax.swing.*;
import org.altusmetrum.altoslib_14.*;
-import org.jfree.ui.*;
+import org.jfree.chart.ui.*;
import org.jfree.chart.*;
import org.jfree.chart.plot.*;
import org.jfree.chart.axis.*;
units.graph_units()),
new java.text.DecimalFormat(time_example),
new java.text.DecimalFormat(example));
- renderer.setBaseToolTipGenerator(ttg);
+ renderer.setSeriesToolTipGenerator(0, ttg);
}
set_data();
}
AltosFlashUI.java \
AltosRomconfigUI.java \
AltosInfoTable.java \
+ AltosFlightConfigTable.java \
AltosFlightInfoTableModel.java \
+ AltosFlightPyroTable.java \
AltosFlightStatsTable.java \
AltosBTDevice.java \
AltosBTDeviceIterator.java \
+++ /dev/null
-#!/bin/sh
-
-VERSION=2.0
-PRODUCT=EasyMega
-BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
-
-echo "$PRODUCT-v$VERSION Test Program"
-echo "Copyright 2018 by Bdale Garbee. Released under GPL v2"
-echo
-echo "Expectations:"
-echo "\t$PRODUCT v$VERSION powered from USB"
-echo
-
-ret=1
-ao-list | while read product serial dev; do
- case "$product" in
- "$PRODUCT-v$VERSION")
-
- echo "Testing $product $serial $dev"
- echo ""
-
- ./test-igniters $dev --rplus=100 --rminus=27 --adcmax=4095 main drogue 3 0 1 2
- echo""
-
- echo "Testing baro sensor"
- ../ao-tools/ao-test-baro/ao-test-baro --tty="$dev"
-
- case $? in
- 0)
- ;;
- *)
- echo "failed"
- exit 1
- esac
- echo""
-
- FLASHSIZE=8388608
-
- echo "Testing flash"
- ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE"
-
- case $? in
- 0)
- ;;
- *)
- echo "failed"
- exit 1
- esac
- echo""
-
- echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
- ret=0
- ;;
- esac
-done
--- /dev/null
+#!/bin/sh
+
+VERSION=2.0
+PRODUCT=EasyMega
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+
+echo "$PRODUCT-v$VERSION Test Program"
+echo "Copyright 2018 by Bdale Garbee. Released under GPL v2"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo
+
+ret=1
+ao-list | while read product serial dev; do
+ case "$product" in
+ "$PRODUCT-v$VERSION")
+
+ echo "Testing $product $serial $dev"
+ echo ""
+
+ ./test-igniters $dev --rplus=100 --rminus=27 --adcmax=4095 main drogue 3 0 1 2
+ echo""
+
+ echo "Testing baro sensor"
+ ../ao-tools/ao-test-baro/ao-test-baro --tty="$dev"
+
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "failed"
+ exit 1
+ esac
+ echo""
+
+ FLASHSIZE=8388608
+
+ echo "Testing flash"
+ ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE"
+
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "failed"
+ exit 1
+ esac
+ echo""
+
+ echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
+ ret=0
+ ;;
+ esac
+done
--- /dev/null
+#!/bin/sh
+
+VERSION=3.0
+PRODUCT=EasyMega
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+
+echo "$PRODUCT-v$VERSION Test Program"
+echo "Copyright 2024 by Bdale Garbee. Released under GPL v3"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo
+
+ret=1
+ao-list | while read product serial dev; do
+ case "$product" in
+ "$PRODUCT-v$VERSION")
+
+ echo "Testing $product $serial $dev"
+ echo ""
+
+ ./test-igniters $dev --rplus=100 --rminus=27 --adcmax=4095 main drogue 3 0 1 2
+ echo""
+
+ echo "Testing baro sensor"
+ ../ao-tools/ao-test-baro/ao-test-baro --tty="$dev"
+
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "failed"
+ exit 1
+ esac
+ echo""
+
+ FLASHSIZE=8388608
+
+ echo "Testing flash"
+ ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE"
+
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "failed"
+ exit 1
+ esac
+ echo""
+
+ echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
+ ret=0
+ ;;
+ esac
+done
--- /dev/null
+#!/bin/bash
+
+VERSION=2.0
+PRODUCT=EasyMini
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+
+echo "$PRODUCT-v$VERSION Test Program"
+echo "Copyright 2014 by Keith Packard. Released under GPL v2"
+echo
+echo "Expectations:"
+echo -e "\t$PRODUCT v$VERSION powered from USB"
+echo
+
+found=0
+while [ $found -eq 0 ]; do
+ (ao-list; echo END END END END) | while read product serial dev; do
+ case "$product" in
+ "$PRODUCT-v$VERSION")
+
+ found=1
+ echo -e '\e[34m'Testing $product $serial $dev'\e[39m'
+ echo ""
+
+ ./test-igniters "$dev" drogue main
+ echo ""
+
+ echo "Testing baro sensor"
+ ../ao-tools/ao-test-baro/ao-test-baro --tty="$dev"
+
+ if [ $? -ne 0 ]; then
+ echo -e '\e[31m'"$PRODUCT-$VERSION serial $serial failed"'\e[39m'
+ exit 1
+ fi
+ echo""
+
+ FLASHSIZE=1048576
+
+ echo "Testing flash"
+ ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE"
+
+ if [ $? -ne 0 ]; then
+ echo -e '\e[31m'"$PRODUCT-$VERSION serial $serial failed"'\e[39m'
+ exit 1
+ fi
+
+ echo ""
+
+ echo -e '\e[32m'"$PRODUCT-v$VERSION" serial "$serial" is ready to ship'\e[39m'
+ exit 0
+ ;;
+ END)
+ exit 2
+ ;;
+ esac
+ done
+ result=$?
+ if [ $result -ne 2 ]; then
+ exit $result
+ fi
+ echo 'No device, sleeping...'
+ sleep 1
+done
+++ /dev/null
-#!/bin/sh
-
-VERSION=1
-PRODUCT=EasyTimer
-BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
-
-echo "$PRODUCT-v$VERSION Test Program"
-echo "Copyright 2020 by Bdale Garbee. Released under GPL v3"
-echo
-echo "Expectations:"
-echo "\t$PRODUCT v$VERSION powered from USB"
-echo
-
-ret=1
-ao-list | while read product serial dev; do
- case "$product" in
- "$PRODUCT-v$VERSION")
-
- echo "Testing $product $serial $dev"
-
- ./test-igniters $dev 0 1
- echo""
-
- case $? in
- 0)
- ;;
- *)
- echo "failed"
- exit 1
- esac
- echo""
-
- echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
- echo "\007"
- ret=0
- ;;
- esac
-done
--- /dev/null
+#!/bin/sh
+
+VERSION=1
+PRODUCT=EasyTimer
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+
+echo "$PRODUCT-v$VERSION Test Program"
+echo "Copyright 2020 by Bdale Garbee. Released under GPL v3"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo
+
+ret=1
+ao-list | while read product serial dev; do
+ case "$product" in
+ "$PRODUCT-v$VERSION")
+
+ echo "Testing $product $serial $dev"
+
+ ./test-igniters $dev 0 1
+ echo""
+
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "failed"
+ exit 1
+ esac
+ echo""
+
+ echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
+ echo "\007"
+ ret=0
+ ;;
+ esac
+done
--- /dev/null
+#!/bin/sh
+
+VERSION=2
+PRODUCT=EasyTimer
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+
+echo "$PRODUCT-v$VERSION Test Program"
+echo "Copyright 2024 by Bdale Garbee. Released under GPL v3"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo
+
+ret=1
+ao-list | while read product serial dev; do
+ case "$product" in
+ "$PRODUCT-v$VERSION")
+
+ echo "Testing $product $serial $dev"
+
+ ./test-igniters $dev 0 1
+ echo""
+
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "failed"
+ exit 1
+ esac
+ echo""
+
+
+ FLASHSIZE=1048576
+
+ echo "Testing flash"
+ ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE"
+
+ if [ $? -ne 0 ]; then
+ echo -e '\e[31m'"$PRODUCT-$VERSION serial $serial failed"'\e[39m'
+ exit 1
+ fi
+ echo ""
+
+
+ echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
+ echo "\007"
+ ret=0
+ ;;
+ esac
+done
--- /dev/null
+#!/bin/sh
+
+VERSION=4.0
+PRODUCT=TeleGPS
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+
+echo "$PRODUCT-v$VERSION Test Program"
+echo "Copyright 2025 by Bdale Garbee. Released under GPL v3"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo
+
+ret=1
+ao-list | while read product serial dev; do
+ case "$product" in
+ "$PRODUCT-v$VERSION")
+
+ echo "Testing $product $serial $dev"
+
+ FLASHSIZE=2097152
+
+ echo "Testing flash"
+ ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE"
+
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "failed"
+ exit 1
+ esac
+
+ echo "Testing GPS"
+ ../ao-tools/ao-test-gps/ao-test-gps --tty="$dev"
+
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "failed"
+ exit 1
+ esac
+
+ echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
+ echo "\007"
+ ret=0
+ ;;
+ *)
+ echo "Skipping $product $serial $dev"
+ ;;
+ esac
+done
--- /dev/null
+#!/bin/sh
+
+VERSION=7.0
+PRODUCT=TeleMega
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+
+echo "$PRODUCT-v$VERSION Test Program"
+echo "Copyright 2025 by Bdale Garbee. Released under GPL v3"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo
+
+ret=1
+ao-list | while read product serial dev; do
+ case "$product" in
+ "$PRODUCT-v$VERSION")
+
+ echo "Testing $product $serial $dev"
+
+ ./test-igniters $dev --rplus=100 --rminus=12 --adcmax=4095 main drogue 3 0 1 2
+ echo""
+
+ echo "Testing baro sensor"
+ ../ao-tools/ao-test-baro/ao-test-baro --tty="$dev"
+
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "failed"
+ exit 1
+ esac
+ echo""
+
+ FLASHSIZE=8388608
+
+ echo "Testing flash"
+ ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE"
+
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "failed"
+ exit 1
+ esac
+ echo""
+
+ echo "Testing GPS"
+ ../ao-tools/ao-test-gps/ao-test-gps --tty="$dev"
+
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "failed"
+ exit 1
+ esac
+ echo""
+
+ echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
+ echo "\007"
+ ret=0
+ ;;
+ esac
+done
+++ /dev/null
-#!/bin/sh
-
-PRODUCT=EasyMega
-VERSION=2.0
-REPO=~/altusmetrumllc/Binaries
-
-if [ -x /usr/bin/ao-flash-stm ]; then
- FLASH_STM=/usr/bin/ao-flash-stm
-else
- echo "Can't find ao-flash-stm! 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
-
-echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
-echo "Copyright 2018 by Bdale Garbee. Released under GPL v2"
-echo
-echo "Expectations:"
-echo "\t$PRODUCT v$VERSION"
-echo "\t\twith USB cable attached"
-echo "\t\twith ST-Link-V2 cabled to debug header"
-echo
-
-case $# in
- 1)
- SERIAL="$1"
- echo "$PRODUCT-$VERSION serial number: $SERIAL"
- ;;
- 0)
- echo -n "$PRODUCT-$VERSION serial number: "
- read SERIAL
- ;;
- *)
- echo "Usage: $0 <serial-number>" 1>&2
- exit 1;
- ;;
-esac
-
-echo $FLASH_STM
-
-$FLASH_STM $REPO/loaders/easymega-v$VERSION*.elf
-
-sleep 3
-
-$USBLOAD --serial=$SERIAL $REPO/easymega-v$VERSION*.elf || exit 1
-
-sleep 5
-
-dev=`ao-list | awk '/'"$PRODUCT"'-v'"$VERSION"'/ { print $3; exit(0); }'`
-
-case "$dev" in
-/dev/tty*)
- echo "$PRODUCT found on $dev"
- ;;
-*)
- echo 'No '"$PRODUCT"'-v'"$VERSION"' found'
- exit 1
- ;;
-esac
-
-echo 'E 0' > $dev
-
-failed=1
-while [ $failed = 1 ]; do
- ../ao-tools/ao-cal-accel/ao-cal-accel $dev
- failed=$?
-done
-
-echo 'E 1' > $dev
-
-./test-easymega
-
-exit $?
--- /dev/null
+turnon_easymega_v3.0
\ No newline at end of file
--- /dev/null
+#!/bin/sh
+
+PRODUCT=EasyMega
+VERSION=2.0
+REPO=~/altusmetrumllc/Binaries
+
+if [ -x /usr/bin/ao-flash-stm ]; then
+ FLASH_STM=/usr/bin/ao-flash-stm
+else
+ echo "Can't find ao-flash-stm! 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
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2018 by Bdale Garbee. Released under GPL v2"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION"
+echo "\t\twith USB cable attached"
+echo "\t\twith ST-Link-V2 cabled to debug header"
+echo
+
+case $# in
+ 1)
+ SERIAL="$1"
+ echo "$PRODUCT-$VERSION serial number: $SERIAL"
+ ;;
+ 0)
+ echo -n "$PRODUCT-$VERSION serial number: "
+ read SERIAL
+ ;;
+ *)
+ echo "Usage: $0 <serial-number>" 1>&2
+ exit 1;
+ ;;
+esac
+
+echo $FLASH_STM
+
+$FLASH_STM $REPO/loaders/easymega-v$VERSION*.elf
+
+sleep 3
+
+$USBLOAD --serial=$SERIAL $REPO/easymega-v$VERSION*.elf || exit 1
+
+sleep 5
+
+dev=`ao-list | awk '/'"$PRODUCT"'-v'"$VERSION"'/ { print $3; exit(0); }'`
+
+case "$dev" in
+/dev/tty*)
+ echo "$PRODUCT found on $dev"
+ ;;
+*)
+ echo 'No '"$PRODUCT"'-v'"$VERSION"' found'
+ exit 1
+ ;;
+esac
+
+echo 'E 0' > $dev
+
+failed=1
+while [ $failed = 1 ]; do
+ ../ao-tools/ao-cal-accel/ao-cal-accel $dev
+ failed=$?
+done
+
+echo 'E 1' > $dev
+
+./test-easymega-v2.0
+
+exit $?
--- /dev/null
+#!/bin/sh
+
+PRODUCT=EasyMega
+VERSION=3.0
+REPO=~/altusmetrumllc/Binaries
+
+if [ -x /usr/bin/ao-usbload ]; then
+ USBLOAD=/usr/bin/ao-usbload
+else
+ echo "Can't find ao-usbload! Aborting."
+ exit 1
+fi
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2024 by Bdale Garbee. Released under GPL v3"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION"
+echo "\t\twith USB cable attached"
+echo
+
+case $# in
+ 1)
+ SERIAL="$1"
+ echo "$PRODUCT-$VERSION serial number: $SERIAL"
+ ;;
+ 0)
+ echo -n "$PRODUCT-$VERSION serial number: "
+ read SERIAL
+ ;;
+ *)
+ echo "Usage: $0 <serial-number>" 1>&2
+ exit 1;
+ ;;
+esac
+
+$USBLOAD --serial=$SERIAL $REPO/easymega-v$VERSION*.elf || exit 1
+
+sleep 5
+
+dev=`ao-list | awk '/'"$PRODUCT"'-v'"$VERSION"'/ { print $3; exit(0); }'`
+
+case "$dev" in
+/dev/tty*)
+ echo "$PRODUCT found on $dev"
+ ;;
+*)
+ echo 'No '"$PRODUCT"'-v'"$VERSION"' found'
+ exit 1
+ ;;
+esac
+
+echo 'E 0' > $dev
+
+failed=1
+while [ $failed = 1 ]; do
+ ../ao-tools/ao-cal-accel/ao-cal-accel $dev
+ failed=$?
+done
+
+echo 'E 1' > $dev
+
+./test-easymega-v3.0
+
+exit $?
+++ /dev/null
-#!/bin/sh
-
-if [ -x ../ao-tools/ao-flash/ao-flash-lpc ]; then
- FLASH_LPC=../ao-tools/ao-flash/ao-flash-lpc
-elif [ -x /usr/bin/ao-flash-lpc ]; then
- FLASH_LPC=/usr/bin/ao-flash-lpc
-else
- echo "Can't find ao-flash-lpc! Aborting."
- exit 1
-fi
-
-if [ -x ../ao-tools/ao-usbload/ao-usbload ]; then
- USBLOAD=../ao-tools/ao-usbload/ao-usbload
-elif [ -x /usr/bin/ao-usbload ]; then
- USBLOAD=/usr/bin/ao-usbload
-else
- echo "Can't find ao-usbload! Aborting."
- exit 1
-fi
-
-VERSION=3.0
-PRODUCT=EasyMini
-BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
-echo $FILE
-
-echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
-echo "Copyright 2022 by Bdale Garbee. Released under GPL v3"
-echo
-echo "Expectations:"
-echo "\t$PRODUCT v$VERSION powered from USB"
-echo "\t\twith ST-Link-V2 cabled to debug header"
-echo
-
-case $# in
- 1)
- SERIAL="$1"
- echo "$PRODUCT-$VERSION serial number: $SERIAL"
- ;;
- 0)
- echo -n "$PRODUCT-$VERSION serial number: "
- read SERIAL
- ;;
- *)
- echo "Usage: $0 <serial-number>" 1>&2
- exit 1;
- ;;
-esac
-
-#
-# Use released versions of everything
-#
-FLASH_FILE=~/altusmetrumllc/Binaries/loaders/easymini-v3.0-altos-flash-*.elf
-ALTOS_FILE=~/altusmetrumllc/Binaries/easymini-v3.0-*.elf
-
-echo $FLASH_LPC $FLASH_FILE
-
-$FLASH_LPC $FLASH_FILE || exit 1
-
-sleep 1
-
-echo $USBLOAD $ALTOS_FILE
-
-$USBLOAD --serial=$SERIAL $ALTOS_FILE || exit 1
-
-sleep 1
-
-./test-easymini-v3.0
-
-exit $?
--- /dev/null
+turnon_easymini_v2.0
\ No newline at end of file
--- /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 ../ao-tools/ao-usbload/ao-usbload ]; then
+ USBLOAD=../ao-tools/ao-usbload/ao-usbload
+elif [ -x /usr/bin/ao-usbload ]; then
+ USBLOAD=/usr/bin/ao-usbload
+else
+ echo "Can't find ao-usbload! Aborting."
+ exit 1
+fi
+
+VERSION=2.0
+PRODUCT=EasyMini
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+echo $FILE
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2024 by Bdale Garbee. Released under GPL v2+"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered and connected to USB"
+echo
+
+case $# in
+ 1)
+ SERIAL="$1"
+ echo "$PRODUCT-$VERSION serial number: $SERIAL"
+ ;;
+ 0)
+ echo -n "$PRODUCT-$VERSION serial number: "
+ read SERIAL
+ ;;
+ *)
+ echo "Usage: $0 <serial-number>" 1>&2
+ exit 1;
+ ;;
+esac
+
+#
+# Use released versions of everything
+#
+#FLASH_FILE=~/altusmetrumllc/Binaries/loaders/easymini-v2.0-altos-flash-*.bin
+ALTOS_FILE=~/altusmetrumllc/Binaries/easymini-v2.0-*.elf
+
+#FLASH_FILE=../src/$BASE-v$VERSION/flash-loader/$BASE-v$VERSION-altos-flash-*.elf
+#ALTOS_FILE=../src/$BASE-v$VERSION/*.ihx
+
+#echo $DFU_UTIL -a 0 -s 0x08000000:leave -D $FLASH_FILE
+
+#$DFU_UTIL -a 0 -s 0x08000000:leave -D $FLASH_FILE || exit 1
+
+#sleep 2
+
+echo $USBLOAD $ALTOS_FILE
+
+$USBLOAD --serial=$SERIAL $ALTOS_FILE || exit 1
+
+sleep 1
+
+./test-easymini-v2.0
+
+exit $?
--- /dev/null
+#!/bin/sh
+
+if [ -x ../ao-tools/ao-flash/ao-flash-lpc ]; then
+ FLASH_LPC=../ao-tools/ao-flash/ao-flash-lpc
+elif [ -x /usr/bin/ao-flash-lpc ]; then
+ FLASH_LPC=/usr/bin/ao-flash-lpc
+else
+ echo "Can't find ao-flash-lpc! Aborting."
+ exit 1
+fi
+
+if [ -x ../ao-tools/ao-usbload/ao-usbload ]; then
+ USBLOAD=../ao-tools/ao-usbload/ao-usbload
+elif [ -x /usr/bin/ao-usbload ]; then
+ USBLOAD=/usr/bin/ao-usbload
+else
+ echo "Can't find ao-usbload! Aborting."
+ exit 1
+fi
+
+VERSION=3.0
+PRODUCT=EasyMini
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+echo $FILE
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2022 by Bdale Garbee. Released under GPL v3"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo "\t\twith ST-Link-V2 cabled to debug header"
+echo
+
+case $# in
+ 1)
+ SERIAL="$1"
+ echo "$PRODUCT-$VERSION serial number: $SERIAL"
+ ;;
+ 0)
+ echo -n "$PRODUCT-$VERSION serial number: "
+ read SERIAL
+ ;;
+ *)
+ echo "Usage: $0 <serial-number>" 1>&2
+ exit 1;
+ ;;
+esac
+
+#
+# Use released versions of everything
+#
+FLASH_FILE=~/altusmetrumllc/Binaries/loaders/easymini-v3.0-altos-flash-*.elf
+ALTOS_FILE=~/altusmetrumllc/Binaries/easymini-v3.0-*.elf
+
+echo $FLASH_LPC $FLASH_FILE
+
+$FLASH_LPC $FLASH_FILE || exit 1
+
+sleep 1
+
+echo $USBLOAD $ALTOS_FILE
+
+$USBLOAD --serial=$SERIAL $ALTOS_FILE || exit 1
+
+sleep 1
+
+./test-easymini-v3.0
+
+exit $?
exit 1;
;;
esac
-otootor
#
# Use released versions of everything
#
#!/bin/sh
-if [ -x /usr/bin/ao-flash-stm ]; then
- FLASH_STM=/usr/bin/ao-flash-stm
-else
- echo "Can't find ao-flash-stm! Aborting."
- exit 1
-fi
+# EasyTimer v2 all arrive from the assembler with
+# the bootloader already flashed.
if [ -x /usr/bin/ao-usbload ]; then
USBLOAD=/usr/bin/ao-usbload
exit 1
fi
-VERSION=1
+VERSION=2
REPO=~/altusmetrumllc/Binaries
PRODUCT=EasyTimer
echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
-echo "Copyright 2020 by Bdale Garbee. Released under GPL v3"
+echo "Copyright 2024 by Bdale Garbee. Released under GPL v3"
echo
echo "Expectations:"
echo "\t$PRODUCT v$VERSION powered from USB"
-echo "\t\twith ST-Link-V2 cabled to debug header"
echo
case $# in
;;
esac
-echo $FLASH_STM
-
-$FLASH_STM $REPO/loaders/easytimer-v$VERSION*.elf
-
-sleep 3
-
$USBLOAD --serial=$SERIAL --force $REPO/easytimer-v$VERSION*.elf || exit 1
sleep 5
echo 'E 1' > $dev
-./test-easytimer
+./test-easytimer-v2
exit $?
--- /dev/null
+#!/bin/sh
+
+if [ -x /usr/bin/ao-flash-stm ]; then
+ FLASH_STM=/usr/bin/ao-flash-stm
+else
+ echo "Can't find ao-flash-stm! 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
+REPO=~/altusmetrumllc/Binaries
+PRODUCT=EasyTimer
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2020 by Bdale Garbee. Released under GPL v3"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo "\t\twith ST-Link-V2 cabled to debug header"
+echo
+
+case $# in
+ 1)
+ SERIAL="$1"
+ echo "$PRODUCT-$VERSION serial number: $SERIAL"
+ ;;
+ 0)
+ echo -n "$PRODUCT-$VERSION serial number: "
+ read SERIAL
+ ;;
+ *)
+ echo "Usage: $0 <serial-number>" 1>&2
+ exit 1;
+ ;;
+esac
+
+echo $FLASH_STM
+
+$FLASH_STM $REPO/loaders/easytimer-v$VERSION*.elf
+
+sleep 3
+
+$USBLOAD --serial=$SERIAL --force $REPO/easytimer-v$VERSION*.elf || exit 1
+
+sleep 5
+
+dev=`ao-list | awk '/EasyTimer-v'"$VERSION"'/ { print $3; exit(0); }'`
+
+case "$dev" in
+/dev/tty*)
+ echo "EasyTimer found on $dev"
+ ;;
+*)
+ echo 'No EasyTimer-v'"$VERSION"' found'
+ exit 1
+ ;;
+esac
+
+echo 'E 0' > $dev
+
+failed=1
+while [ $failed = 1 ]; do
+ ../ao-tools/ao-cal-accel/ao-cal-accel $dev
+ failed=$?
+done
+
+echo 'E 1' > $dev
+
+./test-easytimer
+
+exit $?
+++ /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=4.0
-REPO=~/altusmetrumllc/Binaries
-PRODUCT=TeleBT
-
-echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
-echo "Copyright 2017 by Bdale Garbee. Released under GPL v3+"
-echo
-echo "Expectations:"
-echo "\t$PRODUCT v$VERSION attached by USB"
-echo "\t\twith coax from UHF to frequency counter"
-echo
-
-case $# in
- 1)
- SERIAL="$1"
- echo "$PRODUCT-$VERSION serial number: $SERIAL"
- ;;
- 0)
- echo -n "$PRODUCT-$VERSION serial number: "
- read SERIAL
- ;;
- *)
- echo "Usage: $0 <serial-number>" 1>&2
- exit 1;
- ;;
-esac
-
-FLASH_FILE=$REPO/loaders/telebt-v$VERSION-altos-flash-*.bin
-ALTOS_FILE=$REPO/telebt-v$VERSION-*.elf
-
-$DFU_UTIL -a 0 -s 0x08000000:leave -D $FLASH_FILE
-
-sleep 2
-
-$USBLOAD --serial=$SERIAL $ALTOS_FILE || exit 1
-
-sleep 3
-
-dev=`ao-list | awk '/'"$PRODUCT"'-v'"$VERSION"'/ { print $3; exit(0); }'`
-
-case "$dev" in
-/dev/tty*)
- echo "$PRODUCT found on $dev"
- ;;
-*)
- echo 'No '"$PRODUCT"'-v'"$VERSION"' found'
- exit 1
- ;;
-esac
-
-CALFILE=cal-$SERIAL.txt
-
-../ao-tools/ao-cal-freq/ao-cal-freq --nosave --output=$CALFILE --tty=$dev
-
-CAL_VALUE=`cat $CALFILE`
-echo $SERIAL","$CAL_VALUE >> cal_values
-echo "Reflashing with calibration: $CAL_VALUE"
-$USBLOAD --cal=$CAL_VALUE --tty=$dev $ALTOS_FILE || exit 1
-
-echo -n "checking BlueTooth functionality... "
-btdev=`hcitool scan | awk -F \- '/TeleBT/ { print $2 }'`
-if [ "$btdev" = "$SERIAL" ]; then
- echo "working!"
-else
- echo "device not found"
- exit 1
-fi
-
-echo -n "checking BTLE functionality... "
-btdev=`sudo timeout -s SIGINT 5s hcitool lescan | awk -F \- '/TeleBT/ { print $2 }' | head -n 1`
-if [ "$btdev" = "$SERIAL" ]; then
- echo "working!"
-else
- echo "device not found"
- exit 1
-fi
-
-echo "$PRODUCT-v$VERSION $SERIAL is ready to ship"
-
-exit $?
--- /dev/null
+turnon_telebt_v4d
\ No newline at end of file
--- /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=4.0
+REPO=~/altusmetrumllc/Binaries
+PRODUCT=TeleBT
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2017 by Bdale Garbee. Released under GPL v3+"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION attached by USB"
+echo "\t\twith coax from UHF to frequency counter"
+echo
+
+case $# in
+ 1)
+ SERIAL="$1"
+ echo "$PRODUCT-$VERSION serial number: $SERIAL"
+ ;;
+ 0)
+ echo -n "$PRODUCT-$VERSION serial number: "
+ read SERIAL
+ ;;
+ *)
+ echo "Usage: $0 <serial-number>" 1>&2
+ exit 1;
+ ;;
+esac
+
+FLASH_FILE=$REPO/loaders/telebt-v$VERSION-altos-flash-*.bin
+ALTOS_FILE=$REPO/telebt-v$VERSION-*.elf
+
+$DFU_UTIL -a 0 -s 0x08000000:leave -D $FLASH_FILE
+
+sleep 2
+
+$USBLOAD --serial=$SERIAL $ALTOS_FILE || exit 1
+
+sleep 3
+
+dev=`ao-list | awk '/'"$PRODUCT"'-v'"$VERSION"'/ { print $3; exit(0); }'`
+
+case "$dev" in
+/dev/tty*)
+ echo "$PRODUCT found on $dev"
+ ;;
+*)
+ echo 'No '"$PRODUCT"'-v'"$VERSION"' found'
+ exit 1
+ ;;
+esac
+
+CALFILE=cal-$SERIAL.txt
+
+../ao-tools/ao-cal-freq/ao-cal-freq --nosave --output=$CALFILE --tty=$dev
+
+CAL_VALUE=`cat $CALFILE`
+echo $SERIAL","$CAL_VALUE >> cal_values
+echo "Reflashing with calibration: $CAL_VALUE"
+$USBLOAD --cal=$CAL_VALUE --tty=$dev $ALTOS_FILE || exit 1
+
+echo -n "checking BlueTooth functionality... "
+btdev=`hcitool scan | awk -F \- '/TeleBT/ { print $2 }'`
+if [ "$btdev" = "$SERIAL" ]; then
+ echo "working!"
+else
+ echo "device not found"
+ exit 1
+fi
+
+echo -n "checking BTLE functionality... "
+btdev=`sudo timeout -s SIGINT 5s hcitool lescan | awk -F \- '/TeleBT/ { print $2 }' | head -n 1`
+if [ "$btdev" = "$SERIAL" ]; then
+ echo "working!"
+else
+ echo "device not found"
+ exit 1
+fi
+
+echo "$PRODUCT-v$VERSION $SERIAL is ready to ship"
+
+exit $?
--- /dev/null
+#!/bin/sh
+#
+# the difference with v4.0d is that the bootloader should already
+# have been flashed at Seeed, so don't try to re-flash that part
+
+if [ -x /usr/bin/ao-usbload ]; then
+ USBLOAD=/usr/bin/ao-usbload
+else
+ echo "Can't find ao-usbload! Aborting."
+ exit 1
+fi
+
+VERSION=4.0
+REPO=~/altusmetrumllc/Binaries
+PRODUCT=TeleBT
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2025 by Bdale Garbee. Released under GPL v3"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION attached by USB"
+echo "\t\twith coax from UHF to frequency counter"
+echo
+
+case $# in
+ 1)
+ SERIAL="$1"
+ echo "$PRODUCT-$VERSION serial number: $SERIAL"
+ ;;
+ 0)
+ echo -n "$PRODUCT-$VERSION serial number: "
+ read SERIAL
+ ;;
+ *)
+ echo "Usage: $0 <serial-number>" 1>&2
+ exit 1;
+ ;;
+esac
+
+ALTOS_FILE=$REPO/telebt-v$VERSION-*.elf
+
+$USBLOAD --serial=$SERIAL $ALTOS_FILE || exit 1
+
+sleep 3
+
+dev=`ao-list | awk '/'"$PRODUCT"'-v'"$VERSION"'/ { print $3; exit(0); }'`
+
+case "$dev" in
+/dev/tty*)
+ echo "$PRODUCT found on $dev"
+ ;;
+*)
+ echo 'No '"$PRODUCT"'-v'"$VERSION"' found'
+ exit 1
+ ;;
+esac
+
+CALFILE=cal-$SERIAL.txt
+
+../ao-tools/ao-cal-freq/ao-cal-freq --nosave --output=$CALFILE --tty=$dev
+
+CAL_VALUE=`cat $CALFILE`
+echo $SERIAL","$CAL_VALUE >> cal_values
+echo "Reflashing with calibration: $CAL_VALUE"
+$USBLOAD --cal=$CAL_VALUE --tty=$dev $ALTOS_FILE || exit 1
+
+echo -n "checking BlueTooth functionality... "
+btdev=`hcitool scan | awk -F \- '/TeleBT/ { print $2 }'`
+if [ "$btdev" = "$SERIAL" ]; then
+ echo "working!"
+else
+ echo "device not found"
+ exit 1
+fi
+
+echo -n "checking BTLE functionality... "
+btdev=`sudo timeout -s SIGINT 5s hcitool lescan | awk -F \- '/TeleBT/ { print $2 }' | head -n 1`
+if [ "$btdev" = "$SERIAL" ]; then
+ echo "working!"
+else
+ echo "device not found"
+ exit 1
+fi
+
+echo "$PRODUCT-v$VERSION $SERIAL is ready to ship"
+
+exit $?
+++ /dev/null
-#!/bin/sh
-
-if [ -x ../ao-tools/ao-flash/ao-flash-lpc ]; then
- FLASH_LPC=../ao-tools/ao-flash/ao-flash-lpc
-elif [ -x /usr/bin/ao-flash-lpc ]; then
- FLASH_LPC=/usr/bin/ao-flash-lpc
-else
- echo "Can't find ao-flash-lpc! 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
-
-PRODUCT=TeleGPS
-VERSION=3.0
-BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
-echo $FILE
-
-echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
-echo "Copyright 2023 by Bdale Garbee. Released under GPL v3"
-echo
-echo "Expectations:"
-echo "\t$PRODUCT v$VERSION powered from USB"
-echo "\t\twith ST-Link-V2 cabled to debug header"
-echo
-
-case $# in
- 1)
- SERIAL="$1"
- echo "$PRODUCT-$VERSION serial number: $SERIAL"
- ;;
- 0)
- echo -n "$PRODUCT-$VERSION serial number: "
- read SERIAL
- ;;
- *)
- echo "Usage: $0 <serial-number>" 1>&2
- exit 1;
- ;;
-esac
-
-#
-# Use released versions of everything
-#
-FLASH_FILE=~/altusmetrumllc/Binaries/loaders/telegps-v3.0-altos-flash-*.elf
-ALTOS_FILE=~/altusmetrumllc/Binaries/telegps-v3.0-*.elf
-
-echo $FLASH_LPC $FLASH_FILE
-
-$FLASH_LPC $FLASH_FILE || exit 1
-
-sleep 1
-
-echo $USBLOAD $ALTOS_FILE
-
-$USBLOAD --serial=$SERIAL $ALTOS_FILE || exit 1
-
-sleep 1
-
-dev=`ao-list | awk '/TeleGPS-v'"$VERSION"'/ { print $3; exit(0); }'`
-
-case "$dev" in
-/dev/tty*)
- echo "TeleGPS found on $dev"
- ;;
-*)
- echo 'No TeleGPS-v'"$VERSION"' found'
- exit 1
- ;;
-esac
-
-CALFILE=cal-$SERIAL.txt
-../ao-tools/ao-cal-freq/ao-cal-freq --output=$CALFILE --tty=$dev
-CAL_VALUE=`cat $CALFILE`
-echo $SERIAL","$CAL_VALUE >> cal_values
-
-./test-telegps-v3
-
-exit $?
--- /dev/null
+turnon_telegps_v4
\ No newline at end of file
--- /dev/null
+#!/bin/sh
+
+if [ -x ../ao-tools/ao-flash/ao-flash-lpc ]; then
+ FLASH_LPC=../ao-tools/ao-flash/ao-flash-lpc
+elif [ -x /usr/bin/ao-flash-lpc ]; then
+ FLASH_LPC=/usr/bin/ao-flash-lpc
+else
+ echo "Can't find ao-flash-lpc! 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
+
+PRODUCT=TeleGPS
+VERSION=3.0
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+echo $FILE
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2023 by Bdale Garbee. Released under GPL v3"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo "\t\twith ST-Link-V2 cabled to debug header"
+echo
+
+case $# in
+ 1)
+ SERIAL="$1"
+ echo "$PRODUCT-$VERSION serial number: $SERIAL"
+ ;;
+ 0)
+ echo -n "$PRODUCT-$VERSION serial number: "
+ read SERIAL
+ ;;
+ *)
+ echo "Usage: $0 <serial-number>" 1>&2
+ exit 1;
+ ;;
+esac
+
+#
+# Use released versions of everything
+#
+FLASH_FILE=~/altusmetrumllc/Binaries/loaders/telegps-v3.0-altos-flash-*.elf
+ALTOS_FILE=~/altusmetrumllc/Binaries/telegps-v3.0-*.elf
+
+echo $FLASH_LPC $FLASH_FILE
+
+$FLASH_LPC $FLASH_FILE || exit 1
+
+sleep 1
+
+echo $USBLOAD $ALTOS_FILE
+
+$USBLOAD --serial=$SERIAL $ALTOS_FILE || exit 1
+
+sleep 1
+
+dev=`ao-list | awk '/TeleGPS-v'"$VERSION"'/ { print $3; exit(0); }'`
+
+case "$dev" in
+/dev/tty*)
+ echo "TeleGPS found on $dev"
+ ;;
+*)
+ echo 'No TeleGPS-v'"$VERSION"' found'
+ exit 1
+ ;;
+esac
+
+CALFILE=cal-$SERIAL.txt
+../ao-tools/ao-cal-freq/ao-cal-freq --output=$CALFILE --tty=$dev
+CAL_VALUE=`cat $CALFILE`
+echo $SERIAL","$CAL_VALUE >> cal_values
+
+./test-telegps-v3
+
+exit $?
--- /dev/null
+#!/bin/sh
+
+if [ -x /usr/bin/ao-usbload ]; then
+ USBLOAD=/usr/bin/ao-usbload
+else
+ echo "Can't find ao-usbload! Aborting."
+ exit 1
+fi
+
+VERSION=4.0
+REPO=~/altusmetrumllc/Binaries
+PRODUCT=TeleGPS
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2025 by Bdale Garbee. Released under GPL v3"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo "\t\twith coax from UHF to frequency counter"
+echo
+
+case $# in
+ 1)
+ SERIAL="$1"
+ echo "$PRODUCT-$VERSION serial number: $SERIAL"
+ ;;
+ 0)
+ echo -n "$PRODUCT-$VERSION serial number: "
+ read SERIAL
+ ;;
+ *)
+ echo "Usage: $0 <serial-number>" 1>&2
+ exit 1;
+ ;;
+esac
+
+#
+# Use released versions of everything
+#
+ALTOS_FILE=$REPO/telegps-v$VERSION-*.elf
+
+echo $USBLOAD $ALTOS_FILE
+
+$USBLOAD --serial=$SERIAL $ALTOS_FILE || exit 1
+
+sleep 1
+
+dev=`ao-list | awk '/TeleGPS-v'"$VERSION"'/ { print $3; exit(0); }'`
+
+case "$dev" in
+/dev/tty*)
+ echo "TeleGPS found on $dev"
+ ;;
+*)
+ echo 'No TeleGPS-v'"$VERSION"' found'
+ exit 1
+ ;;
+esac
+
+CALFILE=cal-$SERIAL.txt
+../ao-tools/ao-cal-freq/ao-cal-freq --output=$CALFILE --tty=$dev
+CAL_VALUE=`cat $CALFILE`
+echo $SERIAL","$CAL_VALUE >> cal_values
+
+./test-telegps-v4
+
+exit $?
+++ /dev/null
-#!/bin/sh
-
-if [ -x /usr/bin/ao-flash-stm ]; then
- FLASH_STM=/usr/bin/ao-flash-stm
-else
- echo "Can't find ao-flash-stm! 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=2.0
-REPO=~/altusmetrumllc/Binaries
-PRODUCT=TeleLCO
-
-echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
-echo "Copyright 2018 by Bdale Garbee. Released under GPL v3"
-echo
-echo "Expectations:"
-echo "\t$PRODUCT v$VERSION powered from USB"
-echo "\t\twith ST-Link-V2 cabled to debug header"
-echo "\t\twith coax from UHF to frequency counter"
-echo
-
-case $# in
- 1)
- SERIAL="$1"
- echo "$PRODUCT-$VERSION serial number: $SERIAL"
- ;;
- 0)
- echo -n "$PRODUCT-$VERSION serial number: "
- read SERIAL
- ;;
- *)
- echo "Usage: $0 <serial-number>" 1>&2
- exit 1;
- ;;
-esac
-
-echo $FLASH_STM
-
-$FLASH_STM $REPO/loaders/telelco-v$VERSION*.elf
-
-sleep 3
-
-$USBLOAD --serial=$SERIAL --force $REPO/telelco-v$VERSION*.elf || exit 1
-
-sleep 5
-
-dev=`ao-list | awk '/'"$PRODUCT-v$VERSION"'/ { print $3; exit(0); }'`
-
-case "$dev" in
-/dev/tty*)
- echo "$PRODUCT"' found on $dev'
- ;;
-*)
- echo 'No '"$PRODUCT-v$VERSION"' found'
- exit 1
- ;;
-esac
-
-echo 'E 0' > $dev
-
-SERIAL=$SERIAL ./cal-freq $dev
-
-echo 'E 1' > $dev
-
-echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
-echo "\007"
-
-exit $?
--- /dev/null
+turnon_telelco_v3
\ No newline at end of file
--- /dev/null
+#!/bin/sh
+
+if [ -x /usr/bin/ao-flash-stm ]; then
+ FLASH_STM=/usr/bin/ao-flash-stm
+else
+ echo "Can't find ao-flash-stm! 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=2.0
+REPO=~/altusmetrumllc/Binaries
+PRODUCT=TeleLCO
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2018 by Bdale Garbee. Released under GPL v3"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo "\t\twith ST-Link-V2 cabled to debug header"
+echo "\t\twith coax from UHF to frequency counter"
+echo
+
+case $# in
+ 1)
+ SERIAL="$1"
+ echo "$PRODUCT-$VERSION serial number: $SERIAL"
+ ;;
+ 0)
+ echo -n "$PRODUCT-$VERSION serial number: "
+ read SERIAL
+ ;;
+ *)
+ echo "Usage: $0 <serial-number>" 1>&2
+ exit 1;
+ ;;
+esac
+
+echo $FLASH_STM
+
+$FLASH_STM $REPO/loaders/telelco-v$VERSION*.elf
+
+sleep 3
+
+$USBLOAD --serial=$SERIAL --force $REPO/telelco-v$VERSION*.elf || exit 1
+
+sleep 5
+
+dev=`ao-list | awk '/'"$PRODUCT-v$VERSION"'/ { print $3; exit(0); }'`
+
+case "$dev" in
+/dev/tty*)
+ echo "$PRODUCT"' found on $dev'
+ ;;
+*)
+ echo 'No '"$PRODUCT-v$VERSION"' found'
+ exit 1
+ ;;
+esac
+
+echo 'E 0' > $dev
+
+SERIAL=$SERIAL ./cal-freq $dev
+
+echo 'E 1' > $dev
+
+echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
+echo "\007"
+
+exit $?
--- /dev/null
+#!/bin/sh
+
+if [ -x /usr/bin/ao-flash-stm ]; then
+ FLASH_STM=/usr/bin/ao-flash-stm32f1
+else
+ echo "Can't find ao-flash-stm! 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=3.0
+REPO=~/altusmetrumllc/Binaries
+PRODUCT=TeleLCO
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2024 by Bdale Garbee. Released under GPL v3"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo "\t\twith ST-Link-V2 cabled to debug header"
+echo "\t\twith coax from UHF to frequency counter"
+echo
+
+case $# in
+ 1)
+ SERIAL="$1"
+ echo "$PRODUCT-$VERSION serial number: $SERIAL"
+ ;;
+ 0)
+ echo -n "$PRODUCT-$VERSION serial number: "
+ read SERIAL
+ ;;
+ *)
+ echo "Usage: $0 <serial-number>" 1>&2
+ exit 1;
+ ;;
+esac
+
+echo $FLASH_STM
+
+$FLASH_STM $REPO/loaders/telelco-v$VERSION*.elf
+
+sleep 3
+
+$USBLOAD --serial=$SERIAL --force $REPO/telelco-v$VERSION*.elf || exit 1
+
+sleep 5
+
+dev=`ao-list | awk '/'"$PRODUCT-v$VERSION"'/ { print $3; exit(0); }'`
+
+case "$dev" in
+/dev/tty*)
+ echo "$PRODUCT"' found on $dev'
+ ;;
+*)
+ echo 'No '"$PRODUCT-v$VERSION"' found'
+ exit 1
+ ;;
+esac
+
+echo 'E 0' > $dev
+
+SERIAL=$SERIAL ./cal-freq $dev
+
+echo 'E 1' > $dev
+
+echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
+echo "\007"
+
+exit $?
+++ /dev/null
-#!/bin/sh
-
-if [ -x /usr/bin/ao-flash-stm ]; then
- FLASH_STM=/usr/bin/ao-flash-stm
-else
- echo "Can't find ao-flash-stm! 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=6.0
-REPO=~/altusmetrumllc/Binaries
-PRODUCT=TeleMega
-
-echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
-echo "Copyright 2023 by Bdale Garbee. Released under GPL v3"
-echo
-echo "Expectations:"
-echo "\t$PRODUCT v$VERSION powered from USB"
-echo "\t\twith ST-Link-V2 cabled to debug header"
-echo "\t\twith coax from UHF to frequency counter"
-echo
-
-case $# in
- 1)
- SERIAL="$1"
- echo "$PRODUCT-$VERSION serial number: $SERIAL"
- ;;
- 0)
- echo -n "$PRODUCT-$VERSION serial number: "
- read SERIAL
- ;;
- *)
- echo "Usage: $0 <serial-number>" 1>&2
- exit 1;
- ;;
-esac
-
-echo $FLASH_STM
-
-$FLASH_STM $REPO/loaders/telemega-v$VERSION*.elf
-
-sleep 3
-
-$USBLOAD --serial=$SERIAL --force $REPO/telemega-v$VERSION*.elf || exit 1
-
-sleep 5
-
-dev=`ao-list | awk '/TeleMega-v'"$VERSION"'/ { print $3; exit(0); }'`
-
-case "$dev" in
-/dev/tty*)
- echo "TeleMega found on $dev"
- ;;
-*)
- echo 'No TeleMega-v'"$VERSION"' found'
- exit 1
- ;;
-esac
-
-echo 'E 0' > $dev
-
-SERIAL=$SERIAL ./cal-freq $dev
-
-failed=1
-while [ $failed = 1 ]; do
- ../ao-tools/ao-cal-accel/ao-cal-accel $dev
- failed=$?
-done
-
-echo 'E 1' > $dev
-
-./test-telemega-v6.0
-
-exit $?
--- /dev/null
+turnon_telemega_v7.0
\ No newline at end of file
--- /dev/null
+#!/bin/sh
+
+if [ -x /usr/bin/ao-flash-stm ]; then
+ FLASH_STM=/usr/bin/ao-flash-stm
+else
+ echo "Can't find ao-flash-stm! 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=6.0
+REPO=~/altusmetrumllc/Binaries
+PRODUCT=TeleMega
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2023 by Bdale Garbee. Released under GPL v3"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo "\t\twith ST-Link-V2 cabled to debug header"
+echo "\t\twith coax from UHF to frequency counter"
+echo
+
+case $# in
+ 1)
+ SERIAL="$1"
+ echo "$PRODUCT-$VERSION serial number: $SERIAL"
+ ;;
+ 0)
+ echo -n "$PRODUCT-$VERSION serial number: "
+ read SERIAL
+ ;;
+ *)
+ echo "Usage: $0 <serial-number>" 1>&2
+ exit 1;
+ ;;
+esac
+
+echo $FLASH_STM
+
+$FLASH_STM $REPO/loaders/telemega-v$VERSION*.elf
+
+sleep 3
+
+$USBLOAD --serial=$SERIAL --force $REPO/telemega-v$VERSION*.elf || exit 1
+
+sleep 5
+
+dev=`ao-list | awk '/TeleMega-v'"$VERSION"'/ { print $3; exit(0); }'`
+
+case "$dev" in
+/dev/tty*)
+ echo "TeleMega found on $dev"
+ ;;
+*)
+ echo 'No TeleMega-v'"$VERSION"' found'
+ exit 1
+ ;;
+esac
+
+echo 'E 0' > $dev
+
+SERIAL=$SERIAL ./cal-freq $dev
+
+failed=1
+while [ $failed = 1 ]; do
+ ../ao-tools/ao-cal-accel/ao-cal-accel $dev
+ failed=$?
+done
+
+echo 'E 1' > $dev
+
+./test-telemega-v6.0
+
+exit $?
--- /dev/null
+#!/bin/sh
+
+if [ -x /usr/bin/ao-usbload ]; then
+ USBLOAD=/usr/bin/ao-usbload
+else
+ echo "Can't find ao-usbload! Aborting."
+ exit 1
+fi
+
+VERSION=7.0
+REPO=~/altusmetrumllc/Binaries
+PRODUCT=TeleMega
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2025 by Bdale Garbee. Released under GPL v3"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo "\t\twith coax from UHF to frequency counter"
+echo
+
+case $# in
+ 1)
+ SERIAL="$1"
+ echo "$PRODUCT-$VERSION serial number: $SERIAL"
+ ;;
+ 0)
+ echo -n "$PRODUCT-$VERSION serial number: "
+ read SERIAL
+ ;;
+ *)
+ echo "Usage: $0 <serial-number>" 1>&2
+ exit 1;
+ ;;
+esac
+
+# product ships from SMT assembler with bootloader already flashed
+
+$USBLOAD --serial=$SERIAL --force $REPO/telemega-v$VERSION*.elf || exit 1
+
+sleep 5
+
+dev=`ao-list | awk '/TeleMega-v'"$VERSION"'/ { print $3; exit(0); }'`
+
+case "$dev" in
+/dev/tty*)
+ echo "TeleMega found on $dev"
+ ;;
+*)
+ echo 'No TeleMega-v'"$VERSION"' found'
+ exit 1
+ ;;
+esac
+
+echo 'E 0' > $dev
+
+SERIAL=$SERIAL ./cal-freq $dev
+
+failed=1
+while [ $failed = 1 ]; do
+ ../ao-tools/ao-cal-accel/ao-cal-accel $dev
+ failed=$?
+done
+
+echo 'E 1' > $dev
+
+./test-telemega-v7.0
+
+exit $?
flash(struct cc_usb *usb)
{
struct flash *head = NULL, **tail = &head;
- cc_usb_printf(usb, "c s\nv\n");
+ cc_usb_printf(usb, "c s\nA\nv\n");
for (;;) {
char line[512];
struct flash *b;
do_cal(struct cc_usb *usb) {
struct flash *b;
char **accel;
+ char **sensor;
char line[1024];
int l = 0;
int running = 0;
printf ("Accel cal +1g: %s -1g: %s\n",
accel[3], accel[5]);
+ sensor = find_flash(b, "ADXL375");
+
+ if (sensor) {
+ char *plus_end = NULL, *minus_end = NULL;
+ long accel_plus = strtol(accel[3], &plus_end, 10);
+ long accel_minus = strtol(accel[5], &minus_end, 10);
+ double one_g;
+
+ if (plus_end == NULL || plus_end == accel[3]) {
+ printf("can't extract plus value from %s\n", accel[3]);
+ return 0;
+ }
+
+ if (minus_end == NULL || minus_end == accel[5]) {
+ printf("can't extract minus value from %s\n", accel[5]);
+ return 0;
+ }
+ one_g = (accel_minus - accel_plus) / 2.0;
+ if (one_g < 0)
+ one_g = -one_g;
+
+ if (one_g < 18 || 23 < one_g) {
+ printf("Device out of spec. LSB/g is %g. Should be >= 18.4 and <= 22.6\n", one_g);
+ return 0;
+ }
+
+ printf("Device sensitivity: %g LSB/g\n", one_g);
+ }
+
printf ("Saving..."); fflush(stdout);
cc_usb_printf (usb, "c w\n");
cc_usb_sync(usb);
dnl Process this file with autoconf to create configure.
AC_PREREQ(2.57)
-AC_INIT([altos], 1.9.17)
+AC_INIT([altos], 1.9.21.1)
ANDROID_VERSION=37
AC_CONFIG_SRCDIR([src/kernel/ao.h])
AM_INIT_AUTOMAKE([foreign dist-bzip2])
AM_MAINTAINER_MODE
-RELEASE_DATE=2023-08-30
+RELEASE_DATE=2025-06-27
AC_SUBST(RELEASE_DATE)
DOC_DATE=`LC_ALL=C date -d $RELEASE_DATE +'%d %b %Y'`
if test "x$JVM" = "xauto"; then
AC_MSG_CHECKING([JVM])
- for jvm in default-java java-6-openjdk java-7-openjdk java-8-openjdk java-9-openjdk java-10-openjdk java-11-openjdk java-12-openjdk java-13-openjdk java-6-sun java-8-openjdk-amd64; do
+ for jvm in default-java java-8-openjdk java-9-openjdk java-10-openjdk java-11-openjdk java-12-openjdk java-13-openjdk java-8-openjdk-amd64; do
if test "x$JVM" = "xauto"; then
INCLUDE="/usr/lib/jvm/$jvm/include"
if test -f "$INCLUDE"/jni.h; then
AC_MSG_RESULT([$JVM])
fi
-AC_ARG_WITH(java-version, AS_HELP_STRING([--with-java-version=7],
- [Set java language compatibility version (default is 7)]),
- [JAVA_VERSION=$withval], [JAVA_VERSION=7])
+AC_ARG_WITH(java-version, AS_HELP_STRING([--with-java-version=8],
+ [Set java language compatibility version (default is 8)]),
+ [JAVA_VERSION=$withval], [JAVA_VERSION=8])
JAVAC="$JVM"/bin/javac
JAVA="$JVM"/bin/java
endif
RELNOTES_INC=\
+ release-notes-1.9.22.inc \
+ release-notes-1.9.21.inc \
+ release-notes-1.9.20.inc \
+ release-notes-1.9.19.inc \
+ release-notes-1.9.18.inc \
release-notes-1.9.17.inc \
release-notes-1.9.16.inc \
release-notes-1.9.15.inc \
OUTLINE_TXT_FILES=\
easymega-outline.txt \
easymini-outline.txt \
+ micropeak-outline.txt \
telemega-outline.txt \
telemetrum-outline.txt \
telemini-v1-outline.txt \
telemetrum.svg \
telemini-v1.svg \
telemini-v3.svg \
+ micropeak.svg \
easymega.svg
RELNOTES_HTML=$(RELNOTES_INC:.inc=.html)
asciidoctor $(ATTRIBUTES) -b html5 $*.adoc
.adoc.pdf:
- asciidoctor-pdf $(ATTRIBUTES) -a optimize $*.adoc
+ asciidoctor-pdf $(ATTRIBUTES) --attribute="pdf-version=1.6" -a optimize $*.adoc
all: $(HTML) $(PDF)
telemini-v3-outline.pdf: telemini-v3-outline.txt telemini-v3.svg
+micropeak-outline.pdf: micropeak-outline.txt micropeak.svg
+
install: all
WEB_ROOT=/home/bdale/web/
left:
content: '{page-number}'
right:
- content: '© 2023 Bdale Garbee and Keith Packard. Creative Commons ShareAlike 3.0 License'
+ content: '© 2025 Bdale Garbee and Keith Packard. Creative Commons ShareAlike 3.0 License'
verso:
left:
content: $footer_recto_right_content
:revdate: 1 Jan 1970
:icons:
:icontype: svg
-:copyright: Bdale Garbee and Keith Packard 2023
+:copyright: Bdale Garbee and Keith Packard 2025
:doctype: book
:numbered:
:stylesheet: am.css
[appendix]
== Release Notes
+ :leveloffset: 2
+ include::release-notes-1.9.22.adoc[]
+
+ <<<<
+ :leveloffset: 2
+ include::release-notes-1.9.21.adoc[]
+
+ <<<<
+ :leveloffset: 2
+ include::release-notes-1.9.20.adoc[]
+
+ <<<<
+ :leveloffset: 2
+ include::release-notes-1.9.19.adoc[]
+
+ <<<<
+ :leveloffset: 2
+ include::release-notes-1.9.18.adoc[]
+
+ <<<<
+ :leveloffset: 2
+ include::release-notes-1.9.17.adoc[]
+
+ <<<<
:leveloffset: 2
include::release-notes-1.9.16.adoc[]
[license]
== License
-Copyright © 2023 Bdale Garbee and Keith Packard
+Copyright © 2025 Bdale Garbee and Keith Packard
This document is released under the terms of the link:http://creativecommons.org/licenses/by-sa/3.0/[Creative Commons ShareAlike 3.0 License]
aren't answered in this manual, or just need a little help figuring
things out, we strongly suggest joining the Altus Metrum user email
list, which you can do by visiting
- https://lists.gag.com/mailman/listinfo/altusmetrum. There's a lot
+ https://groups.io/g/altusmetrum. There's a lot
of useful information in the mailing list archives!
The first device created for our community was TeleMetrum, a dual
--- /dev/null
+:notitle:
+:doctype: article
+
+== MicroPeak Outline and Hole Pattern
+
+ This image, when printed, provides a precise template for the
+ mounting holes in MicroPeak. MicroPeak has overall dimensions
+ of 0.700 x 0.560 inches (17.78mm x 14.224mm), and the 0.098
+ inch (2.5mm) mounting holes are 0.075 inches (1.905mm) from
+ the board edges. That means they are in a rectangle measuring
+ 0.550 x 0.410 inches (13.97mm x 10.414mm), sized for use with
+ 2-56 or M2.5 screws.
+
+ image::micropeak.svg[align="center"]
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ width="1.25in"
+ height="1in"
+ viewBox="0 0 120 106"
+ preserveaspectratio="none"
+ id="svg2"
+ version="1.1"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <defs
+ id="defs27" />
+ <g
+ transform="translate(25,25)"
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-linejoin:miter;font-size:24"
+ id="g22">
+ <!-- outline -->
+ <rect
+ width="70"
+ height="56"
+ x="0"
+ y="0"
+ id="rect2" />
+ <!-- holes -->
+ <path
+ d="M7.5,7.5 m-4.9,0 a4.9,4.9,0,1,0,9.8,0 a4.9,4.9,0,1,0,-9.8,0 l9.8,0 m-4.9,-4.9 l0,9.8"
+ id="path4" />
+ <path
+ d="M62.5,7.5 m-4.9,0 a4.9,4.9,0,1,0,9.8,0 a4.9,4.9,0,1,0,-9.8,0 l9.8,0 m-4.9,-4.9 l0,9.8"
+ id="path6" />
+ <path
+ d="M7.5,48.5 m-4.9,0 a4.9,4.9,0,1,0,9.8,0 a4.9,4.9,0,1,0,-9.8,0 l9.8,0 m-4.9,-4.9 l0,9.8"
+ id="path8" />
+ <path
+ d="M62.5,48.5 m-4.9,0 a4.9,4.9,0,1,0,9.8,0 a4.9,4.9,0,1,0,-9.8,0 l9.8,0 m-4.9,-4.9 l0,9.8"
+ id="path10" />
+ <!-- width -->
+ <path
+ d="M0,-5 l0,-10 M70,-5 l0,-10"
+ id="path11" />
+ <text
+ x="35"
+ y="-7"
+ style="fill:#000000;stroke:none;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:10px;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-anchor:middle"
+ text-anchor="middle"
+ id="text16"><tspan
+ id="tspan310">0.700</tspan>
+ </text>
+ <!-- height -->
+ <path
+ d="M-5,0 l-10,0 M-5,56 l-10,0"
+ id="path11" />
+ <text
+ x="28"
+ y="14"
+ transform="rotate(90)"
+ style="fill:#000000;stroke:none;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:10px;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-anchor:middle"
+ text-anchor="middle"
+ id="text16"><tspan
+ id="tspan310">0.560</tspan>
+ </text>
+ <!-- hole H dist -->
+ <path
+ d="M7.5,61 l0,10 M62.5,60 l0,10"
+ id="path11" />
+ <text
+ x="35"
+ y="70"
+ style="fill:#000000;stroke:none;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:10px;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-anchor:middle"
+ text-anchor="middle"
+ id="text16"><tspan
+ id="tspan310">0.550</tspan>
+ </text>
+ <!-- hole V dist -->
+ <path
+ d="M75,7.5 l10,0 M75,48.5 l10,0"
+ id="path11" />
+ <text
+ x="28"
+ y="-77"
+ transform="rotate(90)"
+ style="fill:#000000;stroke:none;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:10px;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-anchor:middle"
+ text-anchor="middle"
+ id="text16"><tspan
+ id="tspan310">0.410</tspan>
+ </text>
+ <!-- label -->
+ <text
+ x="35"
+ y="31"
+ style="fill:#000000;stroke:none;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:10px;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-anchor:middle"
+ text-anchor="middle"
+ id="text16"><tspan
+ id="tspan310">MicroPeak</tspan></text>
+ </g>
+</svg>
can always be improved… If you have questions that aren't answered in this
manual, or just need a little help figuring things out, we strongly suggest
joining the Altus Metrum user email list, which you can do by visiting
-https://lists.gag.com/mailman3.
+https://groups.io/g/altusmetrum.
checklist after the rocket is installed on a launch rail.
The board will beep out a Morse code “P” every few seconds
- indicating that it's in pad mode and ready to detect launch.
- Once launch is detected, the board logs pressure and acceleration
- data 100 times per second throughout the flight.
+ indicating that it's in pad mode and ready to detect the start of
+ the motor burn. Recording starts when chamber pressure rises by
+ at least 50psi, then the board logs pressure and acceleration
+ data 100 times per second until chamber pressure goes low again and
+ remains stable for at least 10 seconds.
- After flight, AltosUI can be used to download the flight data,
- view a quick graph of acceleration and pressure with pan and
+ After flight, attach a USB data cable to the board before powering
+ it on so that it goes in to 'idle mode'. Then AltosUI can be used
+ to download the flight data, view a quick graph of acceleration and
+ pressure with pan and
zoom capabilities, then export it to a comma separated values
(CSV) file. Such a file can easily be loaded into a spreadsheet
- for analysis.
+ for analysis.
--- /dev/null
+= Release Notes for Version 1.9.18
+include::release-head.adoc[]
+:doctype: article
+
+ Version 1.9.18
+
+ == AltOS
+
+ * Add support for EasyTimer V2. The new version of this
+ product has on-board storage to log data during flight.
+
+ == AltosUI & TeleGPS application
+
+ * Add support for EasyTimer V2. This includes support for
+ analyizing flight data from the on-board logs.
+
+ * Allow on-board beepers to be disabled by setting the
+ frequency to 0.
--- /dev/null
+= Release Notes for Version 1.9.19
+include::release-head.adoc[]
+:doctype: article
+
+ Version 1.9.19
+
+ == AltOS
+
+ * Finish support for EasyMega V3.
+
+ == AltosUI & TeleGPS application
+
+ * Show device configuration information when graphing a
+ flight.
--- /dev/null
+= Release Notes for Version 1.9.20
+include::release-head.adoc[]
+:doctype: article
+
+ Version 1.9.20
+
+ == AltOS
+
+ * Add support for TeleGPS v4.0 and TeleMega v7.0
+
+ == AltosUI & TeleGPS application
+
+ * Add support for TeleGPS v4.0 and TeleMega v7.0
+
+ * Add support for 30V pyro voltage range
--- /dev/null
+= Release Notes for Version 1.9.21
+include::release-head.adoc[]
+:doctype: article
+
+ Version 1.9.21
+
+ == AltOS
+
+ * Add support for TeleBT v4.0 factory test.
+
+ * Support Picolibc 1.8.10
+
+ == AltosUI & TeleGPS application
+
+ * Support pressure values below sensor range.
--- /dev/null
+= Release Notes for Version 1.9.22
+include::release-head.adoc[]
+:doctype: article
+
+ Version 1.9.22
+
+ == AltosUI & TeleGPS application
+
+ * Support TeleMega v7 .eeprom files
[appendix]
== Release Notes
+ :leveloffset: 2
+ include::release-notes-1.9.22.adoc[]
+
+ <<<<
+ :leveloffset: 2
+ include::release-notes-1.9.21.adoc[]
+
+ <<<<
+ :leveloffset: 2
+ include::release-notes-1.9.20.adoc[]
+
+ <<<<
+ :leveloffset: 2
+ include::release-notes-1.9.19.adoc[]
+
+ <<<<
+ :leveloffset: 2
+ include::release-notes-1.9.18.adoc[]
+
+ <<<<
:leveloffset: 2
include::release-notes-1.9.17.adoc[]
|40mW
|3.7V
+ |TeleMega v7.0
+ |MS5607 30km (100k')
+ |ADXL375 200g
+ |uBlox Max-10S
+ |BMI088 MMC5983
+ |8MB
+ |40mW
+ |3.7V
+
endif::telemega[]
ifdef::easymega[]
|EasyMega v1.0
|8MB
|-
|3.7V
+
+ |EasyMega v3.0
+ |MS5607 30km (100k')
+ |ADXL375 200g
+ |-
+ |BMI088 MMC5983A
+ |8MB
+ |-
+ |3.7V
endif::easymega[]
ifdef::easytimer[]
|-
|-
|3.7-12V
+
+ |EasyTimer v2.0
+ |-
+ |24g
+ |-
+ |BMI088 MMC5983
+ |1MB
+ |-
+ |3.7-12V
endif::easytimer[]
ifdef::easymotor[]
|-
|8MB
|-
- |6.5-15V
+ |3.7V
endif::easymotor[]
have an
accelerometer we can use to determine orientation, “idle” mode
is selected if the board is connected via USB to a computer,
- otherwise the board enters “flight” mode.
+ otherwise the board enters “flight” mode. This is also how
+ EasyMotor works, since even though it has an accelerometer,
+ it detects the motor burn it is meant to record by detecting\ e\ 1 a rise in chamber pressure, and board orientation doesn't
+ matter.
ifdef::telemini[]
TeleMini
selects “idle” mode if it receives a command packet
[appendix]
== Release Notes
+ :leveloffset: 2
+ include::release-notes-1.9.22.adoc[]
+
+ <<<<
+ :leveloffset: 2
+ include::release-notes-1.9.21.adoc[]
+
+ <<<<
+ :leveloffset: 2
+ include::release-notes-1.9.20.adoc[]
+
+ <<<<
+ :leveloffset: 2
+ include::release-notes-1.9.19.adoc[]
+
+ <<<<
+ :leveloffset: 2
+ include::release-notes-1.9.18.adoc[]
+
+ <<<<
+ :leveloffset: 2
+ include::release-notes-1.9.17.adoc[]
+
+ <<<<
:leveloffset: 2
include::release-notes-1.9.16.adoc[]
[dedication]
== Acknowledgments
- Our profound thanks to Terry Lee for major contributions to making
+ Our profound thanks to Terry Lee (TRA #10206, NAR #3284) for major
+ contributions to making
the TeleLaunch system something we could actually package and sell!
Tripoli Colorado, Oregon Rocketry, New River Valley Rocketry, and
can always be improved... If you have questions that aren't answered in this
manual, or just need a little help figuring things out, we strongly suggest
joining the Altus Metrum user email list, which you can do by visiting
-https://lists.gag.com/mailman/listinfo/altusmetrum.
+https://groups.io/g/altusmetrum.
|0 |uint16_t |serial |Device serial Number
|2 |uint16_t |tick |Device time in 100ths of a second
|4 |uint8_t |type |Packet type
- |5
+ |5 | | |
|====
Each packet starts with these five bytes which serve to identify
|26 |int16_t |ground_accel |TM
|28 |int16_t |accel_plus_g |TM
|30 |int16_t |accel_minus_g |TM
- |32
+ |32 | | |
|====
=== TeleMega Sensor Data
|26 |int16_t |mag_x |X field strength (across)
|28 |int16_t |mag_y |Y field strength (along)
|30 |int16_t |mag_z |Z field strength (through)
- |32
+ |32 | | |
|====
.TeleMega Kalman and Voltage Data Packet Contents
|26 |int16_t |acceleration |m/s² * 16
|28 |int16_t |speed |m/s * 16
|30 |int16_t |height |m
- |32
+ |32 | | |
|====
=== TeleMetrum v2 and newer Sensor Data
|22 |int16_t |sense_d |drogue continuity sense
|24 |int16_t |sense_m |main continuity sense
|26 |pad[6] |pad bytes |
- |32
+ |32 | | |
|====
.TeleMetrum v2 and newer Calibration Data Packet Contents
|14 |int16_t |accel_plus_g |Accel calibration at +1g
|16 |int16_t |accel_minus_g |Accel calibration at -1g
|18 |pad[14] |pad bytes |
- |32
+ |32 | | |
|====
=== TeleMini v3.0 Sensor Data
|22 |int16_t |height |m
|24 |int16_t |ground_pres |Average barometer reading on ground
|28 |pad[4] |pad bytes |
- |32
+ |32 | | |
|====
|14 |uint16_t |flight_log_max |Maximum flight log size (kB)
|16 |char |callsign[8] |Radio operator identifier
|24 |char |version[8] |Software version identifier
- |32
+ |32 | | |
|====
=== GPS Location
|28 |int16_t |climb_rate |cm/s
|30 |uint8_t |course |/ 2
|31 |uint8_t |unused[1] |
- |32
+ |32 | | |
|====
Packed into a one byte field are status flags and the
|5 |uint8_t |channels |Number of reported satellite information
|6 |sat_info_t |sats[12] |See Per-Satellite data table below
|30 |uint8_t |unused[2] |
- |32
+ |32 | | |
|====
.GPS Per-Satellite data (sat_info_t)
|Offset |Data Type |Name |Description
|0 |uint8_t |svid |Space Vehicle Identifier
|1 |uint8_t |c_n_1 |C/N1 signal quality indicator
- |2
+ |2 | | |
|====
=== Companion Data
|6 |uint8_t |update_period |How often telemetry is sent, in 1/100ths of a second
|7 |uint8_t |channels |Number of data channels supplied
|8 |uint16_t[12] |companion_data |Up to 12 channels of 16-bit companion data
- |32
+ |32 | | |
|====
== Data Transmission
#!/bin/sh
# map-N43.799102,W120.586281-hybrid-20.jpg
-export QUERY_STRING="lat=43.799102&lon=-120.586281&zoom=20"
+export QUERY_STRING="lat=43.799102&lon=-120.586281&zoom=17"
export REMOTE_ADDR="127.0.0.1"
./altos-map
telemega-v4.0 telemega-v4.0/flash-loader \
telemega-v5.0 telemega-v5.0/flash-loader \
telemega-v6.0 telemega-v6.0/flash-loader \
+ telemega-v7.0 telemega-v7.0/flash-loader \
telemetrum-v2.0 telemetrum-v2.0/flash-loader \
telemetrum-v3.0 telemetrum-v3.0/flash-loader \
telegps-v0.3 telegps-v0.3/flash-loader \
telegps-v1.0 telegps-v1.0/flash-loader \
telegps-v2.0 telegps-v2.0/flash-loader \
telegps-v3.0 telegps-v3.0/flash-loader \
+ telegps-v4.0 telegps-v4.0/flash-loader \
telelco-v0.2 telelco-v0.2/flash-loader \
telelco-v0.2-cc1200 telelco-v0.2-cc1200/flash-loader \
telelco-v0.3 telelco-v0.3/flash-loader \
AVRDIRS=\
micropeak microkite microsplash
-SUBDIRS=draw
+SUBDIRS=draw test
ifeq ($(strip $(HAVE_ARM_M3_CC)),yes)
SUBDIRS+=$(ARMM3DIRS)
clean:
rm -f $(LCO_TEST_OBJS) ao_font.h ao_logo.h $(FONT_SRCS)
+
+install:
#define AO_ADXL375_SELF_TEST_SAMPLES 10
#define AO_ADXL375_SELF_TEST_SETTLE 4
+#define AO_ADXL375_SELF_TEST_DELAY AO_MS_TO_TICKS(10)
#define MIN_LSB_G 18.4
#define MAX_LSB_G 22.6
-#define SELF_TEST_MIN_G 5.0
-#define SELF_TEST_MAX_G 6.8
+
+/* The self test value can vary within a rather wide range */
+#define SELF_TEST_MIN_G 4.0
+#define SELF_TEST_MAX_G 12.0
#define MIN_SELF_TEST ((int32_t) (MIN_LSB_G * SELF_TEST_MIN_G * AO_ADXL375_SELF_TEST_SAMPLES + 0.5))
#define MAX_SELF_TEST ((int32_t) (MAX_LSB_G * SELF_TEST_MAX_G * AO_ADXL375_SELF_TEST_SAMPLES + 0.5))
total->x += value.x;
total->y += value.y;
total->z += value.z;
- ao_delay(AO_MS_TO_TICKS(10));
+ ao_delay(AO_ADXL375_SELF_TEST_DELAY);
}
}
(0 << AO_ADXL375_POWER_CTL_SLEEP) |
(AO_ADXL375_POWER_CTL_WAKEUP_8 << AO_ADXL375_POWER_CTL_WAKEUP));
+ /* Set to normal mode */
+
+ ao_adxl375_reg_write(AO_ADXL375_DATA_FORMAT,
+ AO_ADXL375_DATA_FORMAT_SETTINGS(0));
+
/* Perform self-test */
struct ao_adxl375_total self_test_off, self_test_on;
if (z_change < MIN_SELF_TEST)
AO_SENSOR_ERROR(AO_DATA_ADXL375);
- /* This check is commented out as maximum self test is unreliable
-
- if (z_change > MAX_SELF_TEST)
+ if (z_change > MAX_SELF_TEST)
AO_SENSOR_ERROR(AO_DATA_ADXL375);
- */
-
/* Discard some samples to let it settle down */
ao_adxl375_total_value(&self_test_off, AO_ADXL375_SELF_TEST_SETTLE);
}
{ 0, NULL }
};
+/* Make sure the radio is alive */
+bool
+ao_radio_post(void)
+{
+ uint8_t partnum;
+
+ partnum = ao_radio_reg_read(CC1200_PARTNUMBER);
+ switch (partnum) {
+ case CC1200_PARTNUMBER_CC1200:
+ case CC1200_PARTNUMBER_CC1201:
+ return true;
+ default:
+ return false;
+ }
+}
+
void
ao_radio_init(void)
{
extern struct ao_pad_query ao_pad_query; /* Last received QUERY from pad */
#ifdef AO_LCO_DRAG_RACE_BOX
-#define AO_LCO_BOX_DRAG 0 /* Box number to enable drag race mode (old LCO bits) */
-#define AO_LCO_BOX_FIRST AO_LCO_BOX_DRAG
+# define AO_LCO_BOX_DRAG 0 /* Box number to enable drag race mode (old LCO bits) */
+# define AO_LCO_BOX_FIRST AO_LCO_BOX_DRAG
#else
-# define AO_LCO_LCO_VOLTAGE 0 /* Box number to show LCO voltage */
-# ifdef AO_LCO_HAS_INFO
-# define AO_LCO_INFO -3
+# ifdef AO_LCO_HAS_CONTRAST
+# define AO_LCO_CONTRAST -2
# ifndef AO_LCO_BOX_FIRST
-# define AO_LCO_BOX_FIRST AO_LCO_INFO
+# define AO_LCO_BOX_FIRST AO_LCO_CONTRAST
# endif
# endif
-# ifdef AO_LCO_HAS_BACKLIGHT
-# define AO_LCO_BACKLIGHT -2
-# ifndef AO_LCO_BOX_FIRST
-# define AO_LCO_BOX_FIRST AO_LCO_BACKLIGHT
-# endif
+# ifdef AO_LCO_HAS_BACKLIGHT_UI
+# define AO_LCO_BACKLIGHT -1
+# ifndef AO_LCO_BOX_FIRST
+# define AO_LCO_BOX_FIRST AO_LCO_BACKLIGHT
+# endif
# endif
-# ifdef AO_LCO_HAS_CONTRAST
-# define AO_LCO_CONTRAST -1
+# if AO_LCO_HAS_LCO_INFO
+# define AO_LCO_LCO_INFO 0 /* Box number to show LCO info */
# ifndef AO_LCO_BOX_FIRST
-# define AO_LCO_BOX_FIRST AO_LCO_CONTRAST
+# define AO_LCO_BOX_FIRST AO_LCO_LCO_INFO
+# endif
+# else
+# define AO_LCO_LCO_VOLTAGE -1
+# ifndef AO_LCO_BOX_FIRST
+# define AO_LCO_BOX_FIRST AO_LCO_LCO_VOLTAGE
# endif
# endif
# ifndef AO_LCO_BOX_FIRST
-# define AO_LCO_BOX_FIRST AO_LCO_LCO_VOLTAGE
+# define AO_LCO_BOX_FIRST 1
# endif
#endif
-#define AO_LCO_PAD_VOLTAGE 0 /* Pad number to show box voltage */
-#define AO_LCO_PAD_RSSI -1 /* Pad number to show box RSSI */
-#define AO_LCO_PAD_FIRST AO_LCO_PAD_RSSI
+
+#ifdef AO_LCO_HAS_PAD_INFO
+# define AO_LCO_PAD_INFO 0 /* Pad number to show box info */
+# define AO_LCO_PAD_FIRST AO_LCO_PAD_INFO
+#else
+# define AO_LCO_PAD_VOLTAGE 0 /* Pad number to show box voltage */
+# define AO_LCO_PAD_RSSI -1 /* Pad number to show box RSSI */
+# define AO_LCO_PAD_FIRST AO_LCO_PAD_RSSI
+#endif
static inline bool
ao_lco_box_pseudo(int16_t box)
case AO_LCO_BACKLIGHT:
return true;
#endif
-#ifdef AO_LCO_INFO
- case AO_LCO_INFO:
+#ifdef AO_LCO_LCO_INFO
+ case AO_LCO_LCO_INFO:
return true;
#endif
default:
ao_lco_pad_pseudo(int8_t pad)
{
switch (pad) {
+#ifdef AO_LCO_PAD_VOLTAGE
case AO_LCO_PAD_VOLTAGE:
return true;
+#endif
+#ifdef AO_LCO_PAD_RSSI
case AO_LCO_PAD_RSSI:
return true;
+#endif
+#ifdef AO_LCO_PAD_INFO
+ case AO_LCO_PAD_INFO:
+ return true;
+#endif
default:
return false;
}
static uint16_t ao_lco_tick_offset[AO_PAD_MAX_BOXES]; /* 16 bit offset from local to remote tick count */
static uint8_t ao_lco_selected[AO_PAD_MAX_BOXES]; /* pads selected to fire */
+static uint32_t ao_lco_query_good, ao_lco_query_bad;
+
uint8_t ao_lco_valid[AO_PAD_MAX_BOXES]; /* AO_LCO_VALID bits per box */
static const AO_LED_TYPE continuity_led[AO_LED_CONTINUITY_NUM] = {
if (r == AO_RADIO_CMAC_OK) {
ao_lco_channels[box] = query->channels;
ao_lco_valid[box] = AO_LCO_VALID_LAST | AO_LCO_VALID_EVER;
- } else
+ ++ao_lco_query_good;
+ } else {
ao_lco_valid[box] &= (uint8_t) ~AO_LCO_VALID_LAST;
- PRINTD("ao_lco_get_channels(%d) rssi %d valid %d ret %d offset %d\n", box, ao_radio_cmac_rssi, ao_lco_valid[box], r, ao_lco_tick_offset[box]);
+ ++ao_lco_query_bad;
+ }
+ PRINTD("ao_lco_get_channels(%d) rssi %d valid %d ret %d offset %d good %"PRIu32" bad %"PRIu32"\n",
+ box, ao_radio_cmac_rssi, ao_lco_valid[box], r, ao_lco_tick_offset[box],
+ ao_lco_query_good, ao_lco_query_bad);
ao_wakeup(&ao_pad_query);
return ao_lco_valid[box];
}
if (!ao_lco_pad_pseudo(ao_lco_pad))
ao_lco_set_pad(ao_lco_pad_first(ao_lco_box));
}
- if (ao_lco_pad_pseudo(ao_lco_pad))
- ao_lco_show();
}
+ if (ao_lco_pad_pseudo(ao_lco_pad))
+ ao_lco_show();
}
uint8_t ao_lco_box_mask[AO_LCO_MASK_SIZE(AO_PAD_MAX_BOXES)];
break;
}
#endif
-#ifdef AO_LCO_HAS_BACKLIGHT
+#ifdef AO_LCO_HAS_BACKLIGHT_UI
case AO_LCO_BACKLIGHT: {
int32_t backlight = ao_lco_get_backlight();
break;
}
#endif
-#ifdef AO_LCO_HAS_INFO
- case AO_LCO_INFO: {
+#if AO_LCO_HAS_LCO_INFO
+ case AO_LCO_LCO_INFO: {
#if AO_LCO_MIN_INFO_PAGE < AO_LCO_MAX_INFO_PAGE
int32_t info_page = ao_lco_get_info_page();
}
static int
-ao_rn_set_name(void)
+ao_rn_set_name(char *name)
{
- char sn[8];
- char *s = sn + 8;
- int n;
-
// ao_rn_dbg("set name...\n");
- *--s = '\0';
- n = ao_serial_number;
- do {
- *--s = (uint8_t) ('0' + n % 10);
- } while (n /= 10);
- ao_rn_send_cmd(AO_RN_SET_NAME_CMD "TeleBT-", s);
+ ao_rn_send_cmd(AO_RN_SET_NAME_CMD, name);
return ao_rn_wait_status();
}
ao_wakeup(&ao_rn_connected);
}
+#ifndef ao_bt_panic
static void
ao_bt_panic(int where)
{
}
}
}
+#endif
static uint8_t ao_rn_stdio;
ao_rn(void)
{
int status = AO_RN_ERROR;
- char name[17];
+ char have_name[17], want_name[17];
int i;
ao_rn_dbg("ao_rn top\n");
/* Check to see if the name is already set and assume
* that the device is ready to go
*/
- status = ao_rn_get_name(name, sizeof (name));
+ status = ao_rn_get_name(have_name, sizeof (have_name));
if (status != AO_RN_OK) {
ao_rn_dbg("get name failed\n");
- status = ao_rn_get_name(name, sizeof (name));
+ status = ao_rn_get_name(have_name, sizeof (have_name));
if (status != AO_RN_OK)
continue;
}
+ snprintf(want_name, sizeof(want_name), "TeleBT-%u", ao_serial_number);
- if (strncmp(name, "TeleBT-", 7) == 0) {
+ if (strcmp(have_name, want_name) == 0) {
ao_rn_dbg("name is set\n");
status = AO_RN_OK;
break;
/* Finally, set the name. Doing this last makes it possible to check
* if the whole sequence has been done
*/
- if (ao_rn_set_name() != AO_RN_OK) {
+ if (ao_rn_set_name(want_name) != AO_RN_OK) {
ao_rn_dbg("set name failed\n");
continue;
}
PROGNAME=easymega-v3.0
PROG=$(PROGNAME)-$(VERSION).elf
HEX=$(PROGNAME)-$(VERSION).ihx
+FLASH_PROG=flash-loader/$(PROGNAME)-altos-flash-$(VERSION).elf
+BOTH_DFU=$(PROGNAME)-combined-$(VERSION).dfu
+BOTH_HEX=$(PROGNAME)-combined-$(VERSION).ihx
+ELFTOHEX=$(TOPDIR)/../ao-tools/ao-elftohex/ao-elftohex
+MAKEBIN=$(TOPDIR)/../ao-tools/ao-makebin/ao-makebin
SRC=$(ALTOS_SRC) ao_easymega.c
OBJ=$(SRC:.c=.o)
-all: $(PROG) $(HEX)
+all: $(PROG) $(HEX) $(BOTH_DFU) $(BOTH_HEX)
$(PROG): Makefile $(OBJ) altos.ld
$(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+$(BOTH_DFU): $(PROG) $(FLASH_PROG)
+ $(MAKEBIN) --dfu --output=$@ --base=$(FLASH_ADDR) $(FLASH_PROG) $(PROG)
+
+$(BOTH_HEX): $(PROG) $(FLASH_PROG)
+ $(ELFTOHEX) --nosym --output=$@ $(FLASH_PROG) $(PROG)
+
+$(FLASH_PROG): FRC
+ +cd flash-loader && make
+
$(OBJ): $(INC)
+FRC:
+
distclean: clean
clean:
clean:
rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx $(PROGNAME)-*.map
+ rm -f $(PROGNAME)-*.dfu
rm -f ao_product.h
install:
#ifndef _AO_H_
#define _AO_H_
-#include <stdint.h>
+#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#include <stddef.h>
+#include <stdarg.h>
#include <stdbool.h>
#include <ao_pins.h>
#include <ao_arch.h>
void
ao_radio_test_off(void);
+bool
+ao_radio_post(void);
+
void
ao_radio_init(void);
#define AO_CONFIG_DEFAULT_PYRO_TIME AO_MS_TO_TICKS(50)
#define AO_CONFIG_DEFAULT_RADIO_10MW 0
#define AO_CONFIG_DEFAULT_REPORT_FEET 0
+#ifndef AO_CONFIG_DEFAULT_ACCEL_PLUS_G
+#define AO_CONFIG_DEFAULT_ACCEL_PLUS_G 0
+#define AO_CONFIG_DEFAULT_ACCEL_MINUS_G 0
+#endif
#if HAS_CONFIG_SAVE
#ifndef USE_INTERNAL_FLASH
#error Please define USE_INTERNAL_FLASH
ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY;
/* Fixups for minor version 2 */
if (minor < 2) {
- ao_config.accel_plus_g = 0;
- ao_config.accel_minus_g = 0;
+ ao_config.accel_plus_g = AO_CONFIG_DEFAULT_ACCEL_PLUS_G;
+ ao_config.accel_minus_g = AO_CONFIG_DEFAULT_ACCEL_MINUS_G;
}
/* Fixups for minor version 3 */
#if HAS_RADIO
#ifndef _AO_CONFIG_H_
#define _AO_CONFIG_H_
+#ifndef AO_FLIGHT_TEST
#include <ao.h>
+#endif
#if AO_PYRO_NUM
#include <ao_pyro.h>
#include <stdint.h>
#define AO_CONVERT_TEST
+#define AO_TICK_TYPE uint32_t
typedef int32_t alt_t;
typedef int32_t pres_t;
#include "ao_host.h"
*/
#include <stdint.h>
+#define AO_TICK_TYPE uint32_t
#define AO_CONVERT_TEST
#define AO_NEED_ALTITUDE_TO_PRES 1
#include "ao_host.h"
int dummy;
};
+enum ao_igniter_status {
+ ao_igniter_unknown, /* unknown status (ambiguous voltage) */
+ ao_igniter_ready, /* continuity detected */
+ ao_igniter_active, /* igniter firing */
+ ao_igniter_open, /* open circuit detected */
+};
+
#define ao_add_task(t,f,n)
#define ao_log_start()
#define ao_log_stop()
#define AO_MS_TO_TICKS(ms) ((ms) / 10)
+#define AO_NS_TO_TICKS(ns) ((ns) / (10000000L))
#define AO_SEC_TO_TICKS(s) ((s) * 100)
#define AO_FLIGHT_TEST
#define AO_LOG_FORMAT_TELEMEGA_6 22 /* 32 byte typed telemega records with 32 bit gyro cal, bmi088 and mmc5983 */
#define AO_LOG_FORMAT_EASYTIMER_2 23 /* 32 byte typed easytimer records with 32 bit gyro cal, bmi088 and mmc5983 */
#define AO_LOG_FORMAT_EASYMEGA_3 24 /* 32 byte typed telemega records with 32 bit gyro cal, bmi088 and mmc5983 */
+#define AO_LOG_FORMAT_TELEMEGA_7 25 /* 32 byte typed telemega records with 32 bit gyro cal, bmi088 and mmc5983, 30V max pyro */
#define AO_LOG_FORMAT_NONE 127 /* No log at all */
/* Return the flight number from the given log slot, 0 if none, -slot on failure */
} u;
};
-#if AO_LOG_FORMAT == AO_LOG_FOMAT_TELEMEGA_OLD || AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMEGA || AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMEGA_3 || AO_LOG_FORMAT == AO_LOG_FORMAT_EASYMEGA_2 || AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMEGA_4 || AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMEGA_5 || AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMEGA_6 || AO_LOG_FORMAT == AO_LOG_FORMAT_EASYMEGA_3
+#if AO_LOG_FORMAT == AO_LOG_FOMAT_TELEMEGA_OLD || AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMEGA || AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMEGA_3 || AO_LOG_FORMAT == AO_LOG_FORMAT_EASYMEGA_2 || AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMEGA_4 || AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMEGA_5 || AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMEGA_6 || AO_LOG_FORMAT == AO_LOG_FORMAT_EASYMEGA_3 || AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMEGA_7
typedef struct ao_log_mega ao_log_type;
#endif
* Receive and validate an incoming packet
*/
+int8_t ao_radio_cmac_last_rssi;
+
static int8_t
radio_cmac_recv(uint8_t len, AO_TICK_TYPE timeout)
{
return AO_RADIO_CMAC_TIMEOUT;
}
+ ao_radio_cmac_last_rssi = ao_radio_rssi;
+
if (!(cmac_data[len + AO_CMAC_KEY_LEN +1] & AO_RADIO_STATUS_CRC_OK))
return AO_RADIO_CMAC_CRC_ERROR;
#define AO_CMAC_KEY_LEN AO_AES_LEN
#define AO_CMAC_MAX_LEN (128 - AO_CMAC_KEY_LEN)
-extern int8_t ao_radio_cmac_rssi;
+extern int8_t ao_radio_cmac_rssi, ao_radio_cmac_last_rssi;
int8_t
ao_radio_cmac_send(void *packet, uint8_t len);
static FILE __stdio = FDEV_SETUP_STREAM(ao_putc, ao_getc, ao_flushc, _FDEV_SETUP_RW);
-#ifdef PICOLIBC_STDIO_GLOBALS
-
#ifdef __strong_reference
#define STDIO_ALIAS(x) __strong_reference(stdin, x);
#else
FILE *const stdin = &__stdio;
STDIO_ALIAS(stdout);
STDIO_ALIAS(stderr);
-
-#else
-
-FILE *const __iob[3] = { &__stdio, &__stdio, &__stdio };
-
-#endif
#if AO_LOG_NORMALIZED
#if AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMEGA_5
telemetry.generic.type = AO_TELEMETRY_MEGA_NORM_MPU6000_MMC5983;
-#elif AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMEGA_6
+#elif AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMEGA_6 || AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMEGA_7
telemetry.generic.type = AO_TELEMETRY_MEGA_NORM_BMI088_MMC5983;
#else
#error unknown normalized log type
/* 32 */
};
-#define AO_TELEMETRY_MEGA_DATA 0x09
+#define AO_TELEMETRY_MEGA_DATA_15V 0x09 /* 100k / 27k */
+#define AO_TELEMETRY_MEGA_DATA_30V 0x15 /* 100k / 12k */
struct ao_telemetry_mega_data {
uint16_t serial; /* 0 */
flush();
c = ao_up_getchar();
}
- putchar(c);
+ putchar((char) c);
}
}
for (;;) {
cli();
#pragma GCC diagnostic ignored "-Wconversion"
+#pragma GCC diagnostic ignored "-Wsign-conversion"
set_sleep_mode((uint8_t) SLEEP_MODE_PWR_DOWN);
sleep_mode();
}
CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS)
-LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stm -Taltos-loader.ld -n
+LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stm -Taltos-loader.ld -n --crt0=minimal
PROGNAME=$(HARDWARE)-altos-flash
PROG=$(PROGNAME)-$(VERSION).elf
--- /dev/null
+ao_product.h
+*.bin
+*.ihx
+*.elf
--- /dev/null
+#
+# AltOS build
+#
+#
+
+include ../stmf0/Makefile.defs
+
+INC = \
+ ao.h \
+ ao_arch.h \
+ ao_arch_funcs.h \
+ ao_boot.h \
+ ao_pins.h \
+ ao_product.h \
+ ao_cc1200_CC1200.h \
+ ao_task.h \
+ ao_rn4678.h \
+ stm32f0.h \
+ Makefile
+
+ALTOS_SRC = \
+ ao_boot_chain.c \
+ ao_interrupt.c \
+ ao_product.c \
+ ao_romconfig.c \
+ ao_cmd.c \
+ ao_config.c \
+ ao_data.c \
+ ao_task.c \
+ ao_led_stmf0.c \
+ ao_stdio.c \
+ ao_panic.c \
+ ao_timer.c \
+ ao_mutex.c \
+ ao_serial_stm.c \
+ ao_rn4678.c \
+ ao_freq.c \
+ ao_dma_stm.c \
+ ao_spi_stm.c \
+ ao_cc1200.c \
+ ao_adc_stm.c \
+ ao_usb_stm.c \
+ ao_exti_stm.c \
+ ao_convert_volt.c \
+ ao_packet_master.c \
+ ao_packet.c \
+ ao_monitor.c \
+ ao_send_packet.c
+
+PRODUCT=TeleBT-v4.0
+PRODUCT_DEF=-DTELEBT_V_4_0
+IDPRODUCT=0x000e
+
+CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS)
+
+PROGNAME=telebt-v4.0-seeed
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+FLASH_PROG=flash-loader/$(PROGNAME)-altos-flash-$(VERSION).elf
+BOTH_HEX=$(PROGNAME)-combined-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_telebt_seeed.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX) $(BOTH_HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+ $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+$(BOTH_HEX): $(PROG) $(FLASH_PROG)
+ ../../ao-tools/ao-elftohex/ao-elftohex -n --output=$@ $(FLASH_PROG) $(PROG)
+
+$(FLASH_PROG): FRC
+ +cd flash-loader && make
+
+$(OBJ): $(INC)
+
+distclean: clean
+
+clean:
+ rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx $(PROGNAME)-*.map
+ rm -f ao_product.h
+
+install:
+
+uninstall:
+
+FRC:
--- /dev/null
+/*
+ * Copyright © 2017 Bdale Garbee <bdale@gag.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.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define AO_STACK_SIZE 504
+
+#define AO_HSE 32000000
+#define AO_RCC_CFGR_PLLMUL STM_RCC_CFGR_PLLMUL_3
+#define AO_RCC_CFGR2_PLLDIV STM_RCC_CFGR2_PREDIV_2
+#define AO_PLLMUL 3
+#define AO_PLLDIV 2
+
+/* 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 0
+
+#define IS_FLASH_LOADER 0
+
+/*
+ * Serial ports
+ */
+#define HAS_SERIAL_1 0
+#define USE_SERIAL_1_STDIN 0
+#define SERIAL_1_PB6_PB7 0
+#define SERIAL_1_PA9_PA10 0
+
+#define HAS_SERIAL_2 1
+#define USE_SERIAL_2_STDIN 1
+#define DELAY_SERIAL_2_STDIN 1
+#define USE_SERIAL_2_FLOW 1
+#define USE_SERIAL_2_SW_FLOW 0
+#define SERIAL_2_PA2_PA3 1
+#define SERIAL_2_PD5_PD6 0
+#define SERIAL_2_PORT_RTS (&stm_gpioa)
+#define SERIAL_2_PIN_RTS 1
+#define SERIAL_2_PORT_CTS (&stm_gpioa)
+#define SERIAL_2_PIN_CTS 0
+
+#define AO_CONFIG_MAX_SIZE 1024
+
+#define HAS_EEPROM 0
+#define USE_INTERNAL_FLASH 0
+#define USE_EEPROM_CONFIG 0
+#define USE_STORAGE_CONFIG 0
+#define HAS_BEEP 0
+#define HAS_BATTERY_REPORT 0
+#define HAS_RADIO 1
+#define HAS_TELEMETRY 0
+#define HAS_APRS 0
+#define HAS_ACCEL 0
+#define HAS_AES 0
+
+#define HAS_SPI_1 1
+#define SPI_1_PA5_PA6_PA7 1 /* CC1200 */
+#define SPI_1_PB3_PB4_PB5 0
+#define SPI_1_PE13_PE14_PE15 0
+#define SPI_1_OSPEEDR STM_OSPEEDR_HIGH
+
+#define HAS_SPI_2 0
+#define SPI_2_PB13_PB14_PB15 0
+#define SPI_2_PD1_PD3_PD4 0
+#define SPI_2_OSPEEDR STM_OSPEEDR_HIGH
+
+#define HAS_I2C_1 0
+#define I2C_1_PB8_PB9 0
+
+#define HAS_I2C_2 0
+#define I2C_2_PB10_PB11 0
+
+#define PACKET_HAS_SLAVE 0
+#define PACKET_HAS_MASTER 1
+
+#define LOW_LEVEL_DEBUG 0
+
+#define LED_PORT_0_ENABLE STM_RCC_AHBENR_IOPBEN
+#define LED_PORT_1_ENABLE STM_RCC_AHBENR_IOPCEN
+#define LED_PORT_0 (&stm_gpiob)
+#define LED_PORT_1 (&stm_gpioc)
+#define LED_PORT_0_SHIFT 0
+#define LED_PORT_1_SHIFT 0
+#define LED_PIN_RED (0 + LED_PORT_0_SHIFT)
+#define LED_PIN_BLUE (15 + LED_PORT_1_SHIFT)
+#define AO_LED_RED (1 << LED_PIN_RED)
+#define AO_LED_BLUE (1 << LED_PIN_BLUE)
+#define LED_PORT_0_MASK (AO_LED_RED)
+#define LED_PORT_1_MASK (AO_LED_BLUE)
+#define AO_BT_LED AO_LED_BLUE
+
+#define AO_FAIL_ADC 1
+#define AO_FAIL_RADIO 2
+#define AO_FAIL_BT 3
+
+#define ao_bt_panic(x) ao_panic(AO_FAIL_BT)
+
+#define LEDS_AVAILABLE (AO_LED_RED | AO_LED_BLUE)
+
+#define HAS_GPS 0
+#define HAS_FLIGHT 0
+#define HAS_ADC 1
+#define HAS_ADC_TEMP 0
+#define HAS_LOG 0
+#undef HAS_BATTERY_REPORT
+#define HAS_BATTERY_REPORT 1
+
+/*
+ * ADC
+ */
+#define AO_DATA_RING 32
+#define AO_ADC_NUM_SENSE 2
+
+struct ao_adc {
+ int16_t v_batt;
+};
+
+#define AO_ADC_DUMP(p) \
+ printf("tick: %5lu batt %5d\n", \
+ (p)->tick, \
+ (p)->adc.v_batt);
+
+#define AO_ADC_V_BATT 4
+#define AO_ADC_V_BATT_PORT (&stm_gpioa)
+#define AO_ADC_V_BATT_PIN 4
+
+#define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_IOPAEN))
+
+#define AO_NUM_ADC_PIN 1
+
+#define AO_ADC_PIN0_PORT AO_ADC_V_BATT_PORT
+#define AO_ADC_PIN0_PIN AO_ADC_V_BATT_PIN
+#define AO_ADC_PIN0_CH AO_ADC_V_BATT_PIN
+
+#define AO_NUM_ADC (AO_NUM_ADC_PIN)
+
+#define AO_ADC_SQ1 AO_ADC_V_BATT
+
+/*
+ * Voltage divider on ADC battery sampler
+ */
+#define AO_BATTERY_DIV_PLUS 51 /* 5.1k */
+#define AO_BATTERY_DIV_MINUS 100 /* 10k */
+
+/*
+ * ADC reference in decivolts
+ */
+#define AO_ADC_REFERENCE_DV 33
+
+/*
+ * RN4678
+ */
+#define HAS_RN 1
+
+#define ao_serial_rn_getchar ao_serial2_getchar
+#define ao_serial_rn_putchar ao_serial2_putchar
+#define _ao_serial_rn_pollchar _ao_serial2_pollchar
+#define _ao_serial_rn_sleep_for _ao_serial2_sleep_for
+#define ao_serial_rn_set_speed ao_serial2_set_speed
+#define ao_serial_rn_drain ao_serial2_drain
+#define ao_serial_rn_rx_fifo (ao_stm_usart2.rx_fifo)
+
+/* Pin 5. BM70 P2_2 */
+#define AO_RN_SW_BTN_PORT (&stm_gpioc)
+#define AO_RN_SW_BTN_PIN 14
+
+/* Pin 12. BM70 P1_5. Status indication along with P0_4 */
+#define AO_RN_P1_5_PORT (&stm_gpiob)
+#define AO_RN_P1_5_PIN 6
+
+/* Pin 21. BM70 RST_N. */
+#define AO_RN_RST_N_PORT (&stm_gpioa)
+#define AO_RN_RST_N_PIN 15
+
+/* Pin 22. BM70 RXD. */
+#define AO_RN_RXD_PORT (&stm_gpioa)
+#define AO_RN_RXD_PIN 2
+
+/* Pin 23. BM70 TXD. */
+#define AO_RN_TXD_PORT (&stm_gpioa)
+#define AO_RN_TXD_PIN 3
+
+/* Pin 24. BM70 P3_1/RSSI_IND. */
+#define AO_RN_P3_1_PORT (&stm_gpiob)
+#define AO_RN_P3_1_PIN 2
+
+/* Pin 29. BM70 P0_7. */
+#define AO_RN_P3_7_PORT (&stm_gpiob)
+#define AO_RN_P3_7_PIN 12
+
+/*
+ * Radio (cc1200)
+ */
+
+/* gets pretty close to 434.550 */
+
+#define AO_RADIO_CAL_DEFAULT 5695485
+
+#define AO_FEC_DEBUG 0
+#define AO_CC1200_SPI_CS_PORT (&stm_gpiob)
+#define AO_CC1200_SPI_CS_PIN 11
+#define AO_CC1200_SPI_BUS AO_SPI_1_PA5_PA6_PA7
+#define AO_CC1200_SPI stm_spi1
+
+#define AO_CC1200_INT_PORT (&stm_gpiob)
+#define AO_CC1200_INT_PIN (10)
+
+#define AO_CC1200_INT_GPIO 2
+#define AO_CC1200_INT_GPIO_IOCFG CC1200_IOCFG2
+
+#define HAS_BOOT_RADIO 0
+
+/* Monitor bits */
+#define HAS_MONITOR 1
+#define LEGACY_MONITOR 0
+#define AO_MONITOR_LED AO_LED_RED
+
+#endif /* _AO_PINS_H_ */
--- /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; 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.
+ */
+
+#include <ao.h>
+#include <ao_exti.h>
+#include <ao_packet.h>
+#include <ao_send_packet.h>
+#include <ao_usb.h>
+#include <ao_rn4678.h>
+
+static void
+ao_validate(void)
+{
+ uint8_t data;
+ int16_t decivolt;
+ int i;
+
+ ao_config_get();
+
+ /* Check the battery voltage */
+ for (i = 0; i < 10; i++) {
+ data = ao_data_head;
+ do {
+ ao_sleep((void *) &ao_data_head);
+ } while (ao_data_head == data);
+ }
+ decivolt = ao_battery_decivolt(ao_data_ring[data].adc.v_batt);
+ if (decivolt < 35 || 55 < decivolt)
+ ao_panic(AO_FAIL_ADC);
+
+ if (!ao_radio_post())
+ ao_panic(AO_FAIL_RADIO);
+
+ /*
+ * Wait for BT module to come online. That will panic if it
+ * doesn't work
+ */
+ for (;;) {
+ if (ao_num_stdios == 2)
+ break;
+ ao_delay(AO_SEC_TO_TICKS(1));
+ }
+
+ ao_led_on(AO_LED_BLUE);
+
+ ao_exit();
+}
+
+struct ao_task ao_validate_task;
+
+int
+main(void)
+{
+ ao_clock_init();
+
+ ao_task_init();
+ ao_led_init();
+ ao_led_off(LEDS_AVAILABLE);
+ ao_timer_init();
+
+ ao_spi_init();
+ ao_dma_init();
+ ao_exti_init();
+
+ ao_adc_init();
+ ao_cmd_init();
+// ao_send_packet_init();
+
+ ao_usb_init();
+ ao_serial_init();
+
+ ao_radio_init();
+// ao_packet_master_init();
+// ao_monitor_init();
+ ao_rn4678_init();
+
+ ao_config_init();
+
+ ao_add_task(&ao_validate_task, ao_validate, "validate");
+
+ ao_start_scheduler();
+ return 0;
+}
--- /dev/null
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=telebt-v4.0-seeed
+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; 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.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#include <ao_flash_stm_pins.h>
+
+/* ground U7 pin 30 to force bootload */
+
+#define AO_BOOT_PIN 1
+#define AO_BOOT_APPLICATION_GPIO stm_gpioa
+#define AO_BOOT_APPLICATION_PIN 9
+#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 0
+
+#endif /* _AO_PINS_H_ */
--- /dev/null
+/*
+ * Copyright © 2024 Bdale Garbee <bdale@gag.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.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define LED_PORT_ENABLE STM_RCC_AHBENR_IOPBEN
+#define LED_PORT (&stm_gpiob)
+#define LED_PIN_GREEN 5
+#define AO_LED_GREEN (1 << LED_PIN_GREEN)
+#define AO_LED_PANIC AO_LED_GREEN
+#define AO_LED_GPS_LOCK AO_LED_GREEN
+
+#define LEDS_AVAILABLE (AO_LED_GREEN)
+
+#define AO_STACK_SIZE 512
+
+#define IS_FLASH_LOADER 0
+#define HAS_BEEP 0
+
+#define AO_HSE 16000000
+#define AO_RCC_CFGR_PLLMUL STM_RCC_CFGR_PLLMUL_3
+#define AO_RCC_CFGR2_PLLDIV STM_RCC_CFGR2_PREDIV_1
+#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 HAS_USB_CONNECT 1
+#define AO_USB_CONNECT_PORT (&stm_gpiob)
+#define AO_USB_CONNECT_PIN 3
+
+#define IS_FLASH_LOADER 0
+
+/* ADC */
+
+#define HAS_ADC 1
+#define AO_ADC_PIN0_PORT (&stm_gpiob)
+#define AO_ADC_PIN0_PIN 1
+#define AO_ADC_PIN0_CH 9
+
+#define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_IOPBEN))
+
+#define ao_telemetry_battery_convert(a) ((a) << 3)
+
+#define AO_NUM_ADC 1
+
+#define AO_DATA_RING 4
+
+/*
+ * Voltage divider on ADC battery sampler
+ */
+#define AO_BATTERY_DIV_PLUS 56 /* 5.6k */
+#define AO_BATTERY_DIV_MINUS 100 /* 10k */
+
+/*
+ * ADC reference in decivolts
+ */
+#define AO_ADC_REFERENCE_DV 33
+
+struct ao_adc {
+ int16_t v_batt;
+};
+
+#define AO_ADC_DUMP(p) \
+ printf("tick: %5lu batt: %5d\n", \
+ (p)->tick, \
+ (p)->adc.v_batt)
+
+/* SPI */
+#define HAS_SPI_1 1
+#define HAS_SPI_2 0
+#define SPI_1_PA5_PA6_PA7 1
+#define SPI_1_PB3_PB4_PB5 0
+#define SPI_1_OSPEEDR STM_OSPEEDR_HIGH
+
+/* Flash */
+
+#define M25_MAX_CHIPS 1
+#define AO_M25_SPI_CS_PORT (&stm_gpiob)
+#define AO_M25_SPI_CS_MASK (1 << 0)
+#define AO_M25_SPI_BUS AO_SPI_1_PA5_PA6_PA7
+
+/* Serial */
+#define HAS_SERIAL_1 0
+#define SERIAL_1_PB6_PB7 1
+#define USE_SERIAL_1_STDIN 0
+
+#define HAS_SERIAL_2 1
+#define SERIAL_2_PA2_PA3 1
+#define USE_SERIAL_2_STDIN 0
+#define USE_SERIAL_2_FLOW 0
+#define USE_SERIAL_2_SW_FLOW 0
+
+#define ao_gps_getchar ao_serial2_getchar
+#define ao_gps_putchar ao_serial2_putchar
+#define ao_gps_set_speed ao_serial2_set_speed
+
+#define HAS_EEPROM 1
+#define USE_INTERNAL_FLASH 0
+#define HAS_RADIO 1
+#define HAS_TELEMETRY 1
+#define HAS_RDF 1
+#define HAS_APRS 1
+
+#define HAS_GPS 1
+#define HAS_FLIGHT 0
+#define HAS_LOG 1
+#define FLIGHT_LOG_APPEND 1
+#define HAS_TRACKER 1
+#define LOG_ADC 0
+
+#define AO_CONFIG_DEFAULT_APRS_INTERVAL 0
+#define AO_CONFIG_DEFAULT_RADIO_POWER 0xc0
+#define AO_LOG_FORMAT AO_LOG_FORMAT_TELEGPS
+
+/*
+ * GPS
+ */
+
+#define AO_SERIAL_SPEED_UBLOX AO_SERIAL_SPEED_9600
+#define AO_UBLOX_VERSION 10
+
+/*
+ * Radio (cc1200)
+ */
+
+/* gets pretty close to 434.550 */
+
+#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 1
+#define AO_CC1200_SPI_BUS AO_SPI_1_PA5_PA6_PA7
+#define AO_CC1200_SPI stm_spi1
+
+#define AO_CC1200_INT_PORT (&stm_gpioa)
+#define AO_CC1200_INT_PIN 4
+
+#define AO_CC1200_INT_GPIO 2
+#define AO_CC1200_INT_GPIO_IOCFG CC1200_IOCFG2
+
+#define HAS_BOOT_RADIO 0
+
+#endif /* _AO_PINS_H_ */
--- /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.
+ */
+
+#include <ao.h>
+#include <ao_log.h>
+#include <ao_exti.h>
+#include <ao_tracker.h>
+
+#define AO_FAIL_FLASH 1
+#define AO_FAIL_ADC 2
+#define AO_FAIL_GPS 3
+#define AO_FAIL_RADIO 4
+
+static void
+ao_validate(void)
+{
+ static struct ao_telemetry_location gps_data;
+ static struct ao_telemetry_satellite gps_tracking_data;
+ uint8_t new;
+ uint8_t data;
+ int16_t decivolt;
+ AO_TICK_TYPE gps_start;
+
+ /* Check the flash part */
+ ao_storage_setup();
+ if (ao_storage_total != 2 * 1024 * 1024)
+ ao_panic(AO_FAIL_FLASH);
+
+ /* Check the battery voltage */
+ data = ao_data_head;
+ do {
+ ao_sleep((void *) &ao_data_head);
+ } while (ao_data_head == data);
+ decivolt = ao_battery_decivolt(ao_data_ring[data].adc.v_batt);
+ if (decivolt < 35 && 55 < decivolt)
+ ao_panic(AO_FAIL_ADC);
+
+ /* Check to make sure GPS data is being received */
+ gps_start = ao_time();
+ for (;;) {
+ while ((new = ao_gps_new) == 0)
+ ao_sleep_for(&ao_gps_new, AO_SEC_TO_TICKS(1));
+ ao_mutex_get(&ao_gps_mutex);
+ if (new & AO_GPS_NEW_DATA)
+ memcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data));
+ if (new & AO_GPS_NEW_TRACKING)
+ memcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data));
+ ao_gps_new = 0;
+ ao_mutex_put(&ao_gps_mutex);
+
+ if (new & AO_GPS_NEW_DATA) {
+ if (gps_data.flags & AO_GPS_RUNNING)
+ break;
+ }
+ if ((AO_TICK_SIGNED) (ao_time() - gps_start) > (AO_TICK_SIGNED) AO_SEC_TO_TICKS(10))
+ ao_panic(AO_FAIL_GPS);
+ }
+
+ if (!ao_radio_post())
+ ao_panic(AO_FAIL_RADIO);
+
+ ao_led_on(LEDS_AVAILABLE);
+ ao_exit();
+}
+
+struct ao_task ao_validate_task;
+
+int
+main(void)
+{
+ ao_clock_init();
+ ao_task_init();
+ ao_cmd_init();
+ ao_config_init();
+
+ ao_led_init();
+ ao_led_off(LEDS_AVAILABLE);
+
+ /* internal systems */
+ ao_timer_init();
+ ao_dma_init();
+ ao_exti_init();
+
+ /* SoC hardware */
+ ao_adc_init();
+ ao_serial_init();
+ ao_spi_init();
+ ao_usb_init();
+
+ /* External hardware */
+ ao_storage_init();
+ ao_radio_init();
+ ao_gps_init();
+
+
+ ao_add_task(&ao_validate_task, ao_validate, "validate");
+
+ ao_start_scheduler();
+}
--- /dev/null
+*.elf
+*.bin
--- /dev/null
+/*
+ * Copyright © 2024 Bdale Garbee <bdale@gag.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.
+ */
+
+#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_gpiob
+#define AO_BOOT_APPLICATION_PIN 6
+#define AO_BOOT_APPLICATION_VALUE 1
+#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP
+
+#define HAS_USB 1
+#define AO_USB_DIRECTIO 0
+#define AO_PA11_PA12_RMP 1
+
+#endif /* _AO_PINS_H_ */
--- /dev/null
+#
+# AltOS build
+#
+#
+
+TOPDIR=..
+
+include $(TOPDIR)/stmf0/Makefile.defs
+
+INC = \
+ ao.h \
+ ao_arch.h \
+ ao_arch_funcs.h \
+ ao_pins.h \
+ ao_product.h \
+ ao_tracker.h \
+ ao_task.h \
+ ao_cc1200.h \
+ ao_fec.h \
+ stm32f0.h \
+ Makefile
+
+
+ALTOS_SRC = \
+ ao_adc_stm.c \
+ ao_led_stmf0.c \
+ ao_interrupt.c \
+ ao_boot_chain.c \
+ ao_product.c \
+ ao_romconfig.c \
+ ao_cmd.c \
+ ao_config.c \
+ ao_task.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_usb_stm.c \
+ ao_exti_stm.c \
+ ao_serial_stm.c \
+ ao_gps_ublox.c \
+ ao_gps_show.c \
+ ao_cc1200.c \
+ ao_aprs.c \
+ ao_tracker.c \
+ ao_telemetry.c \
+ ao_storage.c \
+ ao_m25.c \
+ ao_log.c \
+ ao_log_gps.c \
+ ao_distance.c \
+ ao_sqrt.c \
+ ao_data.c \
+ ao_convert_volt.c \
+ $(SAMPLE_PROFILE)
+
+PRODUCT=TeleGPS-v4.0
+PRODUCT_DEF=-DTELEGPS
+IDPRODUCT=0x0025
+
+CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) $(PROFILE_DEF)
+
+PROGNAME=telegps-v4.0
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_telegps.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+ $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS) -Wl,-Map=$(PROGNAME)-$(VERSION).map
+
+$(OBJ): $(INC)
+
+distclean: clean
+
+clean:
+ rm -f *.o ao_serial_stm.h $(PROGNAME)-*.elf $(PROGNAME)-*.ihx $(PROGNAME)-*.map
+ rm -f ao_product.h
+
+install:
+
+uninstall:
--- /dev/null
+/*
+ * Copyright © 2024 Bdale Garbee <bdale@gag.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.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define LED_PORT_ENABLE STM_RCC_AHBENR_IOPBEN
+#define LED_PORT (&stm_gpiob)
+#define LED_PIN_GREEN 5
+#define AO_LED_GREEN (1 << LED_PIN_GREEN)
+#define AO_LED_PANIC AO_LED_GREEN
+#define AO_LED_GPS_LOCK AO_LED_GREEN
+
+#define LEDS_AVAILABLE (AO_LED_GREEN)
+
+#define AO_STACK_SIZE 512
+
+#define IS_FLASH_LOADER 0
+#define HAS_BEEP 0
+
+#define AO_HSE 16000000
+#define AO_RCC_CFGR_PLLMUL STM_RCC_CFGR_PLLMUL_3
+#define AO_RCC_CFGR2_PLLDIV STM_RCC_CFGR2_PREDIV_1
+#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 HAS_USB_CONNECT 1
+#define AO_USB_CONNECT_PORT (&stm_gpiob)
+#define AO_USB_CONNECT_PIN 3
+
+#define IS_FLASH_LOADER 0
+
+/* ADC */
+
+#define HAS_ADC 1
+#define AO_ADC_PIN0_PORT (&stm_gpiob)
+#define AO_ADC_PIN0_PIN 1
+#define AO_ADC_PIN0_CH 9
+
+#define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_IOPBEN))
+
+#define ao_telemetry_battery_convert(a) ((a) << 3)
+
+#define AO_NUM_ADC 1
+
+#define AO_DATA_RING 4
+
+/*
+ * Voltage divider on ADC battery sampler
+ */
+#define AO_BATTERY_DIV_PLUS 56 /* 5.6k */
+#define AO_BATTERY_DIV_MINUS 100 /* 10k */
+
+/*
+ * ADC reference in decivolts
+ */
+#define AO_ADC_REFERENCE_DV 33
+
+struct ao_adc {
+ int16_t v_batt;
+};
+
+#define AO_ADC_DUMP(p) \
+ printf("tick: %5lu batt: %5d\n", \
+ (p)->tick, \
+ (p)->adc.v_batt)
+
+/* SPI */
+#define HAS_SPI_1 1
+#define HAS_SPI_2 0
+#define SPI_1_PA5_PA6_PA7 1
+#define SPI_1_PB3_PB4_PB5 0
+#define SPI_1_OSPEEDR STM_OSPEEDR_HIGH
+
+/* Flash */
+
+#define M25_MAX_CHIPS 1
+#define AO_M25_SPI_CS_PORT (&stm_gpiob)
+#define AO_M25_SPI_CS_MASK (1 << 0)
+#define AO_M25_SPI_BUS AO_SPI_1_PA5_PA6_PA7
+
+/* Serial */
+#define HAS_SERIAL_1 0
+#define SERIAL_1_PB6_PB7 1
+#define USE_SERIAL_1_STDIN 0
+
+#define HAS_SERIAL_2 1
+#define SERIAL_2_PA2_PA3 1
+#define USE_SERIAL_2_STDIN 0
+#define USE_SERIAL_2_FLOW 0
+#define USE_SERIAL_2_SW_FLOW 0
+
+#define ao_gps_getchar ao_serial2_getchar
+#define ao_gps_putchar ao_serial2_putchar
+#define ao_gps_set_speed ao_serial2_set_speed
+
+#define HAS_EEPROM 1
+#define USE_INTERNAL_FLASH 0
+#define HAS_RADIO 1
+#define HAS_TELEMETRY 1
+#define HAS_RDF 1
+#define HAS_APRS 1
+
+#define HAS_GPS 1
+#define HAS_FLIGHT 0
+#define HAS_LOG 1
+#define FLIGHT_LOG_APPEND 1
+#define HAS_TRACKER 1
+#define LOG_ADC 0
+
+#define AO_CONFIG_DEFAULT_APRS_INTERVAL 0
+#define AO_CONFIG_DEFAULT_RADIO_POWER 0xc0
+#define AO_LOG_FORMAT AO_LOG_FORMAT_TELEGPS
+
+/*
+ * GPS
+ */
+
+#define AO_SERIAL_SPEED_UBLOX AO_SERIAL_SPEED_9600
+#define AO_UBLOX_VERSION 10
+
+/*
+ * Radio (cc1200)
+ */
+
+/* gets pretty close to 434.550 */
+
+#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 1
+#define AO_CC1200_SPI_BUS AO_SPI_1_PA5_PA6_PA7
+#define AO_CC1200_SPI stm_spi1
+
+#define AO_CC1200_INT_PORT (&stm_gpioa)
+#define AO_CC1200_INT_PIN 4
+
+#define AO_CC1200_INT_GPIO 2
+#define AO_CC1200_INT_GPIO_IOCFG CC1200_IOCFG2
+
+#define HAS_BOOT_RADIO 0
+
+#endif /* _AO_PINS_H_ */
--- /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.
+ */
+
+#include <ao.h>
+#include <ao_log.h>
+#include <ao_exti.h>
+#include <ao_tracker.h>
+
+int
+main(void)
+{
+ ao_clock_init();
+ ao_task_init();
+ ao_cmd_init();
+ ao_config_init();
+
+ ao_led_init();
+ ao_led_on(LEDS_AVAILABLE);
+
+ /* internal systems */
+ ao_timer_init();
+ ao_dma_init();
+ ao_exti_init();
+
+ /* SoC hardware */
+ ao_adc_init();
+ ao_serial_init();
+ ao_spi_init();
+ ao_usb_init();
+
+ /* External hardware */
+ ao_storage_init();
+ ao_radio_init();
+ ao_gps_init();
+
+ /* Services */
+ ao_log_init();
+ ao_telemetry_init();
+ ao_tracker_init();
+
+ ao_led_off(LEDS_AVAILABLE);
+
+ ao_start_scheduler();
+}
--- /dev/null
+*.elf
+*.bin
--- /dev/null
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=telegps-v4.0
+include $(TOPDIR)/stmf0/Makefile-flash.defs
--- /dev/null
+/*
+ * Copyright © 2024 Bdale Garbee <bdale@gag.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.
+ */
+
+#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_gpiob
+#define AO_BOOT_APPLICATION_PIN 6
+#define AO_BOOT_APPLICATION_VALUE 1
+#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP
+
+#define HAS_USB 1
+#define AO_USB_DIRECTIO 0
+#define AO_PA11_PA12_RMP 1
+
+#endif /* _AO_PINS_H_ */
ao_timer.c \
ao_mutex.c \
ao_freq.c \
- ao_adc_single_stm.c \
+ ao_adc_stm.c \
+ ao_data.c \
ao_dma_stm.c \
ao_spi_stm.c \
ao_beep_stm.c \
BitstreamVeraSans-Roman-24.c \
BitstreamVeraSans-Roman-10.c \
BitstreamVeraSans-Roman-12.c \
- BenguiatGothicStd-Bold-26.c \
+ BenguiatGothicStd-Bold-24.c \
ao_quadrature.c \
ao_button.c \
ao_event.c \
BitstreamVeraSans-Roman-24.c: ao_font.h
BitstreamVeraSans-Roman-10.c: ao_font.h
BitstreamVeraSans-Roman-12.c: ao_font.h
-BenguiatGothicStd-Bold-26.c: ao_font.h
+BenguiatGothicStd-Bold-24.c: ao_font.h
install:
#include <ao_st7565.h>
#include <ao_adc_single.h>
#include <ao_pwm.h>
+#include <limits.h>
#define WIDTH AO_ST7565_WIDTH
#define HEIGHT AO_ST7565_HEIGHT
};
static const struct ao_transform logo_transform = {
- .x_scale = 48, .x_off = 2,
- .y_scale = 48, .y_off = 0,
+ .x_scale = 40, .x_off = 8,
+ .y_scale = 40, .y_off = 0,
};
static const struct ao_transform show_transform = {
#define VOLT_FONT BitstreamVeraSans_Roman_58_font
#define SMALL_FONT BitstreamVeraSans_Roman_12_font
#define TINY_FONT BitstreamVeraSans_Roman_10_font
-#define LOGO_FONT BenguiatGothicStd_Bold_26_font
+#define LOGO_FONT BenguiatGothicStd_Bold_24_font
#define LABEL_Y (int16_t) (SMALL_FONT.ascent)
#define VALUE_Y (int16_t) (LABEL_Y + 5 + BIG_FONT.ascent)
#define SCAN_X (WIDTH - 100) / 2
#define SCAN_Y 50
#define SCAN_HEIGHT 3
+#define SCANNING_X (WIDTH / 2)
+#define SCANNING_Y (SCAN_Y - 2)
#define FOUND_Y 63
#define FOUND_X 3
#define FOUND_WIDTH (WIDTH - 6)
#define BACKLIGHT_HEIGHT 20
#define BACKLIGHT_VALUE_X 64
#define BACKLIGHT_VALUE_Y (BACKLIGHT_Y + BACKLIGHT_HEIGHT + SMALL_FONT.ascent + 3)
-#define INFO_START_Y ((int16_t) (SMALL_FONT.ascent + 2))
-#define INFO_STEP_Y ((int16_t) (SMALL_FONT.ascent + 3))
+#define INFO_FONT TINY_FONT
+#define INFO_START_Y ((int16_t) (INFO_FONT.ascent + 2))
+#define INFO_STEP_Y ((int16_t) (INFO_FONT.ascent + 2))
#define AO_LCO_DRAG_RACE_START_TIME AO_SEC_TO_TICKS(5)
#define AO_LCO_DRAG_RACE_STOP_TIME AO_SEC_TO_TICKS(2)
static uint8_t ao_lco_display_mutex;
+static uint8_t ao_sample_data;
+static struct ao_data ao_data_cur;
+
static void
_ao_center_text(int16_t x, int16_t y, const struct ao_font *font, const char *str)
{
}
static void
-_ao_lco_show_voltage(uint16_t decivolts, const char *label)
+_ao_format_voltage(char *str, size_t size, uint16_t decivolts)
{
- char str[7];
-
- PRINTD("voltage %d\n", decivolts);
- _ao_center_text(WIDTH/2, LABEL_Y, &SMALL_FONT, label);
- snprintf(str, sizeof(str), "%d.%d", decivolts / 10, decivolts % 10);
- _ao_center_text(WIDTH/2, VALUE_Y, &BIG_FONT, str);
-}
-
-static void
-_ao_lco_batt_voltage(void)
-{
- struct ao_adc packet;
- int16_t decivolt;
-
- ao_adc_single_get(&packet);
- decivolt = ao_battery_decivolt(packet.v_batt);
- _ao_lco_show_voltage((uint16_t) decivolt, "LCO Battery");
- ao_st7565_update(&fb);
+ snprintf(str, size, "%d.%d", decivolts / 10, decivolts % 10);
}
+#if AO_LCO_HAS_CONTRAST
static void
_ao_lco_show_contrast(void)
{
snprintf(buf, sizeof(buf), "%d %%", brightness * 100 / AO_LCO_MAX_CONTRAST);
_ao_center_text(WIDTH/2, CONTRAST_VALUE_Y, &SMALL_FONT, buf);
}
+#endif
+#if AO_LCO_HAS_BACKLIGHT_UI
static void
_ao_lco_show_backlight(void)
{
snprintf(buf, sizeof(buf), "%ld %%", backlight * 100 / AO_LCO_MAX_BACKLIGHT);
_ao_center_text(WIDTH/2, BACKLIGHT_VALUE_Y, &SMALL_FONT, buf);
}
+#endif
static int16_t info_y;
va_start(a, format);
vsnprintf(buf, sizeof(buf), format, a);
va_end(a);
- ao_text(&fb, &SMALL_FONT, 0, info_y, buf, AO_BLACK, AO_COPY);
+ ao_text(&fb, &INFO_FONT, 0, info_y, buf, AO_BLACK, AO_COPY);
info_y += INFO_STEP_Y;
}
static void
-_ao_lco_show_info(void)
+_ao_lco_show_lco_info(void)
{
- info_y = INFO_START_Y;
+ char battery[7];
+ int16_t decivolt;
+
ao_logo_poly(&fb, &show_transform, AO_BLACK, AO_COPY);
+
+ decivolt = ao_battery_decivolt(ao_data_cur.adc.v_batt);
+ _ao_format_voltage(battery, sizeof(battery), (uint16_t) decivolt);
+
+ info_y = INFO_START_Y;
_ao_lco_info("%s", ao_product);
- _ao_lco_info("Version: %s", ao_version);
_ao_lco_info("Serial: %d", ao_serial_number);
+ _ao_lco_info("Battery: %sV", battery);
+ _ao_lco_info("Version: %s", ao_version);
_ao_lco_info("Callsign: %s", ao_config.callsign);
_ao_lco_info("Frequency: %ld.%03d",
ao_config.frequency / 1000,
(int) (ao_config.frequency % 1000));
}
+static uint8_t
+popcount(uint32_t value)
+{
+ uint8_t count = 0;
+ while(value != 0) {
+ count += value & 1;
+ value >>= 1;
+ }
+ return count;
+}
+
+static void
+_ao_lco_show_pad_info(void)
+{
+ char pad_battery[7];
+
+ ao_logo_poly(&fb, &show_transform, AO_BLACK, AO_COPY);
+ info_y = INFO_START_Y;
+ _ao_lco_info("Bank: %d", ao_lco_box);
+ if (!(ao_lco_valid[ao_lco_box] & AO_LCO_VALID_LAST)) {
+ _ao_lco_info("Contact lost");
+ _ao_lco_info("Last RSSI: %ddBm", ao_radio_cmac_last_rssi);
+ } else {
+ _ao_lco_info("Total pads: %d", popcount(ao_pad_query.channels));
+ _ao_lco_info("RSSI: %ddBm", ao_radio_cmac_rssi);
+ _ao_format_voltage(pad_battery, sizeof(pad_battery), ao_pad_query.battery);
+ _ao_lco_info("Battery: %sV", pad_battery);
+ _ao_lco_info("Arming switch: %s", ao_pad_query.arm_status ? "On" : "Off");
+ }
+}
+
+#define AO_LCO_DIM_BACKLIGHT (AO_LCO_MIN_BACKLIGHT + 3 * AO_LCO_BACKLIGHT_STEP)
+#define AO_AUTO_BACKLIGHT_RANGE (AO_LCO_MAX_BACKLIGHT - AO_LCO_DIM_BACKLIGHT)
+#define AO_AUTO_BACKLIGHT_GAP AO_ADC_MAX / 6
+
+static struct {
+ int16_t v_als;
+ int32_t backlight;
+} ao_lco_backlight_map[] = {
+ { .v_als = AO_ADC_MAX / 6, .backlight = AO_LCO_DIM_BACKLIGHT },
+ { .v_als = AO_ADC_MAX / 3, .backlight = (AO_LCO_MAX_BACKLIGHT - AO_LCO_MIN_BACKLIGHT) / 2 },
+ { .v_als = AO_ADC_MAX / 2, .backlight = AO_LCO_MAX_BACKLIGHT },
+ { .v_als = AO_ADC_MAX * 3 / 4, .backlight = 0 },
+};
+
+#define NUM_BACKLIGHT_MAP sizeof(ao_lco_backlight_map)/sizeof(ao_lco_backlight_map[0])
+
+static unsigned ao_backlight_prev = NUM_BACKLIGHT_MAP - 1;
+
static void
-_ao_lco_show_rssi(void)
+ao_auto_backlight(int16_t als_min, int16_t als_max)
{
- char label[20];
- int16_t width;
- snprintf(label, sizeof(label), "Bank %d RSSI", ao_lco_box);
- width = ao_text_width(&SMALL_FONT, label);
- ao_text(&fb, &SMALL_FONT, VALUE_LABEL_X - width / 2, LABEL_Y, label, AO_BLACK, AO_COPY);
- if (!(ao_lco_valid[ao_lco_box] & AO_LCO_VALID_LAST))
- strcpy(label, "---");
- else
- snprintf(label, sizeof(label), "%d", ao_radio_cmac_rssi);
- width = ao_text_width(&VOLT_FONT, label);
- ao_text(&fb, &VOLT_FONT, VALUE_LABEL_X - width / 2, VALUE_Y, label, AO_BLACK, AO_COPY);
+ unsigned ao_backlight;
+
+ PRINTD("ao_auto_backlight min %d max %d\n", als_min, als_max);
+ ao_backlight = ao_backlight_prev;
+ while (als_min > ao_lco_backlight_map[ao_backlight].v_als + AO_AUTO_BACKLIGHT_GAP) {
+ if (ao_backlight == NUM_BACKLIGHT_MAP - 1)
+ break;
+ ao_backlight++;
+ }
+ while (als_max < ao_lco_backlight_map[ao_backlight].v_als - AO_AUTO_BACKLIGHT_GAP) {
+ if (ao_backlight == 0)
+ return;
+ ao_backlight--;
+ }
+ if (ao_backlight != ao_backlight_prev)
+ {
+ PRINTD(" set backlight to %ld\n", ao_lco_backlight_map[ao_backlight].backlight);
+ ao_lco_set_backlight(ao_lco_backlight_map[ao_backlight].backlight);
+ ao_backlight_prev = ao_backlight;
+ }
}
+#define AO_LCO_BACKLIGHT_INTERVAL AO_SEC_TO_TICKS(2)
+
static void
-_ao_lco_show_pad_battery(void)
+ao_lco_data(void)
{
- char label[20];
- snprintf(label, sizeof(label), "Bank %d Battery", ao_lco_box);
- _ao_lco_show_voltage(ao_pad_query.battery, label);
+ AO_TICK_TYPE backlight_tick = ao_time() + AO_LCO_BACKLIGHT_INTERVAL;
+ AO_TICK_TYPE now;
+ int16_t als_min = INT16_MAX;
+ int16_t als_max = INT16_MIN;
+
+ ao_timer_set_adc_interval(AO_MS_TO_TICKS(100));
+ for (;;) {
+ ao_sleep((void *) &ao_data_head);
+
+ while (ao_sample_data != ao_data_head) {
+ struct ao_data *ao_data;
+
+ /* Capture a sample */
+ ao_data = (struct ao_data *) &ao_data_ring[ao_sample_data];
+
+ ao_data_cur = *ao_data;
+ if (ao_data_cur.adc.v_als < als_min)
+ als_min = ao_data_cur.adc.v_als;
+ if (ao_data_cur.adc.v_als > als_max)
+ als_max = ao_data_cur.adc.v_als;
+ ao_sample_data = ao_data_ring_next(ao_sample_data);
+ }
+ now = ao_time();
+ if ((AO_TICK_SIGNED) (backlight_tick - now) < 0) {
+ backlight_tick = now + AO_LCO_BACKLIGHT_INTERVAL;
+ ao_auto_backlight(als_min, als_max);
+ als_min = INT16_MAX;
+ als_max = INT16_MIN;
+ }
+ }
}
void
ao_mutex_get(&ao_lco_display_mutex);
ao_rect(&fb, 0, 0, WIDTH, HEIGHT, AO_WHITE, AO_COPY);
switch (ao_lco_box) {
- case AO_LCO_LCO_VOLTAGE:
- _ao_lco_batt_voltage();
- break;
+#if AO_LCO_HAS_CONTRAST
case AO_LCO_CONTRAST:
_ao_lco_show_contrast();
break;
+#endif
+#if AO_LCO_HAS_BACKLIGHT_UI
case AO_LCO_BACKLIGHT:
_ao_lco_show_backlight();
break;
- case AO_LCO_INFO:
- _ao_lco_show_info();
+#endif
+ case AO_LCO_LCO_INFO:
+ _ao_lco_show_lco_info();
break;
default:
switch (ao_lco_pad) {
- case AO_LCO_PAD_RSSI:
- _ao_lco_show_rssi();
- break;
- case AO_LCO_PAD_VOLTAGE:
- _ao_lco_show_pad_battery();
+ case AO_LCO_PAD_INFO:
+ _ao_lco_show_pad_info();
break;
default:
_ao_lco_show_pad(ao_lco_pad);
}
+#if AO_LCO_HAS_CONTRAST
void
ao_lco_set_contrast(int32_t contrast)
{
{
return (int32_t) ao_st7565_get_brightness();
}
+#endif
+#if AO_LCO_HAS_BACKLIGHT
static uint16_t ao_backlight;
void
{
return (int32_t) ao_backlight;
}
+#endif
static struct ao_task ao_lco_drag_task;
ao_led_on(AO_LEDS_AVAILABLE);
ao_rect(&fb, 0, 0, WIDTH, HEIGHT, AO_BLACK, AO_COPY);
ao_st7565_update(&fb);
- ao_delay(AO_MS_TO_TICKS(250));
+ ao_delay(AO_MS_TO_TICKS(1000));
ao_led_off(AO_LEDS_AVAILABLE);
}
static struct ao_task ao_lco_input_task;
static struct ao_task ao_lco_monitor_task;
+static struct ao_task ao_lco_data_task;
static struct ao_task ao_lco_arm_warn_task;
static struct ao_task ao_lco_igniter_status_task;
{
ao_rect(&fb, 0, 0, WIDTH, HEIGHT, AO_WHITE, AO_COPY);
ao_logo(&fb, &logo_transform, &LOGO_FONT, AO_BLACK, AO_COPY);
+ _ao_center_text(SCANNING_X, SCANNING_Y, &TINY_FONT, "Scanning...");
found_width = 0;
nfound = 0;
}
ao_lco_init(void)
{
ao_add_task(&ao_lco_monitor_task, ao_lco_main, "lco monitor");
+ ao_add_task(&ao_lco_data_task, ao_lco_data, "lco data");
#if DEBUG
ao_cmd_register(&ao_lco_cmds[0]);
#endif
#define AO_BUTTON_0 1
#define AO_BUTTON_DRAG_SELECT 1
-#define AO_BUTTON_1_PORT &stm_gpioc
-#define AO_BUTTON_1 0
+#define AO_BUTTON_1_PORT &stm_gpiod
+#define AO_BUTTON_1 2
#define AO_BUTTON_SPARE1 2
#define AO_BUTTON_2_PORT &stm_gpiob
/* ADC */
-struct ao_adc {
- int16_t v_batt;
-};
-
-#define AO_ADC_DUMP(p) \
- printf("batt: %5d\n", (p)->v_batt)
+#define AO_DATA_RING 8
-#define HAS_ADC_SINGLE 1
+#define HAS_ADC 1
#define HAS_ADC_TEMP 0
#define HAS_BATTERY_REPORT 1
#define AO_ADC_V_BATT_PORT (&stm_gpioa)
#define AO_ADC_V_BATT_PIN 2
+#define AO_ADC_V_ALS 10
+#define AO_ADC_V_ALS_PORT (&stm_gpioc)
+#define AO_ADC_V_ALS_PIN 0
+
#define AO_ADC_PIN0_PORT AO_ADC_V_BATT_PORT
#define AO_ADC_PIN0_PIN AO_ADC_V_BATT_PIN
+#define AO_ADC_PIN1_PORT AO_ADC_V_ALS_PORT
+#define AO_ADC_PIN1_PIN AO_ADC_V_ALS_PIN
+
#define AO_ADC_SQ1 AO_ADC_V_BATT
+#define AO_ADC_SQ2 AO_ADC_V_ALS
-#define AO_NUM_ADC 1
+#define AO_NUM_ADC 2
+
+struct ao_adc {
+ union {
+ struct {
+ int16_t v_batt;
+ int16_t v_als;
+ };
+ int16_t v_vals[AO_NUM_ADC];
+ };
+};
+
+#define AO_ADC_DUMP(p) \
+ printf("batt: %5d als %5d\n", (p)->adc.v_batt, (p)->adc.v_als)
/*
* Voltage divider on ADC battery sampler
#define AO_ADC_REFERENCE_DV 33
#define AO_LCO_SEARCH_API
-#define AO_LCO_HAS_CONTRAST 1
-#define AO_LCO_MIN_CONTRAST 0
-#define AO_LCO_MAX_CONTRAST 63
-#define AO_LCO_CONTRAST_STEP 1
+
+//#define AO_LCO_HAS_CONTRAST 1
+//#define AO_LCO_MIN_CONTRAST 0
+//#define AO_LCO_MAX_CONTRAST 63
+//#define AO_LCO_CONTRAST_STEP 1
#define AO_LCO_HAS_BACKLIGHT 1
#define AO_LCO_MIN_BACKLIGHT 0
#define AO_LCO_MAX_BACKLIGHT 65535
#define AO_LCO_BACKLIGHT_STEP 771
-#define AO_LCO_HAS_INFO 1
+#define AO_LCO_HAS_LCO_INFO 1
#define AO_LCO_MIN_INFO_PAGE 0
#define AO_LCO_MAX_INFO_PAGE 0
+#define AO_LCO_HAS_PAD_INFO 1
+
/*
* LCD Backlight via PWM.
*
#include <ao_st7565.h>
#include <ao_pwm.h>
-#define WIDTH AO_ST7565_WIDTH
-#define HEIGHT AO_ST7565_HEIGHT
-#define STRIDE AO_BITMAP_STRIDE(WIDTH)
-
-static uint32_t image[STRIDE * HEIGHT];
-
-static struct ao_bitmap fb = {
- .base = image,
- .stride = STRIDE,
- .width = WIDTH,
- .height = HEIGHT,
- .damage = AO_BOX_INIT,
-};
-
-static void
-ao_st7565_test(void)
-{
- ao_rect(&fb, 0, 0, WIDTH, HEIGHT, AO_WHITE, AO_COPY);
- ao_st7565_update(&fb);
- ao_text(&fb, &BitstreamVeraSans_Roman_24_font,
- 0, 20, "hello world", AO_BLACK, AO_COPY);
- ao_st7565_update(&fb);
-}
-
-static int16_t x1 = 32, _y1 = 10, x2 = 32, y2 = 40;
-static int16_t dx1 = 2, dy1 = 2, dx2 = -2, dy2 = -1;
-
-#define bounds(v,m,M,d) \
- if (v < m) { \
- v = m + m - v; \
- d = -d; \
- } else if (v > M) { \
- v = M - (v - M); \
- d = -d; \
- }
-
-static void
-ao_st7565_line(void)
-{
- int i;
-
- for (i = 0; i < 100; i++) {
- ao_rect(&fb, 0, 0, WIDTH, HEIGHT, AO_WHITE, AO_COPY);
- ao_line(&fb, x1, _y1, x2, y2, AO_BLACK, AO_COPY);
- ao_st7565_update(&fb);
- x1 += dx1;
- _y1 += dy1;
- x2 += dx2;
- y2 += dy2;
- printf("%d,%d - %d,%d\n", x1, _y1, x2, y2);
- fflush(stdout);
- bounds(x1, 0, WIDTH, dx1);
- bounds(x2, 0, WIDTH, dx2);
- bounds(_y1, 0, HEIGHT, dy1);
- bounds(y2, 0, HEIGHT, dy2);
- ao_delay(AO_MS_TO_TICKS(200));
- }
-}
-
-static const float pad_volts = 12.3f;
-static const float lco_volts = 4.1f;
-static const int rssi = -30;
-
-static int boxes[] = { 1, 2, 3, 5, 8, 11, 13, 17, 19, 23, 29, 31, 37, 62, 97 };
-
-//static int max_box = 97;
-
-#define ARRAYSIZE(a) (sizeof(a) / sizeof((a)[0]))
-
-static bool
-valid_box(int box)
-{
- size_t i;
- if (box == 0)
- return true;
- for (i = 0; i < ARRAYSIZE(boxes); i++)
- if (boxes[i] == box)
- return true;
- return false;
-}
-
-#if 0
-static void
-next_box(void)
-{
- for (int n = box_number + 1; n <= max_box; n++)
- if (valid_box(n)) {
- box_number = n;
- return;
- }
- box_number = 0;
-}
-
-static void
-prev_box(void)
-{
- for (int n = box_number - 1; n >= 0; n--)
- if (valid_box(n)) {
- box_number = n;
- return;
- }
- box_number = max_box;
-}
-#endif
-
-static const struct ao_transform logo_transform = {
- .x_scale = 48, .x_off = 2,
- .y_scale = 48, .y_off = 0,
-};
-
-#define BIG_FONT BitstreamVeraSans_Roman_58_font
-#define VOLT_FONT BitstreamVeraSans_Roman_58_font
-#define SMALL_FONT BitstreamVeraSans_Roman_12_font
-#define TINY_FONT BitstreamVeraSans_Roman_10_font
-#define LOGO_FONT BenguiatGothicStd_Bold_26_font
-
-#define LABEL_Y (int16_t) (SMALL_FONT.ascent)
-#define VALUE_Y (int16_t) (LABEL_Y + BIG_FONT.ascent + 5)
-#define BOX_X 2
-#define PAD_X 90
-#define BOX_LABEL_X 30
-#define VOLT_LABEL_X 25
-#define RSSI_LABEL_X 15
-#define PAD_LABEL_X 95
-#define SEP_X (PAD_X - 8)
-#define SCAN_X (WIDTH - 100) / 2
-#define SCAN_Y 50
-#define SCAN_HEIGHT 3
-#define FOUND_Y 63
-#define FOUND_X 6
-#define FOUND_WIDTH 17
-#define MAX_VALID (WIDTH / FOUND_WIDTH)
-
-static int16_t box_number = 88;
-static int16_t pad_number = 8;
-
-static void
-ao_st7565_poly(void)
-{
- int16_t scan_number;
- char str[8];
- int i;
- int v;
- int last_box;
- int16_t b;
-
- for (scan_number = 0; scan_number < 100; scan_number++) {
- ao_rect(&fb, 0, 0, WIDTH, HEIGHT, AO_WHITE, AO_COPY);
- ao_logo(&fb, &logo_transform, &LOGO_FONT, AO_BLACK, AO_COPY);
- if (scan_number) {
- ao_rect(&fb, SCAN_X, SCAN_Y, (int16_t) scan_number, SCAN_HEIGHT, AO_BLACK, AO_COPY);
- b = 0;
- v = 0;
- last_box = 0;
- for (i = scan_number; i > 1; i--) {
- if (valid_box(i)) {
- if (!last_box)
- last_box = i;
- v++;
- if (v == MAX_VALID)
- break;
- }
- }
- for (; i <= scan_number; i++) {
- if (valid_box(i)) {
- sprintf(str, "%02d%s", i, i == last_box ? "" : ",");
- ao_text(&fb, &TINY_FONT, (int16_t) (FOUND_X + FOUND_WIDTH * b),
- FOUND_Y, str, AO_BLACK, AO_COPY);
- b++;
- }
- }
- }
- ao_st7565_update(&fb);
- ao_delay(AO_MS_TO_TICKS(50));
- }
- ao_rect(&fb, 0, 0, WIDTH, HEIGHT, AO_WHITE, AO_COPY);
- switch (box_number) {
- case 0:
- sprintf(str, "%4.1f", lco_volts);
- ao_text(&fb, &VOLT_FONT, BOX_X, VALUE_Y, str, AO_BLACK, AO_COPY);
- ao_text(&fb, &SMALL_FONT, VOLT_LABEL_X, LABEL_Y, "LCO Battery", AO_BLACK, AO_COPY);
- break;
- default:
- switch (pad_number) {
- case -1:
- sprintf(str, "%4.1f", pad_volts);
- ao_text(&fb, &VOLT_FONT, BOX_X, VALUE_Y, str, AO_BLACK, AO_COPY);
- ao_text(&fb, &SMALL_FONT, VOLT_LABEL_X, LABEL_Y, "Pad Battery", AO_BLACK, AO_COPY);
- break;
- case 0:
- sprintf(str, "%4d", rssi);
- ao_text(&fb, &VOLT_FONT, BOX_X, VALUE_Y, str, AO_BLACK, AO_COPY);
- ao_text(&fb, &SMALL_FONT, RSSI_LABEL_X, LABEL_Y, "Signal Strength", AO_BLACK, AO_COPY);
- break;
- default:
- sprintf(str, "%02d", box_number);
- ao_text(&fb, &BIG_FONT, BOX_X, VALUE_Y, str, AO_BLACK, AO_COPY);
- ao_text(&fb, &SMALL_FONT, BOX_LABEL_X, LABEL_Y, "Box", AO_BLACK, AO_COPY);
-
- sprintf(str, "%d", pad_number);
- ao_text(&fb, &BIG_FONT, PAD_X, VALUE_Y, str, AO_BLACK, AO_COPY);
- ao_text(&fb, &SMALL_FONT, PAD_LABEL_X, LABEL_Y, "Pad", AO_BLACK, AO_COPY);
-
- ao_rect(&fb, SEP_X, 0, 2, HEIGHT, AO_BLACK, AO_COPY);
- }
- break;
- }
- ao_st7565_update(&fb);
-}
-
-const struct ao_cmds ao_st7565_cmds[] = {
- { ao_st7565_test, "g\0Test ST7565 display" },
- { ao_st7565_line, "l\0Draw lines" },
- { ao_st7565_poly, "p\0Draw polygon" },
- { 0, NULL },
-};
-
int
main(void)
{
ao_spi_init();
ao_dma_init();
ao_exti_init();
- ao_adc_single_init();
+ ao_adc_init();
ao_beep_init();
ao_pwm_init();
ao_lco_init();
ao_lco_cmd_init();
-// ao_cmd_register(ao_st7565_cmds);
-
ao_start_scheduler();
return 0;
}
#define LOG_ERASE_MARK 0x55
#define LOG_MAX_ERASE 128
#define AO_LOG_FORMAT AO_LOG_FORMAT_TELEMEGA
+#define AO_TELEMETRY_MEGA_DATA AO_TELEMETRY_MEGA_DATA_15V
#define HAS_EEPROM 1
#define USE_INTERNAL_FLASH 0
#define LOG_ERASE_MARK 0x55
#define LOG_MAX_ERASE 128
#define AO_LOG_FORMAT AO_LOG_FORMAT_TELEMEGA
+#define AO_TELEMETRY_MEGA_DATA AO_TELEMETRY_MEGA_DATA_15V
#define HAS_EEPROM 1
#define USE_INTERNAL_FLASH 0
#define LOG_ERASE_MARK 0x55
#define LOG_MAX_ERASE 128
#define AO_LOG_FORMAT AO_LOG_FORMAT_TELEMEGA
+#define AO_TELEMETRY_MEGA_DATA AO_TELEMETRY_MEGA_DATA_15V
#define HAS_EEPROM 1
#define USE_INTERNAL_FLASH 0
#define LOG_ERASE_MARK 0x55
#define LOG_MAX_ERASE 128
#define AO_LOG_FORMAT AO_LOG_FORMAT_TELEMEGA_3
+#define AO_TELEMETRY_MEGA_DATA AO_TELEMETRY_MEGA_DATA_15V
#define HAS_EEPROM 1
#define USE_INTERNAL_FLASH 0
#define LOG_ERASE_MARK 0x55
#define LOG_MAX_ERASE 128
#define AO_LOG_FORMAT AO_LOG_FORMAT_TELEMEGA_4
+#define AO_TELEMETRY_MEGA_DATA AO_TELEMETRY_MEGA_DATA_15V
#define HAS_EEPROM 1
#define USE_INTERNAL_FLASH 0
#define LOG_ERASE_MARK 0x55
#define LOG_MAX_ERASE 128
#define AO_LOG_FORMAT AO_LOG_FORMAT_TELEMEGA_5
+#define AO_TELEMETRY_MEGA_DATA AO_TELEMETRY_MEGA_DATA_15V
#define AO_LOG_NORMALIZED 1
#define HAS_EEPROM 1
#define LOG_ERASE_MARK 0x55
#define LOG_MAX_ERASE 128
#define AO_LOG_FORMAT AO_LOG_FORMAT_TELEMEGA_6
+#define AO_TELEMETRY_MEGA_DATA AO_TELEMETRY_MEGA_DATA_15V
#define AO_LOG_NORMALIZED 1
#define HAS_EEPROM 1
--- /dev/null
+ao_product.h
+telemega-*.elf
--- /dev/null
+/*
+ * Copyright © 2017 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.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+
+/* 16MHz High speed external crystal */
+#define AO_HSE 16000000
+
+/* PLLVCO = 96MHz (so that USB will work) */
+#define AO_PLLMUL 6
+#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_6)
+
+/* 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_SERIAL_1 0
+#define USE_SERIAL_1_STDIN 0
+#define SERIAL_1_PB6_PB7 0
+#define SERIAL_1_PA9_PA10 0
+
+#define HAS_SERIAL_2 1
+#define USE_SERIAL_2_STDIN 0
+#define SERIAL_2_PA2_PA3 1
+#define SERIAL_2_PD5_PD6 0
+#define USE_SERIAL_2_FLOW 0
+#define USE_SERIAL_2_SW_FLOW 0
+
+#define HAS_SERIAL_3 0
+#define USE_SERIAL_3_STDIN 0
+#define SERIAL_3_PB10_PB11 0
+#define SERIAL_3_PC10_PC11 0
+#define SERIAL_3_PD8_PD9 0
+
+#define ao_gps_getchar ao_serial2_getchar
+#define ao_gps_putchar ao_serial2_putchar
+#define ao_gps_set_speed ao_serial2_set_speed
+#define ao_gps_fifo (ao_stm_usart2.rx_fifo)
+
+#define AO_UBLOX_VERSION 10
+
+#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX (1024 * 1024)
+#define AO_CONFIG_DEFAULT_ACCEL_PLUS_G -20
+#define AO_CONFIG_DEFAULT_ACCEL_MINUS_G 20
+#define AO_CONFIG_MAX_SIZE 1024
+#define LOG_ERASE_MARK 0x55
+#define LOG_MAX_ERASE 128
+#define AO_LOG_FORMAT AO_LOG_FORMAT_TELEMEGA_7
+#define AO_TELEMETRY_MEGA_DATA AO_TELEMETRY_MEGA_DATA_30V
+#define AO_LOG_NORMALIZED 1
+
+#define HAS_EEPROM 1
+#define USE_INTERNAL_FLASH 0
+#define USE_EEPROM_CONFIG 1
+#define USE_STORAGE_CONFIG 0
+#define HAS_USB 1
+#define HAS_BEEP 1
+#define BEEPER_TIMER 3
+#define BEEPER_CHANNEL 2
+#define BEEPER_PORT (&stm_gpioe)
+#define BEEPER_PIN 4
+#define HAS_BATTERY_REPORT 1
+#define HAS_RADIO 1
+#define HAS_TELEMETRY 1
+#define HAS_APRS 1
+#define HAS_COMPANION 1
+
+#define HAS_SPI_1 1
+#define SPI_1_PA5_PA6_PA7 1 /* Barometer */
+#define SPI_1_PB3_PB4_PB5 1 /* Accelerometer */
+#define SPI_1_PE13_PE14_PE15 1 /* MPU6000 */
+#define SPI_1_OSPEEDR STM_OSPEEDR_10MHz
+
+//#define MMC5983_I2C 1
+
+#define HAS_SPI_2 1
+#define SPI_2_PB13_PB14_PB15 1 /* Flash, Companion */
+#ifndef MMC5983_I2C
+#define SPI_2_PD1_PD3_PD4 1 /* MMC5983 */
+#endif
+#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz
+
+#define HAS_I2C_1 0
+#define I2C_1_PB8_PB9 0
+
+#define HAS_I2C_2 0
+#define I2C_2_PB10_PB11 0
+
+#define PACKET_HAS_SLAVE 1
+#define PACKET_HAS_MASTER 0
+
+#define LOW_LEVEL_DEBUG 0
+
+#define LED_PORT_ENABLE STM_RCC_AHBENR_GPIOCEN
+#define LED_PORT (&stm_gpioc)
+#define LED_PIN_RED 8
+#define LED_PIN_GREEN 9
+#define AO_LED_RED (1 << LED_PIN_RED)
+#define AO_LED_GREEN (1 << LED_PIN_GREEN)
+
+#define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN)
+
+#define HAS_GPS 1
+#define HAS_FLIGHT 1
+#define HAS_ADC 1
+#define HAS_ADC_TEMP 1
+#define HAS_LOG 1
+
+/*
+ * Igniter
+ */
+
+#define HAS_IGNITE 1
+#define HAS_IGNITE_REPORT 1
+
+#define AO_SENSE_PYRO(p,n) ((p)->adc.sense[n])
+#define AO_SENSE_DROGUE(p) ((p)->adc.sense[4])
+#define AO_SENSE_MAIN(p) ((p)->adc.sense[5])
+#define AO_IGNITER_CLOSED 400
+#define AO_IGNITER_OPEN 60
+
+/* Pyro A */
+#define AO_PYRO_PORT_0 (&stm_gpiod)
+#define AO_PYRO_PIN_0 6
+
+/* Pyro B */
+#define AO_PYRO_PORT_1 (&stm_gpiod)
+#define AO_PYRO_PIN_1 7
+
+/* Pyro C */
+#define AO_PYRO_PORT_2 (&stm_gpioe)
+#define AO_PYRO_PIN_2 3
+
+/* Pyro D */
+#define AO_PYRO_PORT_3 (&stm_gpioe)
+#define AO_PYRO_PIN_3 2
+
+/* Drogue */
+#define AO_IGNITER_DROGUE_PORT (&stm_gpioe)
+#define AO_IGNITER_DROGUE_PIN 6
+
+/* Main */
+#define AO_IGNITER_MAIN_PORT (&stm_gpioe)
+#define AO_IGNITER_MAIN_PIN 5
+
+/* Number of general purpose pyro channels available */
+#define AO_PYRO_NUM 4
+
+/*
+ * ADC
+ */
+#define AO_DATA_RING 32
+#define AO_ADC_NUM_SENSE 6
+
+struct ao_adc {
+ int16_t sense[AO_ADC_NUM_SENSE];
+ int16_t v_batt;
+ int16_t v_pbatt;
+ int16_t temp;
+};
+
+#define AO_ADC_DUMP(p) \
+ printf("tick: %5lu A: %5d B: %5d C: %5d D: %5d drogue: %5d main: %5d batt: %5d pbatt: %5d temp: %5d\n", \
+ (p)->tick, \
+ (p)->adc.sense[0], (p)->adc.sense[1], (p)->adc.sense[2], \
+ (p)->adc.sense[3], (p)->adc.sense[4], (p)->adc.sense[5], \
+ (p)->adc.v_batt, (p)->adc.v_pbatt, (p)->adc.temp)
+
+#define AO_ADC_SENSE_A 0
+#define AO_ADC_SENSE_A_PORT (&stm_gpioa)
+#define AO_ADC_SENSE_A_PIN 0
+
+#define AO_ADC_SENSE_B 1
+#define AO_ADC_SENSE_B_PORT (&stm_gpioa)
+#define AO_ADC_SENSE_B_PIN 1
+
+#define AO_ADC_SENSE_C 24
+#define AO_ADC_SENSE_C_PORT (&stm_gpioe)
+#define AO_ADC_SENSE_C_PIN 9
+
+#define AO_ADC_SENSE_D 25
+#define AO_ADC_SENSE_D_PORT (&stm_gpioe)
+#define AO_ADC_SENSE_D_PIN 10
+
+#define AO_ADC_SENSE_DROGUE 4
+#define AO_ADC_SENSE_DROGUE_PORT (&stm_gpioa)
+#define AO_ADC_SENSE_DROGUE_PIN 4
+
+#define AO_ADC_SENSE_MAIN 22
+#define AO_ADC_SENSE_MAIN_PORT (&stm_gpioe)
+#define AO_ADC_SENSE_MAIN_PIN 7
+
+#define AO_ADC_V_BATT 8
+#define AO_ADC_V_BATT_PORT (&stm_gpiob)
+#define AO_ADC_V_BATT_PIN 0
+
+#define AO_ADC_V_PBATT 9
+#define AO_ADC_V_PBATT_PORT (&stm_gpiob)
+#define AO_ADC_V_PBATT_PIN 1
+
+#define AO_ADC_TEMP 16
+
+#define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_GPIOAEN) | \
+ (1 << STM_RCC_AHBENR_GPIOEEN) | \
+ (1 << STM_RCC_AHBENR_GPIOBEN))
+
+#define AO_NUM_ADC_PIN (AO_ADC_NUM_SENSE + 2)
+
+#define AO_ADC_PIN0_PORT AO_ADC_SENSE_A_PORT
+#define AO_ADC_PIN0_PIN AO_ADC_SENSE_A_PIN
+#define AO_ADC_PIN1_PORT AO_ADC_SENSE_B_PORT
+#define AO_ADC_PIN1_PIN AO_ADC_SENSE_B_PIN
+#define AO_ADC_PIN2_PORT AO_ADC_SENSE_C_PORT
+#define AO_ADC_PIN2_PIN AO_ADC_SENSE_C_PIN
+#define AO_ADC_PIN3_PORT AO_ADC_SENSE_D_PORT
+#define AO_ADC_PIN3_PIN AO_ADC_SENSE_D_PIN
+#define AO_ADC_PIN4_PORT AO_ADC_SENSE_DROGUE_PORT
+#define AO_ADC_PIN4_PIN AO_ADC_SENSE_DROGUE_PIN
+#define AO_ADC_PIN5_PORT AO_ADC_SENSE_MAIN_PORT
+#define AO_ADC_PIN5_PIN AO_ADC_SENSE_MAIN_PIN
+#define AO_ADC_PIN6_PORT AO_ADC_V_BATT_PORT
+#define AO_ADC_PIN6_PIN AO_ADC_V_BATT_PIN
+#define AO_ADC_PIN7_PORT AO_ADC_V_PBATT_PORT
+#define AO_ADC_PIN7_PIN AO_ADC_V_PBATT_PIN
+
+#define AO_NUM_ADC (AO_ADC_NUM_SENSE + 3)
+
+#define AO_ADC_SQ1 AO_ADC_SENSE_A
+#define AO_ADC_SQ2 AO_ADC_SENSE_B
+#define AO_ADC_SQ3 AO_ADC_SENSE_C
+#define AO_ADC_SQ4 AO_ADC_SENSE_D
+#define AO_ADC_SQ5 AO_ADC_SENSE_DROGUE
+#define AO_ADC_SQ6 AO_ADC_SENSE_MAIN
+#define AO_ADC_SQ7 AO_ADC_V_BATT
+#define AO_ADC_SQ8 AO_ADC_V_PBATT
+#define AO_ADC_SQ9 AO_ADC_TEMP
+
+/*
+ * Voltage divider on ADC battery sampler
+ */
+#define AO_BATTERY_DIV_PLUS 56 /* 5.6k */
+#define AO_BATTERY_DIV_MINUS 100 /* 10k */
+
+/*
+ * Voltage divider on ADC pyro battery sampler
+ */
+#define AO_PYRO_BATTERY_DIV_PLUS 100 /* 100k */
+#define AO_PYRO_BATTERY_DIV_MINUS 12 /* 12k */
+
+/*
+ * Voltage divider on ADC igniter samplers
+ */
+#define AO_IGNITE_DIV_PLUS 100 /* 100k */
+#define AO_IGNITE_DIV_MINUS 12 /* 12k */
+
+/*
+ * ADC reference in decivolts
+ */
+#define AO_ADC_REFERENCE_DV 33
+
+/*
+ * Pressure sensor settings
+ */
+#define HAS_MS5607 1
+#define HAS_MS5611 0
+#define AO_MS5607_PRIVATE_PINS 1
+#define AO_MS5607_CS_PORT (&stm_gpioc)
+#define AO_MS5607_CS_PIN 4
+#define AO_MS5607_CS_MASK (1 << AO_MS5607_CS)
+#define AO_MS5607_MISO_PORT (&stm_gpioa)
+#define AO_MS5607_MISO_PIN 6
+#define AO_MS5607_MISO_MASK (1 << AO_MS5607_MISO)
+#define AO_MS5607_SPI_INDEX AO_SPI_1_PA5_PA6_PA7
+
+/*
+ * SPI Flash memory
+ */
+
+#define M25_MAX_CHIPS 1
+#define AO_M25_SPI_CS_PORT (&stm_gpiod)
+#define AO_M25_SPI_CS_MASK (1 << 10)
+#define AO_M25_SPI_BUS AO_SPI_2_PB13_PB14_PB15
+
+/*
+ * Radio (cc1200)
+ */
+
+/* gets pretty close to 434.550 */
+
+#define AO_RADIO_CAL_DEFAULT 5695733
+
+#define AO_FEC_DEBUG 0
+#define AO_CC1200_SPI_CS_PORT (&stm_gpioc)
+#define AO_CC1200_SPI_CS_PIN 5
+#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 AO_CC1200_MARC_GPIO 3
+#define AO_CC1200_MARC_GPIO_IOCFG CC1200_IOCFG3
+
+#define HAS_BOOT_RADIO 0
+
+
+/*
+ *
+ * Here are the required sensor signs:
+ *
+ * +along nose up
+ * +across USB down
+ * +through TH down
+ *
+ * With the board aligned to have positive accel for the relevant
+ * axis, looking down from above we have:
+ *
+ * +roll counter clockwise (nose up)
+ * +pitch counter clockwise (USB down)
+ * +yaw counter clockwise (TH down)
+ */
+
+/*
+ * On TMega v6, bmi088 pin 1 (NE corner of chip) is placed towards the
+ * USB and antenna edges of the board. Relative to bmi088 specs, to
+ * get the above values, we need to flip the Y axis, assigning values
+ * as follows:
+ *
+ * +along +X +roll +X
+ * +across -Y +pitch -Y
+ * +through +Z +yaw +Z
+ */
+
+#define HAS_BMI088 1
+#define AO_BMI088_SPI_BUS AO_SPI_1_PE13_PE14_PE15
+#define AO_BMI088_ACC_CS_PORT (&stm_gpioc)
+#define AO_BMI088_ACC_CS_PIN 14
+#define AO_BMI088_GYR_CS_PORT (&stm_gpioc)
+#define AO_BMI088_GYR_CS_PIN 13
+#define HAS_IMU 1
+
+#define ao_bmi088_along(m) ((m)->acc.x)
+#define ao_bmi088_across(m) (-(m)->acc.y)
+#define ao_bmi088_through(m) ((m)->acc.z)
+
+#define ao_bmi088_roll(m) ((m)->gyr.x)
+#define ao_bmi088_pitch(m) (-(m)->gyr.y)
+#define ao_bmi088_yaw(m) ((m)->gyr.z)
+
+#define ao_data_along(packet) ao_bmi088_along(&(packet)->bmi088)
+#define ao_data_across(packet) ao_bmi088_across(&(packet)->bmi088)
+#define ao_data_through(packet) ao_bmi088_through(&(packet)->bmi088)
+
+#define ao_data_roll(packet) ao_bmi088_roll(&(packet)->bmi088)
+#define ao_data_pitch(packet) ao_bmi088_pitch(&(packet)->bmi088)
+#define ao_data_yaw(packet) ao_bmi088_yaw(&(packet)->bmi088)
+
+/*
+ * MMC5983
+ *
+ * pin 1 NE corner of chip
+ *
+ * +along -Y
+ * +across +X
+ * +through -Z
+ */
+
+#define HAS_MMC5983 1
+#define AO_MMC5983_INT_PORT (&stm_gpiod)
+#define AO_MMC5983_INT_PIN 5
+#define AO_MMC5983_SPI_CLK_PORT (&stm_gpiod)
+#define AO_MMC5983_SPI_CLK_PIN 1
+#define AO_MMC5983_SPI_MISO_PORT (&stm_gpiod)
+#define AO_MMC5983_SPI_MISO_PIN 3
+#define AO_MMC5983_SPI_MOSI_PORT (&stm_gpiod)
+#define AO_MMC5983_SPI_MOSI_PIN 4
+#define AO_MMC5983_SPI_INDEX (AO_SPI_2_PD1_PD3_PD4 | AO_SPI_MODE_3)
+#define AO_MMC5983_SPI_CS_PORT (&stm_gpioa)
+#define AO_MMC5983_SPI_CS_PIN 15
+
+#define ao_mmc5983_along(m) (-(m)->y)
+#define ao_mmc5983_across(m) ((m)->x)
+#define ao_mmc5983_through(m) (-(m)->z)
+
+#define ao_data_mag_along(packet) ao_mmc5983_along(&(packet)->mmc5983)
+#define ao_data_mag_across(packet) ao_mmc5983_across(&(packet)->mmc5983)
+#define ao_data_mag_through(packet) ao_mmc5983_through(&(packet)->mmc5983)
+
+/*
+ * ADXL375
+ *
+ * pin 1 NW corner of chip
+ *
+ * +along +X
+ * +across +Y
+ * +through +Z
+ */
+
+#define HAS_ADXL375 1
+#define AO_ADXL375_SPI_INDEX (AO_SPI_1_PB3_PB4_PB5 | AO_SPI_MODE_3)
+#define AO_ADXL375_CS_PORT (&stm_gpioc)
+#define AO_ADXL375_CS_PIN 0
+
+#define AO_ADXL375_AXIS x
+#define AO_ADXL375_INVERT 1
+
+#define NUM_CMDS 16
+
+/*
+ * Companion
+ */
+
+#define AO_COMPANION_CS_PORT (&stm_gpiob)
+#define AO_COMPANION_CS_PIN_0 (6)
+#define AO_COMPANION_CS_PIN AO_COMPANION_CS_PIN_0
+#define AO_COMPANION_CS_PIN_1 (7)
+#define AO_COMPANION_SPI_BUS AO_SPI_2_PB13_PB14_PB15
+
+/*
+ * Monitor
+ */
+
+#define HAS_MONITOR 0
+#define LEGACY_MONITOR 0
+#define HAS_MONITOR_PUT 1
+#define AO_MONITOR_LED 0
+#define HAS_RSSI 0
+
+/*
+ * Profiling Viterbi decoding
+ */
+
+#ifndef AO_PROFILE
+#define AO_PROFILE 0
+#endif
+
+/*
+ * PWM output
+ */
+
+#define NUM_PWM 4
+#define PWM_MAX 20000
+#define AO_PWM_TIMER stm_tim4
+#define AO_PWM_TIMER_ENABLE STM_RCC_APB1ENR_TIM4EN
+#define AO_PWM_TIMER_SCALE 32
+
+#define AO_PWM_0_GPIO (&stm_gpiod)
+#define AO_PWM_0_PIN 12
+
+#define AO_PWM_1_GPIO (&stm_gpiod)
+#define AO_PWM_1_PIN 13
+
+#define AO_PWM_2_GPIO (&stm_gpiod)
+#define AO_PWM_2_PIN 15
+
+#define AO_PWM_3_GPIO (&stm_gpiod)
+#define AO_PWM_3_PIN 14
+
+#endif /* _AO_PINS_H_ */
--- /dev/null
+/*
+ * Copyright © 2021 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.
+ */
+
+#include <ao.h>
+#include <ao_bmi088.h>
+#include <ao_mmc5983.h>
+#include <ao_adxl375.h>
+#include <ao_log.h>
+#include <ao_exti.h>
+#include <ao_packet.h>
+#include <ao_companion.h>
+#include <ao_profile.h>
+#include <ao_eeprom.h>
+#include <ao_i2c_bit.h>
+#if HAS_SAMPLE_PROFILE
+#include <ao_sample_profile.h>
+#endif
+#include <ao_pyro.h>
+#if HAS_STACK_GUARD
+#include <ao_mpu.h>
+#endif
+#include <ao_pwm.h>
+
+#define AO_FAIL_FLASH 1
+#define AO_FAIL_ADC 2
+#define AO_FAIL_GPS 3
+#define AO_FAIL_RADIO 4
+#define AO_FAIL_ACCEL 5
+#define AO_FAIL_BARO 6
+#define AO_FAIL_IMU 7
+#define AO_FAIL_MAG 8
+#define AO_FAIL_RANGE 9
+
+static void
+ao_validate(void)
+{
+ static struct ao_telemetry_location gps_data;
+ static struct ao_telemetry_satellite gps_tracking_data;
+ uint8_t new;
+ uint8_t data;
+ int16_t decivolt;
+ AO_TICK_TYPE gps_start;
+
+ ao_config_get();
+ /* Check the flash part */
+ ao_storage_setup();
+ if (ao_storage_total != 8 * 1024 * 1024)
+ ao_panic(AO_FAIL_FLASH);
+
+ /* Check the battery voltage */
+ data = ao_data_head;
+ do {
+ ao_sleep((void *) &ao_data_head);
+ } while (ao_data_head == data);
+ decivolt = ao_battery_decivolt(ao_data_ring[data].adc.v_batt);
+ if (decivolt < 35 || 55 < decivolt)
+ ao_panic(AO_FAIL_ADC);
+
+ /* Check to make sure GPS data is being received */
+ gps_start = ao_time();
+ for (;;) {
+ while ((new = ao_gps_new) == 0)
+ ao_sleep_for(&ao_gps_new, AO_SEC_TO_TICKS(1));
+ ao_mutex_get(&ao_gps_mutex);
+ if (new & AO_GPS_NEW_DATA)
+ memcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data));
+ if (new & AO_GPS_NEW_TRACKING)
+ memcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data));
+ ao_gps_new = 0;
+ ao_mutex_put(&ao_gps_mutex);
+
+ if (new & AO_GPS_NEW_DATA) {
+ if (gps_data.flags & AO_GPS_RUNNING)
+ break;
+ }
+ if ((AO_TICK_SIGNED) (ao_time() - gps_start) > (AO_TICK_SIGNED) AO_SEC_TO_TICKS(10))
+ ao_panic(AO_FAIL_GPS);
+ }
+
+ if (!ao_radio_post())
+ ao_panic(AO_FAIL_RADIO);
+
+ ao_sample_init();
+ ao_flight_state = ao_flight_startup;
+ for (;;) {
+
+ /*
+ * Process ADC samples, just looping
+ * until the sensors are calibrated.
+ */
+ if (ao_sample())
+ break;
+ }
+
+ if (ao_sensor_errors & AO_DATA_MS5607)
+ ao_panic(AO_FAIL_BARO);
+ if (ao_sensor_errors & AO_DATA_BMI088)
+ ao_panic(AO_FAIL_IMU);
+ if (ao_sensor_errors & AO_DATA_MMC5983)
+ ao_panic(AO_FAIL_MAG);
+ if (ao_sensor_errors & AO_DATA_ADXL375)
+ ao_panic(AO_FAIL_ACCEL);
+ if (ao_sensor_errors)
+ ao_panic(AO_FAIL_RANGE);
+
+ /* Check ground accel value to make sure it's somewhat valid */
+ if (ao_ground_accel < (accel_t) AO_CONFIG_DEFAULT_ACCEL_PLUS_G - ACCEL_NOSE_UP ||
+ ao_ground_accel > (accel_t) AO_CONFIG_DEFAULT_ACCEL_MINUS_G + ACCEL_NOSE_UP) {
+ ao_panic(AO_FAIL_ACCEL);
+ }
+ if (ao_ground_height < -1000 || ao_ground_height > 7000)
+ ao_panic(AO_FAIL_BARO);
+
+ ao_led_on(AO_LED_GREEN);
+ ao_beep_for(AO_BEEP_MID_DEFAULT, AO_MS_TO_TICKS(100));
+
+ ao_exit();
+}
+
+struct ao_task ao_validate_task;
+
+int
+main(void)
+{
+ ao_clock_init();
+
+#if HAS_STACK_GUARD
+ ao_mpu_init();
+#endif
+
+ ao_task_init();
+ ao_serial_init();
+ ao_led_init();
+ ao_led_off(LEDS_AVAILABLE);
+ ao_timer_init();
+
+ ao_spi_init();
+#ifdef MMC5983_I2C
+ ao_i2c_bit_init();
+#endif
+ ao_dma_init();
+ ao_exti_init();
+
+ ao_adc_init();
+#if HAS_BEEP
+ ao_beep_init();
+#endif
+ ao_cmd_init();
+
+ ao_ms5607_init();
+ ao_bmi088_init();
+ ao_mmc5983_init();
+ ao_adxl375_init();
+
+ ao_eeprom_init();
+ ao_storage_init();
+
+ ao_usb_init();
+ ao_gps_init();
+
+ ao_radio_init();
+ ao_igniter_init();
+ ao_pyro_init();
+
+ ao_config_init();
+#if AO_PROFILE
+ ao_profile_init();
+#endif
+#if HAS_SAMPLE_PROFILE
+ ao_sample_profile_init();
+#endif
+
+ ao_pwm_init();
+
+ ao_add_task(&ao_validate_task, ao_validate, "validate");
+
+ ao_start_scheduler();
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright © 2021 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.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+/* External crystal at 16MHz */
+#define AO_HSE 16000000
+
+#include <ao_flash_stm_pins.h>
+
+/* Companion port cs_companion0 PB6 */
+
+#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
+ao_product.h
+telemega-*.elf
--- /dev/null
+#
+# AltOS build
+#
+#
+
+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 \
+ altitude-pa.h \
+ ao_kalman.h \
+ ao_product.h \
+ ao_ms5607.h \
+ ao_bmi088.h \
+ ao_mmc5983.h \
+ ao_adxl375.h \
+ ao_cc1200_CC1200.h \
+ ao_profile.h \
+ ao_task.h \
+ ao_whiten.h \
+ ao_sample_profile.h \
+ ao_quaternion.h \
+ ao_mpu.h \
+ stm32l.h \
+ ao_ms5607_convert.c \
+ Makefile
+
+#
+# Common AltOS sources
+#
+
+#PROFILE=ao_profile.c
+#PROFILE_DEF=-DAO_PROFILE=1
+
+#SAMPLE_PROFILE=ao_sample_profile.c \
+# ao_sample_profile_timer.c
+#SAMPLE_PROFILE_DEF=-DHAS_SAMPLE_PROFILE=1
+
+#STACK_GUARD=ao_mpu_stm.c
+#STACK_GUARD_DEF=-DHAS_STACK_GUARD=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_stm.c \
+ ao_stdio.c \
+ ao_panic.c \
+ ao_timer.c \
+ ao_mutex.c \
+ ao_serial_stm.c \
+ ao_gps_ublox.c \
+ ao_gps_show.c \
+ ao_gps_report_mega.c \
+ ao_ignite.c \
+ ao_freq.c \
+ ao_dma_stm.c \
+ ao_spi_stm.c \
+ ao_cc1200.c \
+ ao_data.c \
+ ao_ms5607.c \
+ ao_adxl375.c \
+ ao_adc_stm.c \
+ ao_beep_stm.c \
+ ao_eeprom_stm.c \
+ ao_storage.c \
+ ao_m25.c \
+ ao_usb_stm.c \
+ ao_exti_stm.c \
+ ao_report.c \
+ ao_bmi088.c \
+ ao_mmc5983.c \
+ ao_convert_pa.c \
+ ao_convert_volt.c \
+ ao_log.c \
+ ao_log_mega.c \
+ ao_sample.c \
+ ao_kalman.c \
+ ao_flight.c \
+ ao_telemetry.c \
+ ao_packet_slave.c \
+ ao_packet.c \
+ ao_companion.c \
+ ao_pyro.c \
+ ao_aprs.c \
+ ao_pwm_stm.c \
+ $(PROFILE) \
+ $(SAMPLE_PROFILE) \
+ $(STACK_GUARD)
+
+PRODUCT=TeleMega-v7.0
+PRODUCT_DEF=-DTELEMEGA
+IDPRODUCT=0x0023
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF)
+
+PROGNAME=telemega-v7.0
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_telemega.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+ $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+$(OBJ): $(INC)
+
+distclean: clean
+
+clean:
+ rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx $(PROGNAME)-*.map
+ rm -f ao_product.h
+
+install:
+
+uninstall:
--- /dev/null
+/*
+ * Copyright © 2017 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.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+
+/* 16MHz High speed external crystal */
+#define AO_HSE 16000000
+
+/* PLLVCO = 96MHz (so that USB will work) */
+#define AO_PLLMUL 6
+#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_6)
+
+/* 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_SERIAL_1 0
+#define USE_SERIAL_1_STDIN 0
+#define SERIAL_1_PB6_PB7 0
+#define SERIAL_1_PA9_PA10 0
+
+#define HAS_SERIAL_2 1
+#define USE_SERIAL_2_STDIN 0
+#define SERIAL_2_PA2_PA3 1
+#define SERIAL_2_PD5_PD6 0
+#define USE_SERIAL_2_FLOW 0
+#define USE_SERIAL_2_SW_FLOW 0
+
+#define HAS_SERIAL_3 0
+#define USE_SERIAL_3_STDIN 0
+#define SERIAL_3_PB10_PB11 0
+#define SERIAL_3_PC10_PC11 0
+#define SERIAL_3_PD8_PD9 0
+
+#define ao_gps_getchar ao_serial2_getchar
+#define ao_gps_putchar ao_serial2_putchar
+#define ao_gps_set_speed ao_serial2_set_speed
+#define ao_gps_fifo (ao_stm_usart2.rx_fifo)
+
+#define AO_UBLOX_VERSION 10
+
+#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX (1024 * 1024)
+#define AO_CONFIG_MAX_SIZE 1024
+#define LOG_ERASE_MARK 0x55
+#define LOG_MAX_ERASE 128
+#define AO_LOG_FORMAT AO_LOG_FORMAT_TELEMEGA_7
+#define AO_TELEMETRY_MEGA_DATA AO_TELEMETRY_MEGA_DATA_30V
+#define AO_LOG_NORMALIZED 1
+
+#define HAS_EEPROM 1
+#define USE_INTERNAL_FLASH 0
+#define USE_EEPROM_CONFIG 1
+#define USE_STORAGE_CONFIG 0
+#define HAS_USB 1
+#define HAS_BEEP 1
+#define BEEPER_TIMER 3
+#define BEEPER_CHANNEL 2
+#define BEEPER_PORT (&stm_gpioe)
+#define BEEPER_PIN 4
+#define HAS_BATTERY_REPORT 1
+#define HAS_RADIO 1
+#define HAS_TELEMETRY 1
+#define HAS_APRS 1
+#define HAS_COMPANION 1
+
+#define HAS_SPI_1 1
+#define SPI_1_PA5_PA6_PA7 1 /* Barometer */
+#define SPI_1_PB3_PB4_PB5 1 /* Accelerometer */
+#define SPI_1_PE13_PE14_PE15 1 /* MPU6000 */
+#define SPI_1_OSPEEDR STM_OSPEEDR_10MHz
+
+//#define MMC5983_I2C 1
+
+#define HAS_SPI_2 1
+#define SPI_2_PB13_PB14_PB15 1 /* Flash, Companion */
+#ifndef MMC5983_I2C
+#define SPI_2_PD1_PD3_PD4 1 /* MMC5983 */
+#endif
+#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz
+
+#define HAS_I2C_1 0
+#define I2C_1_PB8_PB9 0
+
+#define HAS_I2C_2 0
+#define I2C_2_PB10_PB11 0
+
+#define PACKET_HAS_SLAVE 1
+#define PACKET_HAS_MASTER 0
+
+#define LOW_LEVEL_DEBUG 0
+
+#define LED_PORT_ENABLE STM_RCC_AHBENR_GPIOCEN
+#define LED_PORT (&stm_gpioc)
+#define LED_PIN_RED 8
+#define LED_PIN_GREEN 9
+#define AO_LED_RED (1 << LED_PIN_RED)
+#define AO_LED_GREEN (1 << LED_PIN_GREEN)
+
+#define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN)
+
+#define HAS_GPS 1
+#define HAS_FLIGHT 1
+#define HAS_ADC 1
+#define HAS_ADC_TEMP 1
+#define HAS_LOG 1
+
+/*
+ * Igniter
+ */
+
+#define HAS_IGNITE 1
+#define HAS_IGNITE_REPORT 1
+
+#define AO_SENSE_PYRO(p,n) ((p)->adc.sense[n])
+#define AO_SENSE_DROGUE(p) ((p)->adc.sense[4])
+#define AO_SENSE_MAIN(p) ((p)->adc.sense[5])
+#define AO_IGNITER_CLOSED 400
+#define AO_IGNITER_OPEN 60
+
+/* Pyro A */
+#define AO_PYRO_PORT_0 (&stm_gpiod)
+#define AO_PYRO_PIN_0 6
+
+/* Pyro B */
+#define AO_PYRO_PORT_1 (&stm_gpiod)
+#define AO_PYRO_PIN_1 7
+
+/* Pyro C */
+#define AO_PYRO_PORT_2 (&stm_gpioe)
+#define AO_PYRO_PIN_2 3
+
+/* Pyro D */
+#define AO_PYRO_PORT_3 (&stm_gpioe)
+#define AO_PYRO_PIN_3 2
+
+/* Drogue */
+#define AO_IGNITER_DROGUE_PORT (&stm_gpioe)
+#define AO_IGNITER_DROGUE_PIN 6
+
+/* Main */
+#define AO_IGNITER_MAIN_PORT (&stm_gpioe)
+#define AO_IGNITER_MAIN_PIN 5
+
+/* Number of general purpose pyro channels available */
+#define AO_PYRO_NUM 4
+
+/*
+ * ADC
+ */
+#define AO_DATA_RING 32
+#define AO_ADC_NUM_SENSE 6
+
+struct ao_adc {
+ int16_t sense[AO_ADC_NUM_SENSE];
+ int16_t v_batt;
+ int16_t v_pbatt;
+ int16_t temp;
+};
+
+#define AO_ADC_DUMP(p) \
+ printf("tick: %5lu A: %5d B: %5d C: %5d D: %5d drogue: %5d main: %5d batt: %5d pbatt: %5d temp: %5d\n", \
+ (p)->tick, \
+ (p)->adc.sense[0], (p)->adc.sense[1], (p)->adc.sense[2], \
+ (p)->adc.sense[3], (p)->adc.sense[4], (p)->adc.sense[5], \
+ (p)->adc.v_batt, (p)->adc.v_pbatt, (p)->adc.temp)
+
+#define AO_ADC_SENSE_A 0
+#define AO_ADC_SENSE_A_PORT (&stm_gpioa)
+#define AO_ADC_SENSE_A_PIN 0
+
+#define AO_ADC_SENSE_B 1
+#define AO_ADC_SENSE_B_PORT (&stm_gpioa)
+#define AO_ADC_SENSE_B_PIN 1
+
+#define AO_ADC_SENSE_C 24
+#define AO_ADC_SENSE_C_PORT (&stm_gpioe)
+#define AO_ADC_SENSE_C_PIN 9
+
+#define AO_ADC_SENSE_D 25
+#define AO_ADC_SENSE_D_PORT (&stm_gpioe)
+#define AO_ADC_SENSE_D_PIN 10
+
+#define AO_ADC_SENSE_DROGUE 4
+#define AO_ADC_SENSE_DROGUE_PORT (&stm_gpioa)
+#define AO_ADC_SENSE_DROGUE_PIN 4
+
+#define AO_ADC_SENSE_MAIN 22
+#define AO_ADC_SENSE_MAIN_PORT (&stm_gpioe)
+#define AO_ADC_SENSE_MAIN_PIN 7
+
+#define AO_ADC_V_BATT 8
+#define AO_ADC_V_BATT_PORT (&stm_gpiob)
+#define AO_ADC_V_BATT_PIN 0
+
+#define AO_ADC_V_PBATT 9
+#define AO_ADC_V_PBATT_PORT (&stm_gpiob)
+#define AO_ADC_V_PBATT_PIN 1
+
+#define AO_ADC_TEMP 16
+
+#define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_GPIOAEN) | \
+ (1 << STM_RCC_AHBENR_GPIOEEN) | \
+ (1 << STM_RCC_AHBENR_GPIOBEN))
+
+#define AO_NUM_ADC_PIN (AO_ADC_NUM_SENSE + 2)
+
+#define AO_ADC_PIN0_PORT AO_ADC_SENSE_A_PORT
+#define AO_ADC_PIN0_PIN AO_ADC_SENSE_A_PIN
+#define AO_ADC_PIN1_PORT AO_ADC_SENSE_B_PORT
+#define AO_ADC_PIN1_PIN AO_ADC_SENSE_B_PIN
+#define AO_ADC_PIN2_PORT AO_ADC_SENSE_C_PORT
+#define AO_ADC_PIN2_PIN AO_ADC_SENSE_C_PIN
+#define AO_ADC_PIN3_PORT AO_ADC_SENSE_D_PORT
+#define AO_ADC_PIN3_PIN AO_ADC_SENSE_D_PIN
+#define AO_ADC_PIN4_PORT AO_ADC_SENSE_DROGUE_PORT
+#define AO_ADC_PIN4_PIN AO_ADC_SENSE_DROGUE_PIN
+#define AO_ADC_PIN5_PORT AO_ADC_SENSE_MAIN_PORT
+#define AO_ADC_PIN5_PIN AO_ADC_SENSE_MAIN_PIN
+#define AO_ADC_PIN6_PORT AO_ADC_V_BATT_PORT
+#define AO_ADC_PIN6_PIN AO_ADC_V_BATT_PIN
+#define AO_ADC_PIN7_PORT AO_ADC_V_PBATT_PORT
+#define AO_ADC_PIN7_PIN AO_ADC_V_PBATT_PIN
+
+#define AO_NUM_ADC (AO_ADC_NUM_SENSE + 3)
+
+#define AO_ADC_SQ1 AO_ADC_SENSE_A
+#define AO_ADC_SQ2 AO_ADC_SENSE_B
+#define AO_ADC_SQ3 AO_ADC_SENSE_C
+#define AO_ADC_SQ4 AO_ADC_SENSE_D
+#define AO_ADC_SQ5 AO_ADC_SENSE_DROGUE
+#define AO_ADC_SQ6 AO_ADC_SENSE_MAIN
+#define AO_ADC_SQ7 AO_ADC_V_BATT
+#define AO_ADC_SQ8 AO_ADC_V_PBATT
+#define AO_ADC_SQ9 AO_ADC_TEMP
+
+/*
+ * Voltage divider on ADC battery sampler
+ */
+#define AO_BATTERY_DIV_PLUS 56 /* 5.6k */
+#define AO_BATTERY_DIV_MINUS 100 /* 10k */
+
+/*
+ * Voltage divider on ADC pyro battery sampler
+ */
+#define AO_PYRO_BATTERY_DIV_PLUS 100 /* 100k */
+#define AO_PYRO_BATTERY_DIV_MINUS 12 /* 12k */
+
+/*
+ * Voltage divider on ADC igniter samplers
+ */
+#define AO_IGNITE_DIV_PLUS 100 /* 100k */
+#define AO_IGNITE_DIV_MINUS 12 /* 12k */
+
+/*
+ * ADC reference in decivolts
+ */
+#define AO_ADC_REFERENCE_DV 33
+
+/*
+ * Pressure sensor settings
+ */
+#define HAS_MS5607 1
+#define HAS_MS5611 0
+#define AO_MS5607_PRIVATE_PINS 1
+#define AO_MS5607_CS_PORT (&stm_gpioc)
+#define AO_MS5607_CS_PIN 4
+#define AO_MS5607_CS_MASK (1 << AO_MS5607_CS)
+#define AO_MS5607_MISO_PORT (&stm_gpioa)
+#define AO_MS5607_MISO_PIN 6
+#define AO_MS5607_MISO_MASK (1 << AO_MS5607_MISO)
+#define AO_MS5607_SPI_INDEX AO_SPI_1_PA5_PA6_PA7
+
+/*
+ * SPI Flash memory
+ */
+
+#define M25_MAX_CHIPS 1
+#define AO_M25_SPI_CS_PORT (&stm_gpiod)
+#define AO_M25_SPI_CS_MASK (1 << 10)
+#define AO_M25_SPI_BUS AO_SPI_2_PB13_PB14_PB15
+
+/*
+ * Radio (cc1200)
+ */
+
+/* gets pretty close to 434.550 */
+
+#define AO_RADIO_CAL_DEFAULT 5695733
+
+#define AO_FEC_DEBUG 0
+#define AO_CC1200_SPI_CS_PORT (&stm_gpioc)
+#define AO_CC1200_SPI_CS_PIN 5
+#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 AO_CC1200_MARC_GPIO 3
+#define AO_CC1200_MARC_GPIO_IOCFG CC1200_IOCFG3
+
+#define HAS_BOOT_RADIO 0
+
+
+/*
+ *
+ * Here are the required sensor signs:
+ *
+ * +along nose up
+ * +across USB down
+ * +through TH down
+ *
+ * With the board aligned to have positive accel for the relevant
+ * axis, looking down from above we have:
+ *
+ * +roll counter clockwise (nose up)
+ * +pitch counter clockwise (USB down)
+ * +yaw counter clockwise (TH down)
+ */
+
+/*
+ * On TMega v6, bmi088 pin 1 (NE corner of chip) is placed towards the
+ * USB and antenna edges of the board. Relative to bmi088 specs, to
+ * get the above values, we need to flip the Y axis, assigning values
+ * as follows:
+ *
+ * +along +X +roll +X
+ * +across -Y +pitch -Y
+ * +through +Z +yaw +Z
+ */
+
+#define HAS_BMI088 1
+#define AO_BMI088_SPI_BUS AO_SPI_1_PE13_PE14_PE15
+#define AO_BMI088_ACC_CS_PORT (&stm_gpioc)
+#define AO_BMI088_ACC_CS_PIN 14
+#define AO_BMI088_GYR_CS_PORT (&stm_gpioc)
+#define AO_BMI088_GYR_CS_PIN 13
+#define HAS_IMU 1
+
+#define ao_bmi088_along(m) ((m)->acc.x)
+#define ao_bmi088_across(m) (-(m)->acc.y)
+#define ao_bmi088_through(m) ((m)->acc.z)
+
+#define ao_bmi088_roll(m) ((m)->gyr.x)
+#define ao_bmi088_pitch(m) (-(m)->gyr.y)
+#define ao_bmi088_yaw(m) ((m)->gyr.z)
+
+#define ao_data_along(packet) ao_bmi088_along(&(packet)->bmi088)
+#define ao_data_across(packet) ao_bmi088_across(&(packet)->bmi088)
+#define ao_data_through(packet) ao_bmi088_through(&(packet)->bmi088)
+
+#define ao_data_roll(packet) ao_bmi088_roll(&(packet)->bmi088)
+#define ao_data_pitch(packet) ao_bmi088_pitch(&(packet)->bmi088)
+#define ao_data_yaw(packet) ao_bmi088_yaw(&(packet)->bmi088)
+
+/*
+ * MMC5983
+ *
+ * pin 1 NE corner of chip
+ *
+ * +along -Y
+ * +across +X
+ * +through -Z
+ */
+
+#define HAS_MMC5983 1
+#define AO_MMC5983_INT_PORT (&stm_gpiod)
+#define AO_MMC5983_INT_PIN 5
+#define AO_MMC5983_SPI_CLK_PORT (&stm_gpiod)
+#define AO_MMC5983_SPI_CLK_PIN 1
+#define AO_MMC5983_SPI_MISO_PORT (&stm_gpiod)
+#define AO_MMC5983_SPI_MISO_PIN 3
+#define AO_MMC5983_SPI_MOSI_PORT (&stm_gpiod)
+#define AO_MMC5983_SPI_MOSI_PIN 4
+#define AO_MMC5983_SPI_INDEX (AO_SPI_2_PD1_PD3_PD4 | AO_SPI_MODE_3)
+#define AO_MMC5983_SPI_CS_PORT (&stm_gpioa)
+#define AO_MMC5983_SPI_CS_PIN 15
+
+#define ao_mmc5983_along(m) (-(m)->y)
+#define ao_mmc5983_across(m) ((m)->x)
+#define ao_mmc5983_through(m) (-(m)->z)
+
+#define ao_data_mag_along(packet) ao_mmc5983_along(&(packet)->mmc5983)
+#define ao_data_mag_across(packet) ao_mmc5983_across(&(packet)->mmc5983)
+#define ao_data_mag_through(packet) ao_mmc5983_through(&(packet)->mmc5983)
+
+/*
+ * ADXL375
+ *
+ * pin 1 NW corner of chip
+ *
+ * +along +X
+ * +across +Y
+ * +through +Z
+ */
+
+#define HAS_ADXL375 1
+#define AO_ADXL375_SPI_INDEX (AO_SPI_1_PB3_PB4_PB5 | AO_SPI_MODE_3)
+#define AO_ADXL375_CS_PORT (&stm_gpioc)
+#define AO_ADXL375_CS_PIN 0
+
+#define AO_ADXL375_AXIS x
+#define AO_ADXL375_INVERT 1
+
+#define NUM_CMDS 16
+
+/*
+ * Companion
+ */
+
+#define AO_COMPANION_CS_PORT (&stm_gpiob)
+#define AO_COMPANION_CS_PIN_0 (6)
+#define AO_COMPANION_CS_PIN AO_COMPANION_CS_PIN_0
+#define AO_COMPANION_CS_PIN_1 (7)
+#define AO_COMPANION_SPI_BUS AO_SPI_2_PB13_PB14_PB15
+
+/*
+ * Monitor
+ */
+
+#define HAS_MONITOR 0
+#define LEGACY_MONITOR 0
+#define HAS_MONITOR_PUT 1
+#define AO_MONITOR_LED 0
+#define HAS_RSSI 0
+
+/*
+ * Profiling Viterbi decoding
+ */
+
+#ifndef AO_PROFILE
+#define AO_PROFILE 0
+#endif
+
+/*
+ * PWM output
+ */
+
+#define NUM_PWM 4
+#define PWM_MAX 20000
+#define AO_PWM_TIMER stm_tim4
+#define AO_PWM_TIMER_ENABLE STM_RCC_APB1ENR_TIM4EN
+#define AO_PWM_TIMER_SCALE 32
+
+#define AO_PWM_0_GPIO (&stm_gpiod)
+#define AO_PWM_0_PIN 12
+
+#define AO_PWM_1_GPIO (&stm_gpiod)
+#define AO_PWM_1_PIN 13
+
+#define AO_PWM_2_GPIO (&stm_gpiod)
+#define AO_PWM_2_PIN 15
+
+#define AO_PWM_3_GPIO (&stm_gpiod)
+#define AO_PWM_3_PIN 14
+
+#endif /* _AO_PINS_H_ */
--- /dev/null
+/*
+ * Copyright © 2021 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.
+ */
+
+#include <ao.h>
+#include <ao_bmi088.h>
+#include <ao_mmc5983.h>
+#include <ao_adxl375.h>
+#include <ao_log.h>
+#include <ao_exti.h>
+#include <ao_packet.h>
+#include <ao_companion.h>
+#include <ao_profile.h>
+#include <ao_eeprom.h>
+#include <ao_i2c_bit.h>
+#if HAS_SAMPLE_PROFILE
+#include <ao_sample_profile.h>
+#endif
+#include <ao_pyro.h>
+#if HAS_STACK_GUARD
+#include <ao_mpu.h>
+#endif
+#include <ao_pwm.h>
+
+int
+main(void)
+{
+ ao_clock_init();
+
+#if HAS_STACK_GUARD
+ ao_mpu_init();
+#endif
+
+ ao_task_init();
+ ao_serial_init();
+ ao_led_init();
+ ao_led_on(LEDS_AVAILABLE);
+ ao_timer_init();
+
+ ao_spi_init();
+#ifdef MMC5983_I2C
+ ao_i2c_bit_init();
+#endif
+ ao_dma_init();
+ ao_exti_init();
+
+ ao_adc_init();
+#if HAS_BEEP
+ ao_beep_init();
+#endif
+ ao_cmd_init();
+
+ ao_ms5607_init();
+ ao_bmi088_init();
+ ao_mmc5983_init();
+ ao_adxl375_init();
+
+ ao_eeprom_init();
+ ao_storage_init();
+
+ ao_flight_init();
+ ao_log_init();
+ ao_report_init();
+
+ ao_usb_init();
+ ao_gps_init();
+ ao_gps_report_mega_init();
+ ao_telemetry_init();
+ ao_radio_init();
+ ao_packet_slave_init(false);
+ ao_igniter_init();
+ ao_companion_init();
+ ao_pyro_init();
+
+ ao_config_init();
+#if AO_PROFILE
+ ao_profile_init();
+#endif
+#if HAS_SAMPLE_PROFILE
+ ao_sample_profile_init();
+#endif
+
+ ao_pwm_init();
+
+ ao_led_off(LEDS_AVAILABLE);
+
+ ao_start_scheduler();
+ return 0;
+}
--- /dev/null
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=telemega-v7.0
+include $(TOPDIR)/stm/Makefile-flash.defs
--- /dev/null
+/*
+ * Copyright © 2021 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.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+/* External crystal at 16MHz */
+#define AO_HSE 16000000
+
+#include <ao_flash_stm_pins.h>
+
+/* Companion port cs_companion0 PB6 */
+
+#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
+ao_product.h
+telemetrum-*.elf
--- /dev/null
+#
+# AltOS build
+#
+#
+
+include ../samd21/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 \
+ altitude-pa.h \
+ ao_kalman.h \
+ ao_product.h \
+ ao_ms5607.h \
+ ao_adxl375.h \
+ ao_cc1200_CC1200.h \
+ ao_task.h \
+ ao_whiten.h \
+ samd21.h \
+ Makefile
+
+# SAMD21G17D
+
+SAMD21_ROM=128
+SAMD21_RAM=16
+
+#PROFILE=ao_profile.c
+#PROFILE_DEF=-DAO_PROFILE=1
+
+#SAMPLE_PROFILE=ao_sample_profile.c \
+# ao_sample_profile_timer.c
+#SAMPLE_PROFILE_DEF=-DHAS_SAMPLE_PROFILE=1
+
+#STACK_GUARD=ao_mpu_stm.c
+#STACK_GUARD_DEF=-DHAS_STACK_GUARD=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_serial_samd21.c \
+ ao_gps_ublox.c \
+ ao_gps_show.c \
+ ao_gps_report_metrum.c \
+ ao_ignite.c \
+ ao_freq.c \
+ ao_dma_samd21.c \
+ ao_spi_samd21.c \
+ ao_cc1200.c \
+ ao_data.c \
+ ao_ms5607.c \
+ ao_adxl375.c \
+ ao_adc_samd21.c \
+ ao_beep_samd21.c \
+ ao_storage.c \
+ ao_m25.c \
+ ao_usb_samd21.c \
+ ao_exti_samd21.c \
+ ao_report.c \
+ ao_convert_pa.c \
+ ao_convert_volt.c \
+ ao_log.c \
+ ao_log_metrum.c \
+ ao_sample.c \
+ ao_kalman.c \
+ ao_flight.c \
+ ao_telemetry.c \
+ ao_packet_slave.c \
+ ao_packet.c \
+ ao_companion.c \
+ ao_aprs.c \
+ $(PROFILE) \
+ $(SAMPLE_PROFILE) \
+ $(STACK_GUARD)
+
+PRODUCT=TeleMetrum-v4.0
+PRODUCT_DEF=-DTELEMETRUM_V_4_0
+IDPRODUCT=0x000b
+
+CFLAGS = $(PRODUCT_DEF) $(SAMD21_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF)
+
+PROGNAME=telemetrum-v4.0-seeed
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+FLASH_PROG=flash-loader/$(PROGNAME)-altos-flash-$(VERSION).elf
+BOTH_HEX=$(PROGNAME)-combined-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_telemetrum_seeed.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX) $(BOTH_HEX)
+
+$(PROG): Makefile $(OBJ)
+ $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+$(BOTH_HEX): $(PROG) $(FLASH_PROG)
+ ../../ao-tools/ao-elftohex/ao-elftohex -n --output=$@ $(FLASH_PROG) $(PROG)
+
+$(FLASH_PROG): FRC
+ +cd flash-loader && make
+
+FRC:
+
+$(OBJ): $(INC)
+
+load: $(PROG)
+ stm-load $(PROG)
+
+distclean: clean
+
+clean:
+ rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx $(PROGNAME)-*.map
+ rm -f ao_product.h
+
+install:
+
+uninstall:
--- /dev/null
+/*
+ * Copyright © 2022 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.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define AO_XOSC 1
+#define AO_XOSC_FREQ 16000000
+#define AO_XOSC_DIV 256
+#define AO_XOSC_MUL 768
+
+#define AO_AHB_PRESCALER 1
+#define AO_APBA_PRESCALER 1
+
+#define HAS_SERIAL_1 1
+#define USE_SERIAL_1_STDIN 0
+
+#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX (512 * 1024)
+#define AO_CONFIG_DEFAULT_ACCEL_PLUS_G -20
+#define AO_CONFIG_DEFAULT_ACCEL_MINUS_G 20
+#define AO_CONFIG_MAX_SIZE 1024
+#define LOG_ERASE_MARK 0x55
+#define LOG_MAX_ERASE 128
+#define AO_LOG_FORMAT AO_LOG_FORMAT_TELEMETRUM
+
+#define HAS_EEPROM 1
+#define USE_INTERNAL_FLASH 0
+#define USE_EEPROM_CONFIG 0
+#define USE_STORAGE_CONFIG 1
+#define HAS_USB 1
+#define USE_USB_STDIO 1
+#define HAS_BATTERY_REPORT 1
+#define BEEPER_CHANNEL 4
+#define BEEPER_TIMER 3
+#define BEEPER_PORT (&samd21_port_a)
+#define BEEPER_PIN 16
+#define HAS_RADIO 1
+#define HAS_RADIO_10MW 1
+#define HAS_TELEMETRY 1
+#define HAS_APRS 1
+#define HAS_COMPANION 1
+
+#define HAS_SPI_0 1
+#define HAS_SPI_3 1
+#define HAS_SPI_5 1
+
+#define PACKET_HAS_SLAVE 1
+#define PACKET_HAS_MASTER 0
+
+#define LOW_LEVEL_DEBUG 0
+
+#define HAS_LED 1
+#define LED_0_PORT (&samd21_port_b)
+#define LED_0_PIN 10
+#define LED_1_PORT (&samd21_port_b)
+#define LED_1_PIN 11
+#define AO_LED_RED (1 << 0)
+#define AO_LED_GREEN (1 << 1)
+
+#define HAS_GPS 1
+#define HAS_FLIGHT 1
+#define HAS_ADC 1
+#define HAS_ADC_TEMP 1
+#define HAS_LOG 1
+
+/*
+ * Beeper
+ */
+
+#define HAS_BEEP 1
+/* Beep on PA16 function E TCC2.0 */
+
+#define AO_BEEP_TCC (&samd21_tcc2)
+#define AO_BEEP_TCC_APBC_MASK SAMD21_PM_APBCMASK_TCC2
+#define AO_BEEP_PORT (&samd21_port_a)
+#define AO_BEEP_PIN (16)
+#define AO_BEEP_FUNC SAMD21_PORT_PMUX_FUNC_E
+
+/*
+ * Igniter
+ */
+
+#define HAS_IGNITE 1
+#define HAS_IGNITE_REPORT 1
+
+#define AO_SENSE_DROGUE(p) ((p)->adc.sense_a)
+#define AO_SENSE_MAIN(p) ((p)->adc.sense_m)
+#define AO_IGNITER_CLOSED 400
+#define AO_IGNITER_OPEN 60
+
+/* Drogue */
+#define AO_IGNITER_DROGUE_PORT (&samd21_port_a)
+#define AO_IGNITER_DROGUE_PIN 19
+
+/* Main */
+#define AO_IGNITER_MAIN_PORT (&samd21_port_a)
+#define AO_IGNITER_MAIN_PIN 18
+
+/*
+ * ADC
+ */
+#define AO_DATA_RING 32
+#define AO_ADC_NUM_SENSE 2
+
+struct ao_adc {
+ int16_t sense_a;
+ int16_t sense_m;
+ int16_t v_batt;
+ int16_t temp;
+};
+
+#define AO_ADC_DUMP(p) \
+ printf("tick: %5lu drogue: %5d main: %5d batt: %5d\n", \
+ (p)->tick, \
+ (p)->adc.sense_a, (p)->adc.sense_m, \
+ (p)->adc.v_batt);
+
+#define AO_ADC_SENSE_DROGUE 18
+#define AO_ADC_SENSE_DROGUE_PORT (&samd21_port_a)
+#define AO_ADC_SENSE_DROGUE_PIN 10
+
+#define AO_ADC_SENSE_MAIN 19
+#define AO_ADC_SENSE_MAIN_PORT (&samd21_port_a)
+#define AO_ADC_SENSE_MAIN_PIN 11
+
+#define AO_ADC_V_BATT 17
+#define AO_ADC_V_BATT_PORT (&samd21_port_a)
+#define AO_ADC_V_BATT_PIN 9
+
+#define AO_ADC_TEMP SAMD21_ADC_INPUTCTRL_MUXPOS_TEMP
+
+#define AO_NUM_ADC_PIN 3
+
+#define AO_ADC_PIN0_PORT AO_ADC_SENSE_DROGUE_PORT
+#define AO_ADC_PIN0_PIN AO_ADC_SENSE_DROGUE_PIN
+#define AO_ADC_PIN1_PORT AO_ADC_SENSE_MAIN_PORT
+#define AO_ADC_PIN1_PIN AO_ADC_SENSE_MAIN_PIN
+#define AO_ADC_PIN2_PORT AO_ADC_V_BATT_PORT
+#define AO_ADC_PIN2_PIN AO_ADC_V_BATT_PIN
+
+#define AO_NUM_ADC (AO_NUM_ADC_PIN + 1)
+
+#define AO_ADC_SQ0 AO_ADC_SENSE_DROGUE
+#define AO_ADC_SQ1 AO_ADC_SENSE_MAIN
+#define AO_ADC_SQ2 AO_ADC_V_BATT
+#define AO_ADC_SQ3 AO_ADC_TEMP
+
+/*
+ * Voltage divider on ADC battery sampler
+ */
+#define AO_BATTERY_DIV_PLUS 56 /* 5.6k */
+#define AO_BATTERY_DIV_MINUS 100 /* 10k */
+
+/*
+ * Voltage divider on ADC igniter samplers
+ */
+#define AO_IGNITE_DIV_PLUS 100 /* 100k */
+#define AO_IGNITE_DIV_MINUS 27 /* 27k */
+
+/*
+ * ADC reference in decivolts
+ */
+#define AO_ADC_REFERENCE_DV 33
+
+/*
+ * GPS
+ */
+
+#define AO_SERIAL_SPEED_UBLOX AO_SERIAL_SPEED_9600
+#define AO_UBLOX_VERSION 10
+
+#define HAS_SERIAL_1 1
+#define USE_SERIAL_1_STDIN 0
+#define SERIAL_1_PA00_PA01 1
+
+#define ao_gps_getchar ao_serial1_getchar
+#define ao_gps_putchar ao_serial1_putchar
+#define ao_gps_set_speed ao_serial1_set_speed
+#define ao_gps_fifo (ao_samd21_usart1.rx_fifo)
+
+/*
+ * Pressure sensor settings
+ */
+#define HAS_MS5607 1
+#define HAS_MS5611 0
+#define AO_MS5607_PRIVATE_PINS 0
+#define AO_MS5607_CS_PORT (&samd21_port_a)
+#define AO_MS5607_CS_PIN 21
+#define AO_MS5607_MISO_PORT (&samd21_port_a)
+#define AO_MS5607_MISO_PIN 20
+#define AO_MS5607_SPI_INDEX AO_SPI_3_PA22_PA23_PA20
+
+/*
+ * SPI Flash memory
+ */
+
+#define M25_MAX_CHIPS 1
+#define AO_M25_SPI_CS_PORT (&samd21_port_a)
+#define AO_M25_SPI_CS_MASK (1 << 27)
+#define AO_M25_SPI_BUS AO_SPI_5_PB22_PB23_PB03
+
+
+/*
+ * Radio (cc1200)
+ */
+
+/* gets pretty close to 434.550 */
+
+#define AO_RADIO_CAL_DEFAULT 5695733
+
+#define AO_CC1200_SPI_CS_PORT (&samd21_port_a)
+#define AO_CC1200_SPI_CS_PIN 7
+#define AO_CC1200_SPI_BUS AO_SPI_5_PB22_PB23_PB03
+
+#define AO_CC1200_INT_PORT (&samd21_port_b)
+#define AO_CC1200_INT_PIN (8)
+#define AO_CC1200_MCU_WAKEUP_PORT (&samd21_port_b)
+#define AO_CC1200_MCU_WAKEUP_PIN (9)
+
+#define AO_CC1200_INT_GPIO 2
+#define AO_CC1200_INT_GPIO_IOCFG CC1200_IOCFG2
+
+#define AO_CC1200_MARC_GPIO 3
+#define AO_CC1200_MARC_GPIO_IOCFG CC1200_IOCFG3
+
+#define HAS_BOOT_RADIO 0
+
+#define HAS_HIGHG_ACCEL 1
+
+/* ADXL375 */
+
+#define HAS_ADXL375 1
+#define AO_ADXL375_CS_PORT (&samd21_port_a)
+#define AO_ADXL375_CS_PIN 8
+#define AO_ADXL375_SPI_INDEX (AO_SPI_0_PA04_PA05_PA06 | AO_SPI_MODE_3)
+
+#define AO_ADXL375_AXIS x
+#define AO_ADXL375_INVERT 1
+
+#define NUM_CMDS 16
+
+/*
+ * Companion
+ */
+
+#define AO_COMPANION_CS_PORT (&samd21_port_a)
+#define AO_COMPANION_CS_PIN (13)
+#define AO_COMPANION_SPI_BUS AO_SPI_5_PB22_PB23_PB03
+
+/*
+ * Monitor
+ */
+
+#define HAS_MONITOR 0
+#define LEGACY_MONITOR 0
+#define HAS_MONITOR_PUT 1
+#define AO_MONITOR_LED 0
+#define HAS_RSSI 0
+
+/*
+ * Profiling Viterbi decoding
+ */
+
+#ifndef AO_PROFILE
+#define AO_PROFILE 0
+#endif
+
+#endif /* _AO_PINS_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; 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.
+ */
+
+#include <ao.h>
+#include <ao_ms5607.h>
+#include <ao_adxl375.h>
+#include <ao_log.h>
+#include <ao_exti.h>
+#include <ao_packet.h>
+#include <ao_companion.h>
+#include <ao_eeprom.h>
+#if HAS_SAMPLE_PROFILE
+#include <ao_profile.h>
+#include <ao_sample_profile.h>
+#endif
+#if HAS_STACK_GUARD
+#include <ao_mpu.h>
+#endif
+#include <ao_dma_samd21.h>
+
+#define AO_FAIL_FLASH 1
+#define AO_FAIL_ADC 2
+#define AO_FAIL_GPS 3
+#define AO_FAIL_RADIO 4
+#define AO_FAIL_ACCEL 5
+#define AO_FAIL_BARO 6
+#define AO_FAIL_RANGE 7
+
+static void
+ao_validate(void)
+{
+ static struct ao_telemetry_location gps_data;
+ static struct ao_telemetry_satellite gps_tracking_data;
+ uint8_t new;
+ uint8_t data;
+ int16_t decivolt;
+ AO_TICK_TYPE gps_start;
+
+ ao_config_get();
+ /* Check the flash part */
+ ao_storage_setup();
+ if (ao_storage_total != 8 * 1024 * 1024)
+ ao_panic(AO_FAIL_FLASH);
+
+ /* Check the battery voltage */
+ data = ao_data_head;
+ do {
+ ao_sleep((void *) &ao_data_head);
+ } while (ao_data_head == data);
+ decivolt = ao_battery_decivolt(ao_data_ring[data].adc.v_batt);
+ if (decivolt < 35 || 55 < decivolt)
+ ao_panic(AO_FAIL_ADC);
+
+ /* Check to make sure GPS data is being received */
+ gps_start = ao_time();
+ for (;;) {
+ while ((new = ao_gps_new) == 0)
+ ao_sleep_for(&ao_gps_new, AO_SEC_TO_TICKS(1));
+ ao_mutex_get(&ao_gps_mutex);
+ if (new & AO_GPS_NEW_DATA)
+ memcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data));
+ if (new & AO_GPS_NEW_TRACKING)
+ memcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data));
+ ao_gps_new = 0;
+ ao_mutex_put(&ao_gps_mutex);
+
+ if (new & AO_GPS_NEW_DATA) {
+ if (gps_data.flags & AO_GPS_RUNNING)
+ break;
+ }
+ if ((AO_TICK_SIGNED) (ao_time() - gps_start) > (AO_TICK_SIGNED) AO_SEC_TO_TICKS(10))
+ ao_panic(AO_FAIL_GPS);
+ }
+
+ if (!ao_radio_post())
+ ao_panic(AO_FAIL_RADIO);
+
+ ao_sample_init();
+ ao_flight_state = ao_flight_startup;
+ for (;;) {
+
+ /*
+ * Process ADC samples, just looping
+ * until the sensors are calibrated.
+ */
+ if (ao_sample())
+ break;
+ }
+
+ if (ao_sensor_errors & AO_DATA_MS5607)
+ ao_panic(AO_FAIL_BARO);
+ if (ao_sensor_errors & AO_DATA_ADXL375)
+ ao_panic(AO_FAIL_ACCEL);
+ if (ao_sensor_errors)
+ ao_panic(AO_FAIL_RANGE);
+
+ /* Check ground accel value to make sure it's somewhat valid */
+ if (ao_ground_accel < (accel_t) AO_CONFIG_DEFAULT_ACCEL_PLUS_G - ACCEL_NOSE_UP ||
+ ao_ground_accel > (accel_t) AO_CONFIG_DEFAULT_ACCEL_MINUS_G + ACCEL_NOSE_UP) {
+ ao_panic(AO_FAIL_ACCEL);
+ }
+ if (ao_ground_height < -1000 || ao_ground_height > 7000)
+ ao_panic(AO_FAIL_BARO);
+
+ ao_led_on(AO_LED_GREEN);
+ ao_beep_for(AO_BEEP_MID_DEFAULT, AO_MS_TO_TICKS(100));
+
+ ao_exit();
+}
+
+struct ao_task ao_validate_task;
+
+int
+main(void)
+{
+ ao_clock_init();
+
+#if HAS_STACK_GUARD
+ ao_mpu_init();
+#endif
+
+ ao_task_init();
+ ao_serial_init();
+ ao_led_init();
+ ao_led_off(LEDS_AVAILABLE);
+ ao_timer_init();
+
+ ao_spi_init();
+ ao_dma_init();
+ ao_exti_init();
+
+ ao_adc_init();
+ ao_beep_init();
+ ao_cmd_init();
+
+ ao_ms5607_init();
+ ao_adxl375_init();
+
+ ao_storage_init();
+
+ ao_usb_init();
+ ao_gps_init();
+
+ ao_radio_init();
+ ao_igniter_init();
+
+ ao_config_init();
+#if AO_PROFILE
+ ao_profile_init();
+#endif
+#if HAS_SAMPLE_PROFILE
+ ao_sample_profile_init();
+#endif
+
+ ao_add_task(&ao_validate_task, ao_validate, "validate");
+
+ ao_start_scheduler();
+ return 0;
+}
--- /dev/null
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=telemetrum-v4.0-seeed
+include $(TOPDIR)/samd21/Makefile-flash.defs
--- /dev/null
+/*
+ * Copyright © 2022 Bdale Garbee <bdale@gag.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.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#include <ao_flash_samd21_pins.h>
+
+/* cs_comp_0 (companion port pin 6) to gnd for boot loader mode */
+
+#define AO_BOOT_PIN 1
+#define AO_BOOT_APPLICATION_GPIO (samd21_port_a)
+#define AO_BOOT_APPLICATION_PIN 13
+#define AO_BOOT_APPLICATION_VALUE 1
+#define AO_BOOT_APPLICATION_MODE AO_MODE_PULL_UP
+
+/* USB */
+#define HAS_USB 1
+
+#define AO_XOSC 1
+#define AO_XOSC_FREQ 16000000
+#define AO_XOSC_DIV 256
+#define AO_XOSC_MUL 768
+
+#endif /* _AO_PINS_H_ */
vpath %.h ..:../kernel:../drivers:../util:../micropeak:../aes:../product
vpath make-kalman ..:../kernel:../drivers:../util:../micropeak:../aes:../product
-PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_flight_test_mm \
+PROGS=ao_flight_test_mm \
ao_flight_test_metrum ao_flight_test_mini \
ao_gps_test ao_gps_test_skytraq ao_gps_test_ublox ao_convert_test ao_convert_pa_test ao_fec_test \
ao_aprs_test ao_micropeak_test ao_fat_test ao_aes_test ao_int64_test \
- ao_ms5607_convert_test ao_quaternion_test
+ ao_ms5607_convert_test ao_quaternion_test \
+ ao_flight_test_tmega4
INCS=ao_kalman.h ao_ms5607.h ao_log.h ao_data.h altitude-pa.h altitude.h ao_quaternion.h ao_eeprom_read.h
TEST_SRC=ao_flight_test.c
KALMAN=make-kalman
-CFLAGS=-I.. -I. -I../kernel -I../drivers -I../micropeak -I../product -I../lisp -O0 -g -Wall -DAO_LISP_TEST -no-pie
+CFLAGS=-I.. -I. -I../kernel -I../drivers -I../product -I../lisp -O0 -g -Wall -DAO_LISP_TEST -no-pie
all: $(PROGS) ao_aprs_data.wav
ao_flight_test_mm: $(TEST_SRC_ALL) ao_host.h ao_flight.c ao_sample.c ao_kalman.c ao_pyro.c ao_pyro.h $(INCS)
cc -DTELEMEGA=1 $(CFLAGS) -o $@ $(TEST_SRC) $(TEST_LIB) -lm
+ao_flight_test_tmega4: $(TEST_SRC_ALL) ao_host.h ao_flight.c ao_sample.c ao_kalman.c ao_pyro.c ao_pyro.h $(INCS)
+ cc -DTELEMEGA_V4=1 $(CFLAGS) -o $@ $(TEST_SRC) $(TEST_LIB) -lm
+
ao_flight_test_metrum: $(TEST_SRC_ALL) ao_host.h ao_flight.c ao_sample.c ao_kalman.c ao_pyro.c ao_pyro.h $(INCS)
cc -DTELEMETRUM_V2=1 $(CFLAGS) -o $@ $(TEST_SRC) $(TEST_LIB) -lm
cc $(CFLAGS) -o $@ ao_micropeak_test.c -lm
ao_fat_test: ao_fat_test.c ao_fat.c ao_bufio.c
- cc $(CFLAGS) -o $@ ao_fat_test.c -lssl -lcrypto
+ cc $(CFLAGS) -o $@ ao_fat_test.c -Wno-deprecated-declarations -lssl -lcrypto
ao_aes_test: ao_aes_test.c ao_aes.c ao_aes_tables.c
cc $(CFLAGS) -o $@ ao_aes_test.c
}
}
- printf ("\n **** Write IO: read %llu write %llu data sectors %llu\n", total_reads, total_writes, (total_file_size + 511) / 512);
+ printf ("\n **** Write IO: read %lu write %lu data sectors %lu\n", total_reads, total_writes, (total_file_size + 511) / 512);
check_bufio("all files created");
printf (" **** All done creating files\n");
check_bufio("file shown");
}
}
- printf ("\n **** Read IO: read %llu write %llu\n", total_reads, total_writes);
+ printf ("\n **** Read IO: read %lu write %lu\n", total_reads, total_writes);
}
char *params[] = {
return ok;
}
+int
+ao_hello_packet(void)
+{
+ uint8_t message[5] = "hello";
+ uint8_t encode[ENCODE_LEN(sizeof(message))];
+ int encode_len;
+ uint8_t transmit[EXPAND_LEN(sizeof(message))];
+ uint8_t decode[DECODE_LEN(sizeof(message))];
+ int transmit_len;
+ int decode_ok;
+
+ printf("Hello packet test:\n");
+ ao_fec_dump_bytes(message, sizeof(message), "Message");
+ encode_len = ao_fec_encode(message, sizeof(message), encode);
+ ao_fec_dump_bytes(encode, encode_len, "Encode");
+ transmit_len = ao_expand(encode, encode_len, transmit);
+ ao_fec_dump_bytes(transmit, transmit_len, "Transmit");
+ decode_ok = ao_fec_decode(transmit, transmit_len, decode, sizeof(message) + 2, NULL);
+ ao_fec_dump_bytes(decode, sizeof(message) + 2, "Receive");
+ printf("Hello result: %s\n", decode_ok ? "success" : "fail");
+ return decode_ok;
+}
+
#define EXPECT_DECODE_FAIL 0
-#define EXPECT_CRC_MISMATCH 6386
+#define EXPECT_CRC_MISMATCH 6304
#define EXPECT_DATA_MISMATCH 0
#define NOISE_AMOUNT 0x50
if (!ao_real_packet())
errors++;
+ if (!ao_hello_packet())
+ errors++;
+
srandom(0);
for (trial = 0; trial < 100000; trial++) {
#include <math.h>
#define log ao_log_data
+#define AO_TICK_TYPE uint32_t
+#define AO_TICK_SIGNED int32_t
+
+typedef int32_t pres_t;
+#define pres_to_altitude(p) ao_pa_to_altitude(p)
+#define ao_data_pres_cook(packet) ao_ms5607_convert(&packet->ms5607_raw, &packet->ms5607_cooked)
+#define ao_data_pres(packet) ((packet)->ms5607_cooked.pres)
+#define AO_ADC_MAX 4095
+#define AO_PYRO_BATTERY_DIV_PLUS 100
+#define AO_PYRO_BATTERY_DIV_MINUS 27
+#define AO_IGNITE_DIV_PLUS 100
+#define AO_IGNITE_DIV_MINUS 27
+#define AO_ADC_REFERENCE_DV 33
+
#define GRAVITY 9.80665
#define AO_HERTZ 100
int ao_gps_new;
-#if !defined(TELEMEGA) && !defined(TELEMETRUM_V2) && !defined(EASYMINI) && !defined(EASYMOTOR_V_2)
+#if !defined(TELEMEGA) && !defined(TELEMETRUM_V2) && !defined(EASYMINI) && !defined(EASYMOTOR_V_2) && !defined(TELEMEGA_V4)
#define TELEMETRUM_V1 1
#endif
};
#endif
+#if TELEMEGA_V4
+#define AO_ADC_NUM_SENSE 6
+#define HAS_MS5607 1
+#define HAS_BMX160 1
+#define HAS_ADXL375 1
+#define AO_ADXL375_INVERT 1
+#define AO_ADXL375_AXIS x
+#define HAS_BEEP 1
+#define HAS_BARO 1
+#define AO_CONFIG_MAX_SIZE 1024
+
+struct ao_adc {
+ int16_t sense[AO_ADC_NUM_SENSE];
+ int16_t v_batt;
+ int16_t v_pbatt;
+ int16_t temp;
+};
+
+#define ao_data_along(packet) ((packet)->bmx160.acc_x)
+#define ao_data_across(packet) (-(packet)->bmx160.acc_y)
+#define ao_data_through(packet) ((packet)->bmx160.acc_z)
+
+#define ao_data_roll(packet) ((packet)->bmx160.gyr_x)
+#define ao_data_pitch(packet) (-(packet)->bmx160.gyr_y)
+#define ao_data_yaw(packet) ((packet)->bmx160.gyr_z)
+
+#define ao_data_mag_along(packet) ((packet)->bmx160.mag_x)
+#define ao_data_mag_across(packet) ((packet)->bmx160.mag_y)
+#define ao_data_mag_through(packet) ((packet)->bmx160.mag_z)
+
+#define ao_data_set_along(packet,v) ((packet)->bmx160.acc_x = (v))
+#define ao_data_set_across(packet,v) ((packet)->bmx160.acc_y = -(v))
+#define ao_data_set_through(packet,v) ((packet)->bmx160.acc_z = (v))
+
+#define ao_data_set_roll(packet,v) ((packet)->bmx160.gyr_x = (v))
+#define ao_data_set_pitch(packet,v) ((packet)->bmx160.gyr_y = -(v))
+#define ao_data_set_yaw(packet,v) ((packet)->bmx160.gyr_z = (v))
+
+#define ao_data_set_mag_along(packet,v) ((packet)->bmx160.mag_x = (v))
+#define ao_data_set_mag_across(packet,v) ((packet)->bmx160.mag_y = (v))
+#define ao_data_set_mag_through(packet,v) ((packet)->bmx160.mag_z = (v))
+#endif
+
#if TELEMETRUM_V2
#define AO_ADC_NUM_SENSE 2
#define HAS_MS5607 1
#define HAS_USB 1
#define HAS_GPS 1
-int16_t
+AO_TICK_TYPE
ao_time(void);
void
#define ao_tick_count (ao_time())
#define ao_wakeup(wchan) ao_dump_state()
+enum ao_igniter_status {
+ ao_igniter_unknown, /* unknown status (ambiguous voltage) */
+ ao_igniter_ready, /* continuity detected */
+ ao_igniter_active, /* igniter firing */
+ ao_igniter_open, /* open circuit detected */
+};
+
#include <ao_data.h>
#include <ao_log.h>
#include <ao_telemetry.h>
#include <ao_sample.h>
-#if TELEMEGA
+#if TELEMEGA || TELEMEGA_V4
int ao_gps_count;
struct ao_telemetry_location ao_gps_first;
struct ao_telemetry_location ao_gps_prev;
int main_height;
double main_time;
-int tick_offset;
+uint32_t tick_offset;
static ao_k_t ao_k_height;
static double simple_speed;
-int16_t
+AO_TICK_TYPE
ao_time(void)
{
return ao_data_static.tick;
};
#define AO_NEED_ALTITUDE_TO_PRES 1
-#if TELEMEGA || TELEMETRUM_V2 || EASYMINI
+#if TELEMEGA || TELEMETRUM_V2 || EASYMINI || TELEMEGA_V4
#include "ao_convert_pa.c"
#include <ao_ms5607.h>
struct ao_ms5607_prom ao_ms5607_prom;
#include "ao_ms5607_convert.c"
-#if TELEMEGA
+#if TELEMEGA || TELEMEGA_V4
#define AO_PYRO_NUM 4
#include <ao_pyro.h>
#endif
typedef int16_t accel_t;
uint16_t ao_serial_number;
-int16_t ao_flight_number;
+uint16_t ao_flight_number;
extern AO_TICK_TYPE ao_sample_tick;
AO_TICK_TYPE ao_sample_prev_tick;
AO_TICK_TYPE prev_tick;
+AO_TICK_TYPE start_tick;
#include "ao_kalman.c"
#include "ao_sample.c"
#include "ao_flight.c"
#include "ao_data.c"
-#if TELEMEGA
+#if TELEMEGA || TELEMEGA_V4
#define AO_PYRO_NUM 4
#define AO_PYRO_0 0
static void
ao_pyro_pin_set(uint8_t pin, uint8_t value)
{
- printf ("set pyro %d %d\n", pin, value);
}
#include "ao_pyro.c"
#if HAS_MPU6000
static struct ao_mpu6000_sample ao_ground_mpu6000;
#endif
+#if HAS_BMX160
+static struct ao_bmx160_sample ao_ground_bmx160;
+#endif
void
ao_test_exit(void)
exit(0);
}
-#ifdef TELEMEGA
+#if TELEMEGA || TELEMEGA_V4
struct ao_azel {
int az;
int el;
#endif
(void) accel;
- if (!tick_offset)
- tick_offset = -ao_data_static.tick;
- if ((prev_tick - ao_data_static.tick) > 0x400)
+ if (!start_tick)
+ start_tick = ao_data_static.tick;
+ if ((AO_TICK_SIGNED) (prev_tick - ao_data_static.tick) > 0x400)
tick_offset += 65536;
if (prev_tick) {
int ticks = ao_data_static.tick - prev_tick;
simple_speed += accel * ticks / 100.0;
}
prev_tick = ao_data_static.tick;
- time = (double) (ao_data_static.tick + tick_offset) / 100;
+ time = (double) (ao_data_static.tick + tick_offset - start_tick) / 100;
double height = 0;
#if HAS_BARO
-#if TELEMEGA || TELEMETRUM_V2 || EASYMINI
+#if TELEMEGA || TELEMETRUM_V2 || EASYMINI || TELEMEGA_V4
ao_ms5607_convert(&ao_data_static.ms5607_raw, &ao_data_static.ms5607_cooked);
height = ao_pa_to_altitude(ao_data_static.ms5607_cooked.pres) - ao_ground_height;
}
if (!ao_summary) {
-#if TELEMEGA
+#if TELEMEGA || TELEMEGA_V4
static struct ao_quaternion ao_ground_mag;
static int ao_ground_mag_set;
#if 1
printf("%7.2f height %8.2f accel %8.3f accel_speed %8.3f "
"state %d k_height %8.2f k_speed %8.3f k_accel %8.3f avg_height %5d drogue %4d main %4d error %5d"
-#if TELEMEGA
+#if TELEMEGA || TELEMEGA_V4
" angle %5d "
"accel_x %8.3f accel_y %8.3f accel_z %8.3f gyro_x %8.3f gyro_y %8.3f gyro_z %8.3f mag_x %8d mag_y %8d, mag_z %8d mag_angle %4d "
- "avg_accel %8.3f "
+ "avg_accel %8.3f pyro %d inhibited %d"
#endif
"\n",
time,
ao_data_static.hmc5883.y,
ao_data_static.hmc5883.z,
ao_mag_angle,
- ao_coast_avg_accel / 16.0
+ ao_coast_avg_accel / 16.0,
+ ao_pyro_fired * 10,
+ ao_pyro_inhibited * 10
+#endif
+#if TELEMEGA_V4
+ , ao_sample_orient,
+
+ ao_bmx160_accel(ao_data_static.bmx160.acc_x),
+ ao_bmx160_accel(ao_data_static.bmx160.acc_y),
+ ao_bmx160_accel(ao_data_static.bmx160.acc_z),
+ ao_bmx160_gyro(ao_data_static.bmx160.gyr_x - ao_ground_bmx160.gyr_x),
+ ao_bmx160_gyro(ao_data_static.bmx160.gyr_y - ao_ground_bmx160.gyr_y),
+ ao_bmx160_gyro(ao_data_static.bmx160.gyr_z - ao_ground_bmx160.gyr_z),
+ ao_data_static.bmx160.mag_x,
+ ao_data_static.bmx160.mag_y,
+ ao_data_static.bmx160.mag_z,
+ ao_mag_angle,
+ ao_coast_avg_accel / 16.0,
+ ao_pyro_fired * 10,
+ ao_pyro_inhibited * 10
#endif
);
#endif
ao_sleep(void *wchan)
{
if (wchan == &ao_data_head) {
-#if TELEMEGA
+#if TELEMEGA || TELEMEGA_V4
if (ao_flight_state >= ao_flight_boost && ao_flight_state < ao_flight_landed)
ao_pyro_check();
#endif
#if TELEMEGA
ao_data_static.mpu6000 = ao_ground_mpu6000;
#endif
+#if TELEMEGA_V4
+ ao_data_static.bmx160 = ao_ground_bmx160;
+#endif
#if TELEMETRUM_V1
ao_data_static.adc.accel = ao_flight_ground_accel;
#endif
}
if (eeprom) {
-#if TELEMEGA || EASYMOTOR_V_2
+#if TELEMEGA || EASYMOTOR_V_2 || TELEMEGA_V4
struct ao_log_mega *log_mega;
#endif
#if EASYMOTOR_V_2
}
break;
#endif
+#if TELEMEGA_V4
+ case AO_LOG_FORMAT_TELEMEGA_4:
+ log_mega = (struct ao_log_mega *) &eeprom->data[eeprom_offset];
+ eeprom_offset += sizeof (*log_mega);
+ switch (log_mega->type) {
+ case AO_LOG_FLIGHT:
+ ao_flight_number = log_mega->u.flight.flight;
+ ao_flight_ground_accel = log_mega->u.flight.ground_accel;
+ ao_flight_started = 1;
+ ao_ground_pres = log_mega->u.flight.ground_pres;
+ ao_ground_height = ao_pa_to_altitude(ao_ground_pres);
+ ao_ground_accel_along = log_mega->u.flight.ground_accel_along;
+ ao_ground_accel_across = log_mega->u.flight.ground_accel_across;
+ ao_ground_accel_through = log_mega->u.flight.ground_accel_through;
+ ao_ground_roll = log_mega->u.flight.ground_roll;
+ ao_ground_pitch = log_mega->u.flight.ground_pitch;
+ ao_ground_yaw = log_mega->u.flight.ground_yaw;
+ ao_ground_bmx160.acc_x = ao_ground_accel_along;
+ ao_ground_bmx160.acc_y = -ao_ground_accel_across;
+ ao_ground_bmx160.acc_z = ao_ground_accel_through;
+ ao_ground_bmx160.gyr_x = ao_ground_roll >> 9;
+ ao_ground_bmx160.gyr_y = -(ao_ground_pitch >> 9);
+ ao_ground_bmx160.gyr_z = ao_ground_yaw >> 9;
+ break;
+ case AO_LOG_STATE:
+ break;
+ case AO_LOG_SENSOR:
+ ao_data_static.tick = log_mega->tick;
+ ao_data_static.ms5607_raw.pres = log_mega->u.sensor.pres;
+ ao_data_static.ms5607_raw.temp = log_mega->u.sensor.temp;
+ ao_data_set_along(&ao_data_static, log_mega->u.sensor.accel_along);
+ ao_data_set_across(&ao_data_static, log_mega->u.sensor.accel_across);
+ ao_data_set_through(&ao_data_static, log_mega->u.sensor.accel_through);
+ ao_data_set_roll(&ao_data_static, log_mega->u.sensor.gyro_roll);
+ ao_data_set_pitch(&ao_data_static, log_mega->u.sensor.gyro_pitch);
+ ao_data_set_yaw(&ao_data_static, log_mega->u.sensor.gyro_yaw);
+ ao_data_set_mag_along(&ao_data_static, log_mega->u.sensor.mag_along);
+ ao_data_set_mag_across(&ao_data_static, log_mega->u.sensor.mag_across);
+ ao_data_set_mag_through(&ao_data_static, log_mega->u.sensor.mag_through);
+#if AO_ADXL375_INVERT
+ ao_data_static.adxl375.AO_ADXL375_AXIS = ao_data_accel_invert(log_mega->u.sensor.accel);
+#else
+ ao_data_static.adxl375.AO_ADXL375_AXIS = log_mega->u.sensor.accel;
+#endif
+ if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP)
+ ao_data_static.adxl375.AO_ADXL375_AXIS = ao_data_accel_invert(ao_data_static.adxl375.AO_ADXL375_AXIS);
+ ao_records_read++;
+ ao_insert();
+ return;
+ case AO_LOG_TEMP_VOLT:
+ if (pyros_fired != log_mega->u.volt.pyro) {
+ printf("pyro changed %x -> %x\n", pyros_fired, log_mega->u.volt.pyro);
+ pyros_fired = log_mega->u.volt.pyro;
+ }
+ break;
+ case AO_LOG_GPS_TIME:
+ ao_gps_prev = ao_gps_static;
+ ao_gps_static.tick = log_mega->tick;
+ ao_gps_static.latitude = log_mega->u.gps.latitude;
+ ao_gps_static.longitude = log_mega->u.gps.longitude;
+ {
+ int16_t altitude_low = log_mega->u.gps.altitude_low;
+ int16_t altitude_high = log_mega->u.gps.altitude_high;
+ int32_t altitude = altitude_low | ((int32_t) altitude_high << 16);
+
+ AO_TELEMETRY_LOCATION_SET_ALTITUDE(&ao_gps_static, altitude);
+ }
+ ao_gps_static.flags = log_mega->u.gps.flags;
+ if (!ao_gps_count)
+ ao_gps_first = ao_gps_static;
+ ao_gps_count++;
+ break;
+ case AO_LOG_GPS_SAT:
+ break;
+ }
+ break;
+#endif
+#ifdef foo_TELEMEGA_V4
+ case AO_LOG_FORMAT_TELEMEGA_4:
+ log_mega = (struct ao_log_mega *) &eeprom->data[eeprom_offset];
+ eeprom_offset += sizeof (*log_mega);
+ switch (log_mega->type) {
+ case AO_LOG_FLIGHT:
+ ao_flight_number = log_mega->u.flight.flight;
+ ao_flight_ground_accel = log_mega->u.flight.ground_accel;
+ ao_flight_started = 1;
+ break;
+ case AO_LOG_SENSOR:
+ ao_data_static.tick = log_mega->tick;
+ ao_data_static.adxl375.AO_ADXL375_AXIS = log_mega->u.sensor.accel;
+ ao_records_read++;
+ ao_insert();
+ return;
+ }
+ break;
+#endif
#if TELEMETRUM_V2
case AO_LOG_FORMAT_TELEMETRUM:
log_metrum = (struct ao_log_metrum *) &eeprom->data[eeprom_offset];
*/
#define AO_GPS_TEST
+#define AO_TICK_TYPE uint32_t
#include "ao_host.h"
#include <termios.h>
#include <errno.h>
*/
#define AO_GPS_TEST
+#define AO_TICK_TYPE uint32_t
#define HAS_GPS 1
+#define tick_count 0
#include "ao_host.h"
#include <termios.h>
#include <errno.h>
int16_t altitude; /* m */
uint16_t ground_speed; /* cm/s */
uint8_t course; /* degrees / 2 */
+ uint8_t pdop; /* unused */
+ uint8_t vdop; /* unused */
uint8_t hdop; /* * 5 */
int16_t climb_rate; /* cm/s */
uint16_t h_error; /* m */
*/
#define AO_GPS_TEST
+#define AO_TICK_TYPE uint32_t
#define HAS_GPS 1
+#define ao_tick_count 0
#include "ao_host.h"
#include <termios.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <stdbool.h>
#include <fcntl.h>
#include <unistd.h>
#define AO_GPS_NUM_SAT_MASK (0xf << 0)
*/
#define _GNU_SOURCE
+#define AO_TICK_TYPE uint32_t
#include <stdint.h>
#include <stdio.h>
exit 1
esac
-gnuplot -persist << EOF
+cat - /dev/tty <<EOF | gnuplot
set ylabel "distance (m)"
set y2label "angle (d)"
set xlabel "time (s)"
set ytics border out nomirror
set y2tics border out nomirror
set title "$title"
-plot "$file" using 1:5 with lines axes x1y1 title "height",\
-"$file" using 1:7 with lines axes x1y2 title "angle",\
-"$file" using 1:13 with lines axes x1y2 title "gps angle",\
-"$file" using 1:15 with lines axes x1y2 title "sats"
+plot "$file" using 1:3 with lines axes x1y1 title "height",\
+"$file" using 1:7 with lines axes x1y1 title "speed", \
+"$file" using 1:5 with lines axes x1y1 title "accel", \
+"$file" using 1:13 with lines axes x1y1 title "k_speed",\
+"$file" using 1:15 with lines axes x1y1 title "k_accel",\
+"$file" using 1:25 with lines axes x1y2 title "angle",\
+"$file" using 1:49 with lines axes x1y2 title "pyro",\
+"$file" using 1:51 with lines axes x1y2 title "inhibited"
EOF
FIRMWARE_TGPS_1_0=$(top_srcdir)/src/telegps-v1.0/telegps-v1.0-$(VERSION).ihx
FIRMWARE_TGPS_2_0=$(top_srcdir)/src/telegps-v2.0/telegps-v2.0-$(VERSION).ihx
FIRMWARE_TGPS_3_0=$(top_srcdir)/src/telegps-v3.0/telegps-v3.0-$(VERSION).ihx
-FIRMWARE_TGPS=$(FIRMWARE_TGPS_1_0) $(FIRMWARE_TGPS_2_0) $(FIRMWARE_TGPS_3_0)
+FIRMWARE_TGPS_4_0=$(top_srcdir)/src/telegps-v4.0/telegps-v4.0-$(VERSION).ihx
+FIRMWARE_TGPS=$(FIRMWARE_TGPS_1_0) $(FIRMWARE_TGPS_2_0) $(FIRMWARE_TGPS_3_0) $(FIRMWARE_TGPS_4_0)
FIRMWARE=$(FIRMWARE_TGPS) $(FIRMWARE_TD) $(FIRMWARE_TBT)
JLabel radio_enable_label;
JLabel radio_10mw_label;
JLabel report_feet_label;
+ JLabel gps_receiver_label;
JLabel rate_label;
JLabel aprs_interval_label;
JLabel aprs_ssid_label;
JRadioButton radio_enable_value;
JRadioButton radio_10mw_value;
JComboBox<String> report_feet_value;
+ JComboBox<String> gps_receiver_value;
AltosUIRateList rate_value;
JComboBox<String> aprs_interval_value;
JComboBox<Integer> aprs_ssid_value;
return AltosLib.MISSING;
}
+ void set_gps_receiver_tool_tip() {
+ if (gps_receiver_value.isVisible())
+ gps_receiver_value.setToolTipText("GPS receiver selection");
+ else
+ gps_receiver_value.setToolTipText("Only TeleMega with new firmware supports alternate GPS receivers");
+ }
+
+ public void set_gps_receiver(int new_gps_receiver) {
+ System.out.printf("set_gps_receiver %d\n", new_gps_receiver);
+ if (new_gps_receiver != AltosLib.MISSING) {
+ if (new_gps_receiver >= AltosLib.gps_receiver_names.length)
+ new_gps_receiver = 0;
+ if (new_gps_receiver < 0) {
+ gps_receiver_value.setEnabled(false);
+ new_gps_receiver = 0;
+ } else {
+ gps_receiver_value.setEnabled(true);
+ }
+ gps_receiver_value.setSelectedIndex(new_gps_receiver);
+ }
+ gps_receiver_value.setVisible(new_gps_receiver != AltosLib.MISSING);
+ gps_receiver_label.setVisible(new_gps_receiver != AltosLib.MISSING);
+
+ set_gps_receiver_tool_tip();
+ }
+
+ public int gps_receiver() {
+ if (gps_receiver_value.isVisible())
+ return gps_receiver_value.getSelectedIndex();
+ else
+ return AltosLib.MISSING;
+ }
+
void set_rate_tool_tip() {
if (rate_value.isVisible())
rate_value.setToolTipText("Select telemetry baud rate");
set_report_feet_tool_tip();
row++;
+ /* GPS Receiver */
+ c = new GridBagConstraints();
+ c.gridx = 0; c.gridy = row;
+ c.gridwidth = 4;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = il;
+ c.ipady = 5;
+ gps_receiver_label = new JLabel("GPS Receiver:");
+ pane.add(gps_receiver_label, c);
+
+ c = new GridBagConstraints();
+ c.gridx = 4; c.gridy = row;
+ c.gridwidth = 4;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.weightx = 1;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = ir;
+ c.ipady = 5;
+ gps_receiver_value = new JComboBox<String>(AltosLib.gps_receiver_names);
+ gps_receiver_value.setEditable(false);
+ gps_receiver_value.addItemListener(this);
+ pane.add(gps_receiver_value, c);
+ set_gps_receiver_tool_tip();
+ row++;
+
/* Radio 10mW limit */
c = new GridBagConstraints();
c.gridx = 0; c.gridy = row;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
-import org.jfree.ui.RefineryUtilities;
+import org.jfree.chart.ui.UIUtils;
public class TeleGPSGraphUI extends AltosUIFrame implements AltosFontListener, AltosUnitsListener, AltosFilterListener
{
File "../src/telegps-v1.0/telegps-v1.0-${VERSION}.ihx"
File "../src/telegps-v2.0/telegps-v2.0-${VERSION}.ihx"
File "../src/telegps-v3.0/telegps-v3.0-${VERSION}.ihx"
+ File "../src/telegps-v4.0/telegps-v4.0-${VERSION}.ihx"
File "../src/teledongle-v3.0/teledongle-v3.0-${VERSION}.ihx"
File "../src/telebt-v3.0/telebt-v3.0-${VERSION}.ihx"
File "../src/telebt-v4.0/telebt-v4.0-${VERSION}.ihx"