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/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
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-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-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;
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 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"))
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;
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 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;
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;
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 \
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
{
if (config_data != null) {
configTable = new AltosFlightConfigTable(config_data);
pane.add("Configuration", configTable);
- if (config_data.npyro > 0) {
+ if (config_data.npyro > 0 && config_data.npyro != AltosLib.MISSING) {
pyroTable = new AltosFlightPyroTable(config_data.pyros, config_data.npyro);
pane.add("Pyros", pyroTable);
}
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_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"
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();
}
--- /dev/null
+#!/bin/sh
+
+case $# in
+1)
+ dev="$1"
+ ;;
+*)
+ echo "Usage: $0 <device>"
+ exit 1;
+ ;;
+esac
+
+../ao-tools/ao-cal-freq/ao-cal-freq --tty=$dev
+case $? in
+ 0)
+ calline=`./get-radio-cal $dev`
+ CAL_VALUE=`echo $calline | awk '{print $2}'`
+ CURRENT_FREQ=`echo $calline | awk '{print $4}'`
+ echo $SERIAL","$CAL_VALUE >> cal_values
+ exit 0
+ ;;
+ *)
+ exit 1
+ ;;
+esac
+++ /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=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 $?
+++ /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.18)
+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=2024-04-28
+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 \
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: '© 2024 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 2024
+: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[]
[license]
== License
-Copyright © 2024 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.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[]
|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[]
|-
|24g
|-
- |BMI088
+ |BMI088 MMC5983
|1MB
|-
|3.7-12V
|-
|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[]
[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 \
#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;
}
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;
}
#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
#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 \
#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
#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("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",
(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;
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_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.
*
ao_spi_init();
ao_dma_init();
ao_exti_init();
- ao_adc_single_init();
+ ao_adc_init();
ao_beep_init();
ao_pwm_init();
#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_ */
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)
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"