Merge branch 'master' into branch-1.9
authorBdale Garbee <bdale@gag.com>
Tue, 21 Sep 2021 03:24:45 +0000 (21:24 -0600)
committerBdale Garbee <bdale@gag.com>
Tue, 21 Sep 2021 03:24:45 +0000 (21:24 -0600)
98 files changed:
Makefile.am
Releasing
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroid.java
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/PreloadMapActivity.java
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TabFlight.java
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TabPad.java
altosdroid/app/src/main/res/layout/tab_flight.xml
altosdroid/app/src/main/res/layout/tab_pad.xml
altosdroid/app/src/main/res/values/strings.xml
altoslib/AltosCalData.java
altoslib/AltosEepromRecordMega.java
altoslib/AltosIMU.java
altoslib/AltosIdleFetch.java
altoslib/AltosLib.java
altoslib/AltosMag.java
altoslib/AltosTelemetry.java
altoslib/AltosTelemetryMegaNorm.java [new file with mode: 0644]
altoslib/AltosTelemetryMegaSensor.java
altoslib/AltosTelemetryStandard.java
altoslib/Makefile.am
altoslib/NewProduct [new file with mode: 0644]
altosui/AltosConfigFCUI.java
altosui/Makefile.am
altosui/altos-windows.nsi.in
altosuilib/AltosUILib.java
ao-bringup/test-easymega
ao-bringup/test-easymini
ao-bringup/test-easymini-v1.0 [new file with mode: 0755]
ao-bringup/test-igniters
ao-bringup/test-igniters-nowait
ao-bringup/test-telemega
ao-bringup/test-telemetrum
ao-bringup/test-telemini
ao-bringup/turnon_easymini
ao-tools/ao-test-igniter/ao-test-igniter.c
configure.ac
doc/Makefile.am
doc/easymega-outline.txt
doc/easymini-outline.txt
doc/easymini-release-notes.inc
doc/pyro-channels.inc
doc/release-notes-1.9.8.inc [new file with mode: 0644]
doc/release-notes.inc
doc/specs.inc
doc/telegps-outline.txt
doc/telegps-release-notes.inc
doc/telemega-outline.txt
doc/telemetrum-outline.txt
doc/telemini-v1-outline.txt
doc/telemini-v3-outline.txt
doc/telemini.inc
icon/Makefile.am
libaltos/.gitignore
libaltos/Makefile.am
libaltos/altos.dll
libaltos/altos64.dll
libaltos/gcc [new file with mode: 0755]
libaltos/libaltos_common.c
libaltos/libaltos_linux.c
libaltos/libaltos_private.h
libaltos/libaltos_windows.c
micropeak/Makefile.am
micropeak/MicroDownload.java
micropeak/MicroPeak.java
src/Makefile
src/drivers/ao_cc1200.c
src/drivers/ao_cc1200.h
src/drivers/ao_mmc5983.c [new file with mode: 0644]
src/drivers/ao_mmc5983.h [new file with mode: 0644]
src/drivers/ao_mpu6000.c
src/kernel/ao_beep.h
src/kernel/ao_config.c
src/kernel/ao_config.h
src/kernel/ao_data.h
src/kernel/ao_flight.c
src/kernel/ao_i2c_bit.c [new file with mode: 0644]
src/kernel/ao_i2c_bit.h [new file with mode: 0644]
src/kernel/ao_log.h
src/kernel/ao_log_mega.c
src/kernel/ao_pyro.c
src/kernel/ao_pyro.h
src/kernel/ao_sample.c
src/kernel/ao_stdio.c
src/kernel/ao_telemetry.c
src/kernel/ao_telemetry.h
src/lpc/lpc.h
src/micropeak-v2.0/ao_micro.c
src/stm/Makefile-flash.defs
src/stm/Makefile.defs
src/stm/ao_arch_funcs.h
src/stm/ao_interrupt.c
src/telemega-v5.0/Makefile [new file with mode: 0644]
src/telemega-v5.0/ao_pins.h [new file with mode: 0644]
src/telemega-v5.0/ao_telemega.c [new file with mode: 0644]
src/telemega-v5.0/flash-loader/Makefile [new file with mode: 0644]
src/telemega-v5.0/flash-loader/ao_pins.h [new file with mode: 0644]
src/telemega-v5.0/notes [new file with mode: 0644]
telegps/Makefile.am

index fa38cf2fcdd1031aa2dba6f957f70b665b5db173..6918c578cf98d7541754e1938424d7c2b86cc172 100644 (file)
@@ -64,6 +64,7 @@ fat_altos = \
        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/telemetrum-v2.0/telemetrum-v2.0-$(VERSION).ihx \
        src/telemetrum-v3.0/telemetrum-v3.0-$(VERSION).ihx \
        src/telelco-v2.0/telelco-v2.0-$(VERSION).ihx \
index b54e236f552eade76a526cf05254ec6ac4b77663..f7721a507b4c9a1216105fa76744ddf0e3daa772 100644 (file)
--- a/Releasing
+++ b/Releasing
@@ -116,7 +116,7 @@ These are Bdale's notes on how to do a release.
           src/teledongle-v3.0/{*.elf,*.ihx,*.map} \
           src/telegps-v1.0/{*.elf,*.ihx,*.map} \
           src/telegps-v2.0/{*.elf,*.ihx,*.map} \
-          src/telemega-v[1-4].0/{*.elf,*.ihx,*.map} \
+          src/telemega-v[1-5].0/{*.elf,*.ihx,*.map} \
           src/telemetrum-v2.0/{*.elf,*.ihx,*.map} \
           src/telemetrum-v3.0/{*.elf,*.ihx,*.map} \
           src/telemini-v3.0/{*.elf,*.ihx,*.map} \
@@ -136,7 +136,7 @@ These are Bdale's notes on how to do a release.
           src/teledongle-v3.0/flash-loader/*.elf \
           src/telegps-v1.0/flash-loader/*.elf \
           src/telegps-v2.0/flash-loader/{*.elf,*.bin,*.map} \
-          src/telemega-v[1-4].0/flash-loader/*.elf \
+          src/telemega-v[1-5].0/flash-loader/*.elf \
           src/telemetrum-v2.0/flash-loader/*.elf \
           src/telemetrum-v3.0/flash-loader/*.elf \
           src/telemini-v3.0/flash-loader/{*.elf,*.bin,*.map} \
index 404b63ace7df8582e90c2e50ecb06ff6c04d1169..5caee5f87aab5323ea0032cf54f865649ff22a8b 100644 (file)
@@ -742,14 +742,23 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,
        private void enable_location_updates() {
                // Listen for GPS and Network position updates
                LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
-               locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, this);
 
-               location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
+               if (locationManager != null)
+               {
+                       try {
+                               locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, this);
+                               location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
+                       } catch (Exception e) {
+                               locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 1, this);
+                               location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
+                       }
 
-               if (location != null)
-                       AltosDebug.debug("Resume, location is %f,%f\n",
-                                        location.getLatitude(),
-                                        location.getLongitude());
+                       if (location != null)
+                               AltosDebug.debug("Resume, location is %f,%f\n",
+                                                location.getLatitude(),
+                                                location.getLongitude());
+                       AltosDebug.debug("Failed to get GPS updates\n");
+               }
 
                update_ui(telemetry_state, state, true);
        }
index f911e1ee85e0ef597ae5e69ff9f04a40ada364ab..eb1230116c7cf4406486a7490d89432a95e9e09f 100644 (file)
@@ -356,8 +356,11 @@ public class PreloadMapActivity extends Activity implements AltosLaunchSiteListe
 
                // Listen for GPS and Network position updates
                LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
-
-               locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, this);
+               try {
+                       locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, this);
+               } catch (Exception e) {
+                       locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 1, this);
+               }
 
                new AltosLaunchSites(this);
        }
index ba45c47eff202c4ab185b9798e91ff7a11f573c1..0346f71c42ad99b073a1af457ba5269fe60ff574 100644 (file)
@@ -28,8 +28,12 @@ import android.location.Location;
 public class TabFlight extends AltosDroidTab {
        private TextView speed_view;
        private TextView height_view;
+       private TextView altitude_view;
+       private View tilt_view;
+       private TextView tilt_value;
        private TextView max_speed_view;
        private TextView max_height_view;
+       private TextView max_altitude_view;
        private TextView elevation_view;
        private TextView range_view;
        private TextView bearing_view;
@@ -50,10 +54,14 @@ public class TabFlight extends AltosDroidTab {
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
                View v = inflater.inflate(R.layout.tab_flight, container, false);
 
-               speed_view     = (TextView) v.findViewById(R.id.speed_value);
-               height_view    = (TextView) v.findViewById(R.id.height_value);
-               max_speed_view = (TextView) v.findViewById(R.id.max_speed_value);
-               max_height_view= (TextView) v.findViewById(R.id.max_height_value);
+               speed_view      = (TextView) v.findViewById(R.id.speed_value);
+               height_view     = (TextView) v.findViewById(R.id.height_value);
+               altitude_view   = (TextView) v.findViewById(R.id.altitude_value);
+               tilt_view       = (View) v.findViewById(R.id.tilt_view);
+               tilt_value      = (TextView) v.findViewById(R.id.tilt_value);
+               max_speed_view  = (TextView) v.findViewById(R.id.max_speed_value);
+               max_height_view = (TextView) v.findViewById(R.id.max_height_value);
+               max_altitude_view= (TextView) v.findViewById(R.id.max_altitude_value);
                elevation_view = (TextView) v.findViewById(R.id.elevation_value);
                range_view     = (TextView) v.findViewById(R.id.range_value);
                bearing_view   = (TextView) v.findViewById(R.id.bearing_value);
@@ -85,8 +93,17 @@ public class TabFlight extends AltosDroidTab {
                if (state != null) {
                        set_value(speed_view, AltosConvert.speed, 1, state.speed());
                        set_value(height_view, AltosConvert.height, 1, state.height());
+                       set_value(altitude_view, AltosConvert.height, 1, state.altitude());
+                       double orient = state.orient();
+                       if (orient == AltosLib.MISSING) {
+                               tilt_view.setVisibility(View.GONE);
+                       } else {
+                               tilt_value.setText(AltosDroid.number("%1.0f°", orient));
+                               tilt_view.setVisibility(View.VISIBLE);
+                       }
                        set_value(max_speed_view, AltosConvert.speed, 1, state.max_speed());
                        set_value(max_height_view, AltosConvert.height, 1, state.max_height());
+                       set_value(max_altitude_view, AltosConvert.height, 1, state.max_altitude());
                        if (from_receiver != null) {
                                elevation_view.setText(AltosDroid.number("%1.0f°", from_receiver.elevation));
                                set_value(range_view, AltosConvert.distance, 1, from_receiver.range);
index f526857f00ccedb3a67011dc9b606309dc2394f1..4a8b3f862b9bbeed9077133fc6e8a5b1b1f84f69 100644 (file)
@@ -62,6 +62,8 @@ public class TabPad extends AltosDroidTab {
        private TextView[] ignite_voltage_label = new TextView[4];
        private GoNoGoLights[] ignite_lights = new GoNoGoLights[4];
 
+       private View tilt_view;
+       private TextView tilt_value;
 
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@@ -107,6 +109,9 @@ public class TabPad extends AltosDroidTab {
                                                   (ImageView) v.findViewById(R.id.gps_ready_greenled),
                                                   getResources());
 
+               tilt_view       = (View) v.findViewById(R.id.tilt_view);
+               tilt_value      = (TextView) v.findViewById(R.id.tilt_value);
+
                for (int i = 0; i < 4; i++) {
                        int row_id, view_id, label_id, lights_id;
                        int red_id, green_id;
@@ -213,8 +218,18 @@ public class TabPad extends AltosDroidTab {
                        } else
                                gps_locked_lights.set(false, true);
                        gps_ready_lights.set(state.gps_ready, state.gps == null);
+
+                       double orient = state.orient();
+
+                       if (orient == AltosLib.MISSING) {
+                               tilt_view.setVisibility(View.GONE);
+                       } else {
+                               tilt_value.setText(AltosDroid.number("%1.0f°", orient));
+                               tilt_view.setVisibility(View.VISIBLE);
+                       }
                }
 
+
                if (telem_state != null) {
                        if (telem_state.receiver_battery == AltosLib.MISSING) {
                                receiver_row.setVisibility(View.GONE);
index 545bf047ed18f348138f503a91e67d082b534245..c588de16b5b32556787d0aebda62a910f363ef9e 100644 (file)
              android:textAppearance="?android:attr/textAppearanceSmall" />
       </TableRow>
 
+      <TableRow
+         android:layout_weight="1"
+         android:padding="2dip"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         >
+
+         <TextView
+             android:id="@+id/altitude_label"
+             android:layout_width="wrap_content"
+             android:layout_height="wrap_content"
+             android:layout_column="2"
+             android:text="@string/altitude_label" />
+
+         <TextView
+             android:id="@+id/altitude_value"
+             android:layout_width="wrap_content"
+             android:layout_height="wrap_content"
+             android:layout_alignParentRight="true"
+             android:text=""
+             android:textAppearance="?android:attr/textAppearanceSmall" />
+      </TableRow>
+
+      <TableRow
+         android:id="@+id/tilt_view"
+         android:visibility="gone"
+         android:layout_gravity="center"
+         android:layout_weight="1"
+         android:padding="2dip"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         >
+
+         <TextView
+             android:id="@+id/tilt_label"
+             android:layout_width="wrap_content"
+             android:layout_height="wrap_content"
+             android:layout_column="2"
+             android:text="@string/tilt_label" />
+
+         <TextView
+             android:id="@+id/tilt_value"
+             android:layout_width="wrap_content"
+             android:layout_height="wrap_content"
+             android:text=""
+             android:textAppearance="?android:attr/textAppearanceSmall" />
+      </TableRow>
+
       <TableRow
          android:layout_gravity="center"
          android:layout_weight="1"
              android:text="" />
       </TableRow>
 
+      <TableRow
+         android:layout_gravity="center"
+         android:layout_weight="1"
+         android:padding="2dip"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         >
+
+         <TextView
+             android:id="@+id/max_altitude_label"
+             android:layout_width="wrap_content"
+             android:layout_height="wrap_content"
+             android:layout_column="2"
+             android:text="@string/max_altitude_label" />
+
+         <TextView
+             android:id="@+id/max_altitude_value"
+             android:layout_width="wrap_content"
+             android:layout_height="wrap_content"
+             android:text="" />
+      </TableRow>
+
       <TableRow
          android:layout_weight="1"
          android:padding="2dip"
index 981f45a880bc7901868618054b07f4aa4e35d365..0eaea9a4e82136160af98584dc294529fedf3c8a 100644 (file)
          android:textAppearance="?android:attr/textAppearanceSmall" />
     </TableRow>
 
+    <TableRow
+       android:id="@+id/tilt_view"
+       android:visibility="gone"
+       android:layout_gravity="center"
+       android:layout_weight="1"
+       android:padding="2dip"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content"
+       >
+
+       <TextView
+           android:id="@+id/tilt_label"
+           android:layout_width="wrap_content"
+           android:layout_height="wrap_content"
+           android:layout_column="2"
+           android:text="@string/tilt_label" />
+
+       <TextView
+           android:id="@+id/tilt_value"
+           android:layout_width="wrap_content"
+           android:layout_height="wrap_content"
+           android:text=""
+           android:textAppearance="?android:attr/textAppearanceSmall" />
+    </TableRow>
+
     <TableRow
        android:padding="2dip"
        android:layout_width="wrap_content"
index 12b6d04f98c209f2be83cb84ec381f5a7540d827..efcfeb22a9413ecf80efff9c6e27ffbaf3e7f902 100644 (file)
 
        <!-- Tab fields -->
        <string name="height_label">Height</string>
+       <string name="altitude_label">Altitude</string>
        <string name="speed_label">Speed</string>
        <string name="accel_label">Acceleration</string>
+       <string name="tilt_label">Tilt</string>
        <string name="bearing_label">Bearing</string>
        <string name="direction_label">Direction</string>
        <string name="elevation_label">Elevation</string>
@@ -80,6 +82,7 @@
        <string name="distance_label">Distance</string>
        <string name="gnd_distance_label">Ground Distance</string>
        <string name="max_height_label">Max Height</string>
+       <string name="max_altitude_label">Max Altitude</string>
        <string name="max_speed_label">Max Speed</string>
        <string name="max_accel_label">Max Accel</string>
        <string name="battery_voltage_label">Battery</string>
index 8bca92291757a42c695985c23bb5337334c9b4e4..c90534a924e4159ea62cc0a1db5575e8493a67d0 100644 (file)
@@ -312,12 +312,24 @@ public class AltosCalData {
                return temp_gps;
        }
 
-       public int      imu_type = AltosLib.MISSING;;
+       public int      imu_type = AltosLib.MISSING;
+
+       public int      imu_model = AltosLib.MISSING;
+
+       public int      mag_model = AltosLib.MISSING;
 
        public void set_imu_type(int imu_type) {
                this.imu_type = imu_type;
        }
 
+       public void set_imu_model(int imu_model) {
+               this.imu_model = imu_model;
+       }
+
+       public void set_mag_model(int mag_model) {
+               this.mag_model = mag_model;
+       }
+
        public double   accel_zero_along, accel_zero_across, accel_zero_through;
 
        public void set_accel_zero(double zero_along, double zero_across, double zero_through) {
@@ -329,15 +341,15 @@ public class AltosCalData {
        }
 
        public double accel_along(double counts) {
-               return AltosIMU.convert_accel(counts - accel_zero_along, imu_type);
+               return AltosIMU.convert_accel(counts - accel_zero_along, imu_type, imu_model);
        }
 
        public double accel_across(double counts) {
-               return AltosIMU.convert_accel(counts - accel_zero_across, imu_type);
+               return AltosIMU.convert_accel(counts - accel_zero_across, imu_type, imu_model);
        }
 
        public double accel_through(double counts) {
-               return AltosIMU.convert_accel(counts - accel_zero_through, imu_type);
+               return AltosIMU.convert_accel(counts - accel_zero_through, imu_type, imu_model);
        }
 
        public double   gyro_zero_roll = AltosLib.MISSING;
@@ -357,19 +369,19 @@ public class AltosCalData {
                if (gyro_zero_roll == AltosLib.MISSING || counts == AltosLib.MISSING)
                        return AltosLib.MISSING;
 
-               return AltosIMU.gyro_degrees_per_second(counts - gyro_zero_roll, imu_type);
+               return AltosIMU.gyro_degrees_per_second(counts - gyro_zero_roll, imu_type, imu_model);
        }
 
        public double gyro_pitch(double counts) {
                if (gyro_zero_pitch == AltosLib.MISSING || counts == AltosLib.MISSING)
                        return AltosLib.MISSING;
-               return AltosIMU.gyro_degrees_per_second(counts - gyro_zero_pitch, imu_type);
+               return AltosIMU.gyro_degrees_per_second(counts - gyro_zero_pitch, imu_type, imu_model);
        }
 
        public double gyro_yaw(double counts) {
                if (gyro_zero_yaw == AltosLib.MISSING || counts == AltosLib.MISSING)
                        return AltosLib.MISSING;
-               return AltosIMU.gyro_degrees_per_second(counts - gyro_zero_yaw, imu_type);
+               return AltosIMU.gyro_degrees_per_second(counts - gyro_zero_yaw, imu_type, imu_model);
        }
 
        private double gyro_zero_overflow(double first) {
@@ -402,19 +414,19 @@ public class AltosCalData {
        public double mag_along(double along) {
                if (along == AltosLib.MISSING)
                        return AltosLib.MISSING;
-               return AltosIMU.convert_gauss(along, imu_type, AltosIMU.mag_along_axis(imu_type));
+               return AltosMag.convert_gauss(along, imu_type, mag_model);
        }
 
        public double mag_across(double across) {
                if (across == AltosLib.MISSING)
                        return AltosLib.MISSING;
-               return AltosIMU.convert_gauss(across, imu_type, AltosIMU.mag_across_axis(imu_type));
+               return AltosMag.convert_gauss(across, imu_type, mag_model);
        }
 
        public double mag_through(double through) {
                if (through == AltosLib.MISSING)
                        return AltosLib.MISSING;
-               return AltosIMU.convert_gauss(through, imu_type, AltosIMU.mag_through_axis(imu_type));
+               return AltosMag.convert_gauss(through, imu_type, mag_model);
        }
 
        public AltosCalData() {
index b858e7098d7f8907938fd8da40c3ccc7e04bc827..57de0a4137406a38b9ca54f9fedd10d8ecc27b1f 100644 (file)
@@ -34,6 +34,7 @@ public class AltosEepromRecordMega extends AltosEepromRecord {
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_3:
                case AltosLib.AO_LOG_FORMAT_EASYMEGA_2:
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_4:
+               case AltosLib.AO_LOG_FORMAT_TELEMEGA_5:
                        return data32(16);
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
                        return data16(14);
@@ -47,6 +48,7 @@ public class AltosEepromRecordMega extends AltosEepromRecord {
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_3:
                case AltosLib.AO_LOG_FORMAT_EASYMEGA_2:
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_4:
+               case AltosLib.AO_LOG_FORMAT_TELEMEGA_5:
                        return data32(20);
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
                        return data16(16);
@@ -60,6 +62,7 @@ public class AltosEepromRecordMega extends AltosEepromRecord {
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_3:
                case AltosLib.AO_LOG_FORMAT_EASYMEGA_2:
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_4:
+               case AltosLib.AO_LOG_FORMAT_TELEMEGA_5:
                        return data32(24);
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
                        return data16(18);
@@ -85,6 +88,17 @@ public class AltosEepromRecordMega extends AltosEepromRecord {
        private int mag_z() { return data16(22); }
        private int mag_y() { return data16(24); }
 
+       /* normalized log data */
+       private int norm_accel_along() { return data16(8); }
+       private int norm_accel_across() { return data16(10); }
+       private int norm_accel_through() { return data16(12); }
+       private int norm_gyro_roll() { return data16(14); }
+       private int norm_gyro_pitch() { return data16(16); }
+       private int norm_gyro_yaw() { return data16(18); }
+       private int norm_mag_along() { return data16(20); }
+       private int norm_mag_across() { return data16(22); }
+       private int norm_mag_through() { return data16(24); }
+
        private int imu_type() {
                switch (log_format) {
                case AltosLib.AO_LOG_FORMAT_TELEMEGA:
@@ -101,7 +115,35 @@ public class AltosEepromRecordMega extends AltosEepromRecord {
                }
        }
 
+       private int imu_model() {
+               switch (log_format) {
+               case AltosLib.AO_LOG_FORMAT_TELEMEGA_5:
+                       return AltosLib.model_mpu6000;
+               }
+               return AltosLib.MISSING;
+       }
+
+       private boolean sensor_normalized() {
+               switch (log_format) {
+               case AltosLib.AO_LOG_FORMAT_TELEMEGA_5:
+                       return true;
+               }
+               return false;
+       }
+
+       private int mag_model() {
+               switch (log_format) {
+               case AltosLib.AO_LOG_FORMAT_TELEMEGA_5:
+                       return AltosLib.model_mmc5983;
+               }
+               return AltosLib.MISSING;
+       }
+
        private int accel_across() {
+               if (sensor_normalized()) {
+                       return norm_accel_across();
+               }
+
                switch (log_format) {
                case AltosLib.AO_LOG_FORMAT_TELEMEGA:
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_3:
@@ -116,6 +158,10 @@ public class AltosEepromRecordMega extends AltosEepromRecord {
        }
 
        private int accel_along(){
+               if (sensor_normalized()) {
+                       return norm_accel_along();
+               }
+
                switch (log_format) {
                case AltosLib.AO_LOG_FORMAT_TELEMEGA:
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_3:
@@ -130,10 +176,18 @@ public class AltosEepromRecordMega extends AltosEepromRecord {
        }
 
        private int accel_through() {
+               if (sensor_normalized()) {
+                       return norm_accel_through();
+               }
+
                return accel_z();
        }
 
        private int gyro_pitch() {
+               if (sensor_normalized()) {
+                       return norm_gyro_pitch();
+               }
+
                switch (log_format) {
                case AltosLib.AO_LOG_FORMAT_TELEMEGA:
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_3:
@@ -149,6 +203,10 @@ public class AltosEepromRecordMega extends AltosEepromRecord {
        }
 
        private int gyro_roll() {
+               if (sensor_normalized()) {
+                       return norm_gyro_roll();
+               }
+
                switch (log_format) {
                case AltosLib.AO_LOG_FORMAT_TELEMEGA:
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_3:
@@ -163,10 +221,18 @@ public class AltosEepromRecordMega extends AltosEepromRecord {
        }
 
        private int gyro_yaw() {
+               if (sensor_normalized()) {
+                       return norm_gyro_yaw();
+               }
+
                return gyro_z();
        }
 
        private int mag_across() {
+               if (sensor_normalized()) {
+                       return norm_mag_across();
+               }
+
                switch (log_format) {
                case AltosLib.AO_LOG_FORMAT_TELEMEGA:
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_3:
@@ -182,6 +248,10 @@ public class AltosEepromRecordMega extends AltosEepromRecord {
        }
 
        private int mag_along() {
+               if (sensor_normalized()) {
+                       return norm_mag_along();
+               }
+
                switch (log_format) {
                case AltosLib.AO_LOG_FORMAT_TELEMEGA:
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_3:
@@ -196,6 +266,10 @@ public class AltosEepromRecordMega extends AltosEepromRecord {
        }
 
        private int mag_through() {
+               if (sensor_normalized()) {
+                       return norm_mag_through();
+               }
+
                return mag_z();
        }
 
@@ -240,6 +314,8 @@ public class AltosEepromRecordMega extends AltosEepromRecord {
                AltosGPS        gps;
 
                cal_data.set_imu_type(imu_type());
+               cal_data.set_imu_model(imu_model());
+               cal_data.set_mag_model(mag_model());
 
                switch (cmd()) {
                case AltosLib.AO_LOG_FLIGHT:
index f3c85e9aa112945f6e8b0c0cb98d1d2927a3e2ae..0ff27c75421618a49753afdd7538af45da7bbcd6 100644 (file)
@@ -26,19 +26,44 @@ public class AltosIMU implements Cloneable {
        public int              accel_y = AltosLib.MISSING;
        public int              accel_z = AltosLib.MISSING;
 
+       public int              accel_along = AltosLib.MISSING;
+       public int              accel_across = AltosLib.MISSING;
+       public int              accel_through = AltosLib.MISSING;
+
        public int              gyro_x = AltosLib.MISSING;
        public int              gyro_y = AltosLib.MISSING;
        public int              gyro_z = AltosLib.MISSING;
 
+       public int              gyro_roll = AltosLib.MISSING;
+       public int              gyro_pitch = AltosLib.MISSING;
+       public int              gyro_yaw = AltosLib.MISSING;
+
        public int              mag_x = AltosLib.MISSING;
        public int              mag_y = AltosLib.MISSING;
        public int              mag_z = AltosLib.MISSING;
 
+       public int              mag_along = AltosLib.MISSING;
+       public int              mag_across = AltosLib.MISSING;
+       public int              mag_through = AltosLib.MISSING;
+
+       public int              imu_model = AltosLib.MISSING;
+       public int              mag_model = AltosLib.MISSING;
+
        public static final double      counts_per_g_mpu = 2048.0;
        public static final double      counts_per_g_bmx = 2048.0;
        public static final double      counts_per_g_adxl = 20.5;
 
-       private static double counts_per_g(int imu_type) {
+       private static double counts_per_g(int imu_type, int imu_model) {
+               switch (imu_model) {
+               case AltosLib.model_mpu6000:
+               case AltosLib.model_mpu9250:
+                       return counts_per_g_mpu;
+               case AltosLib.model_adxl375:
+                       return counts_per_g_adxl;
+               case AltosLib.model_bmx160:
+                       return counts_per_g_bmx;
+               }
+
                switch (imu_type) {
                case imu_type_telemega_v1_v2:
                case imu_type_telemega_v3:
@@ -50,13 +75,13 @@ public class AltosIMU implements Cloneable {
                        return counts_per_g_bmx;
                case imu_type_easymotor_v2:
                        return counts_per_g_adxl;
-               default:
-                       return AltosLib.MISSING;
                }
+
+               return AltosLib.MISSING;
        }
 
-       public static double convert_accel(double counts, int imu_type) {
-               double cpg = counts_per_g(imu_type);
+       public static double convert_accel(double counts, int imu_type, int imu_model) {
+               double cpg = counts_per_g(imu_type, imu_model);
                if (cpg == AltosLib.MISSING)
                        return AltosLib.MISSING;
                return counts / cpg * AltosConvert.gravity;
@@ -69,7 +94,15 @@ public class AltosIMU implements Cloneable {
        public static final double      GYRO_COUNTS_BMX = 32767.0;
        public static final double      counts_per_degree_bmx = GYRO_COUNTS_BMX / GYRO_FULLSCALE_DEGREES_BMX;
 
-       private static double counts_per_degree(int imu_type) {
+       private static double counts_per_degree(int imu_type, int imu_model) {
+               switch (imu_model) {
+               case AltosLib.model_mpu6000:
+               case AltosLib.model_mpu9250:
+                       return counts_per_degree_mpu;
+               case AltosLib.model_bmx160:
+                       return counts_per_degree_bmx;
+               }
+
                switch (imu_type) {
                case imu_type_telemega_v1_v2:
                case imu_type_telemega_v3:
@@ -84,66 +117,76 @@ public class AltosIMU implements Cloneable {
                }
        }
 
-       public static double gyro_degrees_per_second(double counts, int imu_type) {
-               double cpd = counts_per_degree(imu_type);
+       public static double gyro_degrees_per_second(double counts, int imu_type, int imu_model) {
+               double cpd = counts_per_degree(imu_type, imu_model);
+
                if (cpd == AltosLib.MISSING)
                        return AltosLib.MISSING;
                return counts / cpd;
        }
 
-       public static final int imu_axis_x = 0;
-       public static final int imu_axis_y = 1;
-       public static final int imu_axis_z = 2;
-
        public static final double MAG_FULLSCALE_GAUSS_MPU = 48.00;     /* 4800µT */
        public static final double MAG_COUNTS_MPU = 32767.0;
        public static final double counts_per_gauss_mpu = MAG_COUNTS_MPU / MAG_FULLSCALE_GAUSS_MPU;
 
        public static final double counts_per_gauss_bmx = 100.0;        /* BMX driver converts to µT */
 
-       public static double counts_per_gauss(int imu_type, int axis) {
+       public static double counts_per_gauss(int imu_type, int imu_model) {
+               switch (imu_model) {
+               case AltosLib.model_mpu9250:
+                       return counts_per_gauss_mpu;
+               case AltosLib.model_bmx160:
+                       return counts_per_gauss_bmx;
+               }
+
                switch(imu_type) {
-               case imu_type_telemega_v1_v2:
-               case imu_type_easymega_v1:
-                       return AltosMag.counts_per_gauss;
                case imu_type_telemega_v3:
                case imu_type_easymega_v2:
                        return counts_per_gauss_mpu;
                case imu_type_telemega_v4:
                case imu_type_easytimer_v1:
-                       return 100.0;
-               default:
-                       return AltosLib.MISSING;
+                       return counts_per_gauss_bmx;
                }
-       }
-
-       public static double convert_gauss(double counts, int imu_type, int imu_axis) {
-               double cpg = counts_per_gauss(imu_type, imu_axis);
-               if (cpg == AltosLib.MISSING)
-                       return AltosLib.MISSING;
-               return counts / cpg;
+               return AltosLib.MISSING;
        }
 
        public boolean parse_string(String line) {
-               if (!line.startsWith("Accel:"))
-                       return false;
+               if (line.startsWith("Accel:")) {
 
-               String[] items = line.split("\\s+");
+                       String[] items = line.split("\\s+");
 
-               if (items.length >= 8) {
-                       accel_x = Integer.parseInt(items[1]);
-                       accel_y = Integer.parseInt(items[2]);
-                       accel_z = Integer.parseInt(items[3]);
-                       gyro_x = Integer.parseInt(items[5]);
-                       gyro_y = Integer.parseInt(items[6]);
-                       gyro_z = Integer.parseInt(items[7]);
+                       if (items.length >= 8) {
+                               accel_x = Integer.parseInt(items[1]);
+                               accel_y = Integer.parseInt(items[2]);
+                               accel_z = Integer.parseInt(items[3]);
+                               gyro_x = Integer.parseInt(items[5]);
+                               gyro_y = Integer.parseInt(items[6]);
+                               gyro_z = Integer.parseInt(items[7]);
+                       }
+                       if (items.length >= 12) {
+                               mag_x = Integer.parseInt(items[9]);
+                               mag_y = Integer.parseInt(items[10]);
+                               mag_z = Integer.parseInt(items[11]);
+                       }
+                       return true;
                }
-               if (items.length >= 12) {
-                       mag_x = Integer.parseInt(items[9]);
-                       mag_y = Integer.parseInt(items[10]);
-                       mag_z = Integer.parseInt(items[11]);
+               if (line.startsWith("MPU6000:")) {
+                       String[] items = line.split("\\s+");
+
+                       imu_model = AltosLib.model_mpu6000;
+
+                       if (items.length >= 7) {
+                               accel_along = Integer.parseInt(items[1]);
+                               accel_across = Integer.parseInt(items[2]);
+                               accel_through = Integer.parseInt(items[3]);
+                               gyro_roll = Integer.parseInt(items[4]);
+                               gyro_pitch = Integer.parseInt(items[5]);
+                               gyro_yaw = Integer.parseInt(items[6]);
+                       }
+                       return true;
                }
-               return true;
+
+               return false;
        }
 
        public AltosIMU clone() {
@@ -153,14 +196,26 @@ public class AltosIMU implements Cloneable {
                n.accel_y = accel_y;
                n.accel_z = accel_z;
 
+               n.accel_along = accel_along;
+               n.accel_across = accel_across;
+               n.accel_through = accel_through;
+
                n.gyro_x = gyro_x;
                n.gyro_y = gyro_y;
                n.gyro_z = gyro_z;
 
+               n.gyro_roll = gyro_roll;
+               n.gyro_pitch = gyro_pitch;
+               n.gyro_yaw = gyro_yaw;
+
                n.mag_x = mag_x;
                n.mag_y = mag_y;
                n.mag_z = mag_z;
 
+               n.mag_along = mag_along;
+               n.mag_across = mag_across;
+               n.mag_through = mag_through;
+
                return n;
        }
 
@@ -176,6 +231,10 @@ public class AltosIMU implements Cloneable {
        public static final int imu_type_easymotor_v2 = 6;      /* ADXL375 (accel only) */
 
        private int accel_across(int imu_type) {
+
+               if (accel_across != AltosLib.MISSING)
+                       return accel_across;
+
                switch (imu_type) {
                case imu_type_telemega_v1_v2:
                case imu_type_telemega_v3:
@@ -194,6 +253,9 @@ public class AltosIMU implements Cloneable {
        }
 
        private int accel_along(int imu_type) {
+               if (accel_along != AltosLib.MISSING)
+                       return accel_along;
+
                switch (imu_type) {
                case imu_type_telemega_v1_v2:
                case imu_type_telemega_v3:
@@ -211,10 +273,16 @@ public class AltosIMU implements Cloneable {
        }
 
        private int accel_through(int imu_type) {
+               if (accel_through != AltosLib.MISSING)
+                       return accel_through;
+
                return accel_z;
        }
 
        private int gyro_roll(int imu_type) {
+               if (gyro_roll != AltosLib.MISSING)
+                       return gyro_roll;
+
                switch (imu_type) {
                case imu_type_telemega_v1_v2:
                case imu_type_telemega_v3:
@@ -230,6 +298,9 @@ public class AltosIMU implements Cloneable {
        }
 
        private int gyro_pitch(int imu_type) {
+               if (gyro_pitch != AltosLib.MISSING)
+                       return gyro_pitch;
+
                switch (imu_type) {
                case imu_type_telemega_v1_v2:
                case imu_type_telemega_v3:
@@ -246,25 +317,16 @@ public class AltosIMU implements Cloneable {
        }
 
        private int gyro_yaw(int imu_type) {
-               return gyro_z;
-       }
+               if (gyro_yaw != AltosLib.MISSING)
+                       return gyro_yaw;
 
-       public static int mag_across_axis(int imu_type) {
-               switch (imu_type) {
-               case imu_type_telemega_v1_v2:
-               case imu_type_telemega_v3:
-               case imu_type_easymega_v1:
-                       return imu_axis_x;
-               case imu_type_easymega_v2:
-               case imu_type_telemega_v4:
-               case imu_type_easytimer_v1:
-                       return imu_axis_y;
-               default:
-                       return AltosLib.MISSING;
-               }
+               return gyro_z;
        }
 
        private int mag_across(int imu_type) {
+               if (mag_across != AltosLib.MISSING)
+                       return mag_across;
+
                switch (imu_type) {
                case imu_type_telemega_v1_v2:
                case imu_type_telemega_v3:
@@ -280,22 +342,10 @@ public class AltosIMU implements Cloneable {
                }
        }
 
-       public static int mag_along_axis(int imu_type) {
-               switch (imu_type) {
-               case imu_type_telemega_v1_v2:
-               case imu_type_telemega_v3:
-               case imu_type_easymega_v1:
-                       return imu_axis_y;
-               case imu_type_easymega_v2:
-               case imu_type_telemega_v4:
-               case imu_type_easytimer_v1:
-                       return imu_axis_x;
-               default:
-                       return AltosLib.MISSING;
-               }
-       }
-
        private int mag_along(int imu_type) {
+               if (mag_along != AltosLib.MISSING)
+                       return mag_along;
+
                switch (imu_type) {
                case imu_type_telemega_v1_v2:
                case imu_type_telemega_v3:
@@ -310,6 +360,13 @@ public class AltosIMU implements Cloneable {
                }
        }
 
+       private int mag_through(int imu_type) {
+               if (mag_through != AltosLib.MISSING)
+                       return mag_through;
+
+               return mag_z;
+       }
+
        private static boolean is_primary_accel(int imu_type) {
                switch (imu_type) {
                case imu_type_easytimer_v1:
@@ -319,23 +376,20 @@ public class AltosIMU implements Cloneable {
                }
        }
 
-       public static int mag_through_axis(int imu_type) {
-               return imu_axis_z;
-       }
-
-       private int mag_through(int imu_type) {
-               return mag_z;
-       }
-
        static public void provide_data(AltosDataListener listener, AltosLink link, int imu_type) throws InterruptedException {
                try {
                        AltosIMU        imu = new AltosIMU(link);
                        AltosCalData    cal_data = listener.cal_data();
 
-                       cal_data.set_imu_type(imu_type);
-
+                       if (imu_type != AltosLib.MISSING)
+                               cal_data.set_imu_type(imu_type);
                        if (imu != null) {
-                               if (imu.gyro_x != AltosLib.MISSING) {
+                               if (imu.imu_model != AltosLib.MISSING)
+                                       cal_data.set_imu_model(imu.imu_model);
+                               if (imu.mag_model != AltosLib.MISSING)
+                                       cal_data.set_mag_model(imu.mag_model);
+
+                               if (imu.gyro_roll(imu_type) != AltosLib.MISSING) {
                                        cal_data.set_gyro_zero(0, 0, 0);
                                        listener.set_gyro(cal_data.gyro_roll(imu.gyro_roll(imu_type)),
                                                          cal_data.gyro_pitch(imu.gyro_pitch(imu_type)),
@@ -355,7 +409,7 @@ public class AltosIMU implements Cloneable {
                                                accel = -accel;
                                        listener.set_acceleration(cal_data.acceleration(accel));
                                }
-                               if (imu.mag_x != AltosLib.MISSING) {
+                               if (imu.mag_along(imu_type) != AltosLib.MISSING) {
                                        listener.set_mag(cal_data.mag_along(imu.mag_along(imu_type)),
                                                         cal_data.mag_across(imu.mag_across(imu_type)),
                                                         cal_data.mag_through(imu.mag_through(imu_type)));
@@ -366,17 +420,6 @@ public class AltosIMU implements Cloneable {
        }
 
        public AltosIMU() {
-               accel_x = AltosLib.MISSING;
-               accel_y = AltosLib.MISSING;
-               accel_z = AltosLib.MISSING;
-
-               gyro_x = AltosLib.MISSING;
-               gyro_y = AltosLib.MISSING;
-               gyro_z = AltosLib.MISSING;
-
-               mag_x = AltosLib.MISSING;
-               mag_y = AltosLib.MISSING;
-               mag_z = AltosLib.MISSING;
        }
 
        public AltosIMU(AltosLink link) throws InterruptedException, TimeoutException {
index c4a32788d4617dd319ae190a5fe5667ef510ad7d..b2fd3c6f56833b938cc91392f12fa7c48f87f951 100644 (file)
@@ -39,6 +39,7 @@ class AltosIdler {
        static final int        idle_ms5607 = 9;
        static final int        idle_adxl375 = 10;
        static final int        idle_adxl375_easymotor_v2 = 11;
+       static final int        idle_imu = 12;
 
        static final int        idle_sensor_tm = 100;
        static final int        idle_sensor_metrum = 101;
@@ -76,6 +77,9 @@ class AltosIdler {
                        case idle_imu_et_v1:
                                AltosIMU.provide_data(listener, link, AltosIMU.imu_type_easytimer_v1);
                                break;
+                       case idle_imu:
+                               AltosIMU.provide_data(listener, link, AltosLib.MISSING);
+                               break;
                        case idle_mag:
                                AltosMag.provide_data(listener, link);
                                break;
@@ -208,6 +212,12 @@ public class AltosIdleFetch implements AltosDataProvider {
                               AltosIdler.idle_ms5607,
                               AltosIdler.idle_imu_tm_v4,
                               AltosIdler.idle_sensor_mega),
+               new AltosIdler("TeleMega-v5",
+                              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,
index cf1fa1ed4e9b096949f83502a0fcdd67bd9210c0..07ed31e1997c50aae4f73027f82ee3c6ffbad610 100644 (file)
@@ -385,8 +385,16 @@ public class AltosLib {
        public static final int AO_LOG_FORMAT_MICROPEAK2 = 18;
        public static final int AO_LOG_FORMAT_TELEMEGA_4 = 19;
        public static final int AO_LOG_FORMAT_EASYMOTOR = 20;
+       public static final int AO_LOG_FORMAT_TELEMEGA_5 = 21;
        public static final int AO_LOG_FORMAT_NONE = 127;
 
+       public static final int model_mpu6000 = 0;
+       public static final int model_mpu9250 = 1;
+       public static final int model_adxl375 = 2;
+       public static final int model_bmx160 = 3;
+       public static final int model_hmc5883 = 4;
+       public static final int model_mmc5983 = 5;
+
        public static boolean isspace(int c) {
                switch (c) {
                case ' ':
index ab5d3f57e38cb5385350f673912b1df35b566c73..c7f1ac1dfabba9bea522fc55d9c577cf0e9f20d3 100644 (file)
@@ -22,44 +22,84 @@ import java.util.concurrent.*;
 import java.io.*;
 
 public class AltosMag implements Cloneable {
-       public int              x;
-       public int              z;
-       public int              y;
+       public int              along = AltosLib.MISSING;
+       public int              across = AltosLib.MISSING;
+       public int              through = AltosLib.MISSING;
 
-       public static final double counts_per_gauss = 1090;
+       public static final int model_hmc5883 = 0;
+       public static final int model_mmc5983 = 1;
 
-       public static double convert_gauss(double counts) {
-               return counts / counts_per_gauss;
+       public int mag_model = AltosLib.MISSING;
+
+       public static final double counts_per_gauss_hmc5883 = 1090;
+       public static final double counts_per_gauss_mmc5983 = 4096;
+
+       public static double counts_per_gauss(int imu_type, int mag_model) {
+               switch(mag_model) {
+               case AltosLib.model_hmc5883:
+                       return counts_per_gauss_hmc5883;
+               case AltosLib.model_mmc5983:
+                       return counts_per_gauss_mmc5983;
+               }
+               switch (imu_type) {
+               case AltosIMU.imu_type_telemega_v1_v2:
+               case AltosIMU.imu_type_easymega_v1:
+                       return counts_per_gauss_hmc5883;
+               }
+
+               return AltosIMU.counts_per_gauss(imu_type, mag_model);
+       }
+
+       public static double convert_gauss(double counts, int imu_type, int mag_model) {
+               double cpg = counts_per_gauss(imu_type, mag_model);
+
+               if (cpg == AltosLib.MISSING)
+                       return AltosLib.MISSING;
+
+               return counts / cpg;
        }
 
        public boolean parse_string(String line) {
 
-               if (!line.startsWith("X:"))
-                       return false;
+               if (line.startsWith("X:")) {
 
-               String[] items = line.split("\\s+");
+                       String[] items = line.split("\\s+");
 
-               if (items.length >= 6) {
-                       x = Integer.parseInt(items[1]);
-                       z = Integer.parseInt(items[3]);
-                       y = Integer.parseInt(items[5]);
+                       mag_model = model_hmc5883;
+
+                       if (items.length >= 6) {
+                               across = Integer.parseInt(items[1]);
+                               through = Integer.parseInt(items[3]);
+                               along = Integer.parseInt(items[5]);
+                       }
+                       return true;
+               }
+               if (line.startsWith("MMC5983:")) {
+                       String[] items = line.split("\\s+");
+
+                       mag_model = model_mmc5983;
+
+                       if (items.length >= 4) {
+                               along = Integer.parseInt(items[1]);
+                               across = Integer.parseInt(items[2]);
+                               through = Integer.parseInt(items[3]);
+                       }
+                       return true;
                }
-               return true;
+
+               return false;
        }
 
        public AltosMag clone() {
                AltosMag n = new AltosMag();
 
-               n.x = x;
-               n.z = z;
-               n.y = y;
+               n.along = along;
+               n.across = across;
+               n.through = through;
                return n;
        }
 
        public AltosMag() {
-               x = AltosLib.MISSING;
-               z = AltosLib.MISSING;
-               y = AltosLib.MISSING;
        }
 
        static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException {
@@ -67,10 +107,13 @@ public class AltosMag implements Cloneable {
                        AltosMag        mag = new AltosMag(link);
                        AltosCalData    cal_data = listener.cal_data();
 
-                       if (mag != null)
-                               listener.set_mag(cal_data.mag_along(mag.y),
-                                                cal_data.mag_across(mag.x),
-                                                cal_data.mag_through(mag.z));
+                       if (mag != null) {
+                               if (mag.mag_model != AltosLib.MISSING)
+                                       cal_data.set_mag_model(mag.mag_model);
+                               listener.set_mag(cal_data.mag_along(mag.along),
+                                                cal_data.mag_across(mag.across),
+                                                cal_data.mag_through(mag.through));
+                       }
                } catch (TimeoutException te) {
                }
        }
index ec3d8495dc1efff7fe65071e42aefecec471936e..54dd04dac4c2695f006f4b73528a47d556ac98f4 100644 (file)
@@ -81,6 +81,7 @@ public abstract class AltosTelemetry implements AltosDataProvider {
        final static int packet_type_mini2 = 0x10;
        final static int packet_type_mini3 = 0x11;
        final static int packet_type_mega_sensor_bmx160 = 0x12;
+       final static int packet_type_mega_norm_mpu6000_mmc5983 = 0x13;
 
        static AltosTelemetry parse_hex(String hex)  throws ParseException, AltosCRCException {
                AltosTelemetry  telem = null;
diff --git a/altoslib/AltosTelemetryMegaNorm.java b/altoslib/AltosTelemetryMegaNorm.java
new file mode 100644 (file)
index 0000000..4a8bf10
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+
+package org.altusmetrum.altoslib_14;
+
+public class AltosTelemetryMegaNorm extends AltosTelemetryStandard {
+       int     orient() { return int8(5); }
+
+       int     accel() { return int16(6); }
+       int     pres() { return int32(8); }
+       int     temp() { return int16(12); }
+
+       int     accel_along() { return int16(14); }
+       int     accel_across() { return int16(16); }
+       int     accel_through() { return int16(18); }
+
+       int     gyro_roll() { return int16(20); }
+       int     gyro_pitch() { return int16(22); }
+       int     gyro_yaw() { return int16(24); }
+
+       int     mag_along() { return int16(26); }
+       int     mag_across() { return int16(28); }
+       int     mag_through() { return int16(30); }
+
+       int imu_model, mag_model;
+
+       public AltosTelemetryMegaNorm(int[] bytes, int imu_model, int mag_model) throws AltosCRCException {
+               super(bytes);
+               this.imu_model = imu_model;
+               this.mag_model = mag_model;
+       }
+
+       public void provide_data(AltosDataListener listener) {
+               super.provide_data(listener);
+
+               AltosCalData cal_data = listener.cal_data();
+
+               listener.set_acceleration(cal_data.acceleration(accel()));
+               listener.set_pressure(pres());
+               listener.set_temperature(temp() / 100.0);
+
+               listener.set_orient(orient());
+               cal_data.set_imu_model(imu_model);
+               cal_data.set_mag_model(mag_model);
+
+               /* XXX we have no calibration data for these values */
+
+               if (cal_data.accel_zero_along == AltosLib.MISSING)
+                       cal_data.set_accel_zero(0, 0, 0);
+               if (cal_data.gyro_zero_roll == AltosLib.MISSING)
+                       cal_data.set_gyro_zero(0, 0, 0);
+
+               int     accel_along = accel_along();
+               int     accel_across = accel_across();
+               int     accel_through = accel_through();
+
+               int     gyro_roll = gyro_roll();
+               int     gyro_pitch = gyro_pitch();
+               int     gyro_yaw = gyro_yaw();
+
+               int     mag_along = mag_along();
+               int     mag_across = mag_across();
+               int     mag_through = mag_through();
+
+               listener.set_accel(cal_data.accel_along(accel_along),
+                                  cal_data.accel_across(accel_across),
+                                  cal_data.accel_through(accel_through));
+               listener.set_gyro(cal_data.gyro_roll(gyro_roll),
+                                 cal_data.gyro_pitch(gyro_pitch),
+                                 cal_data.gyro_yaw(gyro_yaw));
+               listener.set_mag(cal_data.mag_along(mag_along),
+                                cal_data.mag_across(mag_across),
+                                cal_data.mag_through(mag_through));
+       }
+}
index cda977eb36b3a54f071caa1f550bee33239ad1c0..6acbb5bc5751b48f0db4eb83c6e097a7fd15ede4 100644 (file)
@@ -105,20 +105,6 @@ public class AltosTelemetryMegaSensor extends AltosTelemetryStandard {
                return gyro_z();
        }
 
-       public static int mag_across_axis(int imu_type) {
-               switch (imu_type) {
-               case AltosIMU.imu_type_telemega_v1_v2:
-               case AltosIMU.imu_type_telemega_v3:
-               case AltosIMU.imu_type_easymega_v1:
-                       return AltosIMU.imu_axis_x;
-               case AltosIMU.imu_type_telemega_v4:
-               case AltosIMU.imu_type_easymega_v2:
-                       return AltosIMU.imu_axis_y;
-               default:
-                       return AltosLib.MISSING;
-               }
-       }
-
        private int mag_across(int imu_type) {
                switch (imu_type) {
                case AltosIMU.imu_type_telemega_v1_v2:
@@ -133,20 +119,6 @@ public class AltosTelemetryMegaSensor extends AltosTelemetryStandard {
                }
        }
 
-       public static int mag_along_axis(int imu_type) {
-               switch (imu_type) {
-               case AltosIMU.imu_type_telemega_v1_v2:
-               case AltosIMU.imu_type_telemega_v3:
-               case AltosIMU.imu_type_easymega_v1:
-                       return AltosIMU.imu_axis_y;
-               case AltosIMU.imu_type_easymega_v2:
-               case AltosIMU.imu_type_telemega_v4:
-                       return AltosIMU.imu_axis_x;
-               default:
-                       return AltosLib.MISSING;
-               }
-       }
-
        private int mag_along(int imu_type) {
                switch (imu_type) {
                case AltosIMU.imu_type_telemega_v1_v2:
@@ -161,10 +133,6 @@ public class AltosTelemetryMegaSensor extends AltosTelemetryStandard {
                }
        }
 
-       public static int mag_through_axis(int imu_type) {
-               return AltosIMU.imu_axis_z;
-       }
-
        private int mag_through(int imu_type) {
                return mag_z();
        }
index b8e5d3d6f95979c28810dcf0263e3106d8583fc6..7f6626dbf286074c4ae6782a8f6032c3c63ef904 100644 (file)
@@ -96,6 +96,9 @@ public abstract class AltosTelemetryStandard extends AltosTelemetry {
                case packet_type_mini3:
                        telem = new AltosTelemetryMini3(bytes);
                        break;
+               case packet_type_mega_norm_mpu6000_mmc5983:
+                       telem = new AltosTelemetryMegaNorm(bytes, AltosLib.model_mpu6000, AltosLib.model_mmc5983);
+                       break;
                default:
                        telem = new AltosTelemetryRaw(bytes);
                        break;
index 9c8c66910c4f86c511399fd0497abc93ec7b3613..39e287fa457f4c2a1473cc64448f5bfd99bce54e 100644 (file)
@@ -127,6 +127,7 @@ altoslib_JAVA = \
        AltosTelemetryLocation.java \
        AltosTelemetryMap.java \
        AltosTelemetryMegaSensor.java \
+       AltosTelemetryMegaNorm.java \
        AltosTelemetryMegaData.java \
        AltosTelemetryMini2.java \
        AltosTelemetryMini3.java \
diff --git a/altoslib/NewProduct b/altoslib/NewProduct
new file mode 100644 (file)
index 0000000..e275cce
--- /dev/null
@@ -0,0 +1,52 @@
+When adding a new product to the java code, there are a number of
+places that might need adjustment:
+
+altoslib/
+
+ 1. AltosLib.java
+
+       Declare new log format
+       Declare new USB ids
+       Declare new Product name
+       Add item to product_name function
+
+ 2. AltosIdleFetch.java
+
+       Declare any new sensors, create new sensor class
+       Create new sensor class for ADC values
+       Add new AltosIdler entry to idlers array
+
+ 3. AltosEepromRecordSet.java
+
+       Map new log format to new log record decode class
+
+ 4. AltosIMU.java
+
+       Map new imu_type (which includes orientation) correctly
+
+ 5. AltosConfigData.java
+
+       Adjust invert_accel_value for new log format or product name
+       Adjust use_flash_for_config as needed
+       Adjust various accel_inverted functions
+       Adjust adxl375_axis
+
+ 6. AltosTelemetry.java
+
+       Define new telemetry packet types
+
+
+ 7. AltosTelemetryStandard.java
+
+       Map telemetry packet type to new decoder class
+
+ 8. AltosTelemetry*.java
+
+       Adjust existing telemetry decoders for new sensors
+
+
+altosuilib/
+
+ 1. AltosUSBDevice.java
+
+       Add new product ID as appropriate to matchProduct
index 278d3fea167f076bf0dac50f886f5b94d2040dfd..562c695207613638bb3a61253d04bd3290964a1e 100644 (file)
@@ -140,6 +140,9 @@ public class AltosConfigFCUI
        };
 
        static String[]         beep_values = {
+               "2000",
+               "2100",
+               "2200",
                "3750",
                "4000",
                "4250",
index 1cbb919f16ce299310014934bbd23e86cd0f46ec..fde718d3abe0de246b82254e99fbea9dd0a6da87 100644 (file)
@@ -57,7 +57,7 @@ ALTOSUILIB_CLASS=\
        altosuilib_$(ALTOSUILIB_VERSION).jar
 
 if MULTI_ARCH
-LIBALTOS_LINUX=libaltos32.so libaltos64.so
+LIBALTOS_LINUX=libaltos_i686.so libaltos_amd64.so libaltos_aarch64.so libaltos_armel.so libaltos_armhf.so
 else
 LIBALTOS_LINUX=libaltos.so
 endif
@@ -136,7 +136,8 @@ FIRMWARE_TMEGA_1_0=$(top_srcdir)/src/telemega-v1.0/telemega-v1.0-$(VERSION).ihx
 FIRMWARE_TMEGA_2_0=$(top_srcdir)/src/telemega-v2.0/telemega-v2.0-$(VERSION).ihx
 FIRMWARE_TMEGA_3_0=$(top_srcdir)/src/telemega-v3.0/telemega-v3.0-$(VERSION).ihx
 FIRMWARE_TMEGA_4_0=$(top_srcdir)/src/telemega-v4.0/telemega-v4.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=$(top_srcdir)/src/telemega-v5.0/telemega-v5.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_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
@@ -266,7 +267,7 @@ install-altosuiJAVA: altosui.jar
 classes/altosui:
        mkdir -p classes/altosui
 
-$(JAR): classaltosui.stamp Manifest.txt $(JAVA_ICONS) $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS)
+$(JAR): classaltosui.stamp Manifest.txt $(JAVA_ICONS) $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) build-libaltos
        jar cfm $@ Manifest.txt \
                $(ICONJAR) \
                -C classes altosui \
@@ -315,11 +316,23 @@ libaltos.so: build-libaltos
        -rm -f "$@"
        $(LN_S) ../libaltos/.libs/"$@" .
 
-libaltos32.so: build-libaltos
+libaltos_i686.so: build-libaltos
        -rm -f "$@"
        $(LN_S) ../libaltos/.libs/"$@" .
 
-libaltos64.so: build-libaltos
+libaltos_amd64.so: build-libaltos
+       -rm -f "$@"
+       $(LN_S) ../libaltos/.libs/"$@" .
+
+libaltos_aarch64.so: build-libaltos
+       -rm -f "$@"
+       $(LN_S) ../libaltos/.libs/"$@" .
+
+libaltos_armel.so: build-libaltos
+       -rm -f "$@"
+       $(LN_S) ../libaltos/.libs/"$@" .
+
+libaltos_armhf.so: build-libaltos
        -rm -f "$@"
        $(LN_S) ../libaltos/.libs/"$@" .
 
@@ -327,31 +340,16 @@ libaltos.dylib:
        -rm -f "$@"
        $(LN_S) ../libaltos/"$@" .
 
-altos.dll: ../libaltos/altos.dll
+altos.dll: build-libaltos
        -rm -f "$@"
        $(LN_S) ../libaltos/"$@" .
 
-altos64.dll: ../libaltos/altos64.dll
+altos64.dll: build-libaltos
        -rm -f "$@"
        $(LN_S) ../libaltos/"$@" .
 
-../libaltos/.libs/libaltos64.so: ../libaltos/.libs/libaltos32.so
-
-../libaltos/.libs/libaltos32.so: build-libaltos
-
-../libaltos/.libs/libaltos.so: build-libaltos
-
-../libaltos/altos.dll: build-altos-dll
-
-../libaltos/altos64.dll: build-altos64-dll
-
 build-libaltos:
-       +cd ../libaltos && make libaltos.la
-build-altos-dll:
-       +cd ../libaltos && make altos.dll
-
-build-altos64-dll:
-       +cd ../libaltos && make altos64.dll
+       +cd ../libaltos && make
 
 $(ALTOSLIB_CLASS):
        -rm -f "$@"
index 196dd7411d9e7f0d75777643c34041391c98d295..6e8b1cca8b0362ed491d38fd8ad6f153ed7931fc 100644 (file)
@@ -132,6 +132,7 @@ Section "Firmware"
        File "../src/telemega-v2.0/telemega-v2.0-${VERSION}.ihx"
        File "../src/telemega-v3.0/telemega-v3.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/easymini-v1.0/easymini-v1.0-${VERSION}.ihx"
        File "../src/easymini-v2.0/easymini-v2.0-${VERSION}.ihx"
        File "../src/easymega-v1.0/easymega-v1.0-${VERSION}.ihx"
index 7553a8ac06bf9a84c2a832be60cb4433bf27fdf9..a0cf325d8543ed1f2afcc33e941a8de50eec1dc8 100644 (file)
@@ -89,33 +89,31 @@ public class AltosUILib extends AltosLib {
        static public boolean loaded_library = false;
        static public boolean has_bluetooth = false;
 
-       static final String[] library_names_32 = { "altos", "altos32", "altos64" };
-       static final String[] library_names_64 = { "altos", "altos64", "altos32" };
+       static final String[] library_names = {
+               "altos",
+               "altos32",
+               "altos64",
+               "altos_i686",
+               "altos_amd64",
+               "altos_aarch64",
+               "altos_armel",
+               "altos_armhf"
+       };
 
        public static boolean load_library() {
                if (!initialized) {
-                       String model = System.getProperty("sun.arch.data.model", "missing");
-                       boolean is_64 = false;
-                       if (model.equals("64")) {
-                               is_64 = true;
-                       } else if (model.equals("32")) {
-                               ;
-                       } else {
-                               String arch = System.getProperty("os.arch", "missing");
-                               if (arch.endsWith("64"))
-                                       is_64 = true;
-                       }
-                       for (String name : is_64 ? library_names_64 : library_names_32) {
+                       for (String name : library_names) {
                                try {
                                        System.loadLibrary(name);
                                        libaltos.altos_init();
                                        loaded_library = true;
                                        break;
                                } catch (UnsatisfiedLinkError e) {
-                                       System.out.printf("Link error %s\n", e.getMessage());
                                        loaded_library = false;
                                }
                        }
+                       if (!loaded_library)
+                               System.out.printf("Cannot find 'libaltos' device access library\n");
 
                        String OS = System.getProperty("os.name");
 
index 1e419b4418813ca75f393e6dd73ae5050fa30087..04dfb44bfef9b903b64f97336f669f585a5a246f 100755 (executable)
@@ -19,7 +19,7 @@ ao-list | while read product serial dev; do
            echo "Testing $product $serial $dev"
            echo ""
 
-           ./test-igniters $dev main drogue 3 0 1 2
+           ./test-igniters $dev --rplus=100 --rminus=27 --adcmax=4095 main drogue 3 0 1 2
            echo""
 
            echo "Testing baro sensor"
index c4479680120e4d722353bc1834a06535c3f657d7..3268f44cdb0ddedacad98555d4624b98b3f143e6 100755 (executable)
@@ -23,7 +23,7 @@ while [ $found -eq 0 ]; do
                
                sleep 0.25
 
-               ./test-igniters-nowait "$dev" drogue main
+               ./test-igniters-nowait "$dev" --rplus=100 --rminus=27 --adcmax=32767 drogue main
                echo ""
 
                echo "Testing baro sensor"
diff --git a/ao-bringup/test-easymini-v1.0 b/ao-bringup/test-easymini-v1.0
new file mode 100755 (executable)
index 0000000..8a0836f
--- /dev/null
@@ -0,0 +1,62 @@
+#!/bin/bash
+
+VERSION=1.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 ""
+               
+               sleep 2
+
+               ./test-igniters-nowait "$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
+    sleep 0.25
+done
index 763f42a9aad2c68ebe1257bfcb269e9964ce6046..1cbe4744f70b6b25452cbe5cb0c5c5f2c8b00a7a 100755 (executable)
@@ -2,13 +2,19 @@
 
 dev="$1"
 shift
+args=""
 
 for igniter in "$@"; do
-       pass="n"
-       while [ $pass != "y" ]; do
+    case "$igniter" in
+       -*)
+           args="$args $igniter"
+           ;;
+       *)
+           pass="n"
+           while [ $pass != "y" ]; do
                echo -n "Testing $igniter igniter. Press enter to continue..."
                read foo < /dev/tty
-               ../ao-tools/ao-test-igniter/ao-test-igniter --tty="$dev" $igniter
+               ../ao-tools/ao-test-igniter/ao-test-igniter --tty="$dev" $args $igniter
 
                case $? in
                    0)
@@ -19,7 +25,9 @@ for igniter in "$@"; do
                        echo "Failed. Try again."
                        ;;
                esac
-       done
+           done
+           ;;
+    esac
 done
 
 exit 0
index 849f91de738c56826694f097da3245d1916c4304..338f49af7b058b6811adf943d02a2530e08c6c79 100755 (executable)
@@ -2,13 +2,19 @@
 
 dev="$1"
 shift
+args=""
 
 for igniter in "$@"; do
-       pass="n"
-       while [ $pass != "y" ]; do
+    case "$igniter" in
+       -*)
+           args="$args $igniter"
+           ;;
+       *)
+           pass="n"
+           while [ $pass != "y" ]; do
 
                echo "Testing $igniter igniter."
-               ../ao-tools/ao-test-igniter/ao-test-igniter --tty="$dev" $igniter
+               ../ao-tools/ao-test-igniter/ao-test-igniter --tty="$dev" $args $igniter
 
                case $? in
                    0)
@@ -20,7 +26,9 @@ for igniter in "$@"; do
                        read foo < /dev/tty
                        ;;
                esac
-       done
+           done
+           ;;
+    esac
 done
 
 exit 0
index 8505a682d03c7b7dc0ccd88c5c338752efccbd83..3355d866ba464e381a3c7dfd362d65930237cda5 100755 (executable)
@@ -18,7 +18,7 @@ ao-list | while read product serial dev; do
 
            echo "Testing $product $serial $dev"
 
-           ./test-igniters $dev main drogue 3 0 1 2
+           ./test-igniters $dev --rplus=100 --rminus=27 --adcmax=4095 main drogue 3 0 1 2
            echo""
 
            echo "Testing baro sensor"
index 8fa1d1d3d0fde2302770e4eeff1ea93e86d0d925..914271837af9a6d953f326ae0d88df2e5ae82764 100755 (executable)
@@ -19,7 +19,7 @@ ao-list | while read product serial dev; do
            echo "Testing $product $serial $dev"
            echo ""
 
-           ./test-igniters "$dev" drogue main
+           ./test-igniters "$dev" --rplus=100 --rminus=27 --adcmax=4095 drogue main
            echo ""
 
            echo "Testing baro sensor"
index 7df36a28ade225432a213f3e4df3463fd98122c7..c4a22f64813e267394cd3edb08f20753c23b85e9 100755 (executable)
@@ -19,7 +19,7 @@ ao-list | while read product serial dev; do
            echo "Testing $product $serial $dev"
            echo ""
 
-           ./test-igniters "$dev" drogue main
+           ./test-igniters "$dev" --rplus=100 --rminus=27 --adcmax=4095 drogue main
            echo ""
 
            echo "Testing baro sensor"
index 3bef31450ae27c28dc9c12aff323751a746db11f..2041a448f9d8acc303dbdbeb71cdf0dcf3ad3c06 100755 (executable)
@@ -1,10 +1,12 @@
 #!/bin/sh
 
-if [ -x /usr/bin/dfu-util ]; then
-    DFU_UTIL=/usr/bin/dfu-util
+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 dfu-util! Aborting."
-    exit 1
+       echo "Can't find ao-flash-lpc!  Aborting."
+       exit 1
 fi
 
 if [ -x ../ao-tools/ao-usbload/ao-usbload ]; then
@@ -16,16 +18,17 @@ else
        exit 1
 fi
 
-VERSION=2.0
+VERSION=1.0
 PRODUCT=EasyMini
 BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
 echo $FILE
 
 echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
-echo "Copyright 2010 by Bdale Garbee.  Released under GPL v2+"
+echo "Copyright 2010 by Bdale Garbee.  Released under GPL v2"
 echo
 echo "Expectations:"
-echo "\t$PRODUCT v$VERSION powered and connected to USB"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo "\t\twith ST-Link-V2 cabled to debug header"
 echo
 
 case $# in
@@ -46,19 +49,17 @@ 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=~/altusmetrumllc/Binaries/loaders/easymini-v1.0-altos-flash-*.elf
+ALTOS_FILE=~/altusmetrumllc/Binaries/easymini-v1.0-*.elf
 
 #FLASH_FILE=../src/$BASE-v$VERSION/flash-loader/$BASE-v$VERSION-altos-flash-*.elf
 #ALTOS_FILE=../src/$BASE-v$VERSION/*.ihx
 
-if lsusb -d 0483:df11 | grep -q STM; then
-    echo $DFU_UTIL -v -v -R -a 0 -s 0x08000000:leave -D $FLASH_FILE
+echo $FLASH_LPC $FLASH_FILE
 
-    $DFU_UTIL -a 0 -s 0x08000000:leave -D $FLASH_FILE
+$FLASH_LPC $FLASH_FILE || exit 1
 
-    sleep 2
-fi
+sleep 1
 
 echo $USBLOAD $ALTOS_FILE
 
@@ -66,6 +67,6 @@ $USBLOAD --serial=$SERIAL $ALTOS_FILE || exit 1
 
 sleep 1
 
-./test-easymini
+./test-easymini-v1.0
 
 exit $?
index 62e6c702c1c14d80a0d67327d90df1bca7e5ee5c..17d5aad6451dd22d1ff874db4e2a525fc0f1d045 100644 (file)
@@ -27,6 +27,7 @@
 #include <getopt.h>
 #include <string.h>
 #include <stdbool.h>
+#include <ctype.h>
 #include "ao-elf.h"
 #include "ccdbg.h"
 #include "cc-usb.h"
@@ -38,12 +39,15 @@ static const struct option options[] = {
        { .name = "device", .has_arg = 1, .val = 'D' },
        { .name = "raw", .has_arg = 0, .val = 'r' },
        { .name = "verbose", .has_arg = 1, .val = 'v' },
+       { .name = "rplus", .has_arg = 1, .val = 'a' },
+       { .name = "rminus", .has_arg = 1, .val = 'b' },
+       { .name = "adcmax", .has_arg = 1, .val = 'm' },
        { 0, 0, 0, 0},
 };
 
 static void usage(char *program)
 {
-       fprintf(stderr, "usage: %s [--verbose=<verbose>] [--device=<device>] [-tty=<tty>] main|drogue\n", program);
+       fprintf(stderr, "usage: %s [--verbose=<verbose>] [--device=<device>] [--tty=<tty>] [--rplus=val] [--rminus=val] [--adcmax=val] main|drogue\n", program);
        exit(1);
 }
 
@@ -59,29 +63,69 @@ struct igniter {
        struct igniter  *next;
        char            name[512];
        char            status[512];
+       int             adc;
 };
 
+static bool
+map_igniter_name(char *adc_name, char *igniter_name)
+{
+       char    *colon = strchr(adc_name, ':');
+       if (!colon)
+               return false;
+       *colon = '\0';
+       if (strlen(adc_name) == 1 && isupper(adc_name[0])) {
+               igniter_name[0] = '0' + adc_name[0] - 'A';
+               igniter_name[1] = '\0';
+       } else {
+               strcpy(igniter_name, adc_name);
+       }
+       return true;
+}
+
 static struct igniter *
 igniters(struct cc_usb *usb)
 {
        struct igniter  *head = NULL, **tail = &head;
-       cc_usb_printf(usb, "t\nv\n");
+       cc_usb_printf(usb, "t\na\nv\n");
        for (;;) {
                char    line[512];
                char    name[512];
                char    status[512];
+               char    adc_name[512];
+               char    igniter_name[512];
 
                cc_usb_getline(usb, line, sizeof (line));
                if (strstr(line, "software-version"))
                        break;
                if (sscanf(line, "Igniter: %s Status: %s", name, status) == 2) {
-                       struct igniter  *i = malloc (sizeof (struct igniter));
+                       struct igniter  *i = calloc (1, sizeof (struct igniter));
                        strcpy(i->name, name);
                        strcpy(i->status, status);
                        i->next = NULL;
                        *tail = i;
                        tail = &i->next;
                }
+               if (strncmp(line, "tick:", 5) == 0) {
+                       char    *tok;
+                       char    *l = line;
+                       bool    found_igniter = false;
+
+                       while ((tok = strtok(l, " ")) != NULL) {
+                               l = NULL;
+                               if (found_igniter) {
+                                       struct igniter *i;
+                                       for (i = head; i; i = i->next)
+                                               if (!strcmp(i->name, igniter_name)) {
+                                                       i->adc = atoi(tok);
+                                                       break;
+                                               }
+                                       found_igniter = false;
+                               } else {
+                                       strcpy(adc_name, tok);
+                                       found_igniter = map_igniter_name(adc_name, igniter_name);
+                               }
+                       }
+               }
        }
        return head;
 }
@@ -101,16 +145,27 @@ static struct igniter *
 find_igniter(struct igniter *i, char *name)
 {
        for (; i; i = i->next)
-               if (strcmp(i->name, name) == 0)
+               if (strcmp(i->name, name) == 0) {
+                       printf("igniter %s adc %d\n", i->name, i->adc);
                        return i;
+               }
        return NULL;
 }
 
+static const double ref_volts = 3.3;
+
+static double
+compute_voltage(int adc, double rplus, double rminus, int adc_max)
+{
+       return (double) adc / (double) adc_max * ref_volts * (rplus + rminus) / rminus;
+}
+
 static int
-do_igniter(struct cc_usb *usb, char *name)
+do_igniter(struct cc_usb *usb, char *name, double rplus, double rminus, int adc_max)
 {
        struct igniter  *all = igniters(usb);
        struct igniter  *this = find_igniter(all, name);
+       double volts = -1;
        if (!this) {
                struct igniter  *i;
                printf("no igniter %s found in", name);
@@ -120,6 +175,14 @@ do_igniter(struct cc_usb *usb, char *name)
                free_igniters(all);
                return 0;
        }
+       if (rplus && rminus && adc_max) {
+               volts = compute_voltage(this->adc, rplus, rminus, adc_max);
+               if (volts < 1 || volts > 4) {
+                       printf("igniter %s voltage is %f, not in range of 1-4 volts\n", this->name, volts);
+                       free_igniters(all);
+                       return 0;
+               }
+       }
        if (strcmp(this->status, "ready") != 0) {
                printf("igniter %s status is %s\n", this->name, this->status);
                free_igniters(all);
@@ -142,8 +205,11 @@ main (int argc, char **argv)
        char                    *tty = NULL;
        int                     verbose = 0;
        int                     ret = 0;
+       double                  rplus = 0.0;
+       double                  rminus = 0.0;
+       int                     adcmax = 0;
 
-       while ((c = getopt_long(argc, argv, "rT:D:c:s:v:", options, NULL)) != -1) {
+       while ((c = getopt_long(argc, argv, "rT:D:c:s:v:a:b:m:", options, NULL)) != -1) {
                switch (c) {
                case 'T':
                        tty = optarg;
@@ -154,6 +220,15 @@ main (int argc, char **argv)
                case 'v':
                        verbose++;
                        break;
+               case 'a':
+                       rplus = strtod(optarg, NULL);
+                       break;
+               case 'b':
+                       rminus = strtod(optarg, NULL);
+                       break;
+               case 'm':
+                       adcmax = strtol(optarg, NULL, 0);
+                       break;
                default:
                        usage(argv[0]);
                        break;
@@ -190,7 +265,7 @@ main (int argc, char **argv)
        for (i = optind; i < argc; i++) {
                char    *name = argv[i];
 
-               if (!do_igniter(cc, name))
+               if (!do_igniter(cc, name, rplus, rminus, adcmax))
                        ret++;
        }
        done(cc, ret);
index f389393a9d53c4cc7b742cdb76f975cdeffbd5fd..b00dd70dd6b2d944450ded40b1351fbe15fa0adf 100644 (file)
@@ -18,13 +18,13 @@ dnl
 dnl Process this file with autoconf to create configure.
 
 AC_PREREQ(2.57)
-AC_INIT([altos], 1.9.7)
+AC_INIT([altos], 1.9.8)
 ANDROID_VERSION=29
 AC_CONFIG_SRCDIR([src/kernel/ao.h])
 AM_INIT_AUTOMAKE([foreign dist-bzip2])
 AM_MAINTAINER_MODE
 
-RELEASE_DATE=2021-06-08
+RELEASE_DATE=2021-09-20
 AC_SUBST(RELEASE_DATE)
 
 DOC_DATE=`LC_ALL=C date -d $RELEASE_DATE +'%d %b %Y'`
index 560c868f2c367580b0941236115549c586563504..0f76136ca601ac367290699031b5ef44fa7b3e4c 100644 (file)
@@ -17,6 +17,7 @@ FAKETIME=TZ=UTC faketime -f '$(RELEASE_DATE) 00:00:00 i0'
 endif
 
 RELNOTES_INC=\
+       release-notes-1.9.8.inc \
        release-notes-1.9.7.inc \
        release-notes-1.9.6.inc \
        release-notes-1.9.5.inc \
index d6daf09cab0f91e30fbeef44d68cd375488b15d6..51f3af91ced153154f9a4a0ed0c65c8494a690f7 100644 (file)
@@ -4,7 +4,8 @@
 == EasyMega Outline and Hole Pattern
        This image, when printed, provides a precise template for the
        mounting holes in EasyMega. EasyMega has overall dimensions of
-       1.250 x 2.250 inches, and the mounting holes are sized for use
-       with 4-40 or M3 screws.
+       1.250 x 2.250 inches, and the mounting holes are 0.125 inches from
+       each board edge.  That means the mounting holes are in a rectangle
+       measuring 1.000 x 2.00 inches, sized for use with 4-40 or M3 screws.
 
        image::easymega.svg[align="center"]
index eac1c4afa14d7f38c0961ef2e31333589e555160..e263560c1b1a66586dff01d3105c678b90c3c305 100644 (file)
@@ -5,6 +5,9 @@
        This image, when printed, provides a precise template for the
        mounting holes in EasyMini, EasyMotor, and EasyTimer.  Each of 
        these products has overall dimensions of 0.800 x 1.500 inches, 
-       and the mounting holes are sized for use with 4-40 or M3 screws.
+       and the mounting holes are 0.125 inches from each board edge.
+       That means the mounting holes are in a rectangle measuring
+       0.550 x 1.250 inches apart, sized for use with 4-40 or M3 screws.
 
        image::easymini.svg[align="center"]
+
index dad66c2883449211272e75569f03be3b74a4bdbf..2549c3cf3542e15f980a7fb09b4bc0b4b880d1c7 100644 (file)
@@ -1,5 +1,9 @@
 [appendix]
 == Release Notes
+       :leveloffset: 2
+       include::release-notes-1.9.8.adoc[]
+
+       <<<<
        :leveloffset: 2
        include::release-notes-1.9.7.adoc[]
 
index 1daf2f6e9b9b7bb8257b8da97b311c96c46ac3d7..930245fa2128c6fbebdbe6080ccc434391350368 100644 (file)
@@ -52,6 +52,10 @@ Firmware versions older than 1.8.6 have a bug which resets the time
 since launch to zero each time a motor starts burning. Update firmware
 to get the correct behavior.
 
+[WARNING]
+Firmware versions older than 1.9.8 cannot use times longer
+than 327.67 seconds. Update firmware if you need a longer time.
+
 Ascending:: A deprecated configuration value which was the same as
 setting Ascent rate > 0. Existing configurations using this will be
 cleared and must be reconfigured by the user.
@@ -74,6 +78,10 @@ false, then the pyro channel is disabled and will not fire. If the
 timer expires and all of the other parameters have remained true for
 the entire time, then the pyro channel is fired.
 
+[WARNING]
+Firmware versions older than 1.9.8 cannot use delays longer
+than 327.67 seconds. Update firmware if you need a longer delay.
+
 Flight State:: The flight software tracks the flight
 through a sequence of states:
 
diff --git a/doc/release-notes-1.9.8.inc b/doc/release-notes-1.9.8.inc
new file mode 100644 (file)
index 0000000..9b66a9d
--- /dev/null
@@ -0,0 +1,29 @@
+= Release Notes for Version 1.9.8
+include::release-head.adoc[]
+:doctype: article
+
+       Version 1.9.8
+
+       == AltOS
+
+       * Add support for TeleMega v5.0
+
+       * Extend extra pyro channel times to support delay > 327 seconds
+
+       == AltosUI
+
+       * Support ARM devices in Linux binary release
+
+       * Add support for TeleMega v5.0
+
+       == AltosDroid
+
+       * Show tilt angle in pad and flight tabs
+
+       * Show altitude as well as height (useful for TeleGPS)
+
+       * Support devices without GPS receivers
+
+       == MicroPeak GUI
+
+       * Show error dialog if device open fails
\ No newline at end of file
index 7a4c3348451221608b3c40ca75b8e6c907a0296f..b33e0204a7abc6269024ef9c0a4d6d9c607b3286 100644 (file)
@@ -1,5 +1,9 @@
 [appendix]
 == Release Notes
+       :leveloffset: 2
+       include::release-notes-1.9.8.adoc[]
+
+       <<<<
        :leveloffset: 2
        include::release-notes-1.9.7.adoc[]
 
index 639a2b9a85d38420ff5de6e85d83064beaca9143..4bba9a53d3d716a6328883bf734665bbd98909c1 100644 (file)
        |40mW
        |3.7V
 
+       |TeleMega v5.0
+       |MS5607 30km (100k')
+       |ADXL375 200g
+       |uBlox Max-8Q
+       |MPU6000 MMC5983
+       |8MB
+       |40mW
+       |3.7V
+
        endif::telemega[]
        ifdef::easymega[]
        |EasyMega v1.0
index ca10d124e8c75b1432384d56c0c9f4df4587ad0c..69e243a4b2b43b29ee5e2034cbd60a81c691a626 100644 (file)
@@ -4,7 +4,9 @@
 == TeleGPS Outline and Hole Pattern
        This image, when printed, provides a precise template for the
        mounting holes in TeleGPS.  TeleGPS has overall dimensions
-       of 1.000 x 1.500 inches, and the mounting holes are sized for
-       use with 4-40 or M3 screws.
+       of 1.000 x 1.500 inches, and the mounting holes are 0.125 inches
+       from each board edge.  That means the mounting holes are in a 
+       rectangle measuring 0.750 x 1.250 inches apart, sized for use with 
+       4-40 or M3 screws.
 
        image::telegps.svg[align="center"]
index c87b10e45205a3aa52b2f59310bf5d40b4e6a730..e4df90e8db89dd01a2e0c4921d6b22a17d5c66d9 100644 (file)
@@ -1,5 +1,9 @@
 [appendix]
 == Release Notes
+       :leveloffset: 2
+       include::release-notes-1.9.8.adoc[]
+
+       <<<<
        :leveloffset: 2
        include::release-notes-1.9.7.adoc[]
 
index 7b1d926996428f7b0ce24d39eca828d5f474c56a..57705c98f8764c0e66db1d64306192dae7617521 100644 (file)
@@ -4,7 +4,9 @@
 == TeleMega Outline and Hole Pattern
        This image, when printed, provides a precise template for the
        mounting holes in TeleMega. TeleMega has overall dimensions of
-       1.250 x 3.250 inches, and the mounting holes are sized for use
-       with 4-40 or M3 screws.
+       1.250 x 3.250 inches, and the mounting holes are 0.125 inches
+       from each board edge.  That means the mounting holes are in a 
+       rectangle measuring 1.000 x 3.000 inches apart, sized for use with 
+       4-40 or M3 screws.
 
        image::telemega.svg[align="center"]
index f37fed7498dae6d2b922f39797527e73a5b8e1bc..a57c3621c4a405aef5932487c8e52567d9d53cc6 100644 (file)
@@ -4,7 +4,9 @@
 == TeleMetrum Outline and Hole Pattern
        This image, when printed, provides a precise template for the
        mounting holes in TeleMetrum. TeleMetrum has overall dimensions of
-       1.000 x 2.750 inches, and the mounting holes are sized for use
-       with 4-40 or M3 screws.
+       1.000 x 2.750 inches, and the mounting holes are 0.125 inches from
+       three of the board edges, and 0.375 inches from the screw terminal 
+       end.  That means they are in a rectangle measuring 0.750 x 2.250
+       inches, sized for use with 4-40 or M3 screws.
 
        image::telemetrum.svg[align="center"]
index e331cf8dd5f47276f1953480a07a728b26105579..cbcc57f8a6f1c57007ed4f716d66ca30f35b2716 100644 (file)
@@ -5,8 +5,8 @@
 
        This image, when printed, provides a precise template for the
        mounting holes in TeleMini. TeleMini v1 has overall dimensions of
-       0.500 x 1.500 inches, and the mounting holes are sized for use
-       with 2-56 or M2 screws. The holes are located 0.100 inches
-       from the edge of the board in both directions.
+       0.500 x 1.500 inches, and the mounting holes are sized for use with 
+       2-56 or M2 screws. The holes are located 0.100 inches from the edge 
+       of the board in both directions, meaning they are 0.300 inches apart.
 
        image::telemini-v1.svg[align="center"]
index 57a738ebb6d51d714530b06cc7066f335bf19820..6d52a09fba3bb1ee26a761df6f1838c432e7d357 100644 (file)
@@ -6,6 +6,7 @@
        mounting holes in TeleMini v3. TeleMini v3 has overall dimensions of
        0.500 x 1.670 inches, and the mounting holes are sized for use
        with 2-56 or M2 screws. The holes are located 0.085 inches
-       from the edge of the board in both directions.
+       from the edge of the board in both directions, meaning they are
+       located in a rectangle of 0.330 x 1.500 inches.
 
        image::telemini-v3.svg[align="center"]
index 7dd04bf099d887abc6349d0f217a12c0ab09321a..97bca72b462e7529998299b7430dd0884dd84218 100644 (file)
                callsign settings are, you can temporarily force it
                back to the original default values (frequency
                434.550MHz, callsign N0CALL) by connecting a wire
-               between hole 3 and hole 7 on the debug connector. Hole
-               3 has the square pad around it, hole 7 is the one
+               between hole 3 and hole 6 on the debug connector. Hole
+               3 has the square pad around it, hole 6 is the one
                nearest the MS5607 baro sensor, which is a rectangular
                component with a metal cap that has two holes in it.
 
index 9ce9cba8fb02ba23c6b2e8b0ea48802bb8563422..0f4389d0b5d5c08cdf6b18fdf6e5c1203ceb8e3b 100644 (file)
@@ -1,7 +1,8 @@
 JAVA_RES=16 32 48 64 128 256
 MAC_RES=16 32 128 256 512
 WIN_RES=16 24 32 48 64 72 96 128 180 256
-RES=$(shell echo $(JAVA_RES) $(MAC_RES) $(WIN_RES) | awk '{ for (i = 1; i <= NF; i++) printf("%s\n", $$i); }' | sort -n -u)
+AMAZON_RES=114 512
+RES=$(shell echo $(JAVA_RES) $(MAC_RES) $(WIN_RES) $(AMAZON_RES)| awk '{ for (i = 1; i <= NF; i++) printf("%s\n", $$i); }' | sort -n -u)
 
 # Application icon base names
 
@@ -73,6 +74,10 @@ JAVA_TG_FILES        = $(shell for i in $(JAVA_RES); do echo $(TG_NAME)-$$i.png; done)
 
 JAVA_FILES     = $(JAVA_AM_FILES) $(JAVA_MP_FILES) $(JAVA_TG_FILES)
 
+# Files needed for Amazon store
+
+AMAZON_FILES   = $(shell for i in $(AMAZON_RES); do echo $(AM_NAME)-$$i.png; done)
+
 # PNG files needed by anyone
 
 AM_FILES       = $(shell for i in $(RES); do echo $(AM_NAME)-$$i.png; done)
@@ -120,7 +125,7 @@ java-telegps:
 
 fat: all $(ICO_FILES) $(ICNS_FILES) $(EXE_FILES)
 
-all-local: $(JAVA_FILES) $(AM_XPM) $(LED_ICONS)
+all-local: $(JAVA_FILES) $(AM_XPM) $(LED_ICONS) $(AMAZON_FILES)
 
 clean-local:
        $(RM) $(AM_NAME)-*.png $(TG_NAME)-*.png $(MP_NAME)-*.png
index 6caf63cfd492c30a5e526e5904667d0929b5a8df..0c4f0ecbcbae6213cafde897b0f70ade8439251c 100644 (file)
@@ -11,6 +11,7 @@ libaltosJNI
 cjnitest
 cjnitest32
 cjnitest64
+cjnitest_*
 btletest
 libaltos.swig
 swig_bindings/
index 8c57b3f9d92f4d7a23e4a9fd28977c46d03074aa..2b9a7aa6b85614a05b542eb8f644b68b1fb06c21 100644 (file)
@@ -1,3 +1,4 @@
+export PATH=$(shell echo "$$PWD:$$PATH")
 AM_CFLAGS=-DLINUX -DPOSIX_TTY -I$(JVM_INCLUDE) -I$(JVM_INCLUDE)/linux
 AM_JAVACFLAGS=$(JAVAC_VERSION_FLAGS) -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked
 
@@ -33,27 +34,59 @@ btletest_SOURCES=btletest.c
 btletest_LDADD=-lbluetooth
 
 if MULTI_ARCH
-altoslib_LTLIBRARIES+=libaltos32.la libaltos64.la
-
-libaltos32_la_LDFLAGS=$(libaltos_la_LDFLAGS)
-libaltos64_la_LDFLAGS=$(libaltos_la_LDFLAGS)
-
-libaltos32_la_CFLAGS=-m32 $(AM_CFLAGS)
-libaltos64_la_CFLAGS=-m64 $(AM_CFLAGS)
-
-libaltos32_la_SOURCES=$(libaltos_la_SOURCES)
-libaltos64_la_SOURCES=$(libaltos_la_SOURCES)
-
-noinst_PROGRAMS+=cjnitest32 cjnitest64
-
-cjnitest32_CFLAGS=-m32
-cjnitest64_CFLAGS=-m64
-
-cjnitest32_SOURCES=$(cjnitest_SOURCES)
-cjnitest64_SOURCES=$(cjnitest_SOURCES)
-
-cjnitest32_LDADD=libaltos32.la
-cjnitest64_LDADD=libaltos64.la
+altoslib_LTLIBRARIES+=libaltos_i686.la libaltos_amd64.la libaltos_aarch64.la libaltos_armel.la libaltos_armhf.la
+
+I686=i686-linux-gnu
+libaltos_i686_la_LDFLAGS=-Wl,arch=$(I686) $(libaltos_la_LDFLAGS)
+libaltos_i686_la_CFLAGS=-Warch=i686-linux-gnu $(AM_CFLAGS)
+libaltos_i686_la_SOURCES=$(libaltos_la_SOURCES)
+
+AMD64=x86_64-linux-gnu
+libaltos_amd64_la_LDFLAGS=-Wl,arch=$(AMD64) $(libaltos_la_LDFLAGS)
+libaltos_amd64_la_CFLAGS=-Warch=x86_64-linux-gnu $(AM_CFLAGS)
+libaltos_amd64_la_SOURCES=$(libaltos_la_SOURCES)
+
+AARCH64=aarch64-linux-gnu
+libaltos_aarch64_la_LDFLAGS=-Wl,arch=$(AARCH64) $(libaltos_la_LDFLAGS)
+libaltos_aarch64_la_CFLAGS=-Warch=$(AARCH64) $(AM_CFLAGS)
+libaltos_aarch64_la_SOURCES=$(libaltos_la_SOURCES)
+
+ARMEL=arm-linux-gnueabi
+libaltos_armel_la_LDFLAGS=-Wl,arch=$(ARMEL) $(libaltos_la_LDFLAGS)
+libaltos_armel_la_CFLAGS=-Warch=$(ARMEL) $(AM_CFLAGS)
+libaltos_armel_la_SOURCES=$(libaltos_la_SOURCES)
+
+ARMHF=arm-linux-gnueabihf
+libaltos_armhf_la_LDFLAGS=-Wl,arch=$(ARMHF) $(libaltos_la_LDFLAGS)
+libaltos_armhf_la_CFLAGS=-Warch=$(ARMHF) $(AM_CFLAGS)
+libaltos_armhf_la_SOURCES=$(libaltos_la_SOURCES)
+
+noinst_PROGRAMS+=cjnitest_i686 cjnitest_amd64 cjnitest_aarch64 cjnitest_armel cjnitest_armhf
+
+cjnitest_i686_CFLAGS=$(libaltos_i686_la_CFLAGS)
+cjnitest_i686_LDFLAGS=-Wl,arch=$(I686)
+cjnitest_i686_SOURCES=$(cjnitest_SOURCES)
+cjnitest_i686_LDADD=libaltos_i686.la
+
+cjnitest_amd64_CFLAGS=$(libaltos_amd64_la_CFLAGS)
+cjnitest_amd64_LDFLAGS=-Wl,arch=$(AMD64)
+cjnitest_amd64_SOURCES=$(cjnitest_SOURCES)
+cjnitest_amd64_LDADD=libaltos_amd64.la
+
+cjnitest_aarch64_CFLAGS=$(libaltos_aarch64_la_CFLAGS)
+cjnitest_aarch64_LDFLAGS=-Wl,arch=$(AARCH64)
+cjnitest_aarch64_SOURCES=$(cjnitest_SOURCES)
+cjnitest_aarch64_LDADD=libaltos_aarch64.la
+
+cjnitest_armel_CFLAGS=$(libaltos_armel_la_CFLAGS)
+cjnitest_armel_LDFLAGS=-Wl,arch=$(ARMEL)
+cjnitest_armel_SOURCES=$(cjnitest_SOURCES)
+cjnitest_armel_LDADD=libaltos_armel.la
+
+cjnitest_armhf_CFLAGS=$(libaltos_armhf_la_CFLAGS)
+cjnitest_armhf_LDFLAGS=-Wl,arch=$(ARMHF)
+cjnitest_armhf_SOURCES=$(cjnitest_SOURCES)
+cjnitest_armhf_LDADD=libaltos_armhf.la
 
 endif
 
@@ -70,6 +103,9 @@ $(SWIG_FILE): libaltos.i0 $(HFILES)
 
 all-local: classlibaltos.stamp
 
+test:
+       which gcc
+
 libaltos_wrap.c: classlibaltos.stamp
 
 classlibaltos.stamp: $(SWIG_FILE)
@@ -85,12 +121,11 @@ MINGLIBS=-lsetupapi -lws2_32
 
 fat: all altos.dll altos64.dll
 
-#altos.dll: $(WINDOWS_SRC) $(WINDOWS_H)
-#      $(MINGCC32) -o $@ $(MINGFLAGS) -shared $(WINDOWS_SRC) $(MINGLIBS)
+altos.dll: $(WINDOWS_SRC) $(WINDOWS_H)
+       $(MINGCC32) -o $@ $(MINGFLAGS) -shared $(WINDOWS_SRC) $(MINGLIBS)
 
-#altos64.dll: $(WINDOWS_SRC) $(WINDOWS_H)
-#      $(MINGCC64) -o $@ $(MINGFLAGS) -shared $(WINDOWS_SRC) $(MINGLIBS)
+altos64.dll: $(WINDOWS_SRC) $(WINDOWS_H)
+       $(MINGCC64) -o $@ $(MINGFLAGS) -shared $(WINDOWS_SRC) $(MINGLIBS)
 
 clean-local:
-       -rm -rf libaltosJNI *.class *.java classlibaltos.stamp $(SWIG_FILE) libaltos_wrap.c
-#      -rm -rf  altos.dll altos64.dll  
+       -rm -rf libaltosJNI *.class *.java classlibaltos.stamp $(SWIG_FILE) libaltos_wrap.c altos.dll altos64.dll
index 3a3aca0e3092399dd5b29c645554eb8689712882..ccdf8c813ebe10b154e77619cc638db8a30ba36d 100755 (executable)
Binary files a/libaltos/altos.dll and b/libaltos/altos.dll differ
index c83c59e9293cf09f4365a583cdb320f8b65fa1a6..9bdb8f536200a590d2fd585ae8aa4467718bc38d 100755 (executable)
Binary files a/libaltos/altos64.dll and b/libaltos/altos64.dll differ
diff --git a/libaltos/gcc b/libaltos/gcc
new file mode 100755 (executable)
index 0000000..da261cc
--- /dev/null
@@ -0,0 +1,22 @@
+#!/bin/bash
+NEW_PATH=`echo $PATH | sed 's/^[^:]*://'`
+PATH=$NEW_PATH
+CC=gcc
+args=()
+for i in "$@"; do
+    case "$i" in
+       -Wl,arch=*)
+           arch=`echo "$i" | sed -e 's/^-Wl,arch=//'`
+           CC="$arch"-gcc
+           ;;
+       -Warch=*)
+           arch=`echo "$i" | sed -e 's/^-Warch=//'`
+           CC="$arch"-gcc
+           ;;
+       *)
+           args+=( "$i" )
+           ;;
+    esac
+done
+echo "          " "$CC" "${args[@]}"
+exec "$CC" "${args[@]}"
index fb8c314e3ae1b5f233d605090bbed39147f8a8e2..a2f257358ab973b11dca67e01fdc1413b6e90842 100644 (file)
@@ -89,10 +89,10 @@ static const struct bt_vendor_map altos_bt_vendor_map[] = {
        { .vendor = "00:12:6f:", 1 },   /* Rayson */
        { .vendor = "8c:de:52:", 6 },   /* ISSC */
        { .vendor = "d8:80:39:", 6 },   /* Microchip */
+       { .vendor = "04:91:62:", 6 },   /* New Microchip */
 };
 
 #define NUM_BT_VENDOR_MAP      (sizeof altos_bt_vendor_map / sizeof altos_bt_vendor_map[0])
-#define BT_PORT_DEFAULT                1
 
 static inline int
 ao_tolower(int c) {
@@ -114,7 +114,7 @@ int altos_bt_port(struct altos_bt_device *device) {
                                break;
                }
        }
-       return BT_PORT_DEFAULT;
+       return 0;
 }
 
 PUBLIC void
index 255b977347296078d66bf31220cd742e542cbd78..55038ff0b856d9b4108bf007706070879166d941 100644 (file)
@@ -512,58 +512,66 @@ altos_bt_open(struct altos_bt_device *device)
                goto no_file;
        }
 
-#if 0
-       /*
-        * Search for the RFCOMM service to get the right channel
-        */
-       session = sdp_connect(BDADDR_ANY, &addr.rc_bdaddr, SDP_RETRY_IF_BUSY);
-
-       if (session) {
-               static const uint8_t svc_uuid_int[] = {
-                       0, 0, 0, 0, 0, 0, 0, 0,
-                       0, 0, 0, 0, 0, 0, 0x11, 0x01
-               };
-               int                     err;
-               uuid_t                  svc_uuid;
-               uint32_t                range;
-               sdp_list_t              *search_list, *attrid_list;
-               sdp_list_t              *response_list = NULL, *r;
-               sdp_uuid16_create(&svc_uuid, PUBLIC_BROWSE_GROUP);
-               search_list = sdp_list_append(NULL, &svc_uuid);
-
-               range = 0x0000ffff;
-               attrid_list = sdp_list_append(NULL, &range);
-
-               err = sdp_service_search_attr_req(session, search_list,
-                                                 SDP_ATTR_REQ_RANGE, attrid_list, &response_list);
-
-               if (err >= 0) {
-                       for (r = response_list; r; r = r->next) {
-                               sdp_record_t *rec = (sdp_record_t*) r->data;
-                               sdp_list_t *proto_list;
-                               sdp_list_t *access = NULL;
-                               int proto;
-
-                               proto = sdp_uuid_to_proto(&rec->svclass);
-
-                               if (proto == SERIAL_PORT_SVCLASS_ID) {
-                                       sdp_get_access_protos(rec, &access);
-                                       if (access) {
-                                               int this_chan = sdp_get_proto_port(access, RFCOMM_UUID);
-                                               if (this_chan)
-                                                       channel = this_chan;
+       /* Try the built-in vendor list */
+       channel = altos_bt_port(device);
+
+       /* Not present, try to discover an RFCOMM service */
+       if (channel == 0) {
+               /*
+                * Search for the RFCOMM service to get the right channel
+                */
+               session = sdp_connect(BDADDR_ANY, &addr.rc_bdaddr, SDP_RETRY_IF_BUSY);
+
+               if (session) {
+                       static const uint8_t svc_uuid_int[] = {
+                               0, 0, 0, 0, 0, 0, 0, 0,
+                               0, 0, 0, 0, 0, 0, 0x11, 0x01
+                       };
+                       int                     err;
+                       uuid_t                  svc_uuid;
+                       uint32_t                range;
+                       sdp_list_t              *search_list, *attrid_list;
+                       sdp_list_t              *response_list = NULL, *r;
+                       sdp_uuid16_create(&svc_uuid, PUBLIC_BROWSE_GROUP);
+                       search_list = sdp_list_append(NULL, &svc_uuid);
+
+                       range = 0x0000ffff;
+                       attrid_list = sdp_list_append(NULL, &range);
+
+                       err = sdp_service_search_attr_req(session, search_list,
+                                                         SDP_ATTR_REQ_RANGE, attrid_list, &response_list);
+
+                       if (err >= 0) {
+                               for (r = response_list; r; r = r->next) {
+                                       sdp_record_t *rec = (sdp_record_t*) r->data;
+                                       sdp_list_t *proto_list;
+                                       sdp_list_t *access = NULL;
+                                       int proto;
+
+                                       proto = sdp_uuid_to_proto(&rec->svclass);
+
+                                       if (proto == SERIAL_PORT_SVCLASS_ID) {
+                                               sdp_get_access_protos(rec, &access);
+                                               if (access) {
+                                                       int this_chan = sdp_get_proto_port(access, RFCOMM_UUID);
+                                                       if (this_chan) {
+                                                               printf("found service on channel %d\n", this_chan);
+                                                               channel = this_chan;
+                                                       }
+                                               }
                                        }
                                }
                        }
-               }
 
-               /* Leave the session open so we don't disconnect from the device before opening
-                * the RFCOMM channel
-                */
+                       /* Leave the session open so we don't disconnect from the device before opening
+                        * the RFCOMM channel
+                        */
+               }
        }
-#endif
+
+       /* Still nothing, try the default */
        if (channel == 0)
-               channel = altos_bt_port(device);
+               channel = BT_PORT_DEFAULT;
 
        /* Connect to the channel */
        file = calloc(1, sizeof (struct altos_file_posix));
index f356eb6b4907996f4cfda52d0fa3588e80b06cac..9b9b4ec40a53f9de85ccd0ed3d048bc771469bf8 100644 (file)
@@ -25,6 +25,7 @@
 #include <string.h>
 
 #define BLUETOOTH_PRODUCT_TELEBT       "TeleBT"
+#define BT_PORT_DEFAULT                6
 
 #define USB_BUF_SIZE   64
 
index 43e347c40cb70ce96bb0bbf9dd19875a6e551881..33eb77c7ac7c1149f4e03823e8218ca49e399989 100644 (file)
@@ -757,6 +757,7 @@ altos_bt_open(struct altos_bt_device *device)
        struct altos_file_windows       *file;
        SOCKADDR_BTH            sockaddr_bth;
        int                     ret;
+       int                     channel = 0;
 
        file = calloc(1, sizeof (struct altos_file_windows));
        if (!file) {
@@ -775,7 +776,12 @@ altos_bt_open(struct altos_bt_device *device)
        memset(&sockaddr_bth, '\0', sizeof (sockaddr_bth));
        sockaddr_bth.addressFamily = AF_BTH;
        sockaddr_bth.btAddr = str2ba(device->addr);
-       sockaddr_bth.port = altos_bt_port(device);
+
+       channel = altos_bt_port(device);
+       if (channel == 0)
+               channel = BT_PORT_DEFAULT;
+
+       sockaddr_bth.port = channel;
 
        ret = connect(file->socket, (SOCKADDR *) &sockaddr_bth, sizeof (sockaddr_bth));
 
index 9a0328d7a2e2fbf44e5dc3e1260fcda3619cc904..09cf9617cf9e07485c4a67c73ed15b363544d615 100644 (file)
@@ -37,7 +37,7 @@ JAR=micropeak.jar
 FATJAR=micropeak-fat.jar
 
 if MULTI_ARCH
-LIBALTOS_LINUX=libaltos32.so libaltos64.so
+LIBALTOS_LINUX=libaltos_i686.so libaltos_amd64.so libaltos_aarch64.so libaltos_armel.so libaltos_armhf.so
 else
 LIBALTOS_LINUX=libaltos.so
 endif
@@ -241,11 +241,23 @@ libaltos.so: build-libaltos
        -rm -f "$@"
        $(LN_S) ../libaltos/.libs/"$@" .
 
-libaltos32.so: build-libaltos
+libaltos_i686.so: build-libaltos
        -rm -f "$@"
        $(LN_S) ../libaltos/.libs/"$@" .
 
-libaltos64.so: build-libaltos
+libaltos_amd64.so: build-libaltos
+       -rm -f "$@"
+       $(LN_S) ../libaltos/.libs/"$@" .
+
+libaltos_aarch64.so: build-libaltos
+       -rm -f "$@"
+       $(LN_S) ../libaltos/.libs/"$@" .
+
+libaltos_armel.so: build-libaltos
+       -rm -f "$@"
+       $(LN_S) ../libaltos/.libs/"$@" .
+
+libaltos_armhf.so: build-libaltos
        -rm -f "$@"
        $(LN_S) ../libaltos/.libs/"$@" .
 
@@ -273,6 +285,7 @@ altos64.dll: ../libaltos/altos64.dll
 
 build-libaltos:
        +cd ../libaltos && make libaltos.la
+
 build-altos-dll:
        +cd ../libaltos && make altos.dll
 
index 7e3d1e593dfc6658d737902ec5546afecdffb905..4dcb7a360e928e2457b084bc0bc5d3d6d545c3cd 100644 (file)
@@ -190,12 +190,7 @@ public class MicroDownload extends AltosUIDialog implements Runnable, ActionList
        }
 
        public void start() {
-               try {
-                       serial = new MicroSerial(device);
-                       serial.set_log(this);
-               } catch (FileNotFoundException fe) {
-                       return;
-               }
+               serial.set_log(this);
                serial_thread = new Thread(this);
                serial_thread.start();
 
@@ -212,7 +207,7 @@ public class MicroDownload extends AltosUIDialog implements Runnable, ActionList
                setVisible(false);
        }
 
-       public MicroDownload(MicroPeak owner, AltosDevice device) {
+       public MicroDownload(MicroPeak owner, AltosDevice device, MicroSerial serial) {
                super (owner, "Download MicroPeak Data", false);
 
                int y = 0;
@@ -223,6 +218,7 @@ public class MicroDownload extends AltosUIDialog implements Runnable, ActionList
 
                this.owner = owner;
                this.device = device;
+               this.serial = serial;
 
                pane = getScrollablePane();
                pane.setLayout(new GridBagLayout());
index c34e874aaaa05b2708a17ef2f9c20ae2b65f143c..96fb33ba132d6a368e2436dfedb11fd98eaae256 100644 (file)
@@ -136,9 +136,18 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene
 
        private void DownloadData() {
                AltosDevice     device = MicroDeviceDialog.show(this);
+               MicroSerial     serial = null;
+               try {
+                       serial = new MicroSerial(device);
+               } catch (FileNotFoundException fe) {
+                       JOptionPane.showMessageDialog(this,
+                                                     fe.getMessage(),
+                                                     "Cannot open device",
+                                                     JOptionPane.ERROR_MESSAGE);
+                       return;
+               }
 
-               if (device != null)
-                       new MicroDownload(this, device);
+               new MicroDownload(this, device, serial);
        }
 
        private void no_data() {
index 0b6a7e278b020c45cf4fa1f105d2947a527b411b..2cc04e5354233b247d3bf42084c8c9c450671d91 100644 (file)
@@ -26,6 +26,7 @@ ARMM3DIRS=\
        telemega-v2.0 telemega-v2.0/flash-loader \
        telemega-v3.0 telemega-v3.0/flash-loader \
        telemega-v4.0 telemega-v4.0/flash-loader \
+       telemega-v5.0 telemega-v5.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 \
index 3ccf121f1a1f3301f0b2e720d2308e78febb5be9..6f04380300c59c8547e2fd3e3f85cf811dc7d426 100644 (file)
@@ -25,6 +25,8 @@
 #include <ao_pad.h>
 #endif
 
+static uint8_t cc1201;
+
 static uint8_t ao_radio_mutex;
 
 static uint8_t ao_radio_wake;          /* radio ready. Also used as sleep address */
@@ -329,13 +331,24 @@ ao_radio_idle(void)
 #define PACKET_CHAN_BW_384     ((CC1200_CHAN_BW_ADC_CIC_DECFACT_12 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
                                 (16 << CC1200_CHAN_BW_BB_CIC_DECFACT))
 
+/*
+ * CC1201 doesn't support our low bandwidth receive setups, so we use
+ * larger values for that part, leaving the bandwidth at over 50kHz
+ */
+
 /* 200 / 10 = 20 */
-#define PACKET_CHAN_BW_96      ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
-                                (16 << CC1200_CHAN_BW_BB_CIC_DECFACT))
+#define PACKET_CHAN_BW_96_CC1200       ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
+                                        (16 << CC1200_CHAN_BW_BB_CIC_DECFACT))
+
+#define PACKET_CHAN_BW_96_CC1201       ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
+                                        (8 << CC1200_CHAN_BW_BB_CIC_DECFACT))
 
 /* 200 / 25 = 8 */
-#define PACKET_CHAN_BW_24      ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
-                                (44 << CC1200_CHAN_BW_BB_CIC_DECFACT))
+#define PACKET_CHAN_BW_24_CC1200       ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
+                                        (44 << CC1200_CHAN_BW_BB_CIC_DECFACT))
+
+#define PACKET_CHAN_BW_24_CC1201       ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
+                                        (8 << CC1200_CHAN_BW_BB_CIC_DECFACT))
 
 static const uint16_t packet_setup[] = {
        CC1200_SYMBOL_RATE1,            ((PACKET_SYMBOL_RATE_M >> 8) & 0xff),
@@ -377,7 +390,6 @@ static const uint16_t packet_setup_96[] = {
                                 (PACKET_DEV_E_96 << CC1200_MODCFG_DEV_E_DEV_E)),
        CC1200_SYMBOL_RATE2,    ((PACKET_SYMBOL_RATE_E_96 << CC1200_SYMBOL_RATE2_DATARATE_E) |
                                 (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
-       CC1200_CHAN_BW,         PACKET_CHAN_BW_96,
         CC1200_MDMCFG2,                                  /* General Modem Parameter Configuration Reg. 2 */
                ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
                 (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
@@ -392,7 +404,6 @@ static const uint16_t packet_setup_24[] = {
                                 (PACKET_DEV_E_24 << CC1200_MODCFG_DEV_E_DEV_E)),
        CC1200_SYMBOL_RATE2,    ((PACKET_SYMBOL_RATE_E_24 << CC1200_SYMBOL_RATE2_DATARATE_E) |
                                 (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
-       CC1200_CHAN_BW,         PACKET_CHAN_BW_24,
         CC1200_MDMCFG2,                                  /* General Modem Parameter Configuration Reg. 2 */
                ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
                 (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
@@ -614,9 +625,17 @@ ao_radio_set_mode(uint16_t new_mode)
                        break;
                case AO_RADIO_RATE_9600:
                        ao_radio_set_regs(packet_setup_96);
+                       if (cc1201)
+                               ao_radio_reg_write(CC1200_CHAN_BW, PACKET_CHAN_BW_96_CC1201);
+                       else
+                               ao_radio_reg_write(CC1200_CHAN_BW, PACKET_CHAN_BW_96_CC1200);
                        break;
                case AO_RADIO_RATE_2400:
                        ao_radio_set_regs(packet_setup_24);
+                       if (cc1201)
+                               ao_radio_reg_write(CC1200_CHAN_BW, PACKET_CHAN_BW_24_CC1201);
+                       else
+                               ao_radio_reg_write(CC1200_CHAN_BW, PACKET_CHAN_BW_24_CC1200);
                        break;
                }
        }
@@ -663,6 +682,11 @@ static uint8_t     ao_radio_configured = 0;
 static void
 ao_radio_setup(void)
 {
+       uint8_t partnumber = ao_radio_reg_read(CC1200_PARTNUMBER);
+
+       if (partnumber == CC1200_PARTNUMBER_CC1201)
+               cc1201 = 1;
+
        ao_radio_strobe(CC1200_SRES);
 
        ao_radio_set_regs(radio_setup);
@@ -719,8 +743,8 @@ ao_radio_state(void)
        return (ao_radio_status() >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK;
 }
 
-#if CC1200_DEBUG
-void
+#if CC1200_DEBUG_
+static void
 ao_radio_show_state(char *where)
 {
        printf("%s: state %d len %d rxbytes %d\n",
@@ -1320,7 +1344,7 @@ static void ao_radio_packet(void) {
        ao_radio_send(packet, sizeof (packet));
 }
 
-void
+static void
 ao_radio_test_recv(void)
 {
        static uint8_t  bytes[34];
index 8e17bbd9fb0837b31ac7310ead20c201c0ddecd3..6ab04ecdf87663af8c52b236172bfb01ef71d0d5 100644 (file)
 #define CC1200_FSCAL_CTRL      (CC1200_EXTENDED_BIT | 0x8d)
 #define CC1200_PHASE_ADJUST    (CC1200_EXTENDED_BIT | 0x8e)
 #define CC1200_PARTNUMBER      (CC1200_EXTENDED_BIT | 0x8f)
+#define  CC1200_PARTNUMBER_CC1200      0x20
+#define  CC1200_PARTNUMBER_CC1201      0x21
 #define CC1200_PARTVERSION     (CC1200_EXTENDED_BIT | 0x90)
 #define CC1200_SERIAL_STATUS   (CC1200_EXTENDED_BIT | 0x91)
 #define CC1200_MODEM_STATUS1   (CC1200_EXTENDED_BIT | 0x92)
diff --git a/src/drivers/ao_mmc5983.c b/src/drivers/ao_mmc5983.c
new file mode 100644 (file)
index 0000000..5d97d75
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * 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_mmc5983.h>
+#include <ao_exti.h>
+
+#if HAS_MMC5983
+
+struct ao_mmc5983_sample       ao_mmc5983_current;
+
+static uint8_t ao_mmc5983_configured;
+
+#ifdef MMC5983_I2C
+#include <ao_i2c_bit.h>
+
+static void
+ao_mmc5983_reg_write(uint8_t addr, uint8_t data)
+{
+       uint8_t d[2];
+
+       d[0] = addr;
+       d[1] = data;
+
+       ao_i2c_bit_start(MMC5983_I2C_ADDR);
+       ao_i2c_bit_send(d, 2);
+       ao_i2c_bit_stop();
+}
+
+static uint8_t
+ao_mmc5983_reg_read(uint8_t addr)
+{
+       uint8_t d[1];
+
+       ao_i2c_bit_start(MMC5983_I2C_ADDR);
+       d[0] = addr;
+       ao_i2c_bit_send(d, 1);
+       ao_i2c_bit_restart(MMC5983_I2C_ADDR | 1);
+       ao_i2c_bit_recv(d, 1);
+       ao_i2c_bit_stop();
+       return d[0];
+}
+
+static void
+ao_mmc5983_sample(struct ao_mmc5983_sample *sample)
+{
+       struct ao_mmc5983_raw   raw;
+
+       ao_i2c_bit_start(MMC5983_I2C_ADDR);
+       raw.addr = MMC5983_X_OUT_0;
+       ao_i2c_bit_send(&raw.addr, 1);
+       ao_i2c_bit_restart(MMC5983_I2C_ADDR | 1);
+       ao_i2c_bit_recv(&raw.x0, 7);
+       ao_i2c_bit_stop();
+
+       sample->x = raw.x0 << 10 | raw.x1 << 2 | ((raw.xyz2 >> 6) & 3);
+       sample->y = raw.y0 << 10 | raw.y1 << 2 | ((raw.xyz2 >> 4) & 3);
+       sample->z = raw.z0 << 10 | raw.z1 << 2 | ((raw.xyz2 >> 2) & 3);
+}
+
+#else
+#define AO_MMC5983_SPI_SPEED   ao_spi_speed(2000000)
+
+static void
+ao_mmc5983_start(void) {
+       ao_spi_get_bit(AO_MMC5983_SPI_CS_PORT,
+                      AO_MMC5983_SPI_CS_PIN,
+                      AO_MMC5983_SPI_INDEX,
+                      AO_MMC5983_SPI_SPEED);
+}
+
+static void
+ao_mmc5983_stop(void) {
+       ao_spi_put_bit(AO_MMC5983_SPI_CS_PORT,
+                      AO_MMC5983_SPI_CS_PIN,
+                      AO_MMC5983_SPI_INDEX);
+}
+
+
+static void
+ao_mmc5983_reg_write(uint8_t addr, uint8_t data)
+{
+       uint8_t d[2];
+
+       d[0] = addr;
+       d[1] = data;
+       ao_mmc5983_start();
+       ao_spi_send(d, 2, AO_MMC5983_SPI_INDEX);
+       ao_mmc5983_stop();
+}
+
+static uint8_t
+ao_mmc5983_reg_read(uint8_t addr)
+{
+       uint8_t d[2];
+
+       d[0] = addr | MMC5983_READ;
+       ao_mmc5983_start();
+       ao_spi_duplex(d, d, 2, AO_MMC5983_SPI_INDEX);
+       ao_mmc5983_stop();
+
+       return d[1];
+}
+
+static void
+ao_mmc5983_duplex(uint8_t *dst, uint8_t len)
+{
+       ao_mmc5983_start();
+       ao_spi_duplex(dst, dst, len, AO_MMC5983_SPI_INDEX);
+       ao_mmc5983_stop();
+}
+
+static void
+ao_mmc5983_sample(struct ao_mmc5983_sample *sample)
+{
+       struct ao_mmc5983_raw   raw;
+
+       raw.addr = MMC5983_X_OUT_0 | MMC5983_READ;
+       ao_mmc5983_duplex((uint8_t *) &raw, sizeof (raw));
+
+       sample->x = raw.x0 << 10 | raw.x1 << 2 | ((raw.xyz2 >> 6) & 3);
+       sample->y = raw.y0 << 10 | raw.y1 << 2 | ((raw.xyz2 >> 4) & 3);
+       sample->z = raw.z0 << 10 | raw.z1 << 2 | ((raw.xyz2 >> 2) & 3);
+}
+#endif
+
+static uint8_t product_id;
+
+static uint8_t
+ao_mmc5983_setup(void)
+{
+
+       if (ao_mmc5983_configured)
+               return 1;
+
+       /* Delay for power up time (10ms) */
+       ao_delay(AO_MS_TO_TICKS(10));
+
+       ao_mmc5983_reg_write(MMC5983_CONTROL_1,
+                            1 << MMC5983_CONTROL_1_SW_RST);
+
+       /* Delay for power up time (10ms) */
+       ao_delay(AO_MS_TO_TICKS(10));
+
+       /* Check product ID */
+       product_id = ao_mmc5983_reg_read(MMC5983_PRODUCT_ID);
+       if (product_id != MMC5983_PRODUCT_ID_PRODUCT_I2C &&
+           product_id != MMC5983_PRODUCT_ID_PRODUCT_SPI)
+       {
+               AO_SENSOR_ERROR(AO_DATA_MMC5983);
+       }
+
+       /* Set bandwidth to 200Hz */
+       ao_mmc5983_reg_write(MMC5983_CONTROL_1,
+                            MMC5983_CONTROL_1_BW_200 << MMC5983_CONTROL_1_BW);
+
+       /* Measure at 200Hz so we get recent samples by just reading
+        * the registers
+        */
+       ao_mmc5983_reg_write(MMC5983_CONTROL_2,
+                            (1 << MMC5983_CONTROL_2_CMM_EN) |
+                            (MMC5983_CONTROL_2_CM_FREQ_200HZ << MMC5983_CONTROL_2_CM_FREQ));
+
+       ao_mmc5983_configured = 1;
+       return 1;
+}
+
+struct ao_mmc5983_sample ao_mmc5983_current;
+
+static void
+ao_mmc5983(void)
+{
+       struct ao_mmc5983_sample        sample;
+       ao_mmc5983_setup();
+       for (;;) {
+               ao_mmc5983_sample(&sample);
+               ao_arch_block_interrupts();
+               ao_mmc5983_current = sample;
+               AO_DATA_PRESENT(AO_DATA_MMC5983);
+               AO_DATA_WAIT();
+               ao_arch_release_interrupts();
+       }
+}
+
+static struct ao_task ao_mmc5983_task;
+
+static void
+ao_mmc5983_show(void)
+{
+       printf ("MMC5983: %d %d %d\n",
+               ao_mmc5983_along(&ao_mmc5983_current),
+               ao_mmc5983_across(&ao_mmc5983_current),
+               ao_mmc5983_through(&ao_mmc5983_current));
+}
+
+static const struct ao_cmds ao_mmc5983_cmds[] = {
+       { ao_mmc5983_show,      "M\0Show MMC5983 status" },
+       { 0, NULL }
+};
+
+void
+ao_mmc5983_init(void)
+{
+       ao_mmc5983_configured = 0;
+
+#ifdef MMC5983_I2C
+       ao_enable_output(AO_MMC5983_SPI_CS_PORT, AO_MMC5983_SPI_CS_PIN, 1);
+#else
+       ao_enable_input(AO_MMC5983_SPI_MISO_PORT,
+                       AO_MMC5983_SPI_MISO_PIN,
+                       AO_EXTI_MODE_PULL_NONE);
+
+       ao_enable_output(AO_MMC5983_SPI_CLK_PORT,
+                        AO_MMC5983_SPI_CLK_PIN,
+                        1);
+
+       ao_enable_output(AO_MMC5983_SPI_MOSI_PORT,
+                        AO_MMC5983_SPI_MOSI_PIN,
+                        0);
+
+       ao_spi_init_cs(AO_MMC5983_SPI_CS_PORT, (1 << AO_MMC5983_SPI_CS_PIN));
+#endif
+
+       ao_add_task(&ao_mmc5983_task, ao_mmc5983, "mmc5983");
+       ao_cmd_register(&ao_mmc5983_cmds[0]);
+}
+
+#endif
diff --git a/src/drivers/ao_mmc5983.h b/src/drivers/ao_mmc5983.h
new file mode 100644 (file)
index 0000000..7bff54b
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * 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_MMC5983_H_
+#define _AO_MMC5983_H_
+
+#define MMC5983_READ           0x80
+
+#define MMC5983_I2C_ADDR       0x60
+
+#define MMC5983_CONFIG_A       0
+
+#define  MMC5983_CONFIG_A_MA           5
+#define  MMC5983_CONFIG_A_MA_1                 0
+#define  MMC5983_CONFIG_A_MA_2                 1
+#define  MMC5983_CONFIG_A_MA_4                 2
+#define  MMC5983_CONFIG_A_MA_8                 3
+#define  MMC5983_CONFIG_A_MA_MASK              3
+
+#define  MMC5983_CONFIG_A_DO           2
+#define   MMC5983_CONFIG_A_DO_0_75             0
+#define   MMC5983_CONFIG_A_DO_1_5              1
+#define   MMC5983_CONFIG_A_DO_3                        2
+#define   MMC5983_CONFIG_A_DO_7_5              3
+#define   MMC5983_CONFIG_A_DO_15               4
+#define   MMC5983_CONFIG_A_DO_30               5
+#define   MMC5983_CONFIG_A_DO_75               6
+#define   MMC5983_CONFIG_A_DO_MASK             7
+
+#define MMC5983_CONFIG_A_MS            0
+#define  MMC5983_CONFIG_A_MS_NORMAL            0
+#define  MMC5983_CONFIG_A_MS_POSITIVE_BIAS     1
+#define  MMC5983_CONFIG_A_MS_NEGATIVE_BIAS     2
+#define  MMC5983_CONFIG_A_MS_MASK              3
+
+#define MMC5983_CONFIG_B       1
+
+#define MMC5983_CONFIG_B_GN            5
+#define  MMC5983_CONFIG_B_GN_0_88              0
+#define  MMC5983_CONFIG_B_GN_1_3               1
+#define  MMC5983_CONFIG_B_GN_1_9               2
+#define  MMC5983_CONFIG_B_GN_2_5               3
+#define  MMC5983_CONFIG_B_GN_4_0               4
+#define  MMC5983_CONFIG_B_GN_4_7               5
+#define  MMC5983_CONFIG_B_GN_5_6               6
+#define  MMC5983_CONFIG_B_GN_8_1               7
+#define  MMC5983_CONFIG_B_GN_MASK              7
+
+#define MMC5983_MODE           2
+#define  MMC5983_MODE_CONTINUOUS       0
+#define  MMC5983_MODE_SINGLE           1
+#define  MMC5983_MODE_IDLE             2
+
+#define MMC5983_X_OUT_0                0
+#define MMC5983_X_OUT_1                1
+#define MMC5983_Y_OUT_0                2
+#define MMC5983_Y_OUT_1                3
+#define MMC5983_Z_OUT_0                4
+#define MMC5983_Z_OUT_1                5
+#define MMC5983_XYZ_OUT_2      6
+#define MMC5983_T_OUT          7
+
+#define MMC5983_STATUS         8
+# define MMC5983_STATUS_OTP_READ_DONE          4
+# define MMC5983_STATUS_MEAS_T_DONE            1
+# define MMC5983_STATUS_MEAS_M_DONE            0
+
+#define MMC5983_CONTROL_0      9
+# define MMC5983_CONTROL_0_OTP_READ            6
+# define MMC5983_CONTROL_0_AUTO_SR_EN          5
+# define MMC5983_CONTROL_0_RESET               4
+# define MMC5983_CONTROL_0_SET                 3
+# define MMC5983_CONTROL_0_INT_MEAS_DONE_EN    2
+# define MMC5983_CONTROL_0_TM_T                        1
+# define MMC5983_CONTROL_0_TM_M                        0
+
+#define MMC5983_CONTROL_1      0xa
+# define MMC5983_CONTROL_1_SW_RST              7
+# define MMC5983_CONTROL_1_YZ_INHIBIT          3
+# define MMC5983_CONTROL_1_X_INHIBIT           2
+# define MMC5983_CONTROL_1_BW                  0
+# define MMC5983_CONTROL_1_BW_100                      0
+# define MMC5983_CONTROL_1_BW_200                      1
+# define MMC5983_CONTROL_1_BW_400                      2
+# define MMC5983_CONTROL_1_BW_800                      3
+#define MMC5983_CONTROL_2      0xb
+# define MMC5983_CONTROL_2_EN_PRD_SET          7
+# define MMC5983_CONTROL_2_PRD_SET             4
+# define MMC5983_CONTROL_2_PRD_SET_1                   0
+# define MMC5983_CONTROL_2_PRD_SET_25                  1
+# define MMC5983_CONTROL_2_PRD_SET_75                  2
+# define MMC5983_CONTROL_2_PRD_SET_100                 3
+# define MMC5983_CONTROL_2_PRD_SET_250                 4
+# define MMC5983_CONTROL_2_PRD_SET_500                 5
+# define MMC5983_CONTROL_2_PRD_SET_1000                        6
+# define MMC5983_CONTROL_2_PRD_SET_2000                        7
+# define MMC5983_CONTROL_2_CMM_EN              3
+# define MMC5983_CONTROL_2_CM_FREQ             0
+# define MMC5983_CONTROL_2_CM_FREQ_OFF                 0
+# define MMC5983_CONTROL_2_CM_FREQ_1HZ                 1
+# define MMC5983_CONTROL_2_CM_FREQ_10HZ                        2
+# define MMC5983_CONTROL_2_CM_FREQ_20HZ                        3
+# define MMC5983_CONTROL_2_CM_FREQ_50HZ                        4
+# define MMC5983_CONTROL_2_CM_FREQ_100HZ               5
+# define MMC5983_CONTROL_2_CM_FREQ_200HZ               6
+# define MMC5983_CONTROL_2_CM_FREQ_1000HZ              7
+
+#define MMC5983_CONTROL_3      0xc
+#define  MMC5983_CONTROL_3_SPI_3W              6
+#define  MMC5983_CONTROL_3_ST_ENM              2
+#define  MMC5983_CONTROL_3_ST_ENP              1
+
+#define MMC5983_PRODUCT_ID     0x2f
+#define MMC5983_PRODUCT_ID_PRODUCT_I2C 0x30
+#define MMC5983_PRODUCT_ID_PRODUCT_SPI 0x31
+
+
+struct ao_mmc5983_sample {
+       int16_t         x, y, z;
+};
+
+struct ao_mmc5983_raw {
+       uint8_t         addr;
+       uint8_t         x0;
+       uint8_t         x1;
+       uint8_t         y0;
+       uint8_t         y1;
+       uint8_t         z0;
+       uint8_t         z1;
+       uint8_t         xyz2;
+};
+
+extern struct ao_mmc5983_sample        ao_mmc5983_current;
+
+void
+ao_mmc5983_init(void);
+
+#endif /* _AO_MMC5983_H_ */
index 7c9d6b6bffaa343469576c4429bf4d883fad69d5..79658c552bf2e38b7c917d287523f148df86d271 100644 (file)
@@ -164,6 +164,8 @@ ao_mpu6000_gyro_check(int16_t normal, int16_t test)
        return 0;
 }
 
+static uint8_t mpu_id;
+
 static void
 _ao_mpu6000_wait_alive(void)
 {
@@ -172,11 +174,11 @@ _ao_mpu6000_wait_alive(void)
        /* Wait for the chip to wake up */
        for (i = 0; i < 30; i++) {
                ao_delay(AO_MS_TO_TICKS(100));
-               if (_ao_mpu6000_reg_read(MPU6000_WHO_AM_I) == 0x68)
-                       break;
+               mpu_id = _ao_mpu6000_reg_read(MPU6000_WHO_AM_I);
+               if (mpu_id == 0x68)
+                       return;
        }
-       if (i == 30)
-               ao_panic(AO_PANIC_SELF_TEST_MPU6000);
+       AO_SENSOR_ERROR(AO_DATA_MPU6000);
 }
 
 #define ST_TRIES       10
@@ -355,6 +357,15 @@ static struct ao_task ao_mpu6000_task;
 static void
 ao_mpu6000_show(void)
 {
+#ifdef AO_LOG_NORMALIZED
+       printf ("MPU6000: %7d %7d %7d %7d %7d %7d\n",
+               ao_mpu6000_along(&ao_mpu6000_current),
+               ao_mpu6000_across(&ao_mpu6000_current),
+               ao_mpu6000_through(&ao_mpu6000_current),
+               ao_mpu6000_roll(&ao_mpu6000_current),
+               ao_mpu6000_pitch(&ao_mpu6000_current),
+               ao_mpu6000_yaw(&ao_mpu6000_current));
+#else
        printf ("Accel: %7d %7d %7d Gyro: %7d %7d %7d\n",
                ao_mpu6000_current.accel_x,
                ao_mpu6000_current.accel_y,
@@ -362,6 +373,7 @@ ao_mpu6000_show(void)
                ao_mpu6000_current.gyro_x,
                ao_mpu6000_current.gyro_y,
                ao_mpu6000_current.gyro_z);
+#endif
 }
 
 static const struct ao_cmds ao_mpu6000_cmds[] = {
index 8c5d53435254df11e78ad3c311c6c04fc4de1d3b..8141d85a3d7d5b39ec675df4fa77966f096aeef3 100644 (file)
 #ifndef _AO_BEEP_H_
 #define _AO_BEEP_H_
 
-#ifndef HAS_BEEP_CONFIG
-#if defined(USE_EEPROM_CONFIG) && USE_EEPROM_CONFIG || HAS_EEPROM
-#define HAS_BEEP_CONFIG        1
-#endif
-#endif
-
 /*
  * ao_beep.c
  */
  * frequency = 1/2 (24e6/32) / beep
  */
 
+#ifndef AO_BEEP_MID_DEFAULT
 #define AO_BEEP_MID_DEFAULT    94      /* 3989Hz */
-
-#if HAS_BEEP_CONFIG
-#define AO_BEEP_MID    ao_config.mid_beep
-#else
-#define AO_BEEP_MID    AO_BEEP_MID_DEFAULT
 #endif
 
+#define AO_BEEP_MID    ((int) ao_config.mid_beep)
+
 #define AO_BEEP_MID_PANIC      AO_BEEP_MID_DEFAULT
 
-#define AO_BEEP_LOW    AO_BEEP_MID * 150 / 94  /* 2500Hz */
-#define AO_BEEP_HIGH   AO_BEEP_MID * 75 / 94   /* 5000Hz */
+#ifndef AO_BEEP_MAKE_LOW
+#define AO_BEEP_MAKE_LOW(m)    ((m) * 150 / 94)        /* 2500Hz */
+#endif
+
+#ifndef AO_BEEP_MAKE_HIGH
+#define AO_BEEP_MAKE_HIGH(m)   ((m) * 75 / 94)         /* 5000Hz */
+#endif
+
+#define AO_BEEP_LOW    AO_BEEP_MAKE_LOW(AO_BEEP_MID)
+#define AO_BEEP_HIGH   AO_BEEP_MAKE_HIGH(AO_BEEP_MID)
 
-#define AO_BEEP_LOW_PANIC      (AO_BEEP_MID_PANIC * 150 / 94)
-#define AO_BEEP_HIGH_PANIC     (AO_BEEP_MID_PANIC * 75 / 94)
+#define AO_BEEP_LOW_PANIC      AO_BEEP_MAKE_LOW(AO_BEEP_MID_PANIC)
+#define AO_BEEP_HIGH_PANIC     AO_BEEP_MAKE_HIGH(AO_BEEP_MID_PANIC)
 
 #define AO_BEEP_OFF    0       /* off */
 
index bfc0325e00d9406c59c51cc2d7fd9a23c8682310..ece60ad355124e4bdcf4a703b6e8434713f82433 100644 (file)
@@ -145,6 +145,9 @@ _ao_config_get(void)
        }
        minor = ao_config.minor;
        if (minor != AO_CONFIG_MINOR) {
+#if AO_PYRO_NUM
+               ao_pyro_update_version();
+#endif
                /* Fixups for minor version 1 */
                if (minor < 1)
                        ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY;
@@ -203,7 +206,7 @@ _ao_config_get(void)
                        ao_config.accel_minus_g = 0;
                }
 #endif
-#if HAS_BEEP_CONFIG
+#if HAS_BEEP
                if (minor < 16)
                        ao_config.mid_beep = AO_BEEP_MID_DEFAULT;
 #endif
@@ -842,7 +845,7 @@ ao_config_radio_power_set(void)
 
 #endif
 
-#if HAS_BEEP_CONFIG
+#if HAS_BEEP
 static void
 ao_config_beep_show(void)
 {
@@ -1066,7 +1069,7 @@ const struct ao_config_var ao_config_vars[] = {
        { "A <secs>\0APRS packet interval (0 disable)",
          ao_config_aprs_set, ao_config_aprs_show },
 #endif
-#if HAS_BEEP_CONFIG
+#if HAS_BEEP
        { "b <val>\0Beeper tone (freq = 1/2 (24e6/32) / beep",
          ao_config_beep_set, ao_config_beep_show },
 #endif
index 8a367733ee00e523ef0eb115767af64073a0cd6a..c668b71a1979c418c5f39b145b8e72cb9a65b95e 100644 (file)
@@ -58,7 +58,7 @@
 #endif
 
 #define AO_CONFIG_MAJOR        1
-#define AO_CONFIG_MINOR        24
+#define AO_CONFIG_MINOR        25
 
 #define AO_AES_LEN 16
 
index dcd8fc31b8e9a33ee9debadf826bc9a6e6ed3303..60794cc2d110878e373aaf808ad54caa5e3339b6 100644 (file)
 #define AO_DATA_HMC5883        0
 #endif
 
+#if HAS_MMC5983
+#include <ao_mmc5983.h>
+#define AO_DATA_MMC5983        (1 << 3)
+#else
+#define AO_DATA_MMC5983        0
+#endif
+
 #if HAS_MMA655X
 #include <ao_mma655x.h>
 #define AO_DATA_MMA655X (1 << 4)
@@ -95,7 +102,7 @@ extern uint8_t                       ao_sensor_errors;
 
 #ifdef AO_DATA_RING
 
-#define AO_DATA_ALL    (AO_DATA_ADC|AO_DATA_MS5607|AO_DATA_MPU6000|AO_DATA_HMC5883|AO_DATA_MMA655X|AO_DATA_MPU9250|AO_DATA_ADXL375|AO_DATA_BMX160)
+#define AO_DATA_ALL    (AO_DATA_ADC|AO_DATA_MS5607|AO_DATA_MPU6000|AO_DATA_HMC5883|AO_DATA_MMA655X|AO_DATA_MPU9250|AO_DATA_ADXL375|AO_DATA_BMX160|AO_DATA_MMC5983)
 
 struct ao_data {
        uint16_t                        tick;
@@ -121,6 +128,9 @@ struct ao_data {
 #if HAS_HMC5883
        struct ao_hmc5883_sample        hmc5883;
 #endif
+#if HAS_MMC5983
+       struct ao_mmc5983_sample        mmc5983;
+#endif
 #if HAS_MMA655X
        uint16_t                        mma655x;
 #endif
@@ -378,6 +388,7 @@ typedef int16_t angle_t;    /* in degrees */
 /* X axis is aligned in the other board axis (across) */
 /* Z axis is aligned perpendicular to the board (through) */
 
+#ifndef ao_data_along
 #define ao_data_along(packet)  ((packet)->mpu6000.accel_y)
 #define ao_data_across(packet) ((packet)->mpu6000.accel_x)
 #define ao_data_through(packet)        ((packet)->mpu6000.accel_z)
@@ -385,6 +396,7 @@ typedef int16_t angle_t;    /* in degrees */
 #define ao_data_roll(packet)   ((packet)->mpu6000.gyro_y)
 #define ao_data_pitch(packet)  ((packet)->mpu6000.gyro_x)
 #define ao_data_yaw(packet)    ((packet)->mpu6000.gyro_z)
+#endif
 
 static inline float ao_convert_gyro(float sensor)
 {
@@ -490,6 +502,14 @@ typedef int16_t ao_mag_t;          /* in raw sample units */
 
 #endif
 
+#if !HAS_MAG && HAS_MMC5983
+
+#define HAS_MAG                1
+
+typedef int16_t ao_mag_t;              /* in raw sample units */
+
+#endif
+
 #if !HAS_MAG && HAS_MPU9250
 
 #define HAS_MAG                1
@@ -523,6 +543,9 @@ ao_data_fill(int head) {
 #if HAS_HMC5883
                ao_data_ring[head].hmc5883 = ao_hmc5883_current;
 #endif
+#if HAS_MMC5983
+               ao_data_ring[head].mmc5983 = ao_mmc5983_current;
+#endif
 #if HAS_MPU6000
                ao_data_ring[head].mpu6000 = ao_mpu6000_current;
 #endif
index 3c1067cb44e9e079675d863a2eb38368e096e733..4a7055c415e80d9eef3d86eacae715ce4f8b416b 100644 (file)
@@ -461,7 +461,7 @@ ao_flight(void)
 #if HAS_FLIGHT_DEBUG
                case ao_flight_test:
 #if HAS_GYRO
-                       printf ("angle %4d pitch %7d yaw %7d roll %7d\n",
+                       printf ("angle %4d pitch %7ld yaw %7ld roll %7ld\n",
                                ao_sample_orient,
                                ((ao_sample_pitch << 9) - ao_ground_pitch) >> 9,
                                ((ao_sample_yaw << 9) - ao_ground_yaw) >> 9,
@@ -492,14 +492,14 @@ ao_flight_dump(void)
        printf ("sample:\n");
        printf ("  tick        %d\n", ao_sample_tick);
 #if HAS_BARO
-       printf ("  raw pres    %d\n", ao_sample_pres);
+       printf ("  raw pres    %ld\n", ao_sample_pres);
 #endif
 #if HAS_ACCEL
        printf ("  raw accel   %d\n", ao_sample_accel);
 #endif
 #if HAS_BARO
-       printf ("  ground pres %d\n", ao_ground_pres);
-       printf ("  ground alt  %d\n", ao_ground_height);
+       printf ("  ground pres %ld\n", ao_ground_pres);
+       printf ("  ground alt  %ld\n", ao_ground_height);
 #endif
 #if HAS_ACCEL
        printf ("  raw accel   %d\n", ao_sample_accel);
@@ -508,8 +508,8 @@ ao_flight_dump(void)
 #endif
 
 #if HAS_BARO
-       printf ("  alt         %d\n", ao_sample_alt);
-       printf ("  height      %d\n", ao_sample_height);
+       printf ("  alt         %ld\n", ao_sample_alt);
+       printf ("  height      %ld\n", ao_sample_height);
 #endif
 
 #if HAS_ACCEL
@@ -518,12 +518,12 @@ ao_flight_dump(void)
 
 
        printf ("kalman:\n");
-       printf ("  height      %d\n", ao_height);
+       printf ("  height      %ld\n", ao_height);
        printf ("  speed       %d.%02d\n", int_part(ao_speed), frac_part(ao_speed));
        printf ("  accel       %d.%02d\n", int_part(ao_accel), frac_part(ao_accel));
-       printf ("  max_height  %d\n", ao_max_height);
-       printf ("  avg_height  %d\n", ao_avg_height);
-       printf ("  error_h     %d\n", ao_error_h);
+       printf ("  max_height  %ld\n", ao_max_height);
+       printf ("  avg_height  %ld\n", ao_avg_height);
+       printf ("  error_h     %ld\n", ao_error_h);
 #if !HAS_ACCEL
        printf ("  error_avg   %d\n", ao_error_h_sq_avg);
 #endif
@@ -543,6 +543,7 @@ static void
 ao_orient_test_select(void)
 {
        ao_orient_test = !ao_orient_test;
+       printf("orient test %d\n", ao_orient_test);
 }
 
 const struct ao_cmds ao_flight_cmds[] = {
diff --git a/src/kernel/ao_i2c_bit.c b/src/kernel/ao_i2c_bit.c
new file mode 100644 (file)
index 0000000..01d677b
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * 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_i2c_bit.h>
+#include <ao_exti.h>
+
+#define ao_i2c_bit_set_pin(port, pin) do {                             \
+               ao_enable_output(port, pin, 1);                         \
+               ao_gpio_set_output_mode(port, pin, AO_OUTPUT_OPEN_DRAIN); \
+               ao_gpio_set_mode(port, pin, AO_EXTI_MODE_PULL_UP);      \
+               stm_ospeedr_set(port, pin, STM_OSPEEDR_10MHz);          \
+       } while(0)
+
+
+/* 2µS per half-cycle, for a 125kHz i2c clock */
+#define AO_I2C_TICK    10000
+
+static void
+tick(void)
+{
+       int i;
+
+       for (i = 0; i < 12; i++)
+               ao_arch_nop();
+#if 0
+       uint64_t        target = ao_time_ns() + AO_I2C_TICK;
+
+       do {
+               ao_yield();
+       } while ((int64_t) (ao_time_ns() - target) < 0);
+#endif
+}
+
+static void sda(uint8_t v)
+{
+       ao_gpio_set(AO_I2C_SDA_PORT, AO_I2C_SDA_PIN, v);
+       tick();
+}
+
+static uint8_t in(void)
+{
+       uint8_t v = ao_gpio_get(AO_I2C_SDA_PORT, AO_I2C_SDA_PIN);
+       tick();
+       return v;
+}
+
+static void scl(uint8_t v)
+{
+       ao_gpio_set(AO_I2C_SCL_PORT, AO_I2C_SCL_PIN, v);
+       tick();
+}
+
+static void
+i2c_start(void)
+{
+       sda(0);
+       scl(0);
+}
+
+static bool
+ack(void)
+{
+       bool v;
+       int j;
+
+       sda(1);
+       scl(1);
+       v = false;
+       for (j = 0; j < 100; j++) {
+               if (in() == 0) {
+                       v = true;
+                       break;
+               }
+       }
+       scl(0);
+       sda(1);
+       ao_yield();
+       return v;
+}
+
+static bool
+send(uint8_t byte)
+{
+       uint8_t bit;
+
+       for (bit = 0; bit < 8; bit++) {
+               sda(byte>>7);
+               scl(1);
+               tick();
+               scl(0);
+               byte <<= 1;
+       }
+       return ack();
+}
+
+static uint8_t
+recv(void)
+{
+       uint8_t byte = 0;
+       uint8_t bit;
+
+       for (bit = 0; bit < 8; bit++) {
+               sda(1);
+               scl(1);
+               byte = (byte << 1) | in();
+               scl(0);
+       }
+       ack();
+       return byte;
+}
+
+static void
+stop(void)
+{
+       sda(0);
+       scl(1);
+       sda(1);
+}
+
+static void
+restart(void)
+{
+       sda(1);
+       scl(1);
+       sda(0);
+       scl(0);
+}
+
+static uint8_t
+ao_i2c_bit_mutex;
+
+void
+ao_i2c_bit_get(void)
+{
+       ao_mutex_get(&ao_i2c_bit_mutex);
+}
+
+void
+ao_i2c_bit_put(void)
+{
+       ao_mutex_put(&ao_i2c_bit_mutex);
+}
+
+bool
+ao_i2c_bit_start(uint8_t addr)
+{
+       i2c_start();
+       return send(addr);
+}
+
+bool
+ao_i2c_bit_restart(uint8_t addr)
+{
+       restart();
+       return send(addr);
+}
+
+void
+ao_i2c_bit_stop(void)
+{
+       stop();
+}
+
+void
+ao_i2c_bit_send(void *block, uint16_t len)
+{
+       uint8_t *b = block;
+       while (len--)
+               send(*b++);
+}
+
+void
+ao_i2c_bit_recv(void *block, uint16_t len)
+{
+       uint8_t *b = block;
+
+       while (len--)
+               *b++ = recv();
+}
+
+void
+ao_i2c_bit_init(void)
+{
+       ao_i2c_bit_set_pin(AO_I2C_SCL_PORT, AO_I2C_SCL_PIN);
+       ao_i2c_bit_set_pin(AO_I2C_SDA_PORT, AO_I2C_SDA_PIN);
+}
diff --git a/src/kernel/ao_i2c_bit.h b/src/kernel/ao_i2c_bit.h
new file mode 100644 (file)
index 0000000..bb9807f
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * 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>
+
+void
+ao_i2c_bit_get(void);
+
+void
+ao_i2c_bit_put(void);
+
+bool
+ao_i2c_bit_start(uint8_t addr);
+
+bool
+ao_i2c_bit_restart(uint8_t addr);
+
+void
+ao_i2c_bit_stop(void);
+
+void
+ao_i2c_bit_send(void *block, uint16_t len);
+
+void
+ao_i2c_bit_recv(void *block, uint16_t len);
+
+void
+ao_i2c_bit_init(void);
index 5c150abcefac88a4fb2dc4444d01d4b8a9c0e190..09ae7add80b683f469454cf721c4ad5f7c185410 100644 (file)
@@ -60,6 +60,7 @@ extern enum ao_flight_state ao_log_state;
 #define AO_LOG_FORMAT_MICROPEAK2       18      /* 2-byte baro values with header */
 #define AO_LOG_FORMAT_TELEMEGA_4       19      /* 32 byte typed telemega records with 32 bit gyro cal and Bmx160 */
 #define AO_LOG_FORMAT_EASYMOTOR                20      /* ? byte typed easymotor records with pressure sensor and adxl375 */
+#define AO_LOG_FORMAT_TELEMEGA_5       21      /* 32 byte typed telemega records with 32 bit gyro cal, mpu6000 and mmc5983 */
 #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 */
@@ -258,15 +259,30 @@ struct ao_log_mega {
                struct {
                        uint32_t        pres;           /* 4 */
                        uint32_t        temp;           /* 8 */
-                       int16_t         accel_x;        /* 12 */
-                       int16_t         accel_y;        /* 14 */
-                       int16_t         accel_z;        /* 16 */
-                       int16_t         gyro_x;         /* 18 */
-                       int16_t         gyro_y;         /* 20 */
-                       int16_t         gyro_z;         /* 22 */
-                       int16_t         mag_x;          /* 24 */
-                       int16_t         mag_z;          /* 26 */
-                       int16_t         mag_y;          /* 28 */
+                       union {
+                               struct {
+                                       int16_t         accel_along;    /* 12 */
+                                       int16_t         accel_across;   /* 14 */
+                                       int16_t         accel_through;  /* 16 */
+                                       int16_t         gyro_roll;      /* 18 */
+                                       int16_t         gyro_pitch;     /* 20 */
+                                       int16_t         gyro_yaw;       /* 22 */
+                                       int16_t         mag_along;      /* 24 */
+                                       int16_t         mag_across;     /* 26 */
+                                       int16_t         mag_through;    /* 28 */
+                               };
+                               struct {
+                                       int16_t         accel_x;        /* 12 */
+                                       int16_t         accel_y;        /* 14 */
+                                       int16_t         accel_z;        /* 16 */
+                                       int16_t         gyro_x;         /* 18 */
+                                       int16_t         gyro_y;         /* 20 */
+                                       int16_t         gyro_z;         /* 22 */
+                                       int16_t         mag_x;          /* 24 */
+                                       int16_t         mag_z;          /* 26 */
+                                       int16_t         mag_y;          /* 28 */
+                               };
+                       };
                        int16_t         accel;          /* 30 */
                } sensor;       /* 32 */
                /* AO_LOG_TEMP_VOLT */
@@ -533,7 +549,7 @@ struct ao_log_motor {
        } 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
+#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
 typedef struct ao_log_mega ao_log_type;
 #endif
 
index 85d2aa5c0ec80e2453d6b391f72f37527b21039e..ed1a4739136c75d6da17ede60ebd5949a20540d1 100644 (file)
@@ -75,46 +75,61 @@ ao_log(void)
                /* Write samples to EEPROM */
                while (ao_log_data_pos != ao_data_head) {
                        ao_log_data.tick = ao_data_ring[ao_log_data_pos].tick;
+                       volatile struct ao_data *d = &ao_data_ring[ao_log_data_pos];
                        if ((int16_t) (ao_log_data.tick - next_sensor) >= 0) {
                                ao_log_data.type = AO_LOG_SENSOR;
 #if HAS_MS5607
-                               ao_log_data.u.sensor.pres = ao_data_ring[ao_log_data_pos].ms5607_raw.pres;
-                               ao_log_data.u.sensor.temp = ao_data_ring[ao_log_data_pos].ms5607_raw.temp;
+                               ao_log_data.u.sensor.pres = d->ms5607_raw.pres;
+                               ao_log_data.u.sensor.temp = d->ms5607_raw.temp;
 #endif
 #if HAS_MPU6000
-                               ao_log_data.u.sensor.accel_x = ao_data_ring[ao_log_data_pos].mpu6000.accel_x;
-                               ao_log_data.u.sensor.accel_y = ao_data_ring[ao_log_data_pos].mpu6000.accel_y;
-                               ao_log_data.u.sensor.accel_z = ao_data_ring[ao_log_data_pos].mpu6000.accel_z;
-                               ao_log_data.u.sensor.gyro_x = ao_data_ring[ao_log_data_pos].mpu6000.gyro_x;
-                               ao_log_data.u.sensor.gyro_y = ao_data_ring[ao_log_data_pos].mpu6000.gyro_y;
-                               ao_log_data.u.sensor.gyro_z = ao_data_ring[ao_log_data_pos].mpu6000.gyro_z;
+#ifdef AO_LOG_NORMALIZED
+                               ao_log_data.u.sensor.accel_along = ao_data_along(d);
+                               ao_log_data.u.sensor.accel_across = ao_data_across(d);
+                               ao_log_data.u.sensor.accel_through = ao_data_through(d);
+                               ao_log_data.u.sensor.gyro_roll = ao_data_roll(d);
+                               ao_log_data.u.sensor.gyro_pitch = ao_data_pitch(d);
+                               ao_log_data.u.sensor.gyro_yaw = ao_data_yaw(d);
+#else
+                               ao_log_data.u.sensor.accel_x = d->mpu6000.accel_x;
+                               ao_log_data.u.sensor.accel_y = d->mpu6000.accel_y;
+                               ao_log_data.u.sensor.accel_z = d->mpu6000.accel_z;
+                               ao_log_data.u.sensor.gyro_x = d->mpu6000.gyro_x;
+                               ao_log_data.u.sensor.gyro_y = d->mpu6000.gyro_y;
+                               ao_log_data.u.sensor.gyro_z = d->mpu6000.gyro_z;
+#endif
 #endif
 #if HAS_HMC5883
-                               ao_log_data.u.sensor.mag_x = ao_data_ring[ao_log_data_pos].hmc5883.x;
-                               ao_log_data.u.sensor.mag_z = ao_data_ring[ao_log_data_pos].hmc5883.z;
-                               ao_log_data.u.sensor.mag_y = ao_data_ring[ao_log_data_pos].hmc5883.y;
+                               ao_log_data.u.sensor.mag_x = d->hmc5883.x;
+                               ao_log_data.u.sensor.mag_z = d->hmc5883.z;
+                               ao_log_data.u.sensor.mag_y = d->hmc5883.y;
+#endif
+#ifdef HAS_MMC5983
+                               ao_log_data.u.sensor.mag_along = ao_data_mag_along(d);
+                               ao_log_data.u.sensor.mag_across = ao_data_mag_across(d);
+                               ao_log_data.u.sensor.mag_through = ao_data_mag_through(d);
 #endif
 #if HAS_MPU9250
-                               ao_log_data.u.sensor.accel_x = ao_data_ring[ao_log_data_pos].mpu9250.accel_x;
-                               ao_log_data.u.sensor.accel_y = ao_data_ring[ao_log_data_pos].mpu9250.accel_y;
-                               ao_log_data.u.sensor.accel_z = ao_data_ring[ao_log_data_pos].mpu9250.accel_z;
-                               ao_log_data.u.sensor.gyro_x = ao_data_ring[ao_log_data_pos].mpu9250.gyro_x;
-                               ao_log_data.u.sensor.gyro_y = ao_data_ring[ao_log_data_pos].mpu9250.gyro_y;
-                               ao_log_data.u.sensor.gyro_z = ao_data_ring[ao_log_data_pos].mpu9250.gyro_z;
-                               ao_log_data.u.sensor.mag_x = ao_data_ring[ao_log_data_pos].mpu9250.mag_x;
-                               ao_log_data.u.sensor.mag_z = ao_data_ring[ao_log_data_pos].mpu9250.mag_z;
-                               ao_log_data.u.sensor.mag_y = ao_data_ring[ao_log_data_pos].mpu9250.mag_y;
+                               ao_log_data.u.sensor.accel_x = d->mpu9250.accel_x;
+                               ao_log_data.u.sensor.accel_y = d->mpu9250.accel_y;
+                               ao_log_data.u.sensor.accel_z = d->mpu9250.accel_z;
+                               ao_log_data.u.sensor.gyro_x = d->mpu9250.gyro_x;
+                               ao_log_data.u.sensor.gyro_y = d->mpu9250.gyro_y;
+                               ao_log_data.u.sensor.gyro_z = d->mpu9250.gyro_z;
+                               ao_log_data.u.sensor.mag_x = d->mpu9250.mag_x;
+                               ao_log_data.u.sensor.mag_z = d->mpu9250.mag_z;
+                               ao_log_data.u.sensor.mag_y = d->mpu9250.mag_y;
 #endif
 #if HAS_BMX160
-                               ao_log_data.u.sensor.accel_x = ao_data_ring[ao_log_data_pos].bmx160.acc_x;
-                               ao_log_data.u.sensor.accel_y = ao_data_ring[ao_log_data_pos].bmx160.acc_y;
-                               ao_log_data.u.sensor.accel_z = ao_data_ring[ao_log_data_pos].bmx160.acc_z;
-                               ao_log_data.u.sensor.gyro_x = ao_data_ring[ao_log_data_pos].bmx160.gyr_x;
-                               ao_log_data.u.sensor.gyro_y = ao_data_ring[ao_log_data_pos].bmx160.gyr_y;
-                               ao_log_data.u.sensor.gyro_z = ao_data_ring[ao_log_data_pos].bmx160.gyr_z;
-                               ao_log_data.u.sensor.mag_x = ao_data_ring[ao_log_data_pos].bmx160.mag_x;
-                               ao_log_data.u.sensor.mag_z = ao_data_ring[ao_log_data_pos].bmx160.mag_z;
-                               ao_log_data.u.sensor.mag_y = ao_data_ring[ao_log_data_pos].bmx160.mag_y;
+                               ao_log_data.u.sensor.accel_x = d->bmx160.acc_x;
+                               ao_log_data.u.sensor.accel_y = d->bmx160.acc_y;
+                               ao_log_data.u.sensor.accel_z = d->bmx160.acc_z;
+                               ao_log_data.u.sensor.gyro_x = d->bmx160.gyr_x;
+                               ao_log_data.u.sensor.gyro_y = d->bmx160.gyr_y;
+                               ao_log_data.u.sensor.gyro_z = d->bmx160.gyr_z;
+                               ao_log_data.u.sensor.mag_x = d->bmx160.mag_x;
+                               ao_log_data.u.sensor.mag_z = d->bmx160.mag_z;
+                               ao_log_data.u.sensor.mag_y = d->bmx160.mag_y;
 #endif
                                ao_log_data.u.sensor.accel = ao_data_accel(&ao_data_ring[ao_log_data_pos]);
                                ao_log_write(&ao_log_data);
@@ -125,11 +140,11 @@ ao_log(void)
                        }
                        if ((int16_t) (ao_log_data.tick - next_other) >= 0) {
                                ao_log_data.type = AO_LOG_TEMP_VOLT;
-                               ao_log_data.u.volt.v_batt = ao_data_ring[ao_log_data_pos].adc.v_batt;
-                               ao_log_data.u.volt.v_pbatt = ao_data_ring[ao_log_data_pos].adc.v_pbatt;
+                               ao_log_data.u.volt.v_batt = d->adc.v_batt;
+                               ao_log_data.u.volt.v_pbatt = d->adc.v_pbatt;
                                ao_log_data.u.volt.n_sense = AO_ADC_NUM_SENSE;
                                for (i = 0; i < AO_ADC_NUM_SENSE; i++)
-                                       ao_log_data.u.volt.sense[i] = ao_data_ring[ao_log_data_pos].adc.sense[i];
+                                       ao_log_data.u.volt.sense[i] = d->adc.sense[i];
                                ao_log_data.u.volt.pyro = ao_pyro_fired;
                                ao_log_write(&ao_log_data);
                                next_other = ao_log_data.tick + AO_OTHER_INTERVAL;
index 80e1980ebf28b8204b10be3d2f5090017f2db43b..07a8278d560a85f4d913ccf7a735645131d31cc6 100644 (file)
@@ -161,14 +161,14 @@ ao_pyro_ready(struct ao_pyro *pyro)
 #endif
 
                case ao_pyro_time_less:
-                       if ((int16_t) (ao_time() - ao_launch_tick) <= pyro->time_less)
+                       if ((int32_t) (ao_time() - ao_launch_tick) <= pyro->time_less)
                                continue;
-                       DBG("time %d > %d\n", (int16_t)(ao_time() - ao_launch_tick), pyro->time_less);
+                       DBG("time %d > %d\n", (int32_t)(ao_time() - ao_launch_tick), pyro->time_less);
                        break;
                case ao_pyro_time_greater:
-                       if ((int16_t) (ao_time() - ao_launch_tick) >= pyro->time_greater)
+                       if ((int32_t) (ao_time() - ao_launch_tick) >= pyro->time_greater)
                                continue;
-                       DBG("time %d < %d\n", (int16_t)(ao_time() - ao_launch_tick), pyro->time_greater);
+                       DBG("time %d < %d\n", (int32_t)(ao_time() - ao_launch_tick), pyro->time_greater);
                        break;
 
                case ao_pyro_ascending:
@@ -316,7 +316,7 @@ ao_pyro_check(void)
                                continue;
                        }
 
-                       if ((int16_t) (ao_time() - pyro->delay_done) < 0)
+                       if ((int32_t) (ao_time() - pyro->delay_done) < 0)
                                continue;
                }
 
@@ -431,6 +431,55 @@ ao_pyro_help(void)
 }
 #endif
 
+static int32_t
+ao_pyro_get(void *base, uint8_t offset, uint8_t size)
+{
+       int32_t value;
+       switch (size) {
+       case 8:
+               value = *((uint8_t *) ((char *) base + offset));
+               break;
+       case 16:
+       default:
+               value = *((int16_t *) (void *) ((char *) base + offset));
+               break;
+       case 32:
+               value = *((int32_t *) (void *) ((char *) base + offset));
+               break;
+       }
+       return value;
+}
+
+static bool
+ao_pyro_put(void *base, uint8_t offset, uint8_t size, int32_t value)
+{
+       switch (size) {
+       case 8:
+               if (value < 0)
+                       return false;
+               *((uint8_t *) ((char *) base + offset)) = value;
+               break;
+       case 16:
+       default:
+               *((int16_t *) (void *) ((char *) base + offset)) = value;
+               break;
+       case 32:
+               *((int32_t *) (void *) ((char *) base + offset)) = value;
+               break;
+       }
+       return true;
+}
+
+static uint8_t
+ao_pyro_size(enum ao_pyro_flag flag)
+{
+       if (flag & AO_PYRO_8_BIT_VALUE)
+               return 8;
+       if (flag & AO_PYRO_32_BIT_VALUE)
+               return 32;
+       return 16;
+}
+
 void
 ao_pyro_show(void)
 {
@@ -451,13 +500,10 @@ ao_pyro_show(void)
                                continue;
                        ao_pyro_print_name(v);
                        if (ao_pyro_values[v].offset != NO_VALUE) {
-                               int16_t value;
-
-                               if (ao_pyro_values[v].flag & AO_PYRO_8_BIT_VALUE)
-                                       value = *((uint8_t *) ((char *) pyro + ao_pyro_values[v].offset));
-                               else
-                                       value = *((int16_t *) (void *) ((char *) pyro + ao_pyro_values[v].offset));
-                               printf ("%6d ", value);
+                               printf ("%6ld ",
+                                       (long) ao_pyro_get(pyro,
+                                                          ao_pyro_values[v].offset,
+                                                          ao_pyro_size(ao_pyro_values[v].flag)));
                        } else {
                                printf ("       ");
                        }
@@ -516,7 +562,7 @@ ao_pyro_set(void)
                }
                pyro_tmp.flags |= ao_pyro_values[v].flag;
                if (ao_pyro_values[v].offset != NO_VALUE) {
-                       int16_t r = 1;
+                       int32_t r = 1;
                        ao_cmd_white();
                        if (ao_cmd_lex_c == '-') {
                                r = -1;
@@ -525,14 +571,11 @@ ao_pyro_set(void)
                        r *= ao_cmd_decimal();
                        if (ao_cmd_status != ao_cmd_success)
                                return;
-                       if (ao_pyro_values[v].flag & AO_PYRO_8_BIT_VALUE) {
-                               if (r < 0) {
-                                       ao_cmd_status = ao_cmd_syntax_error;
-                                       return;
-                               }
-                               *((uint8_t *) ((char *) &pyro_tmp + ao_pyro_values[v].offset)) = r;
-                       } else {
-                               *((int16_t *) (void *) ((char *) &pyro_tmp + ao_pyro_values[v].offset)) = r;
+                       if (!ao_pyro_put(&pyro_tmp, ao_pyro_values[v].offset,
+                                        ao_pyro_size(ao_pyro_values[v].flag), r))
+                       {
+                               ao_cmd_status = ao_cmd_syntax_error;
+                               return;
                        }
                }
        }
@@ -552,6 +595,88 @@ ao_pyro_manual(uint8_t p)
        ao_pyro_pins_fire(1 << p);
 }
 
+struct ao_pyro_old_values {
+       enum ao_pyro_flag       flag;
+       uint8_t                 offset;
+       uint8_t                 size;
+};
+
+static const struct ao_pyro_old_values ao_pyro_1_24_values[] = {
+       { .flag = ao_pyro_accel_less, .offset = offsetof(struct ao_pyro_1_24, accel_less), 16 },
+       { .flag = ao_pyro_accel_greater, .offset = offsetof(struct ao_pyro_1_24, accel_greater), 16 },
+       { .flag = ao_pyro_speed_less, .offset = offsetof(struct ao_pyro_1_24, speed_less), 16 },
+       { .flag = ao_pyro_speed_greater, .offset = offsetof(struct ao_pyro_1_24, speed_greater), 16 },
+       { .flag = ao_pyro_height_less, .offset = offsetof(struct ao_pyro_1_24, height_less), 16 },
+       { .flag = ao_pyro_height_greater, .offset = offsetof(struct ao_pyro_1_24, height_greater), 16 },
+       { .flag = ao_pyro_orient_less, .offset = offsetof(struct ao_pyro_1_24, orient_less), 16 },
+       { .flag = ao_pyro_orient_greater, .offset = offsetof(struct ao_pyro_1_24, orient_greater), 16 },
+       { .flag = ao_pyro_time_less, .offset = offsetof(struct ao_pyro_1_24, time_less), 16 },
+       { .flag = ao_pyro_time_greater, .offset = offsetof(struct ao_pyro_1_24, time_greater), 16 },
+       { .flag = ao_pyro_delay, .offset = offsetof(struct ao_pyro_1_24, delay), 16 },
+       { .flag = ao_pyro_state_less, .offset = offsetof(struct ao_pyro_1_24, state_less), 8 },
+       { .flag = ao_pyro_state_greater_or_equal, .offset = offsetof(struct ao_pyro_1_24, state_greater_or_equal), 8 },
+       { .flag = ao_pyro_after_motor, .offset = offsetof(struct ao_pyro_1_24, motor), 16 },
+};
+
+#define NUM_PYRO_1_24_VALUES (sizeof ao_pyro_1_24_values / sizeof ao_pyro_1_24_values[0])
+
+static int32_t
+ao_pyro_get_1_24(void *base, enum ao_pyro_flag flag)
+{
+       unsigned v;
+
+       for (v = 0; v < NUM_PYRO_1_24_VALUES; v++) {
+               if (ao_pyro_1_24_values[v].flag == flag)
+                       return ao_pyro_get(base, ao_pyro_1_24_values[v].offset, ao_pyro_1_24_values[v].size);
+       }
+       return 0;
+}
+
+void
+ao_pyro_update_version(void)
+{
+       if (ao_config.minor <= 24)
+       {
+
+               /* First, move all of the config bits that follow the pyro data */
+
+               char    *pyro_base = (void *) &ao_config.pyro;
+               char    *after_pyro_new = pyro_base + AO_PYRO_NUM * sizeof (struct ao_pyro);
+               char    *after_pyro_1_24 = pyro_base + AO_PYRO_NUM * sizeof (struct ao_pyro_1_24);
+               char    *config_end = (void *) (&ao_config + 1);
+               size_t  to_move = config_end - after_pyro_new;
+
+               memmove(after_pyro_new, after_pyro_1_24, to_move);
+
+               /* Now, adjust all of the pyro entries */
+
+               struct ao_pyro          *pyro_new = ao_config.pyro;
+               struct ao_pyro_1_24     *pyro_old = (void *) ao_config.pyro;
+
+               int p = AO_PYRO_NUM;
+
+               /* New struct is larger than the old, so start at the
+                * last one and work towards the first
+                */
+               while (p-- > 0) {
+                       unsigned v;
+                       int32_t value;
+                       struct ao_pyro  tmp;
+
+                       memset(&tmp, '\0', sizeof(tmp));
+                       tmp.flags = pyro_old[p].flags;
+
+                       for (v = 0; v < NUM_PYRO_VALUES; v++)
+                       {
+                               value = ao_pyro_get_1_24(&pyro_old[v], ao_pyro_values[v].flag);
+                               ao_pyro_put(&tmp, ao_pyro_values[v].offset,
+                                           ao_pyro_size(ao_pyro_values[v].flag), value);
+                       }
+                       memcpy(&pyro_new[p], &tmp, sizeof(tmp));
+               }
+       }
+}
+
 void
 ao_pyro_init(void)
 {
index 3ab5af3bf8972d2f2e1ae2f79e482cc96b272e8e..4a8c3aabb1857c8adb4d7727f00bc4a5f0d4f407 100644 (file)
@@ -52,7 +52,7 @@ enum ao_pyro_flag {
 #endif
        ;
 
-struct ao_pyro {
+struct ao_pyro_1_24 {
        enum ao_pyro_flag       flags;
        int16_t                 accel_less, accel_greater;
        int16_t                 speed_less, speed_greater;
@@ -66,7 +66,22 @@ struct ao_pyro {
        uint8_t                 _unused;        /* was 'fired' */
 };
 
+struct ao_pyro {
+       enum ao_pyro_flag       flags;
+       int16_t                 accel_less, accel_greater;
+       int16_t                 speed_less, speed_greater;
+       int16_t                 height_less, height_greater;
+       int16_t                 orient_less, orient_greater;
+       int32_t                 time_less, time_greater;
+       int32_t                 delay;
+       uint8_t                 state_less, state_greater_or_equal;
+       int16_t                 motor;
+       int32_t                 delay_done;
+       uint8_t                 _unused;        /* was 'fired' */
+};
+
 #define AO_PYRO_8_BIT_VALUE    (ao_pyro_state_less|ao_pyro_state_greater_or_equal)
+#define AO_PYRO_32_BIT_VALUE   (ao_pyro_time_less|ao_pyro_time_greater|ao_pyro_delay)
 
 extern uint8_t ao_pyro_wakeup;
 
@@ -81,6 +96,9 @@ ao_pyro_show(void);
 void
 ao_pyro_init(void);
 
+void
+ao_pyro_update_version(void);
+
 void
 ao_pyro_manual(uint8_t p);
 
index 2c77c36920ed5755046e158c9e32f4e92e2d9aae..9ddbfd8eace7453a6f359267a866cf0972b40c61 100644 (file)
@@ -252,11 +252,13 @@ ao_sample_preflight_set(void)
         */
        ao_quaternion_vectors_to_rotation(&ao_rotation, &up, &orient);
 #if HAS_FLIGHT_DEBUG
-       if (ao_orient_test)
+       if (ao_orient_test) {
                printf("\n\treset across %d through %d along %d\n",
                       (ao_ground_accel_across - ao_config.accel_zero_across),
                       (ao_ground_accel_through - ao_config.accel_zero_through),
                       (ao_ground_accel_along - ao_config.accel_zero_along));
+               fflush(stdout);
+       }
 #endif
 
        ao_sample_compute_orient();
@@ -266,7 +268,6 @@ ao_sample_preflight_set(void)
 }
 
 #if HAS_GYRO
-
 #define TIME_DIV       200.0f
 
 static void
@@ -295,6 +296,7 @@ ao_sample_rotate(void)
                        (int) (y * 1000),
                        (int) (z * 1000),
                        ao_sample_orient);
+               fflush(stdout);
        }
 #endif
        ao_sample_compute_orient();
index a42c97fbb2ecd085c87ce6b59ace4aaae788aa1c..c578c57cd920b3bc6ea5e4af4c1af8520cfd8283 100644 (file)
@@ -188,4 +188,20 @@ ao_flushc(FILE *ignore)
 
 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
+#define STDIO_ALIAS(x) FILE *const x = &__stdio;
+#endif
+
+FILE *const stdin = &__stdio;
+STDIO_ALIAS(stdout);
+STDIO_ALIAS(stderr);
+
+#else
+
 FILE *const __iob[3] = { &__stdio, &__stdio, &__stdio };
+
+#endif
index c2b2eb5a1bad0569d909481c21caf20773269457..3074e4791dfc4c89e305ee924b4cc0ca00591d73 100644 (file)
@@ -136,9 +136,41 @@ ao_send_sensor(void)
 static void
 ao_send_mega_sensor(void)
 {
-               struct ao_data *packet = (struct ao_data *) &ao_data_ring[ao_data_ring_prev(ao_sample_data)];
+       struct ao_data *packet = (struct ao_data *) &ao_data_ring[ao_data_ring_prev(ao_sample_data)];
 
        telemetry.generic.tick = packet->tick;
+#if AO_LOG_NORMALIZED
+#if AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMEGA_5
+       telemetry.generic.type = AO_TELEMETRY_MEGA_NORM_MPU6000_MMC5983;
+#else
+#error unknown normalized log type
+#endif
+
+#if HAS_GYRO
+       telemetry.mega_norm.orient = ao_sample_orient;
+#endif
+       telemetry.mega_norm.accel = ao_data_accel(packet);
+       telemetry.mega_norm.pres = ao_data_pres(packet);
+       telemetry.mega_norm.temp = ao_data_temp(packet);
+
+#if HAS_MPU6000
+       telemetry.mega_norm.accel_along = ao_data_along(packet);
+       telemetry.mega_norm.accel_across = ao_data_across(packet);
+       telemetry.mega_norm.accel_through = ao_data_through(packet);
+
+       telemetry.mega_norm.gyro_roll = ao_data_roll(packet);
+       telemetry.mega_norm.gyro_pitch = ao_data_pitch(packet);
+       telemetry.mega_norm.gyro_yaw = ao_data_yaw(packet);
+#endif
+
+#if HAS_MMC5983
+       telemetry.mega_norm.mag_along = ao_data_mag_along(packet);
+       telemetry.mega_norm.mag_across = ao_data_mag_across(packet);
+       telemetry.mega_norm.mag_through = ao_data_mag_through(packet);
+#endif
+
+#else
+
 #if HAS_BMX160
        telemetry.generic.type = AO_TELEMETRY_MEGA_SENSOR_BMX160;
 #else
@@ -199,7 +231,7 @@ ao_send_mega_sensor(void)
        telemetry.mega_sensor.mag_z = packet->bmx160.mag_z;
        telemetry.mega_sensor.mag_y = packet->bmx160.mag_y;
 #endif
-
+#endif
        ao_telemetry_send();
 }
 
index c7aebe599a317d86de65b5d8675f4694ea43cca8..b718085f8e11eb83d295322c135416bc785ec852 100644 (file)
@@ -297,6 +297,33 @@ struct ao_telemetry_mini {
        /* 32 */
 };
 
+#define AO_TELEMETRY_MEGA_NORM_MPU6000_MMC5983 0x13
+
+struct ao_telemetry_mega_norm {
+       uint16_t        serial;         /*  0 */
+       uint16_t        tick;           /*  2 */
+       uint8_t         type;           /*  4 */
+
+       uint8_t         orient;         /*  5 angle from vertical */
+       int16_t         accel;          /*  6 Z axis */
+
+       int32_t         pres;           /*  8 Pa * 10 */
+       int16_t         temp;           /* 12 °C * 100 */
+
+       int16_t         accel_along;    /* 14 */
+       int16_t         accel_across;   /* 16 */
+       int16_t         accel_through;  /* 18 */
+
+       int16_t         gyro_roll;      /* 20 */
+       int16_t         gyro_pitch;     /* 22 */
+       int16_t         gyro_yaw;       /* 24 */
+
+       int16_t         mag_along;      /* 26 */
+       int16_t         mag_across;     /* 28 */
+       int16_t         mag_through;    /* 30 */
+       /* 32 */
+};
+
 /* #define AO_SEND_ALL_BARO */
 
 #define AO_TELEMETRY_BARO              0x80
@@ -334,6 +361,7 @@ union ao_telemetry_all {
        struct ao_telemetry_metrum_data         metrum_data;
        struct ao_telemetry_mini                mini;
        struct ao_telemetry_baro                baro;
+       struct ao_telemetry_mega_norm           mega_norm;
 };
 
 typedef char ao_check_telemetry_size[sizeof(union ao_telemetry_all) == 32 ? 1 : -1];
index 82f456522c2c0482c8fb62e44a3f4227b2fb1ebc..1cf35dad2e6846fc35d7cfa45846c4b475d7de88 100644 (file)
@@ -868,7 +868,7 @@ struct lpc_usb {
        vuint32_t       introuting;
        uint32_t        r30;
        vuint32_t       eptoggle;
-} lpc_usb;
+};
 
 extern struct lpc_usb lpc_usb;
 #define lpc_usb (*(struct lpc_usb *) 0x40080000)
index 5a21d6582a0e0fd24b1f75d07c2329a4d2059433..efab12c315dd5f1cbbd9bfa8e605fc02d3c454bf 100644 (file)
@@ -23,7 +23,6 @@
 #include <ao_report_micro.h>
 #include <ao_log_micro.h>
 
-uint32_t       pa;
 alt_t          ground_alt, max_alt;
 alt_t          ao_max_height;
 
index 37fad6d1638b5e59d0bfd9c8712c93986ee0c492..776811586fdfb467f91078289ee2bb88991248e9 100644 (file)
@@ -35,7 +35,7 @@ IDPRODUCT=0x000a
 
 CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS)
 
-LDFLAGS=-nostartfiles $(CFLAGS) -L$(TOPDIR)/stm -Taltos-loader.ld -n
+LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stm -Taltos-loader.ld -n
 
 PROGNAME=$(HARDWARE)-altos-flash
 PROG=$(PROGNAME)-$(VERSION).elf
index d6cbe4d4921a3be1d6257146860a16e63206e3be..2ed89f7e3c4ee56b5fdebb37329c4f6fa815bf3c 100644 (file)
@@ -4,4 +4,4 @@ endif
 
 include $(TOPDIR)/stm/Makefile-stm.defs
 
-LDFLAGS=-nostartfiles $(CFLAGS) -L$(TOPDIR)/stm -Taltos.ld -n
+LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stm -Taltos.ld -n
index 083f7a2beb7ad394e57c200d9b1f13dd2ff5f020..d2cc11201a7e7c550d36985d9ef0df871d61764e 100644 (file)
@@ -182,8 +182,8 @@ ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t s
                ao_spi_put(bus);                \
        } while (0)
 
-#define ao_spi_get_bit(reg,bit,bus,speed) ao_spi_get_mask(reg,(1<<bit),bus,speed)
-#define ao_spi_put_bit(reg,bit,bus) ao_spi_put_mask(reg,(1<<bit),bus)
+#define ao_spi_get_bit(reg,bit,bus,speed) ao_spi_get_mask(reg,1<<(bit),bus,speed)
+#define ao_spi_put_bit(reg,bit,bus) ao_spi_put_mask(reg,1<<(bit),bus)
 
 #define ao_enable_port(port) do {                                      \
                if ((port) == &stm_gpioa)                               \
@@ -239,7 +239,7 @@ ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t s
 #define AO_OUTPUT_PUSH_PULL    STM_OTYPER_PUSH_PULL
 #define AO_OUTPUT_OPEN_DRAIN   STM_OTYPER_OPEN_DRAIN
 
-#define ao_gpio_set_output_mode(port,bit,mode) \
+#define ao_gpio_set_output_mode(port,pin,mode) \
        stm_otyper_set(port, pin, mode)
 
 #define ao_gpio_set_mode(port,bit,mode) do {                           \
index 9a0591876348892e85dfddb6efcac07b8e68dc01..0d6e450f581b1911e4ae3e3089154c5348ef1577 100644 (file)
@@ -136,6 +136,7 @@ isr(tim7)
 extern char __stack[];
 void _start(void) __attribute__((__noreturn__));
 void main(void) __attribute__((__noreturn__));
+void ao_setup(void) __attribute__((constructor));
 
 /* This must be exactly 256 bytes long so that the configuration data
  * gets loaded at the right place
@@ -201,16 +202,7 @@ const void * const __interrupt_vector[64] = {
        i(0xf0, tim7),
 };
 
-extern char __data_source[];
-extern char __data_start[];
-extern char __data_size[];
-extern char __bss_start[];
-extern char __bss_size[];
-
-void _start(void) {
-       memcpy(__data_start, __data_source, (uintptr_t) __data_size);
-       memset(__bss_start, '\0', (uintptr_t) __bss_size);
-
+void __attribute__((constructor)) ao_setup(void) {
 #ifdef AO_BOOT_CHAIN
        if (ao_boot_check_chain()) {
 #ifdef AO_BOOT_PIN
@@ -223,5 +215,4 @@ void _start(void) {
 #endif
        /* Set interrupt vector table offset */
        stm_nvic.vto = (uint32_t) &__interrupt_vector;
-       main();
 }
diff --git a/src/telemega-v5.0/Makefile b/src/telemega-v5.0/Makefile
new file mode 100644 (file)
index 0000000..eeadb07
--- /dev/null
@@ -0,0 +1,133 @@
+#
+# 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_mpu6000.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
+
+# Bit-bang MMC5983 chip needs this
+#      ao_i2c_bit.c
+
+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_mpu6000.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-v5.0
+PRODUCT_DEF=-DTELEMEGA
+IDPRODUCT=0x0023
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF)
+
+PROGNAME=telemega-v5.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:
diff --git a/src/telemega-v5.0/ao_pins.h b/src/telemega-v5.0/ao_pins.h
new file mode 100644 (file)
index 0000000..07b3daa
--- /dev/null
@@ -0,0 +1,483 @@
+/*
+ * 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_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_5
+#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 AO_BEEP_MID_DEFAULT    179             /* 2100 Hz */
+#define AO_BEEP_MAKE_LOW(m)    ((m) * 197/179) /* 1900 Hz */
+#define AO_BEEP_MAKE_HIGH(m)   ((m) * 163/179) /* 2300 Hz */
+#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: %5u 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 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
+
+/*
+ * 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
+
+
+/*
+ *
+ * If the board is laying component side up with
+ * the antenna (nose) pointing north
+ *
+ * +along      north   +roll   left up
+ * +across     west    +pitch  nose down
+ * +through    up      +yaw    left turn
+ */
+
+/*
+ * mpu6000
+ *
+ *     pin 1 NW corner of chip
+ *
+ *     +along          +Y      +roll   +Y
+ *     +across         -X      +pitch  -X
+ *     +through        +Z      +yaw    +Z
+ *
+ */
+
+#define HAS_MPU6000            1
+#define AO_MPU6000_INT_PORT    (&stm_gpioe)
+#define AO_MPU6000_INT_PIN     0
+#define AO_MPU6000_SPI_BUS     AO_SPI_1_PE13_PE14_PE15
+#define AO_MPU6000_SPI_CS_PORT (&stm_gpioc)
+#define AO_MPU6000_SPI_CS_PIN  13
+#define HAS_IMU                        1
+
+#define ao_mpu6000_along(m)    ((m)->accel_y)
+#define ao_mpu6000_across(m)   (-(m)->accel_x)
+#define ao_mpu6000_through(m)  ((m)->accel_z)
+
+#define ao_mpu6000_roll(m)     ((m)->gyro_y)
+#define ao_mpu6000_pitch(m)    (-(m)->gyro_x)
+#define ao_mpu6000_yaw(m)      ((m)->gyro_z)
+
+#define ao_data_along(packet)  ao_mpu6000_along(&(packet)->mpu6000)
+#define ao_data_across(packet) ao_mpu6000_across(&(packet)->mpu6000)
+#define ao_data_through(packet)        ao_mpu6000_through(&(packet)->mpu6000)
+
+#define ao_data_roll(packet)   ao_mpu6000_roll(&(packet)->mpu6000)
+#define ao_data_pitch(packet)  ao_mpu6000_pitch(&(packet)->mpu6000)
+#define ao_data_yaw(packet)    ao_mpu6000_yaw(&(packet)->mpu6000)
+
+/* Bit-banging i2c */
+#define AO_I2C_SCL_PORT                (&stm_gpiod)
+#define AO_I2C_SCL_PIN         1
+#define AO_I2C_SDA_PORT                (&stm_gpiod)
+#define AO_I2C_SDA_PIN         4
+
+/*
+ * 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_ */
diff --git a/src/telemega-v5.0/ao_telemega.c b/src/telemega-v5.0/ao_telemega.c
new file mode 100644 (file)
index 0000000..4e85c39
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * 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_mpu6000.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_mpu6000_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;
+}
diff --git a/src/telemega-v5.0/flash-loader/Makefile b/src/telemega-v5.0/flash-loader/Makefile
new file mode 100644 (file)
index 0000000..50cc083
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=telemega-v5.0
+include $(TOPDIR)/stm/Makefile-flash.defs
diff --git a/src/telemega-v5.0/flash-loader/ao_pins.h b/src/telemega-v5.0/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..46ba162
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * 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_ */
diff --git a/src/telemega-v5.0/notes b/src/telemega-v5.0/notes
new file mode 100644 (file)
index 0000000..c4ccd66
--- /dev/null
@@ -0,0 +1,5 @@
+Beeper moved to tim11
+servo lines swapped
+ADC inputs scrambled
+pyro circuits scrambled
+mag sensor on SPI2 pd1/pd3/pd4
index 26e5dfb82d79ca1b7bcc4cc2a0f5e3c55268fd51..7ab0749cfa01162f0389f01c7f82bab851eb0e9e 100644 (file)
@@ -43,7 +43,7 @@ JAR=telegps.jar
 FATJAR=telegps-fat.jar
 
 if MULTI_ARCH
-LIBALTOS_LINUX=libaltos32.so libaltos64.so
+LIBALTOS_LINUX=libaltos_i686.so libaltos_amd64.so libaltos_aarch64.so libaltos_armel.so libaltos_armhf.so
 else
 LIBALTOS_LINUX=libaltos.so
 endif
@@ -244,11 +244,23 @@ libaltos.so: build-libaltos
        -rm -f "$@"
        $(LN_S) ../libaltos/.libs/"$@" .
 
-libaltos32.so: build-libaltos
+libaltos_i686.so: build-libaltos
        -rm -f "$@"
        $(LN_S) ../libaltos/.libs/"$@" .
 
-libaltos64.so: build-libaltos
+libaltos_amd64.so: build-libaltos
+       -rm -f "$@"
+       $(LN_S) ../libaltos/.libs/"$@" .
+
+libaltos_aarch64.so: build-libaltos
+       -rm -f "$@"
+       $(LN_S) ../libaltos/.libs/"$@" .
+
+libaltos_armel.so: build-libaltos
+       -rm -f "$@"
+       $(LN_S) ../libaltos/.libs/"$@" .
+
+libaltos_armhf.so: build-libaltos
        -rm -f "$@"
        $(LN_S) ../libaltos/.libs/"$@" .
 
@@ -256,31 +268,16 @@ libaltos.dylib:
        -rm -f "$@"
        $(LN_S) ../libaltos/"$@" .
 
-altos.dll: ../libaltos/altos.dll
+altos.dll: build-libaltos
        -rm -f "$@"
        $(LN_S) ../libaltos/"$@" .
 
-altos64.dll: ../libaltos/altos64.dll
+altos64.dll: build-libaltos
        -rm -f "$@"
        $(LN_S) ../libaltos/"$@" .
 
-../libaltos/.libs/libaltos64.so: ../libaltos/.libs/libaltos32.so
-
-../libaltos/.libs/libaltos32.so: build-libaltos
-
-../libaltos/.libs/libaltos.so: build-libaltos
-
-../libaltos/altos.dll: build-altos-dll
-
-../libaltos/altos64.dll: build-altos64-dll
-
 build-libaltos:
-       +cd ../libaltos && make libaltos.la
-build-altos-dll:
-       +cd ../libaltos && make altos.dll
-
-build-altos64-dll:
-       +cd ../libaltos && make altos64.dll
+       +cd ../libaltos && make
 
 $(ALTOSLIB_CLASS):
        -rm -f "$@"