Merge branch 'branch-1.5' into debian
authorBdale Garbee <bdale@gag.com>
Wed, 10 Sep 2014 05:28:39 +0000 (23:28 -0600)
committerBdale Garbee <bdale@gag.com>
Wed, 10 Sep 2014 05:28:39 +0000 (23:28 -0600)
Conflicts:
ChangeLog
Releasing
altosui/Instdrv/NSIS/Includes/java.nsh
altosui/altos-windows.nsi.in
configure.ac
doc/Makefile
doc/altusmetrum.xsl
micropeak/micropeak-windows.nsi.in
telegps/telegps-windows.nsi.in

436 files changed:
ChangeLog
Makefile.am
Releasing
altosdroid/Notebook
altosdroid/res/layout/device_list.xml
altosdroid/res/menu/option_menu.xml
altosdroid/res/values/strings.xml
altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java [new file with mode: 0644]
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java
altosdroid/src/org/altusmetrum/AltosDroid/GoNoGoLights.java
altosdroid/src/org/altusmetrum/AltosDroid/TabAscent.java
altosdroid/src/org/altusmetrum/AltosDroid/TabDescent.java
altosdroid/src/org/altusmetrum/AltosDroid/TabLanded.java
altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java
altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java
altosdroid/src/org/altusmetrum/AltosDroid/TabsAdapter.java
altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java
altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java
altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java
altosdroid/src/org/altusmetrum/AltosDroid/TelemetryState.java [new file with mode: 0644]
altoslib/AltosAccel.java
altoslib/AltosCRCException.java
altoslib/AltosCSV.java
altoslib/AltosCompanion.java
altoslib/AltosConfigData.java
altoslib/AltosConfigDataException.java
altoslib/AltosConfigValues.java
altoslib/AltosConvert.java
altoslib/AltosDebug.java
altoslib/AltosDistance.java
altoslib/AltosEeprom.java
altoslib/AltosEepromChunk.java
altoslib/AltosEepromDownload.java
altoslib/AltosEepromFile.java
altoslib/AltosEepromGPS.java
altoslib/AltosEepromHeader.java
altoslib/AltosEepromIterable.java
altoslib/AltosEepromList.java
altoslib/AltosEepromLog.java
altoslib/AltosEepromMega.java
altoslib/AltosEepromMetrum2.java
altoslib/AltosEepromMini.java
altoslib/AltosEepromMonitor.java
altoslib/AltosEepromTM.java
altoslib/AltosEepromTm.java
altoslib/AltosFile.java
altoslib/AltosFlash.java
altoslib/AltosFlashListener.java
altoslib/AltosFlightReader.java
altoslib/AltosFlightStats.java
altoslib/AltosFrequency.java
altoslib/AltosGPS.java
altoslib/AltosGPSSat.java
altoslib/AltosGreatCircle.java
altoslib/AltosHeight.java
altoslib/AltosHexfile.java
altoslib/AltosHexsym.java
altoslib/AltosIMU.java
altoslib/AltosIdle.java
altoslib/AltosIdleFetch.java
altoslib/AltosIdleMonitor.java
altoslib/AltosIdleMonitorListener.java
altoslib/AltosIgnite.java
altoslib/AltosKML.java
altoslib/AltosLatitude.java
altoslib/AltosLib.java
altoslib/AltosLine.java
altoslib/AltosLink.java
altoslib/AltosListenerState.java
altoslib/AltosLocation.java
altoslib/AltosLog.java
altoslib/AltosLongitude.java
altoslib/AltosMag.java
altoslib/AltosMma655x.java
altoslib/AltosMs5607.java
altoslib/AltosNoSymbol.java
altoslib/AltosOrient.java
altoslib/AltosParse.java
altoslib/AltosPreferences.java
altoslib/AltosPreferencesBackend.java
altoslib/AltosProgrammer.java
altoslib/AltosPyro.java
altoslib/AltosReplayReader.java
altoslib/AltosRomconfig.java
altoslib/AltosSelfFlash.java
altoslib/AltosSensorEMini.java
altoslib/AltosSensorMM.java
altoslib/AltosSensorMega.java
altoslib/AltosSensorMetrum.java
altoslib/AltosSensorTM.java
altoslib/AltosSensorTMini.java
altoslib/AltosSpeed.java
altoslib/AltosState.java
altoslib/AltosStateIterable.java
altoslib/AltosStateUpdate.java
altoslib/AltosTelemetry.java
altoslib/AltosTelemetryConfiguration.java
altoslib/AltosTelemetryFile.java
altoslib/AltosTelemetryIterable.java
altoslib/AltosTelemetryLegacy.java
altoslib/AltosTelemetryLocation.java
altoslib/AltosTelemetryMap.java
altoslib/AltosTelemetryMegaData.java
altoslib/AltosTelemetryMegaSensor.java
altoslib/AltosTelemetryMetrumData.java
altoslib/AltosTelemetryMetrumSensor.java
altoslib/AltosTelemetryMini.java
altoslib/AltosTelemetryRaw.java
altoslib/AltosTelemetryReader.java
altoslib/AltosTelemetrySatellite.java
altoslib/AltosTelemetrySensor.java
altoslib/AltosTelemetryStandard.java
altoslib/AltosTemperature.java
altoslib/AltosUnits.java
altoslib/AltosUnitsListener.java
altoslib/AltosVoltage.java
altoslib/AltosWriter.java
altoslib/Makefile.am
altosui/.gitignore
altosui/Altos.java
altosui/AltosAscent.java
altosui/AltosCompanionInfo.java
altosui/AltosConfig.java
altosui/AltosConfigPyroUI.java
altosui/AltosConfigTD.java
altosui/AltosConfigTDUI.java
altosui/AltosConfigUI.java
altosui/AltosConfigureUI.java
altosui/AltosDescent.java
altosui/AltosFlightStatus.java
altosui/AltosFlightStatusTableModel.java
altosui/AltosFlightStatusUpdate.java
altosui/AltosFlightUI.java
altosui/AltosGraphUI.java
altosui/AltosIdleMonitorUI.java
altosui/AltosIgniteUI.java
altosui/AltosIgnitor.java
altosui/AltosLanded.java
altosui/AltosLaunch.java
altosui/AltosLaunchUI.java
altosui/AltosPad.java
altosui/AltosUI.java
altosui/AltosUIPreferencesBackend.java
altosui/Info.plist.in
altosui/Instdrv/NSIS/Includes/java.nsh
altosui/Instdrv/NSIS/Includes/refresh-sh.nsh [new file with mode: 0644]
altosui/Makefile.am
altosui/altos-windows.nsi.in
altosui/altos.desktop.in [deleted file]
altosui/altusmetrum-altosui.desktop.in [new file with mode: 0644]
altosui/linux-install.sh
altosuilib/AltosBTDevice.java
altosuilib/AltosBTDeviceIterator.java
altosuilib/AltosBTKnown.java
altosuilib/AltosBTManage.java
altosuilib/AltosCSVUI.java
altosuilib/AltosConfigFreqUI.java
altosuilib/AltosDataChooser.java
altosuilib/AltosDevice.java
altosuilib/AltosDeviceDialog.java
altosuilib/AltosDeviceUIDialog.java
altosuilib/AltosDisplayThread.java
altosuilib/AltosEepromDelete.java
altosuilib/AltosEepromManage.java
altosuilib/AltosEepromMonitor.java
altosuilib/AltosEepromMonitorUI.java
altosuilib/AltosEepromSelect.java
altosuilib/AltosFlashUI.java
altosuilib/AltosFlightDisplay.java
altosuilib/AltosFlightInfoTableModel.java
altosuilib/AltosFlightStatsTable.java
altosuilib/AltosFontListener.java
altosuilib/AltosFreqList.java [deleted file]
altosuilib/AltosGraph.java
altosuilib/AltosGraphDataPoint.java
altosuilib/AltosGraphDataSet.java
altosuilib/AltosInfoTable.java
altosuilib/AltosLed.java
altosuilib/AltosLights.java
altosuilib/AltosPositionListener.java
altosuilib/AltosRomconfigUI.java
altosuilib/AltosScanUI.java
altosuilib/AltosSerial.java
altosuilib/AltosSerialInUseException.java
altosuilib/AltosUIAxis.java
altosuilib/AltosUIConfigure.java
altosuilib/AltosUIDataMissing.java
altosuilib/AltosUIDataPoint.java
altosuilib/AltosUIDataSet.java
altosuilib/AltosUIDialog.java
altosuilib/AltosUIEnable.java
altosuilib/AltosUIFlightTab.java
altosuilib/AltosUIFrame.java
altosuilib/AltosUIFreqList.java [new file with mode: 0644]
altosuilib/AltosUIGraph.java
altosuilib/AltosUIGrapher.java
altosuilib/AltosUIIndicator.java
altosuilib/AltosUILatLon.java
altosuilib/AltosUILib.java
altosuilib/AltosUIListener.java
altosuilib/AltosUIMap.java
altosuilib/AltosUIMapCache.java
altosuilib/AltosUIMapCacheListener.java [new file with mode: 0644]
altosuilib/AltosUIMapImage.java
altosuilib/AltosUIMapLine.java
altosuilib/AltosUIMapMark.java
altosuilib/AltosUIMapPath.java
altosuilib/AltosUIMapPreload.java
altosuilib/AltosUIMapRectangle.java
altosuilib/AltosUIMapStore.java
altosuilib/AltosUIMapStoreListener.java
altosuilib/AltosUIMapTile.java
altosuilib/AltosUIMapTileListener.java
altosuilib/AltosUIMapTransform.java
altosuilib/AltosUIMapView.java
altosuilib/AltosUIMapZoomListener.java
altosuilib/AltosUIMarker.java
altosuilib/AltosUIPreferences.java
altosuilib/AltosUIPreferencesBackend.java
altosuilib/AltosUIRateList.java [new file with mode: 0644]
altosuilib/AltosUISeries.java
altosuilib/AltosUITelemetryList.java [new file with mode: 0644]
altosuilib/AltosUIUnitsIndicator.java
altosuilib/AltosUIVersion.java.in
altosuilib/AltosUIVoltageIndicator.java
altosuilib/AltosUSBDevice.java
altosuilib/AltosVoice.java
altosuilib/GrabNDrag.java
altosuilib/Makefile.am
altosuilib/OSXAdapter.java [new file with mode: 0755]
ao-bringup/test-easymega [new file with mode: 0755]
ao-bringup/test-easymini
ao-bringup/test-gps
ao-bringup/test-telegps
ao-bringup/turnon_easymega [new file with mode: 0755]
ao-bringup/turnon_telemega
ao-bringup/turnon_telemetrum
ao-tools/Makefile.am
ao-tools/ao-cal-accel/.gitignore [new file with mode: 0644]
ao-tools/ao-cal-accel/Makefile.am [new file with mode: 0644]
ao-tools/ao-cal-accel/ao-cal-accel.1 [new file with mode: 0644]
ao-tools/ao-cal-accel/ao-cal-accel.c [new file with mode: 0644]
ao-tools/ao-send-telem/ao-send-telem.c
ao-tools/ao-test-baro/.gitignore [new file with mode: 0644]
ao-tools/ao-test-baro/Makefile.am [new file with mode: 0644]
ao-tools/ao-test-baro/ao-test-baro.1 [new file with mode: 0644]
ao-tools/ao-test-baro/ao-test-baro.c [new file with mode: 0644]
ao-tools/ao-test-flash/.gitignore [new file with mode: 0644]
ao-tools/ao-test-flash/Makefile.am [new file with mode: 0644]
ao-tools/ao-test-flash/ao-test-flash.1 [new file with mode: 0644]
ao-tools/ao-test-flash/ao-test-flash.c [new file with mode: 0644]
ao-tools/ao-test-igniter/.gitignore [new file with mode: 0644]
ao-tools/ao-test-igniter/Makefile.am [new file with mode: 0644]
ao-tools/ao-test-igniter/ao-test-igniter.1 [new file with mode: 0644]
ao-tools/ao-test-igniter/ao-test-igniter.c [new file with mode: 0644]
ao-tools/lib/cc-convert.c
ao-tools/lib/cc-telemetry.c
ao-tools/lib/cc.h
configure.ac
doc/Makefile
doc/altusmetrum.xsl
doc/configure-altimeter.png
doc/configure-groundstation.png
doc/easymega-outline.xsl [new file with mode: 0644]
doc/easymega-v1.0-bottom.jpg [new file with mode: 0644]
doc/easymega-v1.0-top.jpg [new file with mode: 0644]
doc/easymega.svg [new file with mode: 0644]
doc/release-notes-1.5.xsl [new file with mode: 0644]
doc/scan-channels.png
icon/.gitignore
icon/Makefile.am
icon/altusmetrum-altosui.svg [new file with mode: 0644]
icon/altusmetrum-micropeak.svg [new file with mode: 0644]
icon/altusmetrum-telegps.svg [new file with mode: 0644]
icon/altusmetrum.svg [deleted file]
icon/application-vnd.altusmetrum.eeprom.svg [new file with mode: 0644]
icon/application-vnd.altusmetrum.micropeak.svg [new symlink]
icon/application-vnd.altusmetrum.telemetry.svg [new file with mode: 0644]
icon/creating-linux-icons [new file with mode: 0644]
icon/micropeak.svg [deleted file]
icon/org-altusmetrum-mimetypes.xml [new file with mode: 0644]
icon/telegps.svg [deleted file]
icon/windows-stub.c [new file with mode: 0644]
libaltos/Makefile.am
libaltos/libaltos.c
micropeak/.gitignore
micropeak/Info.plist.in
micropeak/Makefile.am
micropeak/MicroData.java
micropeak/MicroDataPoint.java
micropeak/MicroDeviceDialog.java
micropeak/MicroDownload.java
micropeak/MicroExport.java
micropeak/MicroFile.java
micropeak/MicroFileChooser.java
micropeak/MicroFrame.java
micropeak/MicroGraph.java
micropeak/MicroPeak.app/Contents/Resources/MicroPeak.icns [deleted file]
micropeak/MicroPeak.java
micropeak/MicroRaw.java
micropeak/MicroSave.java
micropeak/MicroSerial.java
micropeak/MicroSerialLog.java
micropeak/MicroStats.java
micropeak/MicroStatsTable.java
micropeak/MicroUSB.java
micropeak/altusmetrum-micropeak.desktop.in [new file with mode: 0644]
micropeak/micropeak-windows.nsi.in
micropeak/micropeak.desktop.in [deleted file]
src/Makefile
src/cc1111/ao_intflash.c
src/cc1111/ao_pins.h
src/cc1111/ao_radio.c
src/cc1111/cc1111.h
src/drivers/ao_aprs.c
src/drivers/ao_cc1120.c
src/drivers/ao_cc1120.h
src/drivers/ao_cc1120_CC1120.h
src/drivers/ao_cc115l.c
src/drivers/ao_gps_skytraq.c
src/drivers/ao_gps_ublox.c
src/drivers/ao_lco_func.c
src/drivers/ao_packet_master.c
src/drivers/ao_pad.c
src/easymega-v0.1/.gitignore [deleted file]
src/easymega-v0.1/Makefile [deleted file]
src/easymega-v0.1/ao_easymega.c [deleted file]
src/easymega-v0.1/ao_pins.h [deleted file]
src/easymega-v0.1/flash-loader/Makefile [deleted file]
src/easymega-v0.1/flash-loader/ao_pins.h [deleted file]
src/easymega-v1.0/.gitignore [new file with mode: 0644]
src/easymega-v1.0/Makefile [new file with mode: 0644]
src/easymega-v1.0/ao_easymega.c [new file with mode: 0644]
src/easymega-v1.0/ao_pins.h [new file with mode: 0644]
src/easymega-v1.0/flash-loader/Makefile [new file with mode: 0644]
src/easymega-v1.0/flash-loader/ao_pins.h [new file with mode: 0644]
src/kalman/kalman.5c
src/kalman/kalman_micro.5c
src/kernel/ao.h
src/kernel/ao_cmd.c
src/kernel/ao_config.c
src/kernel/ao_config.h
src/kernel/ao_convert.c
src/kernel/ao_convert_pa.c
src/kernel/ao_convert_pa_test.c
src/kernel/ao_data.h
src/kernel/ao_flight.c
src/kernel/ao_forward.c [new file with mode: 0644]
src/kernel/ao_forward.h [new file with mode: 0644]
src/kernel/ao_gps_print.c
src/kernel/ao_gps_report.c
src/kernel/ao_gps_report_mega.c
src/kernel/ao_gps_report_metrum.c
src/kernel/ao_gps_show.c
src/kernel/ao_kalman.c
src/kernel/ao_log.c
src/kernel/ao_log.h
src/kernel/ao_log_gps.c
src/kernel/ao_log_gps.h
src/kernel/ao_log_micro.c
src/kernel/ao_microflight.c
src/kernel/ao_microkalman.c
src/kernel/ao_monitor.c
src/kernel/ao_mutex.c
src/kernel/ao_pyro.c
src/kernel/ao_pyro.h
src/kernel/ao_report.c
src/kernel/ao_rssi.c
src/kernel/ao_sample.c
src/kernel/ao_sample.h
src/kernel/ao_telemetry.c
src/kernel/ao_telemetry.h
src/kernel/ao_tracker.c
src/lpc/ao_arch_funcs.h
src/megadongle-v0.1/Makefile
src/megadongle-v0.1/ao_megadongle.c
src/megadongle-v0.1/ao_pins.h
src/microkite/.gitignore [new file with mode: 0644]
src/microkite/Makefile [new file with mode: 0644]
src/microkite/ao_pins.h [new file with mode: 0644]
src/microkite/microkite-load.tmpl [new file with mode: 0644]
src/micropeak/Makefile
src/micropeak/micropeak-load.tmpl [new file with mode: 0644]
src/product/Makefile.teledongle
src/product/Makefile.telelaunch
src/product/Makefile.telemetrum
src/product/Makefile.telenano
src/product/ao_micropeak.c
src/product/ao_micropeak.h
src/stm/ao_arch_funcs.h
src/stm/ao_spi_stm.c
src/telebt-v1.0/ao_pins.h
src/telefire-v0.1/Makefile
src/telefire-v0.1/ao_pins.h
src/telefire-v0.2/Makefile
src/telefire-v0.2/ao_pins.h
src/telegps-v1.0/ao_pins.h
src/telelco-v0.2/ao_lco.c
src/telelco-v0.2/ao_pins.h
src/telemega-v1.0/Makefile
src/telemini-v2.0/Makefile
src/telemini-v2.0/ao_pins.h
src/telerepeat-v1.0/Makefile [new file with mode: 0644]
src/telerepeat-v1.0/ao_pins.h [new file with mode: 0644]
src/telerepeat-v1.0/ao_telerepeat.c [new file with mode: 0644]
src/teleshield-v0.1/ao_pins.h
src/teleterra-v0.2/ao_pins.h
src/test/Makefile
src/test/ao_aprs_test.c
src/test/ao_flight_test.c
src/test/ao_gps_test.c
src/test/ao_gps_test_skytraq.c
src/test/ao_gps_test_ublox.c
src/test/ao_micropeak_test.c
src/test/plottest
src/util/make-altitude-pa
telegps/.gitignore
telegps/Info.plist.in
telegps/Makefile.am
telegps/TeleGPS.java
telegps/TeleGPSConfig.java
telegps/TeleGPSConfigUI.java
telegps/TeleGPSDisplayThread.java
telegps/TeleGPSGraphUI.java
telegps/TeleGPSInfo.java
telegps/TeleGPSPreferences.java
telegps/TeleGPSState.java
telegps/TeleGPSStatus.java
telegps/TeleGPSStatusUpdate.java
telegps/altusmetrum-telegps.desktop.in [new file with mode: 0644]
telegps/telegps-windows.nsi.in
telegps/telegps.desktop.in [deleted file]

index a15dbfa576edda30c05de94c4b9005669493dfee..36f3c8da6047833597e026c18e70efe98364f8c4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
-commit 1517ad263ba4c0b8c9251a726cce1ed8a86a634c
+commit 45f50ad3a8ce69c708974711a5939c42a74bf53b
 Author: Bdale Garbee <bdale@gag.com>
-Date:   Tue Jun 24 21:54:30 2014 -0600
+Date:   Tue Sep 9 23:22:58 2014 -0600
 
-    releasing 1.4.1
+    releasing version 1.5
 
-commit 6986da4407ac53e267b95abb1848211ea9d32b41
-Merge: 5f6059a 237472e
+commit a8c799c48a52bf13466536db627b66bfe2a435cd
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Sep 9 09:38:03 2014 -0700
+
+    altoslib/altosuilib: clean all versions of the .jar file
+    
+    When we switch libary versions, we want to remove the old ones; just
+    have 'make clean' remove all versions of the libaries.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit cef3be371cb3a9e481c2bd6abdf22c51953773f1
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Sep 9 09:37:13 2014 -0700
+
+    altoslib/altosuilib: Add EasyMega support
+    
+    This makes flashing find the right files, and Monitor Idle show all of
+    the state data.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 08a82617c53718055d97df4fa60f3e5051d65383
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Sep 9 09:09:22 2014 -0700
+
+    altos/easymega: Set USB PID for EasyMega to 0x0028
+    
+    It was using 0x0023, which is for TeleMega. 0x0028 is what's listed in
+    usbvidpid.h.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9d3ab4c78f79d659ce800def77bc441c95fa15be
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Sep 9 09:02:51 2014 -0700
+
+    altoslib: Fix idle monitor parsing of MMA655x state
+    
+    There's no ':' after 'MMA655X value' in the output, and the parser
+    returns 'true' on success, not false.
+    
+    With this, 'Monitor Idle' now reports correct accelerometer readings.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2b7ba0a5be70ae1d661afb2592ce8a6bf660c793
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Sep 9 09:01:42 2014 -0700
+
+    Tag version 1.4.9.3
+    
+    This should be the final firmware version for 1.5
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 445d61c3810154193aebbf0f08f075ac8e107baf
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Sep 6 22:56:25 2014 -0700
+
+    altosui: Include EasyMega firmware in fat release
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f0d2d34f84980ab45ecedae17546f4d71e020c5e
+Merge: 8c212cd 6c812f1
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Sat Sep 6 23:42:47 2014 -0600
+
+    Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos
+
+commit 6c812f10761ec4ebf13e29ccef1d6c2c864f1158
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Sep 6 22:28:13 2014 -0700
+
+    doc: Update for version 1.5 release
+    
+    Add stuff about EasyMega and telemetry rate configuration. Update
+    screen shots as needed.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d83afa9320c24056469984873af0a3c70bee0962
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Sep 6 20:44:30 2014 -0700
+
+    altos: Scale packet master receive delay by baud rate
+    
+    Increase the time we wait for return packets based on the remote
+    protocol baud rate.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e7515e3a88d53c50dd9b962cc8f43ce5376ccd0b
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Sep 6 20:43:32 2014 -0700
+
+    altoslib: Increase timeouts when using low baud rate remote protocol
+    
+    When using 2400 or 9600 baud remote link rates, we need to increase
+    the packet timeout from 500ms to much longer values to avoid annoying
+    the user with timeout warnings.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 46f08f8709c538f3fee8e166598f0bb930df6e3c
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Sep 6 20:41:58 2014 -0700
+
+    altoslib: Update local callsign/baud rate when using remote protocol
+    
+    We've had code to synchronously update the local and remote radio
+    frequencies when doing configuration over the remote link. This patch
+    adds the same code when changing the call sign and baud rate.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f395bcaa620490954d4a42de9b4870bc12bedc91
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Sep 6 20:39:37 2014 -0700
+
+    altos: Reduce deviation at 2400/9600 baud
+    
+    There's no reason to use 20.5kHz deviation at 2400 and 9600 baud, and
+    if we get a better receiver, we'll want to use narrower deviation to
+    have less bandwidth sucking noise into the radio. The new values are
+    (nominally) 5.125kHz deviation for 9600 baud and 1.5kHz deviation for
+    2400 baud.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8c212cd5bfa03f71a31d84bd0051314e77d88461
+Merge: e9714e3 dd26ec2
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Sat Sep 6 13:41:36 2014 -0600
+
+    Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos
+    
+    Conflicts:
+       ao-bringup/turnon_telemega
+
+commit e9714e34091abe657aa1b30aeda9466331aa39c1
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Sat Sep 6 13:40:59 2014 -0600
+
+    tweaking test scripts
+
+commit dd26ec2e706bdd29090759deeb90090a0e3b74f0
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Sep 6 00:39:41 2014 -0700
+
+    altosdroid: Mark completed items as 'done'
+    
+    Frequency display
+    Re-load data on restart
+    Auto re-connect to TBT at correct freq
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 18671803d078aa798b603c67b741c3ba4374f41d
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Sep 6 00:14:26 2014 -0700
+
+    altosdroid: Add imperial unit support
+    
+    Provides a menu entry to switch units, changes all value displays to
+    use the AltosLib units conversion code.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2b2ebd2fee46158abd1ae050cd6d1040ead849a0
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Sep 5 23:10:07 2014 -0700
+
+    altosdroid: Update tab contents before switching
+    
+    Make sure the new tab contents are updated before switching tabs so
+    that the user doesn't see old stuff.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 08bbb1c3de73c9aaf920b11247eae544df6eac0c
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Sep 5 22:06:21 2014 -0700
+
+    altosdroid: Ignore TelemetryService messages after service shutdown
+    
+    Messages may get delivered after the service has been shut down;
+    ignore those.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 101ac21f05a69bdeb07d423aa18017eca04fc47f
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Sep 4 11:28:40 2014 -0700
+
+    altosdroid: add new TelemetryState.java
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2b03aca995b0151d7e820775f6a9d4afec462633
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Sep 3 22:59:09 2014 -0700
+
+    altosui: Don't mark altimeter dirty when opening pyro panel
+    
+    Skip setting the UI dirty when filling in the pyro firing time value.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit be38fb88d11bda1ba1caca38220773d3abcede19
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Sep 3 22:58:22 2014 -0700
+
+    altos: Allow negative values for pyro configuration data
+    
+    All of the integer pyro configuration parameters may be negative, so
+    parse that correctly.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3842735e303f0bf6f46ed8cb659c92d8bb9bd137
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Sep 3 22:32:49 2014 -0700
+
+    altosdroid: Use single object to pass data to UI
+    
+    Instead of having separate messages for each piece of telemetry state,
+    package the whole mess up in one object and send it for any
+    change. This simplifies tracking within the UI by avoiding corner
+    cases during reconnect.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit adc46e2f1346d98ef4f6c2351fef95fbc8ddf831
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Sep 3 22:12:15 2014 -0700
+
+    altos/telefire: Add firing length to manual pad command
+    
+    This adds an optional length of time (in 1/10s of a second) to the
+    ao_pad_manual function to enable testing of igniters without needing
+    to use TeleLCO.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b838a974d0dad43ff02060d8d913d9369eb20e96
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Sep 1 18:25:00 2014 -0500
+
+    altosui: Fix 'pad' screen for TeleGPS
+    
+    Don't report pad position for TeleGPS
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7735cee871d02215517cb9d91cd552f003ca6a50
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Sep 1 18:23:42 2014 -0500
+
+    altoslib: Catch a couple null pointers in AltosConfigTD
+    
+    When messing with TD, I hit a couple of paths that could try to
+    dereference null pointers. Check for those.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 57f0ae384f3c206ea777dc7c93b594ae3901f354
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Sep 1 18:21:49 2014 -0500
+
+    altoslib: Ignore extra AO_LOG_FLIGHT records from TeleGPS
+    
+    TeleGPS was inserting a spurious AO_LOG_FLIGHT record each time it
+    turned on, which confused altoslib quite a bit.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a4202b4180e77e2a39ca071d3b8b8256ff0fc7b5
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Sep 1 18:12:29 2014 -0500
+
+    altos: Don't add AO_LOG_FLIGHT to existing GPS logs
+    
+    When appending to a TeleGPS log, don't stick another flight value into
+    the log. That just confuses the ground station software.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit aa7dd289ee72f7a49a08ce0229c4e0e0404499d0
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Aug 31 00:28:15 2014 -0500
+
+    altosdroid: reload previous log file at connect time
+    
+    Use the saved logfile to re-load the previous state at startup time.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 00a3eace5ea885205270137f190538b010fd679f
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Aug 31 00:27:54 2014 -0500
+
+    altosdroid: Add missing preferences backend file
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a5e348905a510bb2dcf6d7734f5681fb8338cd87
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Aug 31 00:11:28 2014 -0500
+
+    altoslib: create logfiles preference object. check link in existing_data
+    
+    The logfiles preference hash wasn't getting created, resulting in
+    crashes.
+    
+    When there was no link, don't try to load existing data.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit bc3fbcb35090be3856284ccf4d908ebf39d02bec
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Aug 31 00:08:33 2014 -0500
+
+    altosdroid: Add quit. Restart. Show freq in title.
+    
+    Add a quit button to menu.
+    When restarting, reconnect to previous device.
+    When connecting, set the freq/rate to previous values.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0b70ea04e807c69a987d5976ab217f9f65fb1e09
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Aug 29 22:33:36 2014 -0500
+
+    altosdroid: fixup fetching active device address
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0014addf3356bad1eff76cffc396fb120308646c
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Aug 29 22:08:43 2014 -0500
+
+    altoslib: TeleMega telemetry pyro voltages are uint8
+    
+    Using int8 means that voltages over about 6V are reported incorrectly.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 810f9a4f79b0480973d84595140d3f8948ce26d9
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Aug 29 15:22:43 2014 -0500
+
+    altosdroid: start restoring from log data on startup
+    
+    Remember which flight was last being received and reload that file
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5872bd10df14b47de0e541bff16d9220af0558aa
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Aug 29 15:12:38 2014 -0500
+
+    altos: Make sure pyro remains valid during delay
+    
+    Keep checking pyro status while waiting for delay to expire to make
+    sure nothing changes. Disable pyro channel if something does.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 54994d02a5ca5bb91512f31748a48a0140d3a640
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Aug 28 19:52:30 2014 -0700
+
+    ao-bringup: Test EasyMega boards
+
+commit 3c9cb4836edd4811fcdbb6ebbd25eb507a2ef5b1
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Aug 18 10:57:26 2014 -0700
+
+    ao-bringup: Use ao-cal-accel instead of cal-accel in turnon scripts
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit fac03ae9762f2af95b1ce5d99894173f9d9146f0
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Aug 18 10:53:04 2014 -0700
+
+    Add ao-tools/ao-cal-accel
+    
+    This C version may be more reliable than the nickle version
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b357544dd64f5b0f209c6cc6cb4fa392a2c3e1fa
 Author: Bdale Garbee <bdale@gag.com>
-Date:   Tue Jun 24 21:31:53 2014 -0600
+Date:   Mon Aug 18 11:25:32 2014 -0600
+
+    turn echo back on after accel cal in turnon_telemetrum so rest is easier
+
+commit 44e389c31e5958c1a050fbe0dce5d7971a9d6a86
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Aug 17 21:03:12 2014 -0700
+
+    altos: Add telerepeat-v1.0
+    
+    This uses TeleBT hardware to provide a telemetry repeater, receiving
+    packets on one frequency and re-transmitting them on another.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5a51efd7f9b49ffadc91ccaf7a0d69566301c009
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Jun 26 16:29:37 2014 -0700
+
+    altosui: Make Windows java test "smarter"
+    
+    Or at least have it try more options, and then finally ask the user
+    before downloading and installing java
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit bb7522acf040f41740ecd059e3d5d2480b652420
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Aug 17 20:59:45 2014 -0700
+
+    telegps-v1.0: Provide one log and append to it
+    
+    Instead of creating per-flight logs, create a single log and append
+    data to it each time TeleGPS is powered on. This avoids potentially
+    running out of log space just because the device is powered off/on.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1530c24cc75cdf9ba87c7e153ff28bf7beb4384c
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Aug 17 20:57:16 2014 -0700
+
+    cc1111: Wait for internal flash write to complete
+    
+    This ensures that we don't try to start another write too soon.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 80e20b241359452028298567c76b2f644da5ad23
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Aug 17 20:56:22 2014 -0700
+
+    Use -ldl when testing whether -m32 and -m64 builds work
+    
+    We only need -ldl, and not -lbluetooth now that libaltos uses dlopen
+    on the bluetooth library
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 830f31fd6dc280e7a63ba689b7a48beff5c49072
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Aug 17 20:55:34 2014 -0700
+
+    ao-tools/ao-send-telem: Support sending TM v2 and Tm v2 telemetry
+    
+    Add state tracking so the telemetry sending code works.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 629b29b2718c174be9c811f224d0acf73fba4aff
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Aug 17 20:54:44 2014 -0700
+
+    altoslib: Remove some debug printfs
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ef1dd370564b99da033109f2fb5f7bf29711a13f
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Aug 17 20:53:31 2014 -0700
+
+    altoslib: Improve performance of AltosLib.hexbytes
+    
+    On an android device, this function was spending quite a bit of time
+    calling hexbyte. Open code the conversion to improve performance.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ee9f68ec877e3e5a67179f8c8abafbccc80eb804
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Aug 17 20:51:36 2014 -0700
+
+    altoslib: Close serial port when AltosFlash fails to detect a target
+    
+    AltosDebug.check_connection raises an exception when the link fails,
+    but the AltosFlash constructor didn't close the serial port in this
+    case, causing the serial port to appear to be busy.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 76fd424e4624cb376ac2cf84b01b77599756680a
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Aug 17 20:50:38 2014 -0700
+
+    altoslib: Handle link timeout in AltosDebug.read_memory
+    
+    link.get_reply returns null on a link error; don't crash in
+    read_memory when this happens.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 935f769fee351545622e223a283fca64608ca410
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Aug 17 20:49:27 2014 -0700
+
+    altoslib: Parse 'Log fixed:' configuration value
+    
+    TeleGPS holds a single flight record and constantly appends data to it
+    instead of having separate flight records on the board. It reports
+    'Log fixed: 1' to let AltosLib know that the size of the per-flight
+    log is not configurable.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 59dfe661fcb504f390d9726378c676f2b5b005f3
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Aug 17 20:48:23 2014 -0700
+
+    altosdroid: Skip updating hidden UI elements
+    
+    Instead of updating everything in the UI, only update the visible UI
+    elements to save a bunch of computation.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b1f1844aa514893228080704da3b3ccf855bda1e
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Aug 17 20:46:48 2014 -0700
+
+    altosdroid: Add telemetry rate support
+    
+    Provides a menu to select the receiver telemetry bit rate
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e935ebe55705cb0506aac0859583d54fd8e5ca46
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Aug 14 19:03:29 2014 -0700
+
+    altos: Report additional pyro channels via beeper
+    
+    Send a beep for each additional pyro channel, low for no igniter, mid
+    for igniter. Does not change the reporting for the apogee/main channels.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c4dd29fcbbb93e991993a0aa444748dba4ee7dde
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jul 22 14:18:06 2014 -0700
+
+    altos: Document which TeleFire alarm pins are which
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d8e2b661e895fc59ded002a02191dcccce75f548
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Jul 19 22:35:30 2014 -0700
+
+    altos: Have MicroKite just start recording at startup
+    
+    This avoids having MicroKite try to detect boost and has it just start
+    recording data immediately.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 59976c44d1b6ee6505cfa4efd9a26ec4302f6c33
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Thu Aug 14 18:16:14 2014 -0600
+
+    change easymega from v0.1 to v1.0, tweak to build on master, add to Makefile
+
+commit 4828be0ca5252ac9cd6061209385dcd6c4c57965
+Merge: 17e894d 165b7dc
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Thu Aug 14 17:08:36 2014 -0600
+
+    Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos
+
+commit 165b7dcf6fba90b15ff32b891cba4b9111c1965b
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jul 16 17:13:25 2014 -0700
+
+    altoslib: Handle TeleGPS files for KML export
+    
+    TeleGPS files had state values that couldn't be converted to colors,
+    which resulted in a truncated file that wasn't much use for anything.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 17e894d1b65231d07df009bc4e8ca92864ccf790
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Tue Jul 15 23:15:50 2014 -0600
+
+    update turnon tools
+
+commit ec7ceb607f5ba7e1ed5cfd32b7a452a5f364b095
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jul 15 00:44:14 2014 -0700
+
+    linux-fat: Fix up fat linux install icons, mime types and .desktop files
+    
+    use the standard xdg utilities to install mime type and .desktop
+    files. The standard xdg icon installer doesn't handle svg icons, so we
+    have to do those manually.
+    
+    With this patch, xfce, gnome3 and kde4 all place the applications in
+    user-visible menus, display correct file icons and launch correct
+    applications for our file types.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit fb914d37018a585a879161483609d3c0be556d1e
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jul 14 02:32:03 2014 -0700
+
+    altosuilib: Fix minor scan UI nits
+    
+    Wasn't computing geometry correctly and overlapped the 2400 baud entry
+    with the list of scan results.
+    
+    Was not saving the telemetry rate/telemetry style when switching to
+    monitor mode, which caused the new monitor to come up with the wrong values.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 54b58e925e27e87bf2903678f87b7544ee2e8167
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jul 14 00:46:41 2014 -0700
+
+    Set version to 1.4.9.2
+
+commit 9e9151c3b4bb9ce329e1b44440a7aceb9f39b9a0
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jul 14 00:45:13 2014 -0700
+
+    altoslib: Parse eeprom 'altitude-32' fields
+    
+    This lets us tell if the altimeter supports 32-bit GPS altitudes in
+    the eeprom log.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0fd867f504dd7df62e95da98ded511bb7b9e4c66
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Jul 13 20:44:39 2014 -0700
+
+    altos/test: Build TeleMetrumV2 flight test variant
+    
+    Parses TeleMetrumV2 eeprom files and runs the TeleMetrumV2 flight code.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 50aec54bdc35962145eff9b465f9cd7b3d9fea0b
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Jul 13 20:43:27 2014 -0700
+
+    altos: Make ao_gps_print deal with telem containing 32-bit altitude values
+    
+    ao_gps_print is used with new telem packets from a few places; use
+    AO_TELEMETRY_LOCATION_ALTITUDE when necessary.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6c3d09bf40f2af6e8722f33a70b41e5d94ceaf9f
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Jul 13 20:42:41 2014 -0700
+
+    altos: Interrupt radio receive when changing data rate
+    
+    This aborts any pending radio receive when changing the data rate so
+    that the radio can be reprogrammed to receive at the correct rate.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5d1adc6775a66633661af747bc4176e06f97630f
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Jul 13 20:41:36 2014 -0700
+
+    ao-tools: Add a few GPS telem/eeprom constants
+    
+    These make it possible to encode/decode GPS data from telemetry and
+    eeprom files
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6c9daa4f471ac90ffce3bfe8876c9008f79a5b7f
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Jul 13 20:40:40 2014 -0700
+
+    ao-tools: Provide altitude to temperature conversion function
+    
+    This takes altitude and computes the 'normal' temperature for
+    that.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e447e1e5c90d3fc1be9c5a1c966c7c688a87ba18
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Jul 13 11:06:29 2014 -0700
+
+    ao-tools: Add TMv2 and Tgps log formats to cc.h
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a60ba449ec237ad3b8dade9dcea603b349dbccb1
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Jul 12 23:52:05 2014 -0700
+
+    altos/telefire,telelco: Add HAS_RADIO_RATE to launch system software
+    
+    This lets us set the rate to a lower value to improve range. 9600 baud
+    works great; 2400 baud makes the initial search take a long time.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit fa155693282746861b227afd6cbccc83dfd1bbed
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Jul 10 21:27:30 2014 -0700
+
+    telegps: Missing function in TeleGPSConfigUI
+    
+    set_altitude_32 was added to the abstract class but not here.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 405626971b47d4d4031312232bf13ad3d4bace7f
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Jul 10 21:13:49 2014 -0700
+
+    libaltos: typo in libaltos broke the build
+    
+    When converting this to use dlopen, I mis-typed the name hci_read_remote_name
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5f5b03879d9daa68a56498b45ae87a804cb1926b
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Jul 10 18:43:31 2014 -0700
+
+    altosui: Don't show bluetooth UI bits on mac/windows
+    
+    This just confuses people into thinking that bluetooth is supported on
+    those machines.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit aac3fdce54233993c91d326df3732a7c448ac54a
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Jul 10 18:42:37 2014 -0700
+
+    libaltos: Bind to libbluetooth at runtime on demand
+    
+    This lets us reliably start and run without libbluetooth present.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 59702e5ff8d0522b0aa9dcca863309eaafbcda09
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Jul 10 17:27:43 2014 -0700
+
+    altoslib: Extend telemetry heights from 16 to 32 bits
+    
+    Uses the GPS data and/or previous kalman data to compute the upper 16
+    bits of the truncated telemetry altitude value.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6dc58c63d202e918f16d5fbe9b188d422edcdd9c
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Jul 10 17:26:19 2014 -0700
+
+    altosui: Fix the 'Graph' button on the landed tab
+    
+    It hasn't been getting enabled since the state tabs were rewritten.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 013e9ccfbe76dc46e8c69ea314950bed83d9a39f
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Jul 10 17:18:38 2014 -0700
+
+    altos: Use 32-bits for flight state data (alt/speed/accel)
+    
+    Stores 32-bits for all of the flight parameters. Uses 64-bit
+    intermediates for kalman computation.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 31ae24b5da3e198e7555ea3768d3cbdec3a28a5f
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Jul 10 17:15:09 2014 -0700
+
+    altos: Record pdop value in TeleMetrumV2 log
+    
+    There's only one byte free, so we'll record the pdop value
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 47e62bb26984f6c84660c1d0451f77c2d6ad7e5a
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Jul 10 17:13:09 2014 -0700
+
+    altos: Scale DOP values by 10 in GPS drivers
+    
+    sky traq was scaling by 5, ublox was scaling by 100.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ed2a08c50d6b8ebcc8c1d2f15e73c1f2a1e25041
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Jul 10 17:10:49 2014 -0700
+
+    altoslib: Handle wide GPS altitude values in eeprom and telemetry
+    
+    Detect when the wider data is present and handle it correctly
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 34d5be68ca23e8beb05db9a480faef63ecc911d0
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Jul 10 17:07:48 2014 -0700
+
+    altos: Extend GPS altitudes to at least 24 bits everywhere
+    
+    Telemetry gets a special 'mode' flag indicating that 24-bit data is
+    present; log files get new data and log readers are expected to detect
+    that via the firmware version number.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0d044af0c5025a63026d05adcab68f265f179668
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Jul 10 16:19:52 2014 -0700
+
+    altosuilib: Allow for unitless axes in graphs
+    
+    DOP values have no units.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a2f44fa867b17a0f1c1ee9aa9b99ecaa102a361b
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Jul 10 16:19:34 2014 -0700
+
+    altosuilib: Add GPS DOP values to info table
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 61cbad00b68d9f4f2fed7b76132433e263966952
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Jul 10 16:19:17 2014 -0700
+
+    altosuilib: Add GPS DOP values to graph
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9dafabd77676e08da4067cd405b6f03bf8d8ff85
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Jul 10 16:17:56 2014 -0700
+
+    altoslib: Ensure CSV output is consistent
+    
+    Scan entire flight to figure out which columns to include before
+    outputing header or data. Limit data output to values which are valid.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b8fa4e9a077e8e04b922d0c434c139ad0a57ee66
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Jul 10 16:15:52 2014 -0700
+
+    altoslib: Clean up GPS DOP support in AltosState
+    
+    Parse out hdop/pdop/vdop from telem and eeprom. Deal with legacy
+    eeprom files that have dop/100 instead of dop/10 values.
+    
+    Clear state DOP values to MISSING at startup
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6f2a4c610dfacbf500650db0eeeca6623bb49c5c
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Jul 10 00:26:55 2014 -0700
+
+    micropeak/altosui/telegps: Fix icon file names
+    
+    The icon file names are now structured to have an organization name
+    and application name component. This should avoid collisions with
+    other packages when the icon files are installed in a shared
+    directory, as on Linux. Within the Java .jar file, the new names need
+    to be correctly referenced or we won't find them.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1684291ba9a4f3bc2828e7b079ac27efcba6a163
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jul 8 23:47:09 2014 -0700
+
+    altos/telemini-v2.0: Enable beep config and radio rate config
+    
+    use the smaller pa to altitude table to make room for the new code
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d926ccfbd4596eb3f981d2fcf8f6fc6ccc427db6
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jul 8 23:46:24 2014 -0700
+
+    altos: Add smaller pa to altitude table for TeleMini
+    
+    TeleMini doesn't have space for the larger table, and the smaller one
+    isn't that much less accurate at lower altitudes.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1a55cbe1923280f7009c13d5eb5b2ccac89219c2
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jul 8 23:45:10 2014 -0700
+
+    altos/telemini-v2.0: Add memory decorations to new telemetry variables
+    
+    This lets TeleMini-v2.0 compile.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 95f3a2825377bdb6737446df051c069d58f42d08
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jul 8 23:43:31 2014 -0700
+
+    altosui: Hide inactive altimeter configuration entries
+    
+    Instead of disabling them, just hide them so that entries that do not
+    apply to a particular device won't get shown at all.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 78db9e350db104da87e0fe4b72aa41bf6cf45e1d
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Jul 6 20:10:21 2014 -0700
+
+    Bump version to 1.4.9.1 -- on the way to 1.5
+
+commit d1527a5457210eb914312cf8857bfb88982a8462
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Jul 6 12:35:13 2014 -0700
+
+    Add support for the "kite" micropeak variant
+    
+    This uses a 100m 'launch detect' altitude and logs data every 19.2s
+    instead of every .192s.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f02cc3eec53e9d703837dad55ec2e6625b192588
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Jul 5 00:16:57 2014 -0700
+
+    telegps: Support variable telemetry rate
+    
+    Add combo box to monitoring window and device configuration.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit efb86669b5a74f244e2218f3385db633c36208af
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Jul 4 23:41:16 2014 -0700
+
+    altosui: Support telemetry data rates
+    
+    Add combo box to flight UI and flight hardware configuration UIs
+    Add telemetry rate to the TD/TBT config dialog
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9557a24b02911a93d74ee29ce359e40266cb4fed
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Jul 4 23:57:42 2014 -0700
+
+    altosuilib: Add telemetry rate to Scan UI
+    
+    Let the user scan for multiple data rates as well as telemetry formats
+    and frequencies
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 55e6558fa7cb23fb1363a86c83fbd6abf67ea324
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jul 2 22:48:13 2014 -0700
+
+    altoslib: Support multiple telemetry rates
+    
+    Altos now supports 2400 and 9600 baud in addition to the classic 38400
+    baud rate. Add support to altoslib for these as well
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 292cb8380b478542555b5f370e8252eafa2f74ac
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Jul 5 00:04:06 2014 -0700
+
+    altos: Rework packet receive for cc1120
+    
+    Instead of blocking on PQT, just set up the receiver to start going
+    and when the first bit interrupt comes in, grab the SPI bus if
+    possible and configure it for reception. This improves sensitivity in
+    the radio by a significant amount while making the code conceptually a
+    bit nicer.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e0ee2ac6bc68b73e13bf34fac3ffd4a3b79dce98
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jul 2 22:34:48 2014 -0700
+
+    altos: Add telemetry rate support to CC1120 driver
+    
+    This supports the new 2400 and 9600 baud rates
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 91461251f3aa8e1b37a3456f8fb94ab16bc0bec2
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Jul 4 23:42:30 2014 -0700
+
+    altos: Packet reception tuning for cc1120 driver
+    
+    This adjusts the cc1120 receive parameters to increase sensitivity at
+    the expense of reporting many more invalid packets to the UI.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8935e29e5aa9c01cd00b275a35dd7b99c00980c3
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jul 2 22:41:20 2014 -0700
+
+    altos: Add 2400 and 9600 baud telemetry support to cc115l driver
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit aba1703a1cff3da001d64bf2d15a591816e3350e
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jul 2 22:31:59 2014 -0700
+
+    altos/cc1111: Add 2400 and 9600 baud telemetry rate support
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c20ddde2f9eb0ad8dbb982e9d0cbe91639160a34
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jul 2 22:30:23 2014 -0700
+
+    altos/cc1111: Adjust receive parameters to improve sensitivity
+    
+    This removes the packet quality test and carrier sense tests when
+    deciding whether to start decoding a packet. This lets more bad
+    packets through, but the CRC check catches those and now we're
+    regularly receiving packets down to -110 or even -112 dBm. Before this
+    change, we'd rarely see packets as low as -105dBm
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ea5887027e7a39da2b7d84a142d74950b7a24703
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Jul 5 00:09:25 2014 -0700
+
+    altos: Call ao_telemetry_reset_interval when telemetry rate changes
+    
+    This lets the radio code adjust the telemetry packet sending pattern
+    when the data rate changes.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 214a38eb2b084baec526aa42016eddb954038639
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jul 2 22:44:07 2014 -0700
+
+    altos: Add config support for 2400 and 9600 baud telemetry rates
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0605b5a1cdff5cfd71fc9ef3161a62d74a1124b4
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jul 2 22:42:10 2014 -0700
+
+    altos: Add defines for 2400 and 9600 baud telemetry rates
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f8567a7be7ccd5dcc57ab65e63efe45e62008127
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Jul 4 23:26:57 2014 -0700
+
+    altos: Reduce configuration data telemetry to once per 5 seconds
+    
+    This data is constant, so we don't need to send it very often. Once
+    every five seconds should be plenty.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 657d455a2fad36193e6b3a7037d9ba7f09ae1168
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jul 2 22:46:07 2014 -0700
+
+    altos: Use TeleMetrum v1.9 board for MegaDongle experiments
+    
+    This configures the MegaDongle v0.1 directory to use the pin
+    assignments in TeleMetrum v1.9 boards.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 48508479b0f6f8d6e73db1cae8ee8acdaba022d8
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jul 2 22:45:01 2014 -0700
+
+    altos: Stop sticking cc1111 firmware in src directory
+    
+    This just clutters src.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 500353ec83af0da7fce3d67f2707f4725b1f50ba
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jul 2 22:42:43 2014 -0700
+
+    altos: ao_rssi subsystem needs to use AO_LED_TYPE instead of uint8_t
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit cb15cb8db5ef570b57f89d4e58734554542f99ff
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Jul 4 23:22:20 2014 -0700
+
+    altosuilib: Remove debug printfs from map cache
+    
+    Just annoying
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2e99ff2c99f5d4a2fa196507e794c690665ab39e
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Jul 4 23:20:51 2014 -0700
+
+    altoslib: Preserve receiver_serial across state reset for new transmitter
+    
+    When the transmitter serial or flight number changes, we re-init the
+    state information, but we want to preserve the receiver serial number
+    so that the log file has that in the name
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d6e64790287d684cb9b70c67fa270825932cc020
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jun 25 13:50:54 2014 -0700
+
+    altoslib: Disable telemetry while getting config data
+    
+    We're seeing some log files created without a suitable -via- number
+    included. My hypothesis is that incoming telemetry is getting
+    interleaved with the configuration data containing the serial
+    number. This change simply disables telemetry while retrieving the
+    configuration data to try and keep that from happening.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
 
-    Merge branch 'branch-1.4' of ssh://git.gag.com/scm/git/fw/altos into branch-1.4
+commit 98c3c3f7edd58358939f7dacf5b8f4c336712f5b
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Jul 4 23:38:53 2014 -0700
+
+    altosui/telegps: Undo the frequency/telemetry menu changes
+    
+    Using menus for these items isn't what we want; we want to show the
+    current value on the screen, which is what a combo box is for. Switch
+    back to those and remove the frequency and telemetry config from the
+    TeleGPS menu bar so that Mac OS X is happy.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
 
-commit 5f6059a9273dfe557145a9f620db81693f3bc27e
+commit 505c6a1f8b8d68fe6f74dcb4428c860157fae3de
 Author: Bdale Garbee <bdale@gag.com>
-Date:   Tue Jun 24 21:22:26 2014 -0600
+Date:   Wed Jun 25 13:37:56 2014 -0600
 
-    need the api key in Bdale's root too
+    note need to push the updated repo with production binaries during release
 
-commit 42fd93b67af396b0478e9e795026cf1a5312e5c9
+commit 75db560e2c9fbb2889db507acc93e889bf15bc2a
 Author: Bdale Garbee <bdale@gag.com>
-Date:   Tue Jun 24 21:12:59 2014 -0600
+Date:   Tue Jun 24 22:43:04 2014 -0600
 
-    make sure to use Google Maps API key for official builds
+    Windows sucks, hard .. make sure filenames are legal in .mdwn files
 
-commit 9a78df4ea121d1d3c14da2abae1a82c34121e13c
+commit 61ca8493566d5ea0da379970ab94f80a462dd368
 Author: Bdale Garbee <bdale@gag.com>
-Date:   Sun Jun 15 18:41:25 2014 -0600
+Date:   Tue Jun 24 22:35:43 2014 -0600
 
-    notes updated for TeleGPS and 1.4 release learnings
+    update Releasing file based on learnings from 1.4.1 release
 
-commit 237472e1b98283a82c674bb48c0347189d9d37bf
+commit 424112349d54bb6360403683f8012b83f49220be
 Author: Keith Packard <keithp@keithp.com>
-Date:   Tue Jun 24 20:15:38 2014 -0700
+Date:   Tue Jun 24 20:57:29 2014 -0700
 
-    altosuilib: Mark 'Configure AltosUI' window with maps key status
+    telegps: Disable tracker config when not available
     
-    This lets us check a build to make sure it has a maps key
+    Tracker motion and interval were both left enabled even when the
+    device being configured didn't support them. Disable them like other
+    elements.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7427f8bac7b3743ce0ab990612bf7168b95e22f9
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 24 20:52:34 2014 -0700
+
+    altosui: Don't show the tracker motion value when switching units
+    
+    The tracker value was left enabled when hidden; the logic for deciding
+    whether to update it with new information used only the enabled state,
+    not the visible state. Set both states when hiding it to keep things
+    more consistent
     
     Signed-off-by: Keith Packard <keithp@keithp.com>
 
-commit 0da9cdfbeacbaed13615ca2daade372920299c4a
+commit 6cb5955ab5aa3b42a507c4a02812cb5569b8562b
 Author: Keith Packard <keithp@keithp.com>
 Date:   Fri Jun 20 11:56:58 2014 -0700
 
@@ -47,7 +1239,7 @@ Date:   Fri Jun 20 11:56:58 2014 -0700
     
     Signed-off-by: Keith Packard <keithp@keithp.com>
 
-commit 2bbbd2c22e32d4c40782a9f12657f1a385cc6bc7
+commit f95b0e03c75d09e8ff4dbf9083cd3c8a30fdc4e6
 Author: Keith Packard <keithp@keithp.com>
 Date:   Fri Jun 20 11:51:11 2014 -0700
 
@@ -55,7 +1247,236 @@ Date:   Fri Jun 20 11:51:11 2014 -0700
     
     Signed-off-by: Keith Packard <keithp@keithp.com>
 
-commit 9dbd752150875f1f9fc93063f66d2153ec15d935
+commit b2c5f7d10265794a5778546f2e3eca7d763eab56
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 24 20:31:50 2014 -0700
+
+    Clean all .desktop files, ignore them too
+    
+    All .desktop files are built from .desktop.in files, so just remove
+    all of them in make clean, and ignore all of them in .gitignore.
+    This makes the rename less painful.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d1065424d144b8dab949db7e57140ffdf244bd48
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Tue Jun 24 21:22:26 2014 -0600
+
+    need the api key in Bdale's root too
+
+commit bd440afc2a6e37b74fffcf1b977e149485095316
+Merge: 5d4f912 a0ccab8
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Tue Jun 24 21:17:53 2014 -0600
+
+    Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos
+
+commit a0ccab8e4235934538a03f8be3b37aa1bbd6b144
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 24 20:15:38 2014 -0700
+
+    altosuilib: Mark 'Configure AltosUI' window with maps key status
+    
+    This lets us check a build to make sure it has a maps key
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5d4f912bcc6784f975c82f7b0ed8dc360e60aae8
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Tue Jun 24 21:12:59 2014 -0600
+
+    make sure to use Google Maps API key for official builds
+
+commit 048ce00ea0d1d2744552942559aa1da2431ab954
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 24 18:26:04 2014 -0700
+
+    icon: Generate altusmetrum.xpm and install it
+    
+    This is for the debian menu, still a required part of a debian package.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit dbff6dd42f8b6fb90c8d3f07bde48a6be0bfddf0
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 24 18:25:31 2014 -0700
+
+    altosuilib: Outline map lines and distance value with white
+    
+    This makes the value and line visible on dark backgrounds
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ade2cc9abb8ca403a9ae5d1f9c145ab72ce94919
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 24 18:24:02 2014 -0700
+
+    altosuilib: Make map cache size configurable
+    
+    Systems with sufficient memory can get smoother map scrolling by
+    making the cache larger. Would be nice to do this automatically?
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 97269bb90c1602a1f8c54fc7b6c34383a0370621
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 24 15:58:35 2014 -0700
+
+    Bump version to 1.4.1.1
+
+commit 309d91d25099bebda21e165165efa9ce86cb0a47
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 24 15:57:13 2014 -0700
+
+    altos/ao_flight_test: Get the Tmega version compiling again
+    
+    A few changes broke this recently.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 443bbb09468df7c1a10f2c76996c92380d8b8c23
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 24 15:56:11 2014 -0700
+
+    altos: Add optional debugging to print out pyro firing status
+    
+    This dumps pyro check failures for ao_flight_test so you can see why
+    pyro charges aren't firing.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0a19073649570016db28d5e2a4a225273732adb5
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Jun 22 21:13:54 2014 -0700
+
+    ao-bringup: Use the C tools to test EasyMini
+    
+    I think my USB driver in the kernel is broken; the nickle versions of
+    these  tools did very strange things and never worked.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit fc3364de2b6cdfff53f5c38b3ae52ae5601ff3b7
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Jun 22 21:12:37 2014 -0700
+
+    ao-tools: Add ao-test-baro, ao-test-igniter and ao-test-flash
+    
+    C versions of the test programs used to validate hardware prior to ship
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6cc2d671c0e335fbedb0e97699f8f273502c6807
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Jun 22 21:06:24 2014 -0700
+
+    altosui/telegps: Expose configurable APRS SSID
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3f3382126bf1122b1a78abe8458af5ec112a1f95
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Jun 22 21:05:05 2014 -0700
+
+    altos: Make APRS SSID configurable
+    
+    This uses the low-digit from the serial number by default, but lets
+    the user change it if desired.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ca1c62ca3ea016a1a5baa4520e484c102280c3e3
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Jun 21 18:27:42 2014 -0700
+
+    altosui: Add Ignitor tab to Monitor Idle mode
+    
+    Oops; missed adding this when I included it in the Monitor Flight window.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 602d6a2424a5c16e22febf6b4e6b3816022261c7
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Jun 20 00:41:17 2014 -0700
+
+    altos/aprs: Encode last serial number in SSID. Transmit serial in comment
+    
+    This makes it a lot easier to tell which device is sending
+    information, and to receive data from multiple devices on the same
+    receiver.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3016ee5f21ec66bf9230b90ab1420b8fad628f8d
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Jun 20 00:40:10 2014 -0700
+
+    altosuilib: Wrap radio frequency menu in JMenuBar when used in config
+    
+    The device config dialogs place the radio frequency menu inside a
+    dialog box; it needs to be inside a MenuBar to work properly, so
+    create one to hold it.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1b0f56ddb2b85b68232c22a7a8b8744cb9ad76f9
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Jun 19 14:33:27 2014 -0700
+
+    Rename icon files to fit XDG specifications. Add file icons. Add mime types
+    
+    Our SVG icons now follow XDG standards by including a vendor
+    prefix. The new file type icons include application-vnd.altusmetrum as
+    a prefix so that they match the mime types declared.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 37856672c57f2fd91184c2391a201bbbdc48545e
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Jun 19 10:25:07 2014 -0700
+
+    linux: .desktop files must begin with organization name
+    
+    The spec requires that .desktop files start with the organization
+    name, so I've renamed all of them to altusmetrum-<application>.desktop
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1d773cb8921848c99f12b8cd9840cb0267b66e1f
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jun 18 20:35:12 2014 -0700
+
+    windows: Missed adding 'refresh-sh.nsh'
+    
+    This script forces windows explorer to reload icons.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7767a045d446ea2bc5fe1ec98d89274155f956c4
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jun 18 16:18:05 2014 -0700
+
+    macosx: Respond to apple messages in all apps
+    
+    This connects the callbacks in AltosUIFrame to actually do something
+    useful with them.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d5bdb1c5974788b9569897435808fd01b04b0c4d
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jun 18 16:14:44 2014 -0700
+
+    altosuilib: Hook up apple messages to callbacks
+    
+    This supports open, quit and preferences. I'm leaving 'about' to the
+    existing stuff until I decide it's worth the effort to create a fancy
+    about dialog.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e3eab18682e77c5394918448409d383a28ba23ad
 Author: Keith Packard <keithp@keithp.com>
 Date:   Wed Jun 18 14:16:36 2014 -0700
 
@@ -63,7 +1484,43 @@ Date:   Wed Jun 18 14:16:36 2014 -0700
     
     Signed-off-by: Keith Packard <keithp@keithp.com>
 
-commit 44f60782d73bf5fdb6e1e54a3fdbe50808b7d7f5
+commit fac94c593285eacda57de257fa2be0548341b567
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jun 18 14:15:27 2014 -0700
+
+    macosx: Define icons for our file types on OS X
+    
+    Adds definitions to the Info.plist files shipped to specify which
+    icons to show for .telem, .eeprom and .mpd files. Note that the
+    applications don't respond to open apple events, so double clicking on
+    a file only starts the application.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5871225a0c442cf5afa41a444ff8bfb8f4002721
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jun 18 02:16:51 2014 -0700
+
+    windows installer: Create file associations for Windows.
+    
+    This makes icons appear for the files in the file manager, and lets
+    you double-click on the files to open the appropriate application.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c93c4efefee0dbf6d193466efd6761d9a1849ae9
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jun 18 02:15:04 2014 -0700
+
+    icon: Construct .exe files to hold windows icons for file associations
+    
+    It appears that creating an executable with an icon resource is the
+    only way to display icons for files. Fortunately, that's not all that
+    hard.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3f4e765c05ddbae83ca0c0176572cd698f285d08
 Author: Keith Packard <keithp@keithp.com>
 Date:   Tue Jun 17 20:46:33 2014 -0700
 
@@ -77,7 +1534,7 @@ Date:   Tue Jun 17 20:46:33 2014 -0700
     
     Signed-off-by: Keith Packard <keithp@keithp.com>
 
-commit 7140ca8a4bc0be8386f8edacadb7ac5d88c6f1b1
+commit 495e84540943cccb6d1cb965a772021f7dc5f639
 Author: Keith Packard <keithp@keithp.com>
 Date:   Tue Jun 17 00:08:03 2014 -0700
 
@@ -88,6 +1545,84 @@ Date:   Tue Jun 17 00:08:03 2014 -0700
     
     Signed-off-by: Keith Packard <keithp@keithp.com>
 
+commit b397e4ff45f054acb1347ffa5468950febc431f7
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jun 16 23:03:49 2014 -0700
+
+    altos/micropeak: Add load script template
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c8078d352a7f54a4a97d25af080155d3f875536a
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jun 16 22:49:34 2014 -0700
+
+    java: Bump java library versions for next release
+    
+    Prepare for future release by bumping java versions now
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 75766b0e7ee30fb3bfbf90ecb68f7758bac6eeba
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jun 16 22:48:25 2014 -0700
+
+    altosui: Fix ground station configure frequency list
+    
+    Fix the API to match the switch to a menu, wrap in a menu bar to make
+    it work.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ed38b1b596062b2232fa78a3181f6eaf5818b651
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jun 16 21:58:13 2014 -0700
+
+    altosuilib: Move menu bars into the Mac OS X top bar
+    
+    Setting these properties causes the top menu bar to get placed into
+    the Mac OS X window system menu bar
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e612693e33ef3b0e22db0656792992fa6e961ff2
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jun 16 21:57:35 2014 -0700
+
+    altosui/telegps: Use menus for frequency list and telemetry formats
+    
+    This will let us move them into the Mac OS X menu bar, as well as
+    making them look a bit nicer.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6579e4cae8fea65780f1c4677f29c1fc17ca41e2
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jun 16 15:59:09 2014 -0700
+
+    altos/micropeak: Create a script to load firmware.
+    
+    The micropeak-load script flashes micropeak with firmware from
+    whatever directory it is sitting in. A 'publish' target in the source
+    directory copies the script and hex to ~/altusmetrumllc/Binaries
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 31beeb0882d27cbc05e28118611feec4ae43d9da
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jun 16 11:02:49 2014 -0700
+
+    doc: Add instructions for flash recovery technique
+    
+    The flash recovery section explained which pins to connect, but lacked
+    explicit instructions on how to make it work.
+
+commit f167d348b147e89d269ad35806e39f28cf104afb
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Sun Jun 15 18:41:25 2014 -0600
+
+    notes updated for TeleGPS and 1.4 release learnings
+
 commit 9ab3a1de95b705783c31a7e16447f52c10b6b480
 Author: Bdale Garbee <bdale@gag.com>
 Date:   Sun Jun 15 17:44:42 2014 -0600
index 15d2c82da0c1263f4a6cc68e120b08efd090b086..2f8a5ee182d1e63c5e5da951cacf73f3a702c636 100644 (file)
@@ -18,6 +18,7 @@ fat:
        cd libaltos && $(MAKE) all
        cd altoslib && $(MAKE) all
        cd altosuilib && $(MAKE) all
+       cd icon && $(MAKE) fat
        cd altosui && $(MAKE) fat
        cd micropeak && $(MAKE) fat
        cd telegps && $(MAKE) fat
index c04a1de84e2b34121bf02f1dc58985c54bf50063..a1c510fdbabbdecf94c03560403ca261cfb4a969 100644 (file)
--- a/Releasing
+++ b/Releasing
@@ -1,5 +1,8 @@
 These are Bdale's notes on how to do a release.
 
+       - make sure build environment is up to date
+               sudo cowbuilder --update
+
        git checkout master
 
        - make sure the Google Maps API key is in the build chroot and root
@@ -75,6 +78,7 @@ These are Bdale's notes on how to do a release.
           src/telemetrum-v2.0/flash-loader/*.elf \
           ~/altusmetrumllc/Binaries/loaders/
        (cd ~/altusmetrumllc ; git add Binaries ; git commit -a) 
+       (cd ~/altusmetrumllc ; git push) 
 
        - copy the relevant release notes file from doc/ to 
            /home/bdale/web/altusmetrum/AltOS/releases/<rev>
@@ -87,9 +91,9 @@ These are Bdale's notes on how to do a release.
                
        - go edit ~/web/altusmetrum/AltOS/releases/<rev>.mdwn, 
          /home/bdale/web/altusmetrum/MicroPeak/releases/<rev>.mdwn, and
-         /home/bdale/web/altusmetrum/TeleGPS/releases/<rev>.mdwn, to 
-         include release date and explicit ref to dir contents so the 
-         web pages shows versioned links, commit and push
+         /home/bdale/web/altusmetrum/TeleGPS/releases/<rev>.mdwn
+
+               - make sure the Windows stuff is like 1-4-1, not 1.4.1!
 
        (cd doc ; make publish)
 
index ebb3578d0f4d4202db3390151338053e4f9bd868..5a4df032ef35a36b6a0511a3c7721cd352f61aa8 100644 (file)
@@ -8,6 +8,8 @@ Desired AltosDroid feature list
 
  *) Highlight current frequency in the frequency list.
 
+       Placed current frequency in title bar
+
  *) Random frequency selection. Provide some mechanism to input
     arbitrary radio frequencies. Could be like AltosUI which allows
     you to edit the list of frequencies and assign names to them,
@@ -23,10 +25,16 @@ Desired AltosDroid feature list
 
  *) Remember most-recently-used TBT and frequency, perhaps
     auto-connect at startup.
+
+       Done
     
  *) Re-loading flight data from .telem file to get back to
     'find my rocket' mode after shutting down the application.
 
+       Done
+
  *) Imperial Units mode
 
+       Done
+
  *) TeleBT battery voltage
index 395695f82e16d48334783bc5a7d41ed2d9a2fd75..93d655172d608655323207004068f85d59b49626 100644 (file)
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     >
-    <TextView android:id="@+id/title_paired_devices"
+    <Button android:id="@+id/button_scan"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:text="@string/title_paired_devices"
+        android:text="@string/button_scan"
+    />
+    <TextView android:id="@+id/title_new_devices"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/title_other_devices"
         android:visibility="gone"
         android:background="#666"
         android:textColor="#fff"
         android:paddingLeft="5dp"
     />
-    <ListView android:id="@+id/paired_devices"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:stackFromBottom="true"
-        android:layout_weight="1"
-    />
-    <TextView android:id="@+id/title_new_devices"
+    <TextView android:id="@+id/title_paired_devices"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:text="@string/title_other_devices"
+        android:text="@string/title_paired_devices"
         android:visibility="gone"
         android:background="#666"
         android:textColor="#fff"
         android:paddingLeft="5dp"
     />
-    <ListView android:id="@+id/new_devices"
+    <ListView android:id="@+id/paired_devices"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:stackFromBottom="true"
-        android:layout_weight="2"
+        android:layout_weight="1"
     />
-    <Button android:id="@+id/button_scan"
+    <ListView android:id="@+id/new_devices"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:text="@string/button_scan"
+        android:stackFromBottom="true"
+        android:layout_weight="2"
     />
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
index d7ba8305766c3106bb6cc656a65885ce2200d77a..3bd5a54e2bb4b6d6dd0abcb81f5fb39d94e7954e 100644 (file)
     <item android:id="@+id/connect_scan"
           android:icon="@android:drawable/ic_menu_search"
           android:title="@string/connect_device" />
+    <item android:id="@+id/quit"
+          android:icon="@android:drawable/ic_menu_close_clear_cancel"
+          android:title="@string/quit" />
     <item android:id="@+id/select_freq"
           android:icon="@android:drawable/ic_menu_preferences"
           android:title="@string/select_freq" />
+    <item android:id="@+id/select_rate"
+          android:icon="@android:drawable/ic_menu_preferences"
+          android:title="@string/select_rate" />
+    <item android:id="@+id/change_units"
+         android:icon="@android:drawable/ic_menu_view"
+         android:title="@string/change_units" />
 </menu>
index 90da617b2ffe9af6e29e49e5f476ebe600415a79..0cc9934937ad07634cbf97a75c19b5d51020f75d 100644 (file)
        <!-- AltosDroid -->
        <string name="bt_not_enabled">Bluetooth was not enabled.</string>
        <string name="title_connecting">connecting…</string>
-       <string name="title_connected_to">connected</string>
+       <string name="title_connected_to">connected</string>
        <string name="title_not_connected">not connected</string>
 
        <!-- Options Menu -->
        <string name="connect_device">Connect a device</string>
+       <string name="quit">Quit</string>
        <string name="select_freq">Select radio frequency</string>
+       <string name="select_rate">Select data rate</string>
+       <string name="change_units">Change units</string>
 
        <!-- DeviceListActivity -->
        <string name="scanning">scanning for devices…</string>
index 1b4d45ed3e66536eabac8b1ca25633fa6d1a4be3..51ef5e94652d2c2dfe47a3d0b774497d873a1f7c 100644 (file)
@@ -31,7 +31,7 @@ import android.os.Handler;
 //import android.os.Message;
 import android.util.Log;
 
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public class AltosBluetooth extends AltosLink {
 
@@ -52,6 +52,7 @@ public class AltosBluetooth extends AltosLink {
 
        // Constructor
        public AltosBluetooth(BluetoothDevice in_device, Handler in_handler) {
+//             set_debug(D);
                adapter = BluetoothAdapter.getDefaultAdapter();
                device = in_device;
                handler = in_handler;
@@ -136,9 +137,27 @@ public class AltosBluetooth extends AltosLink {
                }
        }
 
+       public double frequency() {
+               return frequency;
+       }
+
+       public int telemetry_rate() {
+               return telemetry_rate;
+       }
+
+       public void save_frequency() {
+               AltosPreferences.set_frequency(0, frequency);
+       }
+
+       public void save_telemetry_rate() {
+               AltosPreferences.set_telemetry_rate(0, telemetry_rate);
+       }
+
        private synchronized void wait_connected() throws InterruptedException, IOException {
                if (input == null) {
+                       if (D) Log.d(TAG, "wait_connected...");
                        wait();
+                       if (D) Log.d(TAG, "wait_connected done");
                        if (input == null) throw new IOException();
                }
        }
@@ -174,18 +193,29 @@ public class AltosBluetooth extends AltosLink {
                } catch (InterruptedException e) {
                        connection_lost();
                }
-       }               
+       }
+
+       private static final int buffer_size = 1024;
+
+       private byte[] buffer = new byte[buffer_size];
+       private int buffer_len = 0;
+       private int buffer_off = 0;
 
        public int getchar() {
-               try {
-                       wait_connected();
-                       return input.read();
-               } catch (IOException e) {
-                       connection_lost();
-               } catch (java.lang.InterruptedException e) {
-                       connection_lost();
+               while (buffer_off == buffer_len) {
+                       try {
+                               wait_connected();
+                               buffer_len = input.read(buffer);
+                               buffer_off = 0;
+                       } catch (IOException e) {
+                               connection_lost();
+                               return AltosLink.ERROR;
+                       } catch (java.lang.InterruptedException e) {
+                               connection_lost();
+                               return AltosLink.ERROR;
+                       }
                }
-               return AltosLink.ERROR;
+               return buffer[buffer_off++];
        }
 
        public void close() {
index f61baf1e411a933518bc1cf245f20ddd8673511d..f6cceac947dbab97cc6b6d838a7fd22e2f21f960 100644 (file)
@@ -37,35 +37,40 @@ import android.os.Message;
 import android.os.Messenger;
 import android.os.RemoteException;
 import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentManager;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.Window;
+import android.view.View;
 import android.widget.TabHost;
 import android.widget.TextView;
+import android.widget.RelativeLayout;
 import android.widget.Toast;
 import android.app.AlertDialog;
 import android.location.Location;
 
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
-public class AltosDroid extends FragmentActivity {
+public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
        // Debugging
-       private static final String TAG = "AltosDroid";
-       private static final boolean D = true;
+       static final String TAG = "AltosDroid";
+       static final boolean D = true;
 
        // Message types received by our Handler
-       public static final int MSG_STATE_CHANGE    = 1;
-       public static final int MSG_TELEMETRY       = 2;
-       public static final int MSG_UPDATE_AGE      = 3;
-       public static final int MSG_LOCATION        = 4;
-       public static final int MSG_CRC_ERROR       = 5;
+
+       public static final int MSG_STATE           = 1;
+       public static final int MSG_UPDATE_AGE      = 2;
 
        // Intent request codes
-       private static final int REQUEST_CONNECT_DEVICE = 1;
-       private static final int REQUEST_ENABLE_BT      = 2;
+       public static final int REQUEST_CONNECT_DEVICE = 1;
+       public static final int REQUEST_ENABLE_BT      = 2;
+
+       public static FragmentManager   fm;
+
+       private BluetoothAdapter mBluetoothAdapter = null;
 
        // Layout Views
        private TextView mTitle;
@@ -75,12 +80,16 @@ public class AltosDroid extends FragmentActivity {
        private TextView mRSSIView;
        private TextView mSerialView;
        private TextView mFlightView;
+       private RelativeLayout mStateLayout;
        private TextView mStateView;
        private TextView mAgeView;
 
        // field to display the version at the bottom of the screen
        private TextView mVersion;
 
+       private double frequency;
+       private int telemetry_rate;
+
        // Tabs
        TabHost         mTabHost;
        AltosViewPager  mViewPager;
@@ -89,23 +98,14 @@ public class AltosDroid extends FragmentActivity {
        int             tabHeight;
 
        // Timer and Saved flight state for Age calculation
-       private Timer timer = new Timer();
+       private Timer timer;
        AltosState saved_state;
-       Location saved_location;
 
        // Service
        private boolean mIsBound   = false;
        private Messenger mService = null;
        final Messenger mMessenger = new Messenger(new IncomingHandler(this));
 
-       // Preferences
-       private AltosDroidPreferences prefs = null;
-
-       // TeleBT Config data
-       private AltosConfigData mConfigData = null;
-       // Local Bluetooth adapter
-       private BluetoothAdapter mBluetoothAdapter = null;
-
        // Text to Speech
        private AltosVoice mAltosVoice = null;
 
@@ -117,38 +117,21 @@ public class AltosDroid extends FragmentActivity {
                @Override
                public void handleMessage(Message msg) {
                        AltosDroid ad = mAltosDroid.get();
+
                        switch (msg.what) {
-                       case MSG_STATE_CHANGE:
-                               if(D) Log.d(TAG, "MSG_STATE_CHANGE: " + msg.arg1);
-                               switch (msg.arg1) {
-                               case TelemetryService.STATE_CONNECTED:
-                                       ad.mConfigData = (AltosConfigData) msg.obj;
-                                       String str = String.format(" %s S/N: %d", ad.mConfigData.product, ad.mConfigData.serial);
-                                       ad.mTitle.setText(R.string.title_connected_to);
-                                       ad.mTitle.append(str);
-                                       Toast.makeText(ad.getApplicationContext(), "Connected to " + str, Toast.LENGTH_SHORT).show();
-                                       break;
-                               case TelemetryService.STATE_CONNECTING:
-                                       ad.mTitle.setText(R.string.title_connecting);
-                                       break;
-                               case TelemetryService.STATE_READY:
-                               case TelemetryService.STATE_NONE:
-                                       ad.mConfigData = null;
-                                       ad.mTitle.setText(R.string.title_not_connected);
-                                       break;
+                       case MSG_STATE:
+                               if(D) Log.d(TAG, "MSG_STATE");
+                               TelemetryState telemetry_state = (TelemetryState) msg.obj;
+                               if (telemetry_state == null) {
+                                       Log.d(TAG, "telemetry_state null!");
+                                       return;
                                }
+
+                               ad.update_state(telemetry_state);
                                break;
-                       case MSG_TELEMETRY:
-                               ad.update_ui((AltosState) msg.obj);
-                               break;
-                       case MSG_LOCATION:
-                               ad.set_location((Location) msg.obj);
-                               break;
-                       case MSG_CRC_ERROR:
                        case MSG_UPDATE_AGE:
-                               if (ad.saved_state != null) {
-                                       ad.mAgeView.setText(String.format("%d", (System.currentTimeMillis() - ad.saved_state.received_time + 500) / 1000));
-                               }
+                               if(D) Log.d(TAG, "MSG_UPDATE_AGE");
+                               ad.update_age();
                                break;
                        }
                }
@@ -204,57 +187,180 @@ public class AltosDroid extends FragmentActivity {
                mTabs.remove(mTab);
        }
 
-       void set_location(Location location) {
-               saved_location = location;
-               update_ui(saved_state);
+       public void units_changed(boolean imperial_units) {
+               for (AltosDroidTab mTab : mTabs)
+                       mTab.units_changed(imperial_units);
        }
 
-       void update_ui(AltosState state) {
-               if (state != null && saved_state != null) {
-                       if (saved_state.state != state.state) {
-                               String currentTab = mTabHost.getCurrentTabTag();
-                               switch (state.state) {
-                               case AltosLib.ao_flight_boost:
-                                       if (currentTab.equals("pad")) mTabHost.setCurrentTabByTag("ascent");
-                                       break;
-                               case AltosLib.ao_flight_drogue:
-                                       if (currentTab.equals("ascent")) mTabHost.setCurrentTabByTag("descent");
-                                       break;
-                               case AltosLib.ao_flight_landed:
-                                       if (currentTab.equals("descent")) mTabHost.setCurrentTabByTag("landed");
-                                       break;
-                               }
+       void update_title(TelemetryState telemetry_state) {
+               switch (telemetry_state.connect) {
+               case TelemetryState.CONNECT_CONNECTED:
+                       if (telemetry_state.config != null) {
+                               String str = String.format("S/N %d %6.3f MHz", telemetry_state.config.serial,
+                                                          telemetry_state.frequency);
+                               if (telemetry_state.telemetry_rate != AltosLib.ao_telemetry_rate_38400)
+                                       str = str.concat(String.format(" %d bps",
+                                                                      AltosLib.ao_telemetry_rate_values[telemetry_state.telemetry_rate]));
+                               mTitle.setText(str);
+                       } else {
+                               mTitle.setText(R.string.title_connected_to);
                        }
+                       break;
+               case TelemetryState.CONNECT_CONNECTING:
+                       mTitle.setText(R.string.title_connecting);
+                       break;
+               case TelemetryState.CONNECT_READY:
+               case TelemetryState.CONNECT_NONE:
+                       mTitle.setText(R.string.title_not_connected);
+                       break;
                }
-               saved_state = state;
+       }
 
-               AltosGreatCircle from_receiver = null;
+       void start_timer() {
+               if (timer == null) {
+                       timer = new Timer();
+                       timer.scheduleAtFixedRate(new TimerTask(){ public void run() {onTimerTick();}}, 1000L, 1000L);
+               }
+       }
+
+       void stop_timer() {
+               if (timer != null) {
+                       timer.cancel();
+                       timer.purge();
+                       timer = null;
+               }
+       }
+
+       boolean registered_units_listener;
+
+       void update_state(TelemetryState telemetry_state) {
 
-               if (state != null && saved_location != null && state.gps != null && state.gps.locked) {
-                       double altitude = 0;
-                       if (saved_location.hasAltitude())
-                               altitude = saved_location.getAltitude();
-                       from_receiver = new AltosGreatCircle(saved_location.getLatitude(),
-                                                            saved_location.getLongitude(),
-                                                            altitude,
-                                                            state.gps.lat,
-                                                            state.gps.lon,
-                                                            state.gps.alt);
+               if (!registered_units_listener) {
+                       registered_units_listener = true;
+                       AltosPreferences.register_units_listener(this);
                }
 
+               update_title(telemetry_state);
+               update_ui(telemetry_state.state, telemetry_state.location);
+               if (telemetry_state.connect == TelemetryState.CONNECT_CONNECTED)
+                       start_timer();
+               else
+                       stop_timer();
+       }
+
+       boolean same_string(String a, String b) {
+               if (a == null) {
+                       if (b == null)
+                               return true;
+                       return false;
+               } else {
+                       if (b == null)
+                               return false;
+                       return a.equals(b);
+               }
+       }
+
+       void update_age() {
+               if (saved_state != null)
+                       mAgeView.setText(String.format("%d", (System.currentTimeMillis() - saved_state.received_time + 500) / 1000));
+       }
+
+       void update_ui(AltosState state, Location location) {
+
+               Log.d(TAG, "update_ui");
+
+               int prev_state = AltosLib.ao_flight_invalid;
+
+               AltosGreatCircle from_receiver = null;
+
+               if (saved_state != null)
+                       prev_state = saved_state.state;
+
                if (state != null) {
-                       mCallsignView.setText(state.callsign);
-                       mSerialView.setText(String.format("%d", state.serial));
-                       mFlightView.setText(String.format("%d", state.flight));
-                       mStateView.setText(state.state_name());
-                       mRSSIView.setText(String.format("%d", state.rssi));
+                       Log.d(TAG, String.format("prev state %d new state  %d\n", prev_state, state.state));
+                       if (state.state == AltosLib.ao_flight_stateless) {
+                               boolean prev_locked = false;
+                               boolean locked = false;
+
+                               if(state.gps != null)
+                                       locked = state.gps.locked;
+                               if (saved_state != null && saved_state.gps != null)
+                                       prev_locked = saved_state.gps.locked;
+                               if (prev_locked != locked) {
+                                       String currentTab = mTabHost.getCurrentTabTag();
+                                       if (locked) {
+                                               if (currentTab.equals("pad")) mTabHost.setCurrentTabByTag("descent");
+                                       } else {
+                                               if (currentTab.equals("descent")) mTabHost.setCurrentTabByTag("pad");
+                                       }
+                               }
+                       } else {
+                               if (prev_state != state.state) {
+                                       String currentTab = mTabHost.getCurrentTabTag();
+                                       Log.d(TAG, "switch state");
+                                       switch (state.state) {
+                                       case AltosLib.ao_flight_boost:
+                                               if (currentTab.equals("pad")) mTabHost.setCurrentTabByTag("ascent");
+                                               break;
+                                       case AltosLib.ao_flight_drogue:
+                                               if (currentTab.equals("ascent")) mTabHost.setCurrentTabByTag("descent");
+                                               break;
+                                       case AltosLib.ao_flight_landed:
+                                               if (currentTab.equals("descent")) mTabHost.setCurrentTabByTag("landed");
+                                               break;
+                                       case AltosLib.ao_flight_stateless:
+                                               if (currentTab.equals("pad")) mTabHost.setCurrentTabByTag("descent");
+                                               break;
+                                       }
+                               }
+                       }
+
+                       if (location != null && state.gps != null && state.gps.locked) {
+                               double altitude = 0;
+                               if (location.hasAltitude())
+                                       altitude = location.getAltitude();
+                               from_receiver = new AltosGreatCircle(location.getLatitude(),
+                                                                    location.getLongitude(),
+                                                                    altitude,
+                                                                    state.gps.lat,
+                                                                    state.gps.lon,
+                                                                    state.gps.alt);
+                       }
+
+                       if (saved_state == null || !same_string(saved_state.callsign, state.callsign)) {
+                               Log.d(TAG, "update callsign");
+                               mCallsignView.setText(state.callsign);
+                       }
+                       if (saved_state == null || state.serial != saved_state.serial) {
+                               Log.d(TAG, "update serial");
+                               mSerialView.setText(String.format("%d", state.serial));
+                       }
+                       if (saved_state == null || state.flight != saved_state.flight) {
+                               Log.d(TAG, "update flight");
+                               mFlightView.setText(String.format("%d", state.flight));
+                       }
+                       if (saved_state == null || state.state != saved_state.state) {
+                               Log.d(TAG, "update state");
+                               if (state.state == AltosLib.ao_flight_stateless) {
+                                       mStateLayout.setVisibility(View.GONE);
+                               } else {
+                                       mStateView.setText(state.state_name());
+                                       mStateLayout.setVisibility(View.VISIBLE);
+                               }
+                       }
+                       if (saved_state == null || state.rssi != saved_state.rssi) {
+                               Log.d(TAG, "update rssi");
+                               mRSSIView.setText(String.format("%d", state.rssi));
+                       }
                }
 
                for (AltosDroidTab mTab : mTabs)
-                       mTab.update_ui(state, from_receiver, saved_location);
+                       mTab.update_ui(state, from_receiver, location, mTab == mTabsAdapter.currentItem());
 
                if (state != null)
-                       mAltosVoice.tell(state);
+                       mAltosVoice.tell(state, from_receiver);
+
+               saved_state = state;
        }
 
        private void onTimerTick() {
@@ -301,12 +407,9 @@ public class AltosDroid extends FragmentActivity {
                if (mBluetoothAdapter == null) {
                        Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();
                        finish();
-                       return;
                }
 
-               // Initialise preferences
-               prefs = new AltosDroidPreferences(this);
-               AltosPreferences.init(prefs);
+               fm = getSupportFragmentManager();
 
                // Set up the window layout
                requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
@@ -349,7 +452,6 @@ public class AltosDroid extends FragmentActivity {
                for (int i = 0; i < 5; i++)
                        mTabHost.getTabWidget().getChildAt(i).getLayoutParams().height = tabHeight;
 
-
                // Set up the custom title
                mTitle = (TextView) findViewById(R.id.title_left_text);
                mTitle.setText(R.string.app_name);
@@ -365,11 +467,10 @@ public class AltosDroid extends FragmentActivity {
                mRSSIView      = (TextView) findViewById(R.id.rssi_value);
                mSerialView    = (TextView) findViewById(R.id.serial_value);
                mFlightView    = (TextView) findViewById(R.id.flight_value);
+               mStateLayout   = (RelativeLayout) findViewById(R.id.state_container);
                mStateView     = (TextView) findViewById(R.id.state_value);
                mAgeView       = (TextView) findViewById(R.id.age_value);
 
-               timer.scheduleAtFixedRate(new TimerTask(){ public void run() {onTimerTick();}}, 1000L, 100L);
-
                mAltosVoice = new AltosVoice(this);
        }
 
@@ -378,15 +479,16 @@ public class AltosDroid extends FragmentActivity {
                super.onStart();
                if(D) Log.e(TAG, "++ ON START ++");
 
+               // Start Telemetry Service
+               startService(new Intent(AltosDroid.this, TelemetryService.class));
+
                if (!mBluetoothAdapter.isEnabled()) {
                        Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
-                       startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
+                       startActivityForResult(enableIntent, AltosDroid.REQUEST_ENABLE_BT);
                }
 
-               // Start Telemetry Service
-               startService(new Intent(AltosDroid.this, TelemetryService.class));
-
                doBindService();
+
        }
 
        @Override
@@ -415,6 +517,7 @@ public class AltosDroid extends FragmentActivity {
                if(D) Log.e(TAG, "--- ON DESTROY ---");
 
                if (mAltosVoice != null) mAltosVoice.stop();
+               stop_timer();
        }
 
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
@@ -442,19 +545,21 @@ public class AltosDroid extends FragmentActivity {
                }
        }
 
-       private void connectDevice(Intent data) {
-               // Get the device MAC address
-               String address = data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
-               // Get the BLuetoothDevice object
-               BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
+       private void connectDevice(String address) {
                // Attempt to connect to the device
                try {
-                       if (D) Log.d(TAG, "Connecting to " + device.getName());
-                       mService.send(Message.obtain(null, TelemetryService.MSG_CONNECT, device));
+                       if (D) Log.d(TAG, "Connecting to " + address);
+                       mService.send(Message.obtain(null, TelemetryService.MSG_CONNECT, address));
                } catch (RemoteException e) {
                }
        }
 
+       private void connectDevice(Intent data) {
+               // Get the device MAC address
+               String address = data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
+               connectDevice(address);
+       }
+
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
                MenuInflater inflater = getMenuInflater();
@@ -476,6 +581,33 @@ public class AltosDroid extends FragmentActivity {
                }
        }
 
+       void setBaud(int baud) {
+               try {
+                       mService.send(Message.obtain(null, TelemetryService.MSG_SETBAUD, baud));
+               } catch (RemoteException e) {
+               }
+       }
+
+       void setBaud(String baud) {
+               try {
+                       int     value = Integer.parseInt(baud);
+                       int     rate = AltosLib.ao_telemetry_rate_38400;
+                       switch (value) {
+                       case 2400:
+                               rate = AltosLib.ao_telemetry_rate_2400;
+                               break;
+                       case 9600:
+                               rate = AltosLib.ao_telemetry_rate_9600;
+                               break;
+                       case 38400:
+                               rate = AltosLib.ao_telemetry_rate_38400;
+                               break;
+                       }
+                       setBaud(rate);
+               } catch (NumberFormatException e) {
+               }
+       }
+
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
                Intent serverIntent = null;
@@ -485,6 +617,11 @@ public class AltosDroid extends FragmentActivity {
                        serverIntent = new Intent(this, DeviceListActivity.class);
                        startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
                        return true;
+               case R.id.quit:
+                       Log.d(TAG, "R.id.quit");
+                       stopService(new Intent(AltosDroid.this, TelemetryService.class));
+                       finish();
+                       return true;
                case R.id.select_freq:
                        // Set the TBT radio frequency
 
@@ -501,16 +638,40 @@ public class AltosDroid extends FragmentActivity {
                                "Channel 9 (435.450MHz)"
                        };
 
-                       AlertDialog.Builder builder = new AlertDialog.Builder(this);
-                       builder.setTitle("Pick a frequency");
-                       builder.setItems(frequencies,
+                       AlertDialog.Builder builder_freq = new AlertDialog.Builder(this);
+                       builder_freq.setTitle("Pick a frequency");
+                       builder_freq.setItems(frequencies,
                                         new DialogInterface.OnClickListener() {
                                                 public void onClick(DialogInterface dialog, int item) {
                                                         setFrequency(frequencies[item]);
                                                 }
                                         });
-                       AlertDialog alert = builder.create();
-                       alert.show();
+                       AlertDialog alert_freq = builder_freq.create();
+                       alert_freq.show();
+                       return true;
+               case R.id.select_rate:
+                       // Set the TBT baud rate
+
+                       final String[] rates = {
+                               "38400",
+                               "9600",
+                               "2400",
+                       };
+
+                       AlertDialog.Builder builder_rate = new AlertDialog.Builder(this);
+                       builder_rate.setTitle("Pick a baud rate");
+                       builder_rate.setItems(rates,
+                                        new DialogInterface.OnClickListener() {
+                                                public void onClick(DialogInterface dialog, int item) {
+                                                        setBaud(rates[item]);
+                                                }
+                                        });
+                       AlertDialog alert_rate = builder_rate.create();
+                       alert_rate.show();
+                       return true;
+               case R.id.change_units:
+                       boolean imperial = AltosPreferences.imperial_units();
+                       AltosPreferences.set_imperial_units(!imperial);
                        return true;
                }
                return false;
index f6e6881de3df550b08eb29832541af0ae8fc37e0..9cef131905abad0c1437dc1722aa155a0cbfba38 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2012 Mike Beattie <mike@ethernal.org>
+ * Copyright © 2014 Keith Packard <keithp@keithp.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
-
 package org.altusmetrum.AltosDroid;
 
-import java.io.File;
-import java.util.Map;
 import android.content.Context;
-import android.content.SharedPreferences;
-import android.os.Environment;
-
-import org.altusmetrum.altoslib_4.*;
-
-public class AltosDroidPreferences implements AltosPreferencesBackend {
-       public final static String        NAME    = "org.altusmetrum.AltosDroid";
-       private Context                   context = null;
-       private SharedPreferences         prefs   = null;
-       private SharedPreferences.Editor  editor  = null;
-
-       public AltosDroidPreferences(Context in_context) {
-               this(in_context, NAME);
-       }
-
-       public AltosDroidPreferences(Context in_context, String in_prefs) {
-               context = in_context;
-               prefs   = context.getSharedPreferences(in_prefs, 0);
-               editor  = prefs.edit();
-       }
-
-       public String[] keys() {
-               Map<String, ?> all = prefs.getAll();
-               return (String[])all.keySet().toArray();
-       }
-
-       public AltosPreferencesBackend node(String key) {
-               return new AltosDroidPreferences(context, key);
-       }
-
-       public boolean nodeExists(String key) {
-               return prefs.contains(key);
-       }
-
-       public boolean getBoolean(String key, boolean def) {
-               return prefs.getBoolean(key, def);
-       }
-
-       public double getDouble(String key, double def) {
-               Float f = Float.valueOf(prefs.getFloat(key, (float)def));
-               return f.doubleValue();
-       }
-
-       public int getInt(String key, int def) {
-               return prefs.getInt(key, def);
-       }
+import org.altusmetrum.altoslib_5.*;
 
-       public String getString(String key, String def) {
-               return prefs.getString(key, def);
-       }
+public class AltosDroidPreferences extends AltosPreferences {
 
-       public void putBoolean(String key, boolean value) {
-               editor.putBoolean(key, value);
-       }
+       /* Active device preference name */
+       final static String activeDevicePreference = "ACTIVE-DEVICE";
 
-       public void putDouble(String key, double value) {
-               editor.putFloat(key, (float)value);
-       }
+       static String active_device_address;
 
-       public void putInt(String key, int value) {
-               editor.putInt(key, value);
-       }
+       public static void init(Context context) {
+               if (backend != null)
+                       return;
 
-       public void putString(String key, String value) {
-               editor.putString(key, value);
-       }
+               AltosPreferences.init(new AltosDroidPreferencesBackend(context));
 
-       public void remove(String key) {
-               editor.remove(key);
+               active_device_address = backend.getString(activeDevicePreference, null);
        }
 
-       public void flush() {
-               editor.apply();
+       public static void set_active_device(String address) {
+               synchronized(backend) {
+                       active_device_address = address;
+                       backend.putString(activeDevicePreference, active_device_address);
+                       flush_preferences();
+               }
        }
 
-       public File homeDirectory() {
-               return Environment.getExternalStorageDirectory();
+       public static String active_device() {
+               synchronized(backend) {
+                       return active_device_address;
+               }
        }
 }
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java
new file mode 100644 (file)
index 0000000..be41ae7
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright © 2012 Mike Beattie <mike@ethernal.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.io.File;
+import java.util.Map;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Environment;
+
+import org.altusmetrum.altoslib_5.*;
+
+public class AltosDroidPreferencesBackend implements AltosPreferencesBackend {
+       public final static String        NAME    = "org.altusmetrum.AltosDroid";
+       private Context                   context = null;
+       private SharedPreferences         prefs   = null;
+       private SharedPreferences.Editor  editor  = null;
+
+       public AltosDroidPreferencesBackend(Context in_context) {
+               this(in_context, NAME);
+       }
+
+       public AltosDroidPreferencesBackend(Context in_context, String in_prefs) {
+               context = in_context;
+               prefs   = context.getSharedPreferences(in_prefs, 0);
+               editor  = prefs.edit();
+       }
+
+       public String[] keys() {
+               Map<String, ?> all = prefs.getAll();
+               return (String[])all.keySet().toArray();
+       }
+
+       public AltosPreferencesBackend node(String key) {
+               return new AltosDroidPreferencesBackend(context, key);
+       }
+
+       public boolean nodeExists(String key) {
+               return prefs.contains(key);
+       }
+
+       public boolean getBoolean(String key, boolean def) {
+               return prefs.getBoolean(key, def);
+       }
+
+       public double getDouble(String key, double def) {
+               Float f = Float.valueOf(prefs.getFloat(key, (float)def));
+               return f.doubleValue();
+       }
+
+       public int getInt(String key, int def) {
+               return prefs.getInt(key, def);
+       }
+
+       public String getString(String key, String def) {
+               return prefs.getString(key, def);
+       }
+
+       public void putBoolean(String key, boolean value) {
+               editor.putBoolean(key, value);
+       }
+
+       public void putDouble(String key, double value) {
+               editor.putFloat(key, (float)value);
+       }
+
+       public void putInt(String key, int value) {
+               editor.putInt(key, value);
+       }
+
+       public void putString(String key, String value) {
+               editor.putString(key, value);
+       }
+
+       public void remove(String key) {
+               editor.remove(key);
+       }
+
+       public void flush() {
+               editor.apply();
+       }
+
+       public File homeDirectory() {
+               return Environment.getExternalStorageDirectory();
+       }
+}
index fac4b8d4530027de625ccd39430828b6d940d1ab..8e625da6563b8268242d9166a6019cc23e47fac3 100644 (file)
 
 package org.altusmetrum.AltosDroid;
 
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 import android.location.Location;
+import android.app.Activity;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentTransaction;
+import android.support.v4.app.FragmentManager;
+import android.location.Location;
+import android.util.Log;
+import android.widget.TextView;
+
+public abstract class AltosDroidTab extends Fragment implements AltosUnitsListener {
+       AltosState              last_state;
+       AltosGreatCircle        last_from_receiver;
+       Location                last_receiver;
+
+       public abstract void show(AltosState state, AltosGreatCircle from_receiver, Location receiver);
+
+       public abstract String tab_name();
+
+       public void units_changed(boolean imperial_units) {
+               if (!isHidden() && last_state != null)
+                       show(last_state, last_from_receiver, last_receiver);
+       }
+
+       public void set_value(TextView text_view,
+                             AltosUnits units,
+                             int width,
+                             double value) {
+               if (value == AltosLib.MISSING)
+                       text_view.setText("");
+               else
+                       text_view.setText(units.show(width, value));
+       }
+
+       public void set_visible(boolean visible) {
+               FragmentTransaction     ft = AltosDroid.fm.beginTransaction();
+               if (visible) {
+                       AltosState              state = last_state;
+                       AltosGreatCircle        from_receiver = last_from_receiver;
+                       Location                receiver = last_receiver;
+
+                       show(state, from_receiver, receiver);
+                       ft.show(this);
+               } else
+                       ft.hide(this);
+               ft.commit();
+       }
+
+       public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver, boolean is_current) {
+               last_state = state;
+               last_from_receiver = from_receiver;
+               last_receiver = receiver;
+               if (is_current) {
+                       if (AltosDroid.D) Log.d(AltosDroid.TAG, String.format("%s: visible, performing update", tab_name()));
 
-public interface AltosDroidTab {
-       public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver);
+                       show(state, from_receiver, receiver);
+               } else {
+                       if (AltosDroid.D) Log.d(AltosDroid.TAG, String.format("%s: not visible, skipping update", tab_name()));
+                       return;
+               }
+       }
 }
index 5e8515cb35d8a06e753e6fdb210809e73199a2de..969992d3026c20f4fa1d94793353dd03457d6956 100644 (file)
@@ -21,7 +21,7 @@ package org.altusmetrum.AltosDroid;
 import android.speech.tts.TextToSpeech;
 import android.speech.tts.TextToSpeech.OnInitListener;
 
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public class AltosVoice {
 
@@ -45,7 +45,7 @@ public class AltosVoice {
 
        }
 
-       public void speak(String s) {
+       public synchronized void speak(String s) {
                if (!tts_enabled) return;
                tts.speak(s, TextToSpeech.QUEUE_ADD, null);
        }
@@ -58,7 +58,7 @@ public class AltosVoice {
                }
        }
 
-       public void tell(AltosState state) {
+       public void tell(AltosState state, AltosGreatCircle from_receiver) {
                if (!tts_enabled) return;
 
                boolean spoke = false;
@@ -68,12 +68,14 @@ public class AltosVoice {
                        if ((old_state == null || old_state.state <= AltosLib.ao_flight_boost) &&
                            state.state > AltosLib.ao_flight_boost) {
                                if (state.max_speed() != AltosLib.MISSING)
-                                       speak(String.format("max speed: %d meters per second.", (int) (state.max_speed() + 0.5)));
+                                       speak(String.format("Max speed: %s.",
+                                                           AltosConvert.speed.say_units(state.max_speed())));
                                spoke = true;
                        } else if ((old_state == null || old_state.state < AltosLib.ao_flight_drogue) &&
                                   state.state >= AltosLib.ao_flight_drogue) {
                                if (state.max_height() != AltosLib.MISSING)
-                                       speak(String.format("max height: %d meters.", (int) (state.max_height() + 0.5)));
+                                       speak(String.format("Max height: %s.",
+                                                           AltosConvert.height.say_units(state.max_height())));
                                spoke = true;
                        }
                }
@@ -87,13 +89,15 @@ public class AltosVoice {
                        }
                }
                old_state = state;
-               idle_thread.notice(state, spoke);
+               if (idle_thread != null)
+                       idle_thread.notice(state, from_receiver, spoke);
        }
 
 
        class IdleThread extends Thread {
                boolean            started;
                private AltosState state;
+               private AltosGreatCircle from_receiver;
                int                reported_landing;
                int                report_interval;
                long               report_time;
@@ -111,22 +115,30 @@ public class AltosVoice {
                                return;
                        }
 
-                       /* If the rocket isn't on the pad, then report height */
-                       if (((AltosLib.ao_flight_drogue <= state.state &&
+                       /* If the rocket isn't on the pad, then report location */
+                       if ((AltosLib.ao_flight_drogue <= state.state &&
                              state.state < AltosLib.ao_flight_landed) ||
-                            state.state == AltosLib.ao_flight_stateless) &&
-                           state.range >= 0)
+                            state.state == AltosLib.ao_flight_stateless)
                        {
-                               speak(String.format("Height %d, bearing %s %d, elevation %d, range %d.\n",
-                                                   (int) (state.height() + 0.5),
-                                       state.from_pad.bearing_words(
-                                             AltosGreatCircle.BEARING_VOICE),
-                                                   (int) (state.from_pad.bearing + 0.5),
-                                                   (int) (state.elevation + 0.5),
-                                                   (int) (state.range + 0.5)));
+                               AltosGreatCircle        position;
+
+                               if (from_receiver != null)
+                                       position = from_receiver;
+                               else
+                                       position = state.from_pad;
+
+                               if (position != null) {
+                                       speak(String.format("Height %s, bearing %s %d, elevation %d, range %s.\n",
+                                                           AltosConvert.height.say_units(state.height()),
+                                                           position.bearing_words(
+                                                                   AltosGreatCircle.BEARING_VOICE),
+                                                           (int) (position.bearing + 0.5),
+                                                           (int) (position.elevation + 0.5),
+                                                           AltosConvert.distance.say_units(position.range)));
+                               }
                        } else if (state.state > AltosLib.ao_flight_pad) {
                                if (state.height() != AltosLib.MISSING)
-                                       speak(String.format("%d meters", (int) (state.height() + 0.5)));
+                                       speak(AltosConvert.height.say_units(state.height()));
                        } else {
                                reported_landing = 0;
                        }
@@ -145,9 +157,9 @@ public class AltosVoice {
                                else
                                        speak("rocket may have crashed");
                                if (state.from_pad != null)
-                                       speak(String.format("Bearing %d degrees, range %d meters.",
+                                       speak(String.format("Bearing %d degrees, range %s.",
                                                            (int) (state.from_pad.bearing + 0.5),
-                                                           (int) (state.from_pad.distance + 0.5)));
+                                                           AltosConvert.distance.say_units(state.from_pad.distance)));
                                ++reported_landing;
                        }
                }
@@ -178,9 +190,10 @@ public class AltosVoice {
                        }
                }
 
-               public synchronized void notice(AltosState new_state, boolean spoken) {
+               public synchronized void notice(AltosState new_state, AltosGreatCircle new_from_receiver, boolean spoken) {
                        AltosState old_state = state;
                        state = new_state;
+                       from_receiver = new_from_receiver;
                        if (!started && state.state > AltosLib.ao_flight_pad) {
                                started = true;
                                start();
index 8e8d9c03a32c9105f0d6553b461a107d773a785e..267c90f8e57cc2f0df621f82959e5b9a344a4573 100644 (file)
@@ -20,6 +20,7 @@ package org.altusmetrum.AltosDroid;
 import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
 import android.widget.ImageView;
+import android.view.View;
 
 public class GoNoGoLights {
        private Boolean state;
@@ -51,14 +52,27 @@ public class GoNoGoLights {
                missing = m;
                set = true;
                if (missing) {
+                       hide();
                        red.setImageDrawable(dGray);
                        green.setImageDrawable(dGray);
                } else if (state) {
                        red.setImageDrawable(dGray);
                        green.setImageDrawable(dGreen);
+                       show();
                } else {
                        red.setImageDrawable(dRed);
                        green.setImageDrawable(dGray);
+                       show();
                }
        }
+
+       public void show() {
+               red.setVisibility(View.VISIBLE);
+               green.setVisibility(View.VISIBLE);
+       }
+
+       public void hide() {
+               red.setVisibility(View.GONE);
+               green.setVisibility(View.GONE);
+       }
 }
index e4a815eb6f929f57b218a2988da17fe25dc76215..fa4e3c8b3da13e7c5c957a422bf7e85ab1da9d62 100644 (file)
@@ -17,7 +17,7 @@
 
 package org.altusmetrum.AltosDroid;
 
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 import android.app.Activity;
 import android.os.Bundle;
@@ -29,7 +29,7 @@ import android.widget.ImageView;
 import android.widget.TextView;
 import android.location.Location;
 
-public class TabAscent extends Fragment implements AltosDroidTab {
+public class TabAscent extends AltosDroidTab {
        AltosDroid mAltosDroid;
 
        private TextView mHeightView;
@@ -85,14 +85,19 @@ public class TabAscent extends Fragment implements AltosDroidTab {
                mAltosDroid = null;
        }
 
-       public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver) {
+       public String tab_name() {
+               return "ascent";
+       }
+
+       public void show(AltosState state, AltosGreatCircle from_receiver, Location receiver) {
                if (state != null) {
-                       mHeightView.setText(AltosDroid.number("%6.0f m", state.height()));
-                       mMaxHeightView.setText(AltosDroid.number("%6.0f m", state.max_height()));
-                       mSpeedView.setText(AltosDroid.number("%6.0f m/s", state.speed()));
-                       mMaxSpeedView.setText(AltosDroid.number("%6.0f m/s", state.max_speed()));
-                       mAccelView.setText(AltosDroid.number("%6.0f m/s²", state.acceleration()));
-                       mMaxAccelView.setText(AltosDroid.number("%6.0f m/s²", state.max_acceleration()));
+                       set_value(mHeightView, AltosConvert.height, 6, state.height());
+                       set_value(mHeightView, AltosConvert.height, 6, state.height());
+                       set_value(mMaxHeightView, AltosConvert.height, 6, state.max_height());
+                       set_value(mSpeedView, AltosConvert.speed, 6, state.speed());
+                       set_value(mMaxSpeedView, AltosConvert.speed, 6, state.max_speed());
+                       set_value(mAccelView, AltosConvert.accel, 6, state.acceleration());
+                       set_value(mMaxAccelView, AltosConvert.accel, 6, state.max_acceleration());
 
                        if (state.gps != null) {
                                mLatitudeView.setText(AltosDroid.pos(state.gps.lat, "N", "S"));
index cbbe4d4473ab9bc62f09c201d0248e008def6737..28068666a4df627de6302450d8182936706205fa 100644 (file)
@@ -17,7 +17,7 @@
 
 package org.altusmetrum.AltosDroid;
 
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 import android.app.Activity;
 import android.os.Bundle;
@@ -29,7 +29,7 @@ import android.widget.ImageView;
 import android.widget.TextView;
 import android.location.Location;
 
-public class TabDescent extends Fragment implements AltosDroidTab {
+public class TabDescent extends AltosDroidTab {
        AltosDroid mAltosDroid;
 
        private TextView mSpeedView;
@@ -89,16 +89,18 @@ public class TabDescent extends Fragment implements AltosDroidTab {
                mAltosDroid = null;
        }
 
-       public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver) {
+       public String tab_name() { return "descent"; }
+
+       public void show(AltosState state, AltosGreatCircle from_receiver, Location receiver) {
                if (state != null) {
-                       mSpeedView.setText(AltosDroid.number("%6.0f m/s", state.speed()));
-                       mHeightView.setText(AltosDroid.number("%6.0f m", state.height()));
+                       set_value(mSpeedView, AltosConvert.speed, 6, state.speed());
+                       set_value(mHeightView, AltosConvert.height, 6, state.height());
                        if (from_receiver != null) {
                                mElevationView.setText(AltosDroid.number("%3.0f°", from_receiver.elevation));
-                               mRangeView.setText(AltosDroid.number("%6.0f m", from_receiver.range));
+                               set_value(mRangeView, AltosConvert.distance, 6, from_receiver.range);
                                mBearingView.setText(AltosDroid.number("%3.0f°", from_receiver.bearing));
                                mCompassView.setText(from_receiver.bearing_words(AltosGreatCircle.BEARING_LONG));
-                               mDistanceView.setText(AltosDroid.number("%6.0f m", from_receiver.distance));
+                               set_value(mDistanceView, AltosConvert.distance, 6, from_receiver.distance);
                        } else { 
                                mElevationView.setText("<unknown>");
                                mRangeView.setText("<unknown>");
index b2e6fd2016a87877cca3d12fa973804239f7f8d8..b257b9365d652c51fc67a3db2676138bb1fe53c6 100644 (file)
@@ -17,7 +17,7 @@
 
 package org.altusmetrum.AltosDroid;
 
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 import android.app.Activity;
 import android.os.Bundle;
@@ -28,7 +28,7 @@ import android.view.ViewGroup;
 import android.widget.TextView;
 import android.location.Location;
 
-public class TabLanded extends Fragment implements AltosDroidTab {
+public class TabLanded extends AltosDroidTab {
        AltosDroid mAltosDroid;
 
        private TextView mBearingView;
@@ -73,10 +73,12 @@ public class TabLanded extends Fragment implements AltosDroidTab {
                mAltosDroid = null;
        }
 
-       public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver) {
+       public String tab_name() { return "landed"; }
+
+       public void show(AltosState state, AltosGreatCircle from_receiver, Location receiver) {
                if (from_receiver != null) {
                        mBearingView.setText(String.format("%3.0f°", from_receiver.bearing));
-                       mDistanceView.setText(String.format("%6.0f m", from_receiver.distance));
+                       set_value(mDistanceView, AltosConvert.distance, 6, from_receiver.distance);
                }
                if (state != null && state.gps != null) {
                        mTargetLatitudeView.setText(AltosDroid.pos(state.gps.lat, "N", "S"));
@@ -87,12 +89,11 @@ public class TabLanded extends Fragment implements AltosDroidTab {
                        mReceiverLatitudeView.setText(AltosDroid.pos(receiver.getLatitude(), "N", "S"));
                        mReceiverLongitudeView.setText(AltosDroid.pos(receiver.getLongitude(), "W", "E"));
                }
-              
+
                if (state != null) {
-                       mMaxHeightView.setText(String.format("%6.0f m", state.max_height()));
-                       mMaxAccelView.setText(String.format("%6.0f m/s²", state.max_acceleration()));
-                       mMaxSpeedView.setText(String.format("%6.0f m/s", state.max_speed()));
+                       set_value(mMaxHeightView, AltosConvert.height, 6, state.max_height());
+                       set_value(mMaxAccelView, AltosConvert.accel, 6, state.max_acceleration());
+                       set_value(mMaxSpeedView, AltosConvert.speed, 6, state.max_speed());
                }
        }
-
 }
index 38922771f73f097e4938ccbddca1423ceca4a2a8..ab338ac26284cc45370a291d1edd99999435dee0 100644 (file)
@@ -19,7 +19,7 @@ package org.altusmetrum.AltosDroid;
 
 import java.util.Arrays;
 
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 import com.google.android.gms.maps.CameraUpdateFactory;
 import com.google.android.gms.maps.GoogleMap;
@@ -42,7 +42,7 @@ import android.view.ViewGroup;
 import android.widget.TextView;
 import android.location.Location;
 
-public class TabMap extends Fragment implements AltosDroidTab {
+public class TabMap extends AltosDroidTab {
        AltosDroid mAltosDroid;
 
        private SupportMapFragment mMapFragment;
@@ -51,6 +51,7 @@ public class TabMap extends Fragment implements AltosDroidTab {
 
        private Marker mRocketMarker;
        private Marker mPadMarker;
+       private boolean pad_set;
        private Polyline mPolyline;
 
        private TextView mDistanceView;
@@ -152,10 +153,12 @@ public class TabMap extends Fragment implements AltosDroidTab {
                }
        }
 
-       public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver) {
+       public String tab_name() { return "map"; }
+
+       public void show(AltosState state, AltosGreatCircle from_receiver, Location receiver) {
                if (from_receiver != null) {
                        mBearingView.setText(String.format("%3.0f°", from_receiver.bearing));
-                       mDistanceView.setText(String.format("%6.0f m", from_receiver.distance));
+                       set_value(mDistanceView, AltosConvert.distance, 6, from_receiver.distance);
                }
 
                if (state != null) {
@@ -168,7 +171,8 @@ public class TabMap extends Fragment implements AltosDroidTab {
                                        mPolyline.setVisible(true);
                                }
 
-                               if (state.state == AltosLib.ao_flight_pad) {
+                               if (!pad_set && state.pad_lat != AltosLib.MISSING) {
+                                       pad_set = true;
                                        mPadMarker.setPosition(new LatLng(state.pad_lat, state.pad_lon));
                                        mPadMarker.setVisible(true);
                                }
@@ -194,5 +198,4 @@ public class TabMap extends Fragment implements AltosDroidTab {
                }
 
        }
-
 }
index 2d88974d3d787f516c15ea352b6e3936a5cfae84..32df71d760a2543d55945f967ce2edfcd4a99a5f 100644 (file)
@@ -17,7 +17,7 @@
 
 package org.altusmetrum.AltosDroid;
 
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 import android.app.Activity;
 import android.os.Bundle;
@@ -29,14 +29,17 @@ import android.widget.ImageView;
 import android.widget.TextView;
 import android.location.Location;
 
-public class TabPad extends Fragment implements AltosDroidTab {
+public class TabPad extends AltosDroidTab {
        AltosDroid mAltosDroid;
 
        private TextView mBatteryVoltageView;
+       private TextView mBatteryVoltageLabel;
        private GoNoGoLights mBatteryLights;
        private TextView mApogeeVoltageView;
+       private TextView mApogeeVoltageLabel;
        private GoNoGoLights mApogeeLights;
        private TextView mMainVoltageView;
+       private TextView mMainVoltageLabel;
        private GoNoGoLights mMainLights;
        private TextView mDataLoggingView;
        private GoNoGoLights mDataLoggingLights;
@@ -59,16 +62,19 @@ public class TabPad extends Fragment implements AltosDroidTab {
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
                View v = inflater.inflate(R.layout.tab_pad, container, false);
                mBatteryVoltageView = (TextView) v.findViewById(R.id.battery_voltage_value);
+               mBatteryVoltageLabel = (TextView) v.findViewById(R.id.battery_voltage_label);
                mBatteryLights = new GoNoGoLights((ImageView) v.findViewById(R.id.battery_redled),
                                                  (ImageView) v.findViewById(R.id.battery_greenled),
                                                  getResources());
 
                mApogeeVoltageView = (TextView) v.findViewById(R.id.apogee_voltage_value);
+               mApogeeVoltageLabel = (TextView) v.findViewById(R.id.apogee_voltage_label);
                mApogeeLights = new GoNoGoLights((ImageView) v.findViewById(R.id.apogee_redled),
                                                 (ImageView) v.findViewById(R.id.apogee_greenled),
                                                 getResources());
 
                mMainVoltageView = (TextView) v.findViewById(R.id.main_voltage_value);
+               mMainVoltageLabel = (TextView) v.findViewById(R.id.main_voltage_label);
                mMainLights = new GoNoGoLights((ImageView) v.findViewById(R.id.main_redled),
                                               (ImageView) v.findViewById(R.id.main_greenled),
                                               getResources());
@@ -101,15 +107,29 @@ public class TabPad extends Fragment implements AltosDroidTab {
                mAltosDroid = null;
        }
 
-       public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver) {
+       public String tab_name() { return "pad"; }
+
+       public void show(AltosState state, AltosGreatCircle from_receiver, Location receiver) {
                if (state != null) {
                        mBatteryVoltageView.setText(AltosDroid.number("%4.2f V", state.battery_voltage));
                        mBatteryLights.set(state.battery_voltage >= AltosLib.ao_battery_good, state.battery_voltage == AltosLib.MISSING);
-
-                       mApogeeVoltageView.setText(AltosDroid.number("%4.2f V", state.apogee_voltage));
+                       if (state.apogee_voltage == AltosLib.MISSING) {
+                               mApogeeVoltageView.setVisibility(View.GONE);
+                               mApogeeVoltageLabel.setVisibility(View.GONE);
+                       } else {
+                               mApogeeVoltageView.setText(AltosDroid.number("%4.2f V", state.apogee_voltage));
+                               mApogeeVoltageView.setVisibility(View.VISIBLE);
+                               mApogeeVoltageLabel.setVisibility(View.VISIBLE);
+                       }
                        mApogeeLights.set(state.apogee_voltage >= AltosLib.ao_igniter_good, state.apogee_voltage == AltosLib.MISSING);
-
-                       mMainVoltageView.setText(AltosDroid.number("%4.2f V", state.main_voltage));
+                       if (state.main_voltage == AltosLib.MISSING) {
+                               mMainVoltageView.setVisibility(View.GONE);
+                               mMainVoltageLabel.setVisibility(View.GONE);
+                       } else {
+                               mMainVoltageView.setText(AltosDroid.number("%4.2f V", state.main_voltage));
+                               mMainVoltageView.setVisibility(View.VISIBLE);
+                               mMainVoltageLabel.setVisibility(View.VISIBLE);
+                       }
                        mMainLights.set(state.main_voltage >= AltosLib.ao_igniter_good, state.main_voltage == AltosLib.MISSING);
 
                        if (state.flight != 0) {
@@ -139,12 +159,12 @@ public class TabPad extends Fragment implements AltosDroidTab {
                }
 
                if (receiver != null) {
-                       double altitude = 0;
+                       double altitude = AltosLib.MISSING;
                        if (receiver.hasAltitude())
                                altitude = receiver.getAltitude();
                        mPadLatitudeView.setText(AltosDroid.pos(receiver.getLatitude(), "N", "S"));
                        mPadLongitudeView.setText(AltosDroid.pos(receiver.getLongitude(), "W", "E"));
-                       mPadAltitudeView.setText(AltosDroid.number("%4.0f m", altitude));
+                       set_value(mPadAltitudeView, AltosConvert.height, 6, altitude);
                }
        }
 
index a4758c376a4586df2e093ccda740c71bf895ea21..1ac34f9d5590ea5a2c0b8a16b030b9a9df5ba8fe 100644 (file)
@@ -21,6 +21,7 @@ import java.util.ArrayList;
 import android.content.Context;
 import android.os.Bundle;
 import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentTransaction;
 import android.support.v4.app.FragmentActivity;
 import android.support.v4.app.FragmentPagerAdapter;
 import android.support.v4.view.ViewPager;
@@ -28,8 +29,7 @@ import android.view.View;
 import android.view.ViewGroup;
 import android.widget.TabHost;
 import android.widget.TabWidget;
-
-
+import android.util.Log;
 
 /**
  * This is a helper class that implements the management of tabs and all
@@ -48,11 +48,13 @@ public class TabsAdapter extends FragmentPagerAdapter
        private final TabHost mTabHost;
        private final ViewPager mViewPager;
        private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
+       private int position;
 
-       static final class TabInfo {
+       static class TabInfo {
                private final String tag;
                private final Class<?> clss;
                private final Bundle args;
+               private Fragment fragment;
 
                TabInfo(String _tag, Class<?> _class, Bundle _args) {
                        tag = _tag;
@@ -104,11 +106,32 @@ public class TabsAdapter extends FragmentPagerAdapter
        @Override
        public Fragment getItem(int position) {
                TabInfo info = mTabs.get(position);
-               return Fragment.instantiate(mContext, info.clss.getName(), info.args);
+               Log.d(AltosDroid.TAG, String.format("TabsAdapter.getItem(%d)", position));
+               info.fragment = Fragment.instantiate(mContext, info.clss.getName(), info.args);
+               return info.fragment;
+       }
+
+       public Fragment currentItem() {
+               TabInfo info = mTabs.get(position);
+               return info.fragment;
        }
 
        public void onTabChanged(String tabId) {
-               int position = mTabHost.getCurrentTab();
+               AltosDroidTab   prev_frag = (AltosDroidTab) mTabs.get(position).fragment;
+
+               position = mTabHost.getCurrentTab();
+
+               AltosDroidTab   cur_frag = (AltosDroidTab) mTabs.get(position).fragment;
+
+               if (prev_frag != cur_frag) {
+                       if (prev_frag != null) {
+                               prev_frag.set_visible(false);
+                       }
+               }
+               if (cur_frag != null) {
+                       cur_frag.set_visible(true);
+               }
+               Log.d(AltosDroid.TAG, String.format("TabsAdapter.onTabChanged(%s) = %d", tabId, position));
                mViewPager.setCurrentItem(position);
        }
 
index 4215a3303df0d757a8b14ca80ee016f6654a2094..49bcfb884d6fc94792b44746a8d48aae0cf81095 100644 (file)
@@ -1,6 +1,6 @@
 package org.altusmetrum.AltosDroid;
 
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 import android.content.BroadcastReceiver;
 import android.content.Context;
index 5bc4b90dd9e417ec4901611e9b2b0b10ea968ac4..971c3e80ddab085af28e729d9e34e3197c25641c 100644 (file)
@@ -25,12 +25,13 @@ import java.util.concurrent.*;
 import android.util.Log;
 import android.os.Handler;
 
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 
 public class TelemetryReader extends Thread {
 
        private static final String TAG = "TelemetryReader";
+       private static final boolean D = true;
 
        int         crc_errors;
 
@@ -39,6 +40,8 @@ public class TelemetryReader extends Thread {
        AltosLink   link;
        AltosState  state = null;
 
+       AltosFlightReader       stacked;
+
        LinkedBlockingQueue<AltosLine> telemQueue;
 
        public AltosState read() throws ParseException, AltosCRCException, InterruptedException, IOException {
@@ -56,6 +59,10 @@ public class TelemetryReader extends Thread {
 
        public void close() {
                state = null;
+               if (stacked != null) {
+                       stacked.close(false);
+                       stacked = null;
+               }
                link.remove_monitor(telemQueue);
                link = null;
                telemQueue.clear();
@@ -66,7 +73,27 @@ public class TelemetryReader extends Thread {
                AltosState  state = null;
 
                try {
-                       for (;;) {
+                       if (D) Log.d(TAG, "starting reader");
+                       while (stacked != null) {
+                               AltosState      stacked_state = null;
+                               try {
+                                       stacked_state = stacked.read();
+                               } catch (ParseException pe) {
+                                       continue;
+                               } catch (AltosCRCException ce) {
+                                       continue;
+                               }
+                               if (stacked_state != null)
+                                       state = stacked_state;
+                               else
+                                       stacked = null;
+                       }
+                       if (state != null) {
+                               if (D) Log.d(TAG, "Send initial state");
+                               handler.obtainMessage(TelemetryService.MSG_TELEMETRY, state).sendToTarget();
+                       }
+                       if (D) Log.d(TAG, "starting loop");
+                       while (telemQueue != null) {
                                try {
                                        state = read();
                                        handler.obtainMessage(TelemetryService.MSG_TELEMETRY, state).sendToTarget();
@@ -84,12 +111,34 @@ public class TelemetryReader extends Thread {
                }
        }
 
-       public TelemetryReader (AltosLink in_link, Handler in_handler) {
+       public TelemetryReader (AltosLink in_link, Handler in_handler, AltosFlightReader in_stacked) {
+               if (D) Log.d(TAG, "connected TelemetryReader create started");
                link    = in_link;
                handler = in_handler;
+               stacked = in_stacked;
 
                state = null;
                telemQueue = new LinkedBlockingQueue<AltosLine>();
                link.add_monitor(telemQueue);
+               link.set_telemetry(AltosLib.ao_telemetry_standard);
+
+               if (D) Log.d(TAG, "connected TelemetryReader created");
+       }
+
+       private static AltosFlightReader existing_data(AltosLink link) {
+               if (link == null)
+                       return null;
+
+               File    file = AltosPreferences.logfile(link.serial);
+               if (file != null) {
+                       AltosStateIterable      iterable = AltosStateIterable.iterable(file);
+                       if (iterable != null)
+                               return new AltosReplayReader(iterable.iterator(), file, false);
+               }
+               return null;
+       }
+
+       public TelemetryReader(AltosLink link, Handler handler) {
+               this(link, handler, existing_data(link));
        }
 }
index da5e044f0abc5b122416b996c4c81149ccb07c11..30d94409a917a339aeeed88b4de31ca560a843b5 100644 (file)
@@ -28,6 +28,7 @@ import android.app.Notification;
 import android.app.PendingIntent;
 import android.app.Service;
 import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothAdapter;
 import android.content.Intent;
 import android.content.Context;
 import android.os.Bundle;
@@ -44,7 +45,7 @@ import android.location.LocationManager;
 import android.location.LocationListener;
 import android.location.Criteria;
 
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 
 public class TelemetryService extends Service implements LocationListener {
@@ -61,11 +62,7 @@ public class TelemetryService extends Service implements LocationListener {
        static final int MSG_TELEMETRY         = 7;
        static final int MSG_SETFREQUENCY      = 8;
        static final int MSG_CRC_ERROR         = 9;
-
-       public static final int STATE_NONE       = 0;
-       public static final int STATE_READY      = 1;
-       public static final int STATE_CONNECTING = 2;
-       public static final int STATE_CONNECTED  = 3;
+       static final int MSG_SETBAUD           = 10;
 
        // Unique Identification Number for the Notification.
        // We use it on Notification start, and to cancel it.
@@ -80,21 +77,17 @@ public class TelemetryService extends Service implements LocationListener {
        final Messenger mMessenger = new Messenger(mHandler); // Target we publish for clients to send messages to IncomingHandler.
 
        // Name of the connected device
-       private BluetoothDevice device           = null;
+       String address;
        private AltosBluetooth  mAltosBluetooth  = null;
-       private AltosConfigData mConfigData      = null;
        private TelemetryReader mTelemetryReader = null;
        private TelemetryLogger mTelemetryLogger = null;
+       // Local Bluetooth adapter
+       private BluetoothAdapter mBluetoothAdapter = null;
 
-       // internally track state of bluetooth connection
-       private int state = STATE_NONE;
+       private TelemetryState  telemetry_state;
 
        // Last data seen; send to UI when it starts
 
-       private AltosState last_state;
-       private Location last_location;
-       private int last_crc_errors;
-
        // Handler of incoming messages from clients.
        static class IncomingHandler extends Handler {
                private final WeakReference<TelemetryService> service;
@@ -103,17 +96,15 @@ public class TelemetryService extends Service implements LocationListener {
                @Override
                public void handleMessage(Message msg) {
                        TelemetryService s = service.get();
+                       if (s == null)
+                               return;
                        switch (msg.what) {
                        case MSG_REGISTER_CLIENT:
                                s.mClients.add(msg.replyTo);
                                try {
                                        // Now we try to send the freshly connected UI any relavant information about what
-                                       // we're talking to - Basically state and Config Data.
-                                       msg.replyTo.send(Message.obtain(null, AltosDroid.MSG_STATE_CHANGE, s.state, -1, s.mConfigData));
-                                       // We also send any recent telemetry or location data that's cached
-                                       if (s.last_state      != null) msg.replyTo.send(Message.obtain(null, AltosDroid.MSG_TELEMETRY, s.last_state     ));
-                                       if (s.last_location   != null) msg.replyTo.send(Message.obtain(null, AltosDroid.MSG_LOCATION , s.last_location  ));
-                                       if (s.last_crc_errors != 0   ) msg.replyTo.send(Message.obtain(null, AltosDroid.MSG_CRC_ERROR, s.last_crc_errors));
+                                       // we're talking to
+                                       msg.replyTo.send(s.message());
                                } catch (RemoteException e) {
                                        s.mClients.remove(msg.replyTo);
                                }
@@ -125,42 +116,59 @@ public class TelemetryService extends Service implements LocationListener {
                                break;
                        case MSG_CONNECT:
                                if (D) Log.d(TAG, "Connect command received");
-                               s.device = (BluetoothDevice) msg.obj;
-                               s.startAltosBluetooth();
+                               String address = (String) msg.obj;
+                               AltosDroidPreferences.set_active_device(address);
+                               s.startAltosBluetooth(address);
                                break;
                        case MSG_CONNECTED:
                                if (D) Log.d(TAG, "Connected to device");
-                               s.connected();
+                               try {
+                                       s.connected();
+                               } catch (InterruptedException ie) {
+                               }
                                break;
                        case MSG_CONNECT_FAILED:
                                if (D) Log.d(TAG, "Connection failed... retrying");
-                               s.startAltosBluetooth();
+                               if (s.address != null)
+                                       s.startAltosBluetooth(s.address);
                                break;
                        case MSG_DISCONNECTED:
-                               // Only do the following if we haven't been shutdown elsewhere..
-                               if (s.device != null) {
-                                       if (D) Log.d(TAG, "Disconnected from " + s.device.getName());
-                                       s.stopAltosBluetooth();
-                               }
+                               Log.d(TAG, "MSG_DISCONNECTED");
+                               s.stopAltosBluetooth();
                                break;
                        case MSG_TELEMETRY:
                                // forward telemetry messages
-                               s.last_state = (AltosState) msg.obj;
-                               s.sendMessageToClients(Message.obtain(null, AltosDroid.MSG_TELEMETRY, msg.obj));
+                               s.telemetry_state.state = (AltosState) msg.obj;
+                               if (D) Log.d(TAG, "MSG_TELEMETRY");
+                               s.sendMessageToClients();
                                break;
                        case MSG_CRC_ERROR:
                                // forward crc error messages
-                               s.last_crc_errors = (Integer) msg.obj;
-                               s.sendMessageToClients(Message.obtain(null, AltosDroid.MSG_CRC_ERROR, msg.obj));
+                               s.telemetry_state.crc_errors = (Integer) msg.obj;
+                               if (D) Log.d(TAG, "MSG_CRC_ERROR");
+                               s.sendMessageToClients();
                                break;
                        case MSG_SETFREQUENCY:
-                               if (s.state == STATE_CONNECTED) {
+                               if (D) Log.d(TAG, "MSG_SETFREQUENCY");
+                               s.telemetry_state.frequency = (Double) msg.obj;
+                               if (s.telemetry_state.connect == TelemetryState.CONNECT_CONNECTED) {
                                        try {
-                                               s.mAltosBluetooth.set_radio_frequency((Double) msg.obj);
+                                               s.mAltosBluetooth.set_radio_frequency(s.telemetry_state.frequency);
+                                               s.mAltosBluetooth.save_frequency();
                                        } catch (InterruptedException e) {
                                        } catch (TimeoutException e) {
                                        }
                                }
+                               s.sendMessageToClients();
+                               break;
+                       case MSG_SETBAUD:
+                               if (D) Log.d(TAG, "MSG_SETBAUD");
+                               s.telemetry_state.telemetry_rate = (Integer) msg.obj;
+                               if (s.telemetry_state.connect == TelemetryState.CONNECT_CONNECTED) {
+                                       s.mAltosBluetooth.set_telemetry_rate(s.telemetry_state.telemetry_rate);
+                                       s.mAltosBluetooth.save_telemetry_rate();
+                               }
+                               s.sendMessageToClients();
                                break;
                        default:
                                super.handleMessage(msg);
@@ -168,9 +176,18 @@ public class TelemetryService extends Service implements LocationListener {
                }
        }
 
-       private void sendMessageToClients(Message m) {
+       private Message message() {
+               if (telemetry_state == null)
+                       Log.d(TAG, "telemetry_state null!");
+               return Message.obtain(null, AltosDroid.MSG_STATE, telemetry_state);
+       }
+
+       private void sendMessageToClients() {
+               Message m = message();
+               if (D) Log.d(TAG, String.format("Send message to %d clients", mClients.size()));
                for (int i=mClients.size()-1; i>=0; i--) {
                        try {
+                               if (D) Log.d(TAG, String.format("Send message to client %d", i));
                                mClients.get(i).send(m);
                        } catch (RemoteException e) {
                                mClients.remove(i);
@@ -180,7 +197,7 @@ public class TelemetryService extends Service implements LocationListener {
 
        private void stopAltosBluetooth() {
                if (D) Log.d(TAG, "stopAltosBluetooth(): begin");
-               setState(STATE_READY);
+               telemetry_state.connect = TelemetryState.CONNECT_READY;
                if (mTelemetryReader != null) {
                        if (D) Log.d(TAG, "stopAltosBluetooth(): stopping TelemetryReader");
                        mTelemetryReader.interrupt();
@@ -200,18 +217,21 @@ public class TelemetryService extends Service implements LocationListener {
                        mAltosBluetooth.close();
                        mAltosBluetooth = null;
                }
-               device = null;
-               mConfigData = null;
+               telemetry_state.config = null;
+               if (D) Log.d(TAG, "stopAltosBluetooth(): send message to clients");
+               sendMessageToClients();
        }
 
-       private void startAltosBluetooth() {
-               if (device == null) {
-                       return;
-               }
+       private void startAltosBluetooth(String address) {
+               // Get the BLuetoothDevice object
+               BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
+
+               this.address = address;
                if (mAltosBluetooth == null) {
                        if (D) Log.d(TAG, String.format("startAltosBluetooth(): Connecting to %s (%s)", device.getName(), device.getAddress()));
                        mAltosBluetooth = new AltosBluetooth(device, mHandler);
-                       setState(STATE_CONNECTING);
+                       telemetry_state.connect = TelemetryState.CONNECT_CONNECTING;
+                       sendMessageToClients();
                } else {
                        // This is a bit of a hack - if it appears we're still connected, we treat this as a restart.
                        // So, to give a suitable delay to teardown/bringup, we just schedule a resend of a message
@@ -219,28 +239,19 @@ public class TelemetryService extends Service implements LocationListener {
                        // ... then we tear down the existing connection.
                        // We do it this way around so that we don't lose a reference to the device when this method
                        // is called on reception of MSG_CONNECT_FAILED in the handler above.
-                       mHandler.sendMessageDelayed(Message.obtain(null, MSG_CONNECT, device), 3000);
+                       mHandler.sendMessageDelayed(Message.obtain(null, MSG_CONNECT, address), 3000);
                        stopAltosBluetooth();
                }
        }
 
-       private synchronized void setState(int s) {
-               if (D) Log.d(TAG, "setState(): " + state + " -> " + s);
-               state = s;
-
-               // This shouldn't be required - mConfigData should be null for any non-connected
-               // state, but to be safe and to reduce message size
-               AltosConfigData acd = (state == STATE_CONNECTED) ? mConfigData : null;
-
-               sendMessageToClients(Message.obtain(null, AltosDroid.MSG_STATE_CHANGE, state, -1, acd));
-       }
-
-       private void connected() {
+       private void connected() throws InterruptedException {
+               if (D) Log.d(TAG, "connected top");
                try {
                        if (mAltosBluetooth == null)
                                throw new InterruptedException("no bluetooth");
-                       mConfigData = mAltosBluetooth.config_data();
-               } catch (InterruptedException e) {
+                       telemetry_state.config = mAltosBluetooth.config_data();
+                       mAltosBluetooth.set_radio_frequency(telemetry_state.frequency);
+                       mAltosBluetooth.set_telemetry_rate(telemetry_state.telemetry_rate);
                } catch (TimeoutException e) {
                        // If this timed out, then we really want to retry it, but
                        // probably safer to just retry the connection from scratch.
@@ -248,19 +259,25 @@ public class TelemetryService extends Service implements LocationListener {
                        return;
                }
 
-               setState(STATE_CONNECTED);
+               if (D) Log.d(TAG, "connected bluetooth configured");
+               telemetry_state.connect = TelemetryState.CONNECT_CONNECTED;
 
                mTelemetryReader = new TelemetryReader(mAltosBluetooth, mHandler);
                mTelemetryReader.start();
-               
+
+               if (D) Log.d(TAG, "connected TelemetryReader started");
+
                mTelemetryLogger = new TelemetryLogger(this, mAltosBluetooth);
-       }
 
+               if (D) Log.d(TAG, "Notify UI of connection");
+
+               sendMessageToClients();
+       }
 
        private void onTimerTick() {
                if (D) Log.d(TAG, "Timer wakeup");
                try {
-                       if (mClients.size() <= 0 && state != STATE_CONNECTED) {
+                       if (mClients.size() <= 0 && telemetry_state.connect != TelemetryState.CONNECT_CONNECTED) {
                                stopSelf();
                        }
                } catch (Throwable t) {
@@ -271,19 +288,35 @@ public class TelemetryService extends Service implements LocationListener {
 
        @Override
        public void onCreate() {
+               // Get local Bluetooth adapter
+               mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+
+               // If the adapter is null, then Bluetooth is not supported
+               if (mBluetoothAdapter == null) {
+                       Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();
+               }
+
+               // Initialise preferences
+               AltosDroidPreferences.init(this);
+
+               telemetry_state = new TelemetryState();
+
                // Create a reference to the NotificationManager so that we can update our notifcation text later
                //mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
 
-               setState(STATE_READY);
+               telemetry_state.connect = TelemetryState.CONNECT_READY;
 
                // Start our timer - first event in 10 seconds, then every 10 seconds after that.
                timer.scheduleAtFixedRate(new TimerTask(){ public void run() {onTimerTick();}}, 10000L, 10000L);
 
                // Listen for GPS and Network position updates
                LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
-               
+
                locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, this);
-//             locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
+
+               String address = AltosDroidPreferences.active_device();
+               if (address != null)
+                       startAltosBluetooth(address);
        }
 
        @Override
@@ -339,8 +372,9 @@ public class TelemetryService extends Service implements LocationListener {
 
 
        public void onLocationChanged(Location location) {
-               last_location = location;
-               sendMessageToClients(Message.obtain(null, AltosDroid.MSG_LOCATION, location));
+               telemetry_state.location = location;
+               if (D) Log.d(TAG, "location changed");
+               sendMessageToClients();
        }
 
        public void onStatusChanged(String provider, int status, Bundle extras) {
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryState.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryState.java
new file mode 100644 (file)
index 0000000..d334173
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright © 2012 Mike Beattie <mike@ethernal.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import org.altusmetrum.altoslib_5.*;
+import android.location.Location;
+
+public class TelemetryState {
+       public static final int CONNECT_NONE       = 0;
+       public static final int CONNECT_READY      = 1;
+       public static final int CONNECT_CONNECTING = 2;
+       public static final int CONNECT_CONNECTED  = 3;
+
+       int             connect;
+       AltosConfigData config;
+       AltosState      state;
+       Location        location;
+       int             crc_errors;
+       double          frequency;
+       int             telemetry_rate;
+
+       public TelemetryState() {
+               connect = CONNECT_NONE;
+               config = null;
+               state = null;
+               location = null;
+               crc_errors = 0;
+               frequency = AltosPreferences.frequency(0);
+               telemetry_rate = AltosPreferences.telemetry_rate(0);
+       }
+}
index 3d340e5d2c32f7d31e1a11535cf9cdef0133f4be..d91da4dab0235ec35742e142ad2b60dec8cb8165 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public class AltosAccel extends AltosUnits {
 
index 253ca435dc83753330397a623639133ace8401b3..507c446bdbe05a6c550b2cfd56f8747dfd7c492d 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public class AltosCRCException extends Exception {
        public int rssi;
index 27e1fade54c76bdb54b4cae8a3b16a6c66369edc..4a9278d901fefd1348120d4a5d72d4f75991cf8f 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 import java.util.*;
@@ -29,6 +29,14 @@ public class AltosCSV implements AltosWriter {
        LinkedList<AltosState>  pad_states;
        AltosState              state;
 
+       static boolean          has_basic;
+       static boolean          has_battery;
+       static boolean          has_flight_state;
+       static boolean          has_advanced;
+       static boolean          has_gps;
+       static boolean          has_gps_sat;
+       static boolean          has_companion;
+
        static final int ALTOS_CSV_VERSION = 5;
 
        /* Version 4 format:
@@ -55,10 +63,12 @@ public class AltosCSV implements AltosWriter {
         *      accelerometer speed (m/s)
         *      barometer speed (m/s)
         *      temp (°C)
-        *      battery (V)
         *      drogue (V)
         *      main (V)
         *
+        * Battery
+        *      battery (V)
+        *
         * Advanced sensors (if available)
         *      accel_x (m/s²)
         *      accel_y (m/s²)
@@ -87,7 +97,9 @@ public class AltosCSV implements AltosWriter {
         *      from_pad_azimuth (deg true)
         *      from_pad_range (m)
         *      from_pad_elevation (deg from horizon)
+        *      pdop
         *      hdop
+        *      vdop
         *
         * GPS Sat data
         *      C/N0 data for all 32 valid SDIDs
@@ -107,7 +119,7 @@ public class AltosCSV implements AltosWriter {
        void write_general(AltosState state) {
                out.printf("%s, %d, %d, %s, %8.2f, %8.2f, %4d, %3d",
                           ALTOS_CSV_VERSION, state.serial, state.flight, state.callsign,
-                          (double) state.time, (double) state.tick / 100.0,
+                          (double) state.time_since_boost(), (double) state.tick / 100.0,
                           state.rssi,
                           state.status & 0x7f);
        }
@@ -121,11 +133,11 @@ public class AltosCSV implements AltosWriter {
        }
 
        void write_basic_header() {
-               out.printf("acceleration,pressure,altitude,height,accel_speed,baro_speed,temperature,battery_voltage,drogue_voltage,main_voltage");
+               out.printf("acceleration,pressure,altitude,height,accel_speed,baro_speed,temperature,drogue_voltage,main_voltage");
        }
 
        void write_basic(AltosState state) {
-               out.printf("%8.2f,%10.2f,%8.2f,%8.2f,%8.2f,%8.2f,%5.1f,%5.2f,%5.2f,%5.2f",
+               out.printf("%8.2f,%10.2f,%8.2f,%8.2f,%8.2f,%8.2f,%5.1f,%5.2f,%5.2f",
                           state.acceleration(),
                           state.pressure(),
                           state.altitude(),
@@ -133,11 +145,18 @@ public class AltosCSV implements AltosWriter {
                           state.speed(),
                           state.speed(),
                           state.temperature,
-                          state.battery_voltage,
                           state.apogee_voltage,
                           state.main_voltage);
        }
 
+       void write_battery_header() {
+               out.printf("battery_voltage");
+       }
+
+       void write_battery(AltosState state) {
+               out.printf("%5.2f", state.battery_voltage);
+       }
+
        void write_advanced_header() {
                out.printf("accel_x,accel_y,accel_z,gyro_x,gyro_y,gyro_z");
        }
@@ -150,14 +169,14 @@ public class AltosCSV implements AltosWriter {
                        imu = new AltosIMU();
                if (mag == null)
                        mag = new AltosMag();
-               out.printf("%6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d",
+               out.printf("%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f",
                           imu.accel_x, imu.accel_y, imu.accel_z,
                           imu.gyro_x, imu.gyro_y, imu.gyro_z,
                           mag.x, mag.y, mag.z);
        }
 
        void write_gps_header() {
-               out.printf("connected,locked,nsat,latitude,longitude,altitude,year,month,day,hour,minute,second,pad_dist,pad_range,pad_az,pad_el,hdop");
+               out.printf("connected,locked,nsat,latitude,longitude,altitude,year,month,day,hour,minute,second,pad_dist,pad_range,pad_az,pad_el,pdop,hdop,vdop");
        }
 
        void write_gps(AltosState state) {
@@ -169,7 +188,7 @@ public class AltosCSV implements AltosWriter {
                if (from_pad == null)
                        from_pad = new AltosGreatCircle();
 
-               out.printf("%2d,%2d,%3d,%12.7f,%12.7f,%8.1f,%5d,%3d,%3d,%3d,%3d,%3d,%9.0f,%9.0f,%4.0f,%4.0f,%6.1f",
+               out.printf("%2d,%2d,%3d,%12.7f,%12.7f,%8.1f,%5d,%3d,%3d,%3d,%3d,%3d,%9.0f,%9.0f,%4.0f,%4.0f,%6.1f,%6.1f,%6.1f",
                           gps.connected?1:0,
                           gps.locked?1:0,
                           gps.nsat,
@@ -186,7 +205,9 @@ public class AltosCSV implements AltosWriter {
                           state.range,
                           from_pad.bearing,
                           state.elevation,
-                          gps.hdop);
+                          gps.pdop,
+                          gps.hdop,
+                          gps.vdop);
        }
 
        void write_gps_sat_header() {
@@ -239,52 +260,83 @@ public class AltosCSV implements AltosWriter {
                        out.printf(",0");
        }
 
-       void write_header(boolean advanced, boolean gps, boolean companion) {
+       void write_header() {
                out.printf("#"); write_general_header();
-               out.printf(","); write_flight_header();
-               out.printf(","); write_basic_header();
-               if (advanced)
-                       out.printf(","); write_advanced_header();
-               if (gps) {
-                       out.printf(","); write_gps_header();
-                       out.printf(","); write_gps_sat_header();
+               if (has_flight_state) {
+                       out.printf(",");
+                       write_flight_header();
                }
-               if (companion) {
-                       out.printf(","); write_companion_header();
+               if (has_basic) {
+                       out.printf(",");
+                       write_basic_header();
+               }
+               if (has_battery) {
+                       out.printf(",");
+                       write_battery_header();
+               }
+               if (has_advanced) {
+                       out.printf(",");
+                       write_advanced_header();
+               }
+               if (has_gps) {
+                       out.printf(",");
+                       write_gps_header();
+               }
+               if (has_gps_sat) {
+                       out.printf(",");
+                       write_gps_sat_header();
+               }
+               if (has_companion) {
+                       out.printf(",");
+                       write_companion_header();
                }
                out.printf ("\n");
        }
 
        void write_one(AltosState state) {
-               write_general(state); out.printf(",");
-               write_flight(state); out.printf(",");
-               write_basic(state); out.printf(",");
-               if (state.imu != null || state.mag != null)
+               write_general(state);
+               if (has_flight_state) {
+                       out.printf(",");
+                       write_flight(state);
+               }
+               if (has_basic) {
+                       out.printf(",");
+                       write_basic(state);
+               }
+               if (has_battery) {
+                       out.printf(",");
+                       write_battery(state);
+               }
+               if (has_advanced) {
+                       out.printf(",");
                        write_advanced(state);
-               if (state.gps != null) {
+               }
+               if (has_gps) {
+                       out.printf(",");
+                       write_gps(state);
+               }
+               if (has_gps_sat) {
                        out.printf(",");
-                       write_gps(state); out.printf(",");
                        write_gps_sat(state);
                }
-               if (state.companion != null) {
+               if (has_companion) {
                        out.printf(",");
                        write_companion(state);
                }
                out.printf ("\n");
        }
 
-       void flush_pad() {
+       private void flush_pad() {
                while (!pad_states.isEmpty()) {
                        write_one (pad_states.remove());
                }
        }
 
-       public void write(AltosState state) {
+       private void write(AltosState state) {
                if (state.state == AltosLib.ao_flight_startup)
                        return;
                if (!header_written) {
-                       write_header(state.imu != null || state.mag != null,
-                                    state.gps != null, state.companion != null);
+                       write_header();
                        header_written = true;
                }
                if (!seen_boost) {
@@ -300,7 +352,7 @@ public class AltosCSV implements AltosWriter {
                        pad_states.add(state);
        }
 
-       public PrintStream out() {
+       private PrintStream out() {
                return out;
        }
 
@@ -314,6 +366,31 @@ public class AltosCSV implements AltosWriter {
 
        public void write(AltosStateIterable states) {
                states.write_comments(out());
+
+               has_flight_state = false;
+               has_basic = false;
+               has_battery = false;
+               has_advanced = false;
+               has_gps = false;
+               has_gps_sat = false;
+               has_companion = false;
+               for (AltosState state : states) {
+                       if (state.state != AltosLib.ao_flight_stateless && state.state != AltosLib.ao_flight_invalid && state.state != AltosLib.ao_flight_startup)
+                               has_flight_state = true;
+                       if (state.acceleration() != AltosLib.MISSING || state.pressure() != AltosLib.MISSING)
+                               has_basic = true;
+                       if (state.battery_voltage != AltosLib.MISSING)
+                               has_battery = true;
+                       if (state.imu != null || state.mag != null)
+                               has_advanced = true;
+                       if (state.gps != null) {
+                               has_gps = true;
+                               if (state.gps.cc_gps_sat != null)
+                                       has_gps_sat = true;
+                       }
+                       if (state.companion != null)
+                               has_companion = true;
+               }
                for (AltosState state : states)
                        write(state);
        }
index 09bfe9f3c7482e3a5238b27e7340be074ee1de63..47deb2a3dd1be6bb0212eb5ce767bd7d931ed8d2 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public class AltosCompanion {
        public final static int board_id_telescience = 0x0a;
index e104395803c7dd2cc3ba63b36fe8d8081d99c350..fc1f2442ebfa04fd66074a096449eda21022fdc3 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.util.*;
 import java.text.*;
@@ -31,6 +31,7 @@ public class AltosConfigData implements Iterable<String> {
        public int      log_format;
        public int      log_space;
        public String   version;
+       public int      altitude_32;
 
        /* Strings returned */
        public LinkedList<String>       lines;
@@ -46,6 +47,7 @@ public class AltosConfigData implements Iterable<String> {
        public String   callsign;
        public int      radio_enable;
        public int      radio_calibration;
+       public int      telemetry_rate;
        /* Old HAS_RADIO values */
        public int      radio_channel;
        public int      radio_setting;
@@ -56,6 +58,7 @@ public class AltosConfigData implements Iterable<String> {
 
        /* HAS_LOG */
        public int      flight_log_max;
+       public int      log_fixed;
 
        /* HAS_IGNITE */
        public int      ignite_mode;
@@ -71,6 +74,7 @@ public class AltosConfigData implements Iterable<String> {
 
        /* HAS_APRS */
        public int              aprs_interval;
+       public int              aprs_ssid;
 
        /* HAS_BEEP */
        public int              beep;
@@ -234,12 +238,14 @@ public class AltosConfigData implements Iterable<String> {
                radio_calibration = -1;
                radio_channel = -1;
                radio_setting = -1;
+               telemetry_rate = -1;
 
                accel_cal_plus = -1;
                accel_cal_minus = -1;
                pad_orientation = -1;
 
                flight_log_max = -1;
+               log_fixed = -1;
                ignite_mode = -1;
 
                aes_key = "";
@@ -250,6 +256,7 @@ public class AltosConfigData implements Iterable<String> {
                pyro_firing_time = -1;
 
                aprs_interval = -1;
+               aprs_ssid = -1;
 
                beep = -1;
 
@@ -270,6 +277,7 @@ public class AltosConfigData implements Iterable<String> {
                try { flight = get_int(line, "current-flight"); } catch (Exception e) {}
                try { log_format = get_int(line, "log-format"); } catch (Exception e) {}
                try { log_space = get_int(line, "log-space"); } catch (Exception e) {}
+               try { altitude_32 = get_int(line, "altitude-32"); } catch (Exception e) {}
                try { version = get_string(line, "software-version"); } catch (Exception e) {}
 
                /* Version also contains MS5607 info, which we ignore here */
@@ -290,6 +298,7 @@ public class AltosConfigData implements Iterable<String> {
                try { callsign = get_string(line, "Callsign:"); } catch (Exception e) {}
                try { radio_enable = get_int(line, "Radio enable:"); } catch (Exception e) {}
                try { radio_calibration = get_int(line, "Radio cal:"); } catch (Exception e) {}
+               try { telemetry_rate = get_int(line, "Telemetry rate:"); } catch (Exception e) {}
 
                /* Old HAS_RADIO values */
                try { radio_channel = get_int(line, "Radio channel:"); } catch (Exception e) {}
@@ -309,6 +318,7 @@ public class AltosConfigData implements Iterable<String> {
 
                /* HAS_LOG */
                try { flight_log_max = get_int(line, "Max flight log:"); } catch (Exception e) {}
+               try { log_fixed = get_int(line, "Log fixed:"); } catch (Exception e) {}
 
                /* HAS_IGNITE */
                try { ignite_mode = get_int(line, "Ignite mode:"); } catch (Exception e) {}
@@ -333,6 +343,7 @@ public class AltosConfigData implements Iterable<String> {
 
                /* HAS_APRS */
                try { aprs_interval = get_int(line, "APRS interval:"); } catch (Exception e) {}
+               try { aprs_ssid = get_int(line, "APRS SSID:"); } catch (Exception e) {}
 
                /* HAS_BEEP */
                try { beep = get_int(line, "Beeper setting:"); } catch (Exception e) {}
@@ -375,6 +386,10 @@ public class AltosConfigData implements Iterable<String> {
                return radio_frequency >= 0 || radio_setting >= 0 || radio_channel >= 0;
        }
 
+       public boolean has_telemetry_rate() {
+               return telemetry_rate >= 0;
+       }
+
        public void set_frequency(double freq) {
                int     frequency = radio_frequency;
                int     setting = radio_setting;
@@ -414,6 +429,8 @@ public class AltosConfigData implements Iterable<String> {
                        return false;
                if (product.startsWith("TeleMetrum-v2"))
                        return false;
+               if (product.startsWith("EasyMega"))
+                       return false;
                return true;
        }
 
@@ -437,6 +454,8 @@ public class AltosConfigData implements Iterable<String> {
                        callsign = source.callsign();
                if (radio_calibration >= 0)
                        radio_calibration = source.radio_calibration();
+               if (telemetry_rate >= 0)
+                       telemetry_rate = source.telemetry_rate();
 
                /* HAS_ACCEL */
                if (pad_orientation >= 0)
@@ -459,6 +478,8 @@ public class AltosConfigData implements Iterable<String> {
                /* HAS_APRS */
                if (aprs_interval >= 0)
                        aprs_interval = source.aprs_interval();
+               if (aprs_ssid >= 0)
+                       aprs_ssid = source.aprs_ssid();
 
                /* HAS_BEEP */
                if (beep >= 0)
@@ -474,16 +495,21 @@ public class AltosConfigData implements Iterable<String> {
                dest.set_serial(serial);
                dest.set_product(product);
                dest.set_version(version);
+               dest.set_altitude_32(altitude_32);
                dest.set_main_deploy(main_deploy);
                dest.set_apogee_delay(apogee_delay);
                dest.set_apogee_lockout(apogee_lockout);
                dest.set_radio_calibration(radio_calibration);
                dest.set_radio_frequency(frequency());
+               dest.set_telemetry_rate(telemetry_rate);
                boolean max_enabled = true;
 
                if (log_space() == 0)
                        max_enabled = false;
 
+               if (log_fixed > 0)
+                       max_enabled = false;
+
                switch (log_format) {
                case AltosLib.AO_LOG_FORMAT_TINY:
                        max_enabled = false;
@@ -507,6 +533,7 @@ public class AltosConfigData implements Iterable<String> {
                        dest.set_pyros(null);
                dest.set_pyro_firing_time(pyro_firing_time);
                dest.set_aprs_interval(aprs_interval);
+               dest.set_aprs_ssid(aprs_ssid);
                dest.set_beep(beep);
                dest.set_tracker_motion(tracker_motion);
                dest.set_tracker_interval(tracker_interval);
@@ -537,14 +564,36 @@ public class AltosConfigData implements Iterable<String> {
                                                        radio_calibration);
                        /* When remote, reset the dongle frequency at the same time */
                        if (remote) {
+                               link.flush_output();
                                link.stop_remote();
                                link.set_radio_frequency(frequency);
+                               link.flush_output();
                                link.start_remote();
                        }
                }
 
-               if (callsign != null)
+               if (telemetry_rate >= 0) {
+                       link.printf("c T %d\n", telemetry_rate);
+                       if (remote) {
+                               link.flush_output();
+                               link.stop_remote();
+                               link.set_telemetry_rate(telemetry_rate);
+                               link.flush_output();
+                               link.start_remote();
+                       }
+               }
+
+               if (callsign != null) {
                        link.printf("c c %s\n", callsign);
+                       if (remote) {
+                               link.flush_output();
+                               link.stop_remote();
+                               link.set_callsign(callsign);
+                               link.flush_output();
+                               link.start_remote();
+                       }
+               }
+
                if (radio_enable >= 0)
                        link.printf("c e %d\n", radio_enable);
 
@@ -577,6 +626,8 @@ public class AltosConfigData implements Iterable<String> {
                /* HAS_APRS */
                if (aprs_interval >= 0)
                        link.printf("c A %d\n", aprs_interval);
+               if (aprs_ssid >= 0)
+                       link.printf("c S %d\n", aprs_ssid);
 
                /* HAS_BEEP */
                if (beep >= 0)
index ae5621ccd59c9d2e3f20d1b102010aafd4243f4f..a932d3e38e6adf79be9c9b444279c652f0469e82 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public class AltosConfigDataException extends Exception {
 
index 724ba7dc4bc91e3dc8e7aa282074b0b3fc34d23f..3f0a70758bf20ede9539ec3912f968b16079bab2 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public interface AltosConfigValues {
        /* set and get all of the dialog values */
@@ -25,6 +25,8 @@ public interface AltosConfigValues {
 
        public abstract void set_serial(int serial);
 
+       public abstract void set_altitude_32(int altitude_32);
+
        public abstract void set_main_deploy(int new_main_deploy);
 
        public abstract int main_deploy() throws AltosConfigDataException;
@@ -53,6 +55,10 @@ public interface AltosConfigValues {
 
        public abstract String callsign();
 
+       public abstract void set_telemetry_rate(int new_telemetry_rate);
+
+       public abstract int telemetry_rate() throws AltosConfigDataException;
+
        public abstract void set_flight_log_max(int new_flight_log_max);
 
        public abstract void set_flight_log_max_enabled(boolean enable);
@@ -81,6 +87,10 @@ public interface AltosConfigValues {
 
        public abstract void set_aprs_interval(int new_aprs_interval);
 
+       public abstract int aprs_ssid() throws AltosConfigDataException;
+
+       public abstract void set_aprs_ssid(int new_aprs_ssid);
+
        public abstract int beep() throws AltosConfigDataException;
 
        public abstract void set_beep(int new_beep);
index dc0fbb6253608529b0e6e6fb33ec02be7687f21d..18878c026dd01115501e87f8880a9bcb613feea6 100644 (file)
@@ -18,7 +18,7 @@
 /*
  * Sensor data conversion functions
  */
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public class AltosConvert {
        /*
index b0e52fc1c5855abfd1b41e9bd4209b6980dce92a..e58fbaf2eafa12f5f1fd765dbc9ab1c0ddd18029 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 
@@ -52,7 +52,7 @@ public class AltosDebug {
        public static final byte GET_CHIP_ID =          0x68;
 
 
-       AltosLink       link;
+       private AltosLink       link;
 
        boolean debug_mode;
 
@@ -112,7 +112,11 @@ public class AltosDebug {
                int i = 0;
                int start = 0;
                while (i < length) {
-                       String  line = link.get_reply().trim();
+                       String  line = link.get_reply();
+                       if (line == null)
+                               throw new IOException("No reply");
+
+                       line = line.trim();
                        if (!AltosLib.ishex(line) || line.length() % 2 != 0)
                                throw new IOException(
                                        String.format
@@ -277,4 +281,4 @@ public class AltosDebug {
        public AltosDebug (AltosLink link) {
                this.link = link;
        }
-}
\ No newline at end of file
+}
index 76ca20c07521995323dc31690763956f052e2ced..67bb58e9e65f5717a82f56b1ca0c3cca8a55a7ff 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public class AltosDistance extends AltosUnits {
 
index 020590ebfc0a9f667d82c67fbbfe906ea0a954d5..532c9f1d9c64f03a8c32391607edb77ab9b1ab7d 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 import java.util.*;
index 91eebc5ab18edee44feb72586b2a994febc51813..4d12f564057bc92e35ed21ec712269e6bb18f55c 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.text.*;
 import java.util.concurrent.*;
index a2dfc438afcf76838b9c212a3c4ad34e48297124..a448ee645270ce6283ca743f0e3ce5bfaac03631 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 import java.util.*;
index b7e446ce6a1627fbdd8b6d4637176bfe1f4351a6..a1579b550d86a0e0ce3c925cff7815d3505d7eaa 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 import java.util.*;
index 3c1852c0350258a1ce34830ea28895ed26e9ee53..8c991a6e392a822a5094c406a77f27967f158437 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 import java.util.*;
@@ -37,7 +37,7 @@ public class AltosEepromGPS extends AltosEeprom {
        /* AO_LOG_GPS_TIME elements */
        public int latitude() { return data32(0); }
        public int longitude() { return data32(4); }
-       public int altitude() { return data16(8); }
+       public int altitude_low() { return data16(8); }
        public int hour() { return data8(10); }
        public int minute() { return data8(11); }
        public int second() { return data8(12); }
@@ -52,6 +52,7 @@ public class AltosEepromGPS extends AltosEeprom {
        public int hdop() { return data8(23); }
        public int vdop() { return data8(24); }
        public int mode() { return data8(25); }
+       public int altitude_high() { return data16(26); }
 
        public boolean has_seconds() { return cmd == AltosLib.AO_LOG_GPS_TIME; }
 
@@ -90,8 +91,10 @@ public class AltosEepromGPS extends AltosEeprom {
 
                switch (cmd) {
                case AltosLib.AO_LOG_FLIGHT:
-                       state.set_boost_tick(tick);
-                       state.set_flight(flight());
+                       if (state.flight == AltosLib.MISSING) {
+                               state.set_boost_tick(tick);
+                               state.set_flight(flight());
+                       }
                        /* no place to log start lat/lon yet */
                        break;
                case AltosLib.AO_LOG_GPS_TIME:
@@ -99,7 +102,10 @@ public class AltosEepromGPS extends AltosEeprom {
                        gps = state.make_temp_gps(false);
                        gps.lat = latitude() / 1e7;
                        gps.lon = longitude() / 1e7;
-                       gps.alt = altitude();
+                       if (state.altitude_32())
+                               gps.alt = (altitude_low() & 0xffff) | (altitude_high() << 16);
+                       else
+                               gps.alt = altitude_low();
 
                        gps.hour = hour();
                        gps.minute = minute();
@@ -118,8 +124,21 @@ public class AltosEepromGPS extends AltosEeprom {
                        gps.ground_speed = ground_speed() * 1.0e-2;
                        gps.course = course() * 2;
                        gps.climb_rate = climb_rate() * 1.0e-2;
-                       gps.hdop = hdop();
-                       gps.vdop = vdop();
+                       if (state.compare_version("1.4.9") >= 0) {
+                               gps.pdop = pdop() / 10.0;
+                               gps.hdop = hdop() / 10.0;
+                               gps.vdop = vdop() / 10.0;
+                       } else {
+                               gps.pdop = pdop() / 100.0;
+                               if (gps.pdop < 0.8)
+                                       gps.pdop += 2.56;
+                               gps.hdop = hdop() / 100.0;
+                               if (gps.hdop < 0.8)
+                                       gps.hdop += 2.56;
+                               gps.vdop = vdop() / 100.0;
+                               if (gps.vdop < 0.8)
+                                       gps.vdop += 2.56;
+                       }
                        break;
                }
        }
index 839aa06e0fbdac648bb1de80ab60ac24d17f8078..7103065526aa693283f38587ee474cae75791c61 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 import java.util.*;
@@ -96,6 +96,22 @@ public class AltosEepromHeader extends AltosEeprom {
                case AltosLib.AO_LOG_SOFTWARE_VERSION:
                        state.set_firmware_version(data);
                        break;
+               case AltosLib.AO_LOG_FREQUENCY:
+               case AltosLib.AO_LOG_APOGEE_LOCKOUT:
+               case AltosLib.AO_LOG_RADIO_RATE:
+               case AltosLib.AO_LOG_IGNITE_MODE:
+               case AltosLib.AO_LOG_PAD_ORIENTATION:
+               case AltosLib.AO_LOG_RADIO_ENABLE:
+               case AltosLib.AO_LOG_AES_KEY:
+               case AltosLib.AO_LOG_APRS:
+               case AltosLib.AO_LOG_BEEP_SETTING:
+               case AltosLib.AO_LOG_TRACKER_SETTING:
+               case AltosLib.AO_LOG_PYRO_TIME:
+               case AltosLib.AO_LOG_APRS_ID:
+                       break;
+               case AltosLib.AO_LOG_ALTITUDE_32:
+                       state.set_altitude_32(config_a);
+                       break;
                }
        }
 
@@ -161,6 +177,22 @@ public class AltosEepromHeader extends AltosEeprom {
                case AltosLib.AO_LOG_BARO_CRC:
                        out.printf ("# Baro crc: %d\n", config_a);
                        break;
+               case AltosLib.AO_LOG_FREQUENCY:
+               case AltosLib.AO_LOG_APOGEE_LOCKOUT:
+               case AltosLib.AO_LOG_RADIO_RATE:
+               case AltosLib.AO_LOG_IGNITE_MODE:
+               case AltosLib.AO_LOG_PAD_ORIENTATION:
+               case AltosLib.AO_LOG_RADIO_ENABLE:
+               case AltosLib.AO_LOG_AES_KEY:
+               case AltosLib.AO_LOG_APRS:
+               case AltosLib.AO_LOG_BEEP_SETTING:
+               case AltosLib.AO_LOG_TRACKER_SETTING:
+               case AltosLib.AO_LOG_PYRO_TIME:
+               case AltosLib.AO_LOG_APRS_ID:
+                       break;
+               case AltosLib.AO_LOG_ALTITUDE_32:
+                       out.printf("# Altitude-32: %d\n", config_a);
+                       break;
                }
        }
 
@@ -205,6 +237,9 @@ public class AltosEepromHeader extends AltosEeprom {
                        } else if (tokens[0].equals("log-format")) {
                                cmd = AltosLib.AO_LOG_LOG_FORMAT;
                                config_a = Integer.parseInt(tokens[1]);
+                       } else if (tokens[0].equals("altitude-32")) {
+                               cmd = AltosLib.AO_LOG_ALTITUDE_32;
+                               config_a = Integer.parseInt(tokens[1]);
                        } else if (tokens[0].equals("software-version")) {
                                cmd = AltosLib.AO_LOG_SOFTWARE_VERSION;
                                data = tokens[1];
index d6832c1b91bbd30e539591fffa54c9544cb60a67..dd0afd9f1501bd347683f5cd10871e78a12669f8 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 import java.util.*;
index ab853a884a89d000faafc41103720a23ad480970..740499d302139f7c353110e8006291815ca52e5e 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 import java.util.*;
index 1a430c03dd2273f3eb25af49055b7f7198453a4d..5a11fa5441196d1a409eeb278d1e20586fc00424 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.text.*;
 import java.util.concurrent.*;
index 71719a26477eb47db8a103790abe6f314ac2cfe8..adaa7f3197f84a1a0d1a5a9b99518fed9bcfa53d 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 import java.util.*;
@@ -67,7 +67,7 @@ public class AltosEepromMega extends AltosEeprom {
        /* AO_LOG_GPS_TIME elements */
        public int latitude() { return data32(0); }
        public int longitude() { return data32(4); }
-       public int altitude() { return data16(8); }
+       public int altitude_low() { return data16(8); }
        public int hour() { return data8(10); }
        public int minute() { return data8(11); }
        public int second() { return data8(12); }
@@ -82,6 +82,7 @@ public class AltosEepromMega extends AltosEeprom {
        public int hdop() { return data8(23); }
        public int vdop() { return data8(24); }
        public int mode() { return data8(25); }
+       public int altitude_high() { return data16(26); }
 
        /* AO_LOG_GPS_SAT elements */
        public int nsat() { return data16(0); }
@@ -168,7 +169,11 @@ public class AltosEepromMega extends AltosEeprom {
                        gps = state.make_temp_gps(false);
                        gps.lat = latitude() / 1e7;
                        gps.lon = longitude() / 1e7;
-                       gps.alt = altitude();
+
+                       if (state.altitude_32())
+                               gps.alt = (altitude_low() & 0xffff) | (altitude_high() << 16);
+                       else
+                               gps.alt = altitude_low();
 
                        gps.hour = hour();
                        gps.minute = minute();
@@ -187,8 +192,21 @@ public class AltosEepromMega extends AltosEeprom {
                        gps.ground_speed = ground_speed() * 1.0e-2;
                        gps.course = course() * 2;
                        gps.climb_rate = climb_rate() * 1.0e-2;
-                       gps.hdop = hdop();
-                       gps.vdop = vdop();
+                       if (state.compare_version("1.4.9") >= 0) {
+                               gps.pdop = pdop() / 10.0;
+                               gps.hdop = hdop() / 10.0;
+                               gps.vdop = vdop() / 10.0;
+                       } else {
+                               gps.pdop = pdop() / 100.0;
+                               if (gps.pdop < 0.8)
+                                       gps.pdop += 2.56;
+                               gps.hdop = hdop() / 100.0;
+                               if (gps.hdop < 0.8)
+                                       gps.hdop += 2.56;
+                               gps.vdop = vdop() / 100.0;
+                               if (gps.vdop < 0.8)
+                                       gps.vdop += 2.56;
+                       }
                        break;
                case AltosLib.AO_LOG_GPS_SAT:
                        state.set_tick(tick);
index d137614a8949a30069d771d50260b7d8d921d6a1..d9a65989d8f19bd4e833506d50d97424cbf541b9 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 import java.util.*;
@@ -49,7 +49,8 @@ public class AltosEepromMetrum2 extends AltosEeprom {
        /* AO_LOG_GPS_POS elements */
        public int latitude() { return data32(0); }
        public int longitude() { return data32(4); }
-       public int altitude() { return data16(8); }
+       public int altitude_low() { return data16(8); }
+       public int altitude_high() { return data16(10); }
 
        /* AO_LOG_GPS_TIME elements */
        public int hour() { return data8(0); }
@@ -59,6 +60,7 @@ public class AltosEepromMetrum2 extends AltosEeprom {
        public int year() { return data8(4); }
        public int month() { return data8(5); }
        public int day() { return data8(6); }
+       public int pdop() { return data8(7); }
 
        /* AO_LOG_GPS_SAT elements */
        public int nsat() { return data8(0); }
@@ -117,7 +119,10 @@ public class AltosEepromMetrum2 extends AltosEeprom {
                        gps = state.make_temp_gps(false);
                        gps.lat = latitude() / 1e7;
                        gps.lon = longitude() / 1e7;
-                       gps.alt = altitude();
+                       if (state.altitude_32())
+                               gps.alt = (altitude_low() & 0xffff) | (altitude_high() << 16);
+                       else
+                               gps.alt = altitude_low();
                        break;
                case AltosLib.AO_LOG_GPS_TIME:
                        gps = state.make_temp_gps(false);
@@ -136,6 +141,7 @@ public class AltosEepromMetrum2 extends AltosEeprom {
                        gps.year = 2000 + year();
                        gps.month = month();
                        gps.day = day();
+                       gps.pdop = pdop() / 10.0;
                        break;
                case AltosLib.AO_LOG_GPS_SAT:
                        gps = state.make_temp_gps(true);
index 32985639e52b73729ce021c897f29029dfc874d9..f197539eb5c6bf0d66775c217a6a072adff2e5fd 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 import java.util.*;
index b97287c3b1801a1d69ce911f528c3f3b4e86e43d..173a2cd82f680dca096838f710328d28ec18f14f 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public interface AltosEepromMonitor {
 
index 77fe20c5789d31eb99a5ce57d617b74a5e5f11ff..6d36cf47a9e1ed87169c71641e9d19c1106bb6d0 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 import java.util.*;
index 6cbb72535740d74a6fa31d573f5bb84a4f539402..81b42f21eb74e0de9eb2f7721eafa7b08113cf38 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 import java.util.*;
index 2a7389960b08bb8604fabe0c4beb3e5ea3f347d9..ba639a046fd95516983a104624fb58c5676255ca 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.File;
 import java.util.*;
index 8e8722c2727dec1b343b5127fbb28ab57183c632..a8519550d98b62dd4e757243ce5f435a4d51409e 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 
@@ -345,9 +345,23 @@ public class AltosFlash extends AltosProgrammer {
                        debug = new AltosDebug(link);
                input = new FileInputStream(file);
                image = new AltosHexfile(input);
-               if (debug != null && !debug.check_connection()) {
+
+               boolean connection_ok = true;
+
+               if (debug != null) {
+                       try {
+                               connection_ok = debug.check_connection();
+                       } catch (IOException ie) {
+                               debug.close();
+                               throw ie;
+                       } catch (InterruptedException ie) {
+                               debug.close();
+                               throw ie;
+                       }
+               }
+               if (!connection_ok) {
                        debug.close();
                        throw new IOException("Debug port not connected");
                }
        }
-}
\ No newline at end of file
+}
index 8bb86bba1c42aaf0a9d69c11f94503d51cca0f7b..7a51c3305c2c7ef6ed210d3ad90cad72f8142474 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public interface AltosFlashListener {
        public void position(String label, int percent);
index 2fcd556ea6c5ad0e607b3a58df9d22390cb73c88..be103838a2ccd683df7dd48f47c1d9a91a142b9d 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.text.*;
 import java.io.*;
 import java.util.concurrent.*;
 
-public class AltosFlightReader {
+public abstract class AltosFlightReader {
        public String name;
 
        public int serial;
 
-       public void init() { }
+       public void init() {}
 
-       public AltosState read() throws InterruptedException, ParseException, AltosCRCException, IOException { return null; }
+       public abstract AltosState read() throws InterruptedException, ParseException, AltosCRCException, IOException;
 
-       public void close(boolean interrupted) { }
+       public abstract void close(boolean interrupted);
 
        public void set_frequency(double frequency) throws InterruptedException, TimeoutException { }
 
@@ -38,12 +38,18 @@ public class AltosFlightReader {
 
        public void set_telemetry(int telemetry) { }
 
+       public void set_telemetry_rate(int telemetry_rate) throws InterruptedException, TimeoutException { }
+
        public void save_telemetry() { }
 
+       public void save_telemetry_rate() { }
+
        public void update(AltosState state) throws InterruptedException { }
 
        public boolean supports_telemetry(int telemetry) { return false; }
 
+       public boolean supports_telemetry_rate(int telemetry_rate) { return false; }
+
        public File backing_file() { return null; }
 
        public boolean has_monitor_battery() throws InterruptedException { return false; }
index 56feb848c3bf62d1613f0a94944b1f2dbc3c1041..1b88cb9fc7e56e7b8b2abf7ae308571837c862ad 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 
index 7c291ea9036b29f0169730c5bbb39525ec0b9adb..6093df495700498ce8646795b545a277c4552001 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public class AltosFrequency {
        public double   frequency;
@@ -41,4 +41,4 @@ public class AltosFrequency {
                frequency = f;
                description = d;
        }
-}
\ No newline at end of file
+}
index 2708d026e840184a0013c8b632a26a1ffe7780db..0154e95d7c96d3231d831d18973010a32f1989f9 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.text.*;
 import java.util.concurrent.*;
@@ -40,10 +40,11 @@ public class AltosGPS implements Cloneable {
        public double   ground_speed;   /* m/s */
        public int      course;         /* degrees */
        public double   climb_rate;     /* m/s */
+       public double   pdop;           /* unitless */
        public double   hdop;           /* unitless */
        public double   vdop;           /* unitless */
-       public int      h_error;        /* m */
-       public int      v_error;        /* m */
+       public double   h_error;        /* m */
+       public double   v_error;        /* m */
 
        public AltosGPSSat[] cc_gps_sat;        /* tracking data */
 
@@ -95,6 +96,7 @@ public class AltosGPS implements Cloneable {
                                                      AltosLib.MISSING, 1/100.0);
                        course = map.get_int(AltosTelemetryLegacy.AO_TELEM_GPS_COURSE,
                                             AltosLib.MISSING);
+                       pdop = map.get_double(AltosTelemetryLegacy.AO_TELEM_GPS_PDOP, MISSING, 1.0);
                        hdop = map.get_double(AltosTelemetryLegacy.AO_TELEM_GPS_HDOP, MISSING, 1.0);
                        vdop = map.get_double(AltosTelemetryLegacy.AO_TELEM_GPS_VDOP, MISSING, 1.0);
                        h_error = map.get_int(AltosTelemetryLegacy.AO_TELEM_GPS_HERROR, MISSING);
@@ -268,14 +270,26 @@ public class AltosGPS implements Cloneable {
                cc_gps_sat[cc_gps_sat.length - 1] = sat;
        }
 
-       public AltosGPS() {
+       private void init() {
                lat = AltosLib.MISSING;
                lon = AltosLib.MISSING;
                alt = AltosLib.MISSING;
+               ground_speed = AltosLib.MISSING;
+               course = AltosLib.MISSING;
+               climb_rate = AltosLib.MISSING;
+               pdop = AltosLib.MISSING;
+               hdop = AltosLib.MISSING;
+               vdop = AltosLib.MISSING;
+               h_error = AltosLib.MISSING;
+               v_error = AltosLib.MISSING;
                ClearGPSTime();
                cc_gps_sat = null;
        }
 
+       public AltosGPS() {
+               init();
+       }
+
        public AltosGPS clone() {
                AltosGPS        g = new AltosGPS();
 
@@ -295,7 +309,9 @@ public class AltosGPS implements Cloneable {
                g.ground_speed = ground_speed;  /* m/s */
                g.course = course;              /* degrees */
                g.climb_rate = climb_rate;      /* m/s */
-               g.hdop = hdop;          /* unitless? */
+               g.pdop = pdop;          /* unitless */
+               g.hdop = hdop;          /* unitless */
+               g.vdop = vdop;          /* unitless */
                g.h_error = h_error;    /* m */
                g.v_error = v_error;    /* m */
 
@@ -327,9 +343,11 @@ public class AltosGPS implements Cloneable {
                        ground_speed = old.ground_speed;        /* m/s */
                        course = old.course;            /* degrees */
                        climb_rate = old.climb_rate;    /* m/s */
+                       pdop = old.pdop;                /* unitless? */
                        hdop = old.hdop;                /* unitless? */
-                       h_error = old.h_error;  /* m */
-                       v_error = old.v_error;  /* m */
+                       vdop = old.vdop;                /* unitless? */
+                       h_error = old.h_error;          /* m */
+                       v_error = old.v_error;          /* m */
 
                        if (old.cc_gps_sat != null) {
                                cc_gps_sat = new AltosGPSSat[old.cc_gps_sat.length];
@@ -340,11 +358,7 @@ public class AltosGPS implements Cloneable {
                                }
                        }
                } else {
-                       lat = AltosLib.MISSING;
-                       lon = AltosLib.MISSING;
-                       alt = AltosLib.MISSING;
-                       ClearGPSTime();
-                       cc_gps_sat = null;
+                       init();
                }
        }
 
index ef24d4974f844f0a055bf5d354a2dec6e293a30e..adbcbe61ad2bfbec023fad34b721fd948414ff46 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public class AltosGPSSat {
        public int      svid;
index 4782c34d34d858ed6fd361594ae69befb1853120..716eeef98396c61ad3ec3d6f063143ad4cfe1d8e 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.lang.Math;
 
index 84981032a76e909e6af429b7ff32f72c72db6fdc..8c67e043960ecbb7cb37463a3d758714aa05452c 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public class AltosHeight extends AltosUnits {
 
index d5fa8f5fe1c08b86e99649e09bec6895f5129dcf..9ee64bdc72e585871bbeabc63e63c0a5e96229f6 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 import java.util.LinkedList;
index 403b5644b50d3bdb524a59cccefff2b286304448..52eb81db0354e1a0cea00dd4ba627277f7b67853 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public class AltosHexsym {
        String  name;
index a22b3fed29290ca6e59f765734c581f388d1e55c..89d7def4a3bb2066b5ff1adbdd364107dd575ad3 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.util.concurrent.*;
 
index 55f6f5c9d834e5cfa5fa6a009da66c568060cf73..0f723d142293e299e1d1ccf7fdd84b4a04132efa 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 import java.util.*;
index 5cd8bf367944907ebec648aa6dc3e99c35f4e582..50745d9755d9be1436932d62c848615bdb51f255 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 import java.util.*;
@@ -118,6 +118,10 @@ public class AltosIdleFetch implements AltosStateUpdate {
                               AltosIdler.idle_ms5607, AltosIdler.idle_mma655x,
                               AltosIdler.idle_imu, AltosIdler.idle_mag,
                               AltosIdler.idle_sensor_mega),
+               new AltosIdler("EasyMega",
+                              AltosIdler.idle_ms5607, AltosIdler.idle_mma655x,
+                              AltosIdler.idle_imu, AltosIdler.idle_mag,
+                              AltosIdler.idle_sensor_mega),
        };
 
        AltosLink               link;
index f81abdff0baac58d40094beb566b1a5a4ee23461..85bcff10d295e3a7920ba511b29b72727858123b 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 import java.util.concurrent.*;
index 6a9abea24dea350540620a9160473f5eb49829f7..4382430c667634acb9995078e0d5ec009e7cdee5 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public interface AltosIdleMonitorListener {
        public void update(AltosState state, AltosListenerState listener_state);
index c21f17ac2234da61d93ad414494180747aa4ea27..b458911ec61884d4bd144a5b50d934d8fd2fc454 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.util.*;
 import java.io.*;
index d55da9ef2d9474276178a4999d69dea1ad73b46f..e701fda3ade3f3791b71f0271ec1d221f8688e8c 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 
@@ -28,18 +28,25 @@ public class AltosKML implements AltosWriter {
        double                  gps_start_altitude;
 
        static final String[] kml_state_colors = {
-               "FF000000",
-               "FF000000",
-               "FF000000",
-               "FF0000FF",
-               "FF4080FF",
-               "FF00FFFF",
-               "FFFF0000",
-               "FF00FF00",
-               "FF000000",
-               "FFFFFFFF"
+               "FF000000",     // startup
+               "FF000000",     // idle
+               "FF000000",     // pad
+               "FF0000FF",     // boost
+               "FF4080FF",     // fast
+               "FF00FFFF",     // coast
+               "FFFF0000",     // drogue
+               "FF00FF00",     // main
+               "FF000000",     // landed
+               "FFFFFFFF",     // invalid
+               "FFFF0000",     // stateless
        };
 
+       static String state_color(int state) {
+               if (state < 0 || kml_state_colors.length <= state)
+                       return kml_state_colors[AltosLib.ao_flight_invalid];
+               return kml_state_colors[state];
+       }
+
        static final String kml_header_start =
                "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                "<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n" +
@@ -95,7 +102,8 @@ public class AltosKML implements AltosWriter {
 
        void state_start(AltosState state) {
                String  state_name = AltosLib.state_name(state.state);
-               out.printf(kml_style_start, state_name, kml_state_colors[state.state]);
+               String  state_color = state_color(state.state);
+               out.printf(kml_style_start, state_name, state_color);
                out.printf("\tState: %s\n", state_name);
                out.printf("%s", kml_style_end);
                out.printf(kml_placemark_start, state_name, state_name);
index 6156d6dc79f9899fcd609ce09c1da0107ee2a86f..2b5071734bcd618f700e5158e9abcfbe30728f18 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public class AltosLatitude extends AltosLocation {
        public String pos() { return "N"; }
index 69c6d604003d7ff39bacba50b7affb14270c1d73..2e9dc6486a1907f2dc7027de20f3157adba84556 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.util.*;
 import java.io.*;
@@ -51,6 +51,20 @@ public class AltosLib {
        public static final int AO_LOG_SERIAL_NUMBER = 2002;
        public static final int AO_LOG_LOG_FORMAT = 2003;
 
+       public static final int AO_LOG_FREQUENCY = 2004;
+       public static final int AO_LOG_APOGEE_LOCKOUT = 2005;
+       public static final int AO_LOG_RADIO_RATE = 2006;
+       public static final int AO_LOG_IGNITE_MODE = 2007;
+       public static final int AO_LOG_PAD_ORIENTATION = 2008;
+       public static final int AO_LOG_RADIO_ENABLE = 2009;
+       public static final int AO_LOG_AES_KEY = 2010;
+       public static final int AO_LOG_APRS = 2011;
+       public static final int AO_LOG_BEEP_SETTING = 2012;
+       public static final int AO_LOG_TRACKER_SETTING = 2013;
+       public static final int AO_LOG_PYRO_TIME = 2014;
+       public static final int AO_LOG_APRS_ID = 2015;
+       public static final int AO_LOG_ALTITUDE_32 = 2016;
+
        /* Added for header fields in telemega files */
        public static final int AO_LOG_BARO_RESERVED = 3000;
        public static final int AO_LOG_BARO_SENS = 3001;
@@ -98,6 +112,7 @@ public class AltosLib {
        public final static int product_telegps = 0x0025;
        public final static int product_easymini = 0x0026;
        public final static int product_telemini = 0x0027;
+       public final static int product_easymega = 0x0028;
        public final static int product_altusmetrum_min = 0x000a;
        public final static int product_altusmetrum_max = 0x002c;
 
@@ -129,7 +144,8 @@ public class AltosLib {
                new Product("megadongle", product_megadongle),
                new Product("telegps", product_telegps),
                new Product("easymini", product_easymini),
-               new Product("telemini", product_telemini)
+               new Product("telemini", product_telemini),
+               new Product("easymega", product_easymega)
        };
 
        public static int name_to_product(String name) {
@@ -161,6 +177,15 @@ public class AltosLib {
                "Off", "Standard Telemetry", "TeleMetrum v0.9", "TeleMetrum v0.8"
        };
 
+       public static final int ao_telemetry_rate_38400 = 0;
+       public static final int ao_telemetry_rate_9600 = 1;
+       public static final int ao_telemetry_rate_2400 = 2;
+       public static final int ao_telemetry_rate_max = 2;
+
+       public static final Integer[] ao_telemetry_rate_values = {
+               38400, 9600, 2400
+       };
+
        public static final String launch_sites_url = "http://www.altusmetrum.org/AltOS/launch-sites.txt";
 
        public static final int ao_telemetry_standard_len = 32;
@@ -206,6 +231,31 @@ public class AltosLib {
                                                                 telemetry));
        }
 
+       private static int[] split_version(String version) {
+               String[] tokens = version.split("\\.");
+               int[] ret = new int[tokens.length];
+               for (int i = 0; i < tokens.length; i++)
+                       ret[i] = Integer.parseInt(tokens[i]);
+               return ret;
+       }
+
+       public static int compare_version(String version_a, String version_b) {
+               int[] a = split_version(version_a);
+               int[] b = split_version(version_b);
+
+               for (int i = 0; i < Math.min(a.length, b.length); i++) {
+                       if (a[i] < b[i])
+                               return -1;
+                       if (a[i] > b[i])
+                               return 1;
+               }
+               if (a.length < b.length)
+                       return -1;
+               if (a.length > b.length)
+                       return 1;
+               return 0;
+       }
+
        private static String[] state_to_string = {
                "startup",
                "idle",
@@ -281,7 +331,7 @@ public class AltosLib {
                return false;
        }
 
-       public static boolean ishex(int c) {
+       public static final boolean ishex(int c) {
                if ('0' <= c && c <= '9')
                        return true;
                if ('a' <= c && c <= 'f')
@@ -291,7 +341,7 @@ public class AltosLib {
                return false;
        }
 
-       public static boolean ishex(String s) {
+       public static final boolean ishex(String s) {
                for (int i = 0; i < s.length(); i++)
                        if (!ishex(s.charAt(i)))
                                return false;
@@ -415,10 +465,17 @@ public class AltosLib {
 
                if ((s.length() & 1) != 0)
                        throw new NumberFormatException(String.format("invalid line \"%s\"", s));
-               n = s.length() / 2;
+               byte[] bytes = s.getBytes(unicode_set);
+               n = bytes.length / 2;
                r = new int[n];
-               for (i = 0; i < n; i++)
-                       r[i] = hexbyte(s, i * 2);
+               for (i = 0; i < n; i++) {
+                       int h = fromhex(bytes[(i << 1)]);
+                       int l = fromhex(bytes[(i << 1) + 1]);
+                       if (h < 0 || l < 0)
+                               throw new NumberFormatException(String.format("invalid hex \"%c%c\"",
+                                                                             bytes[(i<<1)], bytes[(i<<1) + 1]));
+                       r[i] = (h << 4) + l;
+               }
                return r;
        }
 
index f9c712a327597ecdac8010da611affc5c50d6a80..f56938c6a116201c5035e7c820874aef1300215b 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public class AltosLine {
        public String   line;
index 7f434a064200921d881eaf5051a580d6d1258ac8..62bd82b93c2ae617c4d67a305696e99a32bd3ba7 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 import java.util.concurrent.*;
@@ -163,8 +163,21 @@ public abstract class AltosLink implements Runnable {
                if (!can_cancel && remote)
                        System.out.printf("Uh-oh, reading remote serial device from swing thread\n");
 
-               if (remote && can_cancel)
+               if (remote && can_cancel) {
                        timeout = 500;
+                       switch (telemetry_rate) {
+                       case AltosLib.ao_telemetry_rate_38400:
+                       default:
+                               timeout = 500;
+                               break;
+                       case AltosLib.ao_telemetry_rate_9600:
+                               timeout = 2000;
+                               break;
+                       case AltosLib.ao_telemetry_rate_2400:
+                               timeout = 8000;
+                               break;
+                       }
+               }
                try {
                        ++in_reply;
 
@@ -274,6 +287,8 @@ public abstract class AltosLink implements Runnable {
        }
 
        public void flush_output() {
+               if (pending_output == null)
+                       return;
                for (String s : pending_output)
                        System.out.print(s);
                pending_output.clear();
@@ -305,6 +320,7 @@ public abstract class AltosLink implements Runnable {
         */
        public boolean monitor_mode = false;
        public int telemetry = AltosLib.ao_telemetry_standard;
+       public int telemetry_rate = -1;
        public double frequency;
        public String callsign;
        AltosConfigData config_data;
@@ -356,6 +372,15 @@ public abstract class AltosLink implements Runnable {
                flush_output();
        }
 
+       public void set_telemetry_rate(int in_telemetry_rate) {
+               telemetry_rate = in_telemetry_rate;
+               if (monitor_mode)
+                       printf("m 0\nc T %d\nm %x\n", telemetry_rate, telemetry_len());
+               else
+                       printf("c T %d\n", telemetry_rate);
+               flush_output();
+       }
+
        public void set_monitor(boolean monitor) {
                monitor_mode = monitor;
                if (monitor)
@@ -383,10 +408,14 @@ public abstract class AltosLink implements Runnable {
                flush_output();
        }
 
-       public AltosConfigData config_data() throws InterruptedException, TimeoutException {
+       public AltosConfigData config_data() throws InterruptedException, TimeoutException {
                synchronized(config_data_lock) {
-                       if (config_data == null)
+                       if (config_data == null) {
+                               printf("m 0\n");
                                config_data = new AltosConfigData(this);
+                               if (monitor_mode)
+                                       set_monitor(true);
+                       }
                        return config_data;
                }
        }
@@ -430,7 +459,12 @@ public abstract class AltosLink implements Runnable {
                if (debug)
                        System.out.printf("start remote %7.3f\n", frequency);
                set_radio_frequency(frequency);
-               set_callsign(AltosPreferences.callsign());
+               if (telemetry_rate < 0)
+                       telemetry_rate = AltosPreferences.telemetry_rate(serial);
+               set_telemetry_rate(telemetry_rate);
+               if (callsign.equals(""))
+                       callsign = AltosPreferences.callsign();
+               set_callsign(callsign);
                printf("p\nE 0\n");
                flush_input();
                remote = true;
index 5bf761b0a5fa035d0a01b91952b48ecba0daf33b..054ff1d06431d12bab7eb88bbc02c4012be94c9b 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public class AltosListenerState {
        public int      crc_errors;
index 725a02ba6a0a7f8492c5f8c7ee376bb2b8b4ca23..9bbbb8990c2ae948d542e194a483595ac46a5589 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public abstract class AltosLocation extends AltosUnits {
 
index c4e9e4257a1f318dbf7a90bfe00fd85bf2d1918e..28116e3dcdb801a062199a8c7c8f070b1a72b1f8 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 import java.text.*;
@@ -72,6 +72,7 @@ public class AltosLog implements Runnable {
                        }
                        log_file.flush();
                        file = a;
+                       AltosPreferences.set_logfile(link.serial, file);
                }
                return log_file != null;
        }
index 29a5dcd46374949afae6e3239c1e616340a0f020..dbcd6bf026cf9afa6b447e95ec8539f3c8df9674 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public class AltosLongitude extends AltosLocation {
        public String pos() { return "E"; }
index 9262de2d3e8e6f06fc1892cb22bbc3cff3af8618..690241f13e53c98ed97da0a8a76a0ef2c51aaaf6 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.util.concurrent.*;
 
index cb2e63d4269cb9de38004377cf4f2471a19bae3e..7f0dab98f421621c70aea8d063f6dd5299fa2b07 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.util.concurrent.*;
 
@@ -23,14 +23,15 @@ public class AltosMma655x implements Cloneable {
 
        int     accel;
 
-       public boolean parse_line(String line) {
-               String[] items = line.split("\\s+");
-               if (line.startsWith("MMA655X value:")) {
-                       if (items.length >= 3)
-                               accel = Integer.parseInt(items[1]);
-               } else
-                       return false;
-               return true;
+       public boolean parse_line(String line) throws NumberFormatException {
+               if (line.startsWith("MMA655X value")) {
+                       String[] items = line.split("\\s+");
+                       if (items.length >= 3) {
+                               accel = Integer.parseInt(items[2]);
+                               return true;
+                       }
+               }
+               return false;
        }
 
        public AltosMma655x() {
@@ -51,17 +52,18 @@ public class AltosMma655x implements Cloneable {
                        if (mma655x != null)
                                state.set_accel(mma655x.accel);
                } catch (TimeoutException te) {
+               } catch (NumberFormatException ne) {
                }
        }
 
-       public AltosMma655x(AltosLink link) throws InterruptedException, TimeoutException {
+       public AltosMma655x(AltosLink link) throws InterruptedException, TimeoutException, NumberFormatException {
                this();
                link.printf("A\n");
                for (;;) {
                        String line = link.get_reply_no_dialog(5000);
                        if (line == null)
                                throw new TimeoutException();
-                       if (!parse_line(line))
+                       if (parse_line(line))
                                break;
                }
        }
index 5aa3a7ec6bf8bb0f673a8308ea9b0b818f458390..81e0641c2d9a8f42301dffbfba4fb29483ca8e49 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.util.concurrent.*;
 
index f5e53b8cb032e663e4ad1a290022e833f0b3109d..d436c3f1a78d577abe5d03f035c31c640b44d5dd 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public class AltosNoSymbol extends Exception {
        public AltosNoSymbol(String name) {
index 5fcbe28dd16b5fb38b80daeaf339ceae6c6c1e92..348c6844a6d5894bd50dbe24c77890443eea0eaa 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public class AltosOrient extends AltosUnits {
 
index 1bff76823f0d7d1d2d69c85404815c7d52ca4b1e..9cb99a0d452e3689270f4432247fe798d3e0257d 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.text.*;
 
index d299f27b02ddd865e23f8e4e05c8a06ce3361ed5..dba57dcb73d055f0509257e809346c721dacde92 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 import java.util.*;
@@ -35,6 +35,12 @@ public class AltosPreferences {
        /* telemetry format preference name */
        public final static String telemetryPreferenceFormat = "TELEMETRY-%d";
 
+       /* telemetry rate format preference name */
+       public final static String telemetryRatePreferenceFormat = "RATE-%d";
+
+       /* log file format preference name */
+       public final static String logfilePreferenceFormat = "LOGFILE-%d";
+
        /* voice preference name */
        public final static String voicePreference = "VOICE";
 
@@ -50,6 +56,9 @@ public class AltosPreferences {
        /* scanning telemetry preferences name */
        public final static String scanningTelemetryPreference = "SCANNING-TELEMETRY";
 
+       /* scanning telemetry rate preferences name */
+       public final static String scanningTelemetryRatePreference = "SCANNING-RATE";
+
        /* Launcher serial preference name */
        public final static String launcherSerialPreference = "LAUNCHER-SERIAL";
 
@@ -74,6 +83,12 @@ public class AltosPreferences {
        /* Telemetry (map serial to telemetry format) */
        public static Hashtable<Integer, Integer> telemetries;
 
+       /* Telemetry rate (map serial to telemetry format) */
+       public static Hashtable<Integer, Integer> telemetry_rates;
+
+       /* Log file (map serial to logfile name) */
+       public static Hashtable<Integer, File> logfiles;
+
        /* Voice preference */
        public static boolean voice;
 
@@ -86,6 +101,8 @@ public class AltosPreferences {
        /* Scanning telemetry */
        public static int scanning_telemetry;
 
+       public static int scanning_telemetry_rate;
+
        /* List of frequencies */
        public final static String common_frequencies_node_name = "COMMON-FREQUENCIES";
        public static AltosFrequency[] common_frequencies;
@@ -140,6 +157,10 @@ public class AltosPreferences {
        public static int launcher_channel;
 
        public static void init(AltosPreferencesBackend in_backend) {
+
+               if (backend != null)
+                       return;
+
                backend = in_backend;
 
                /* Initialize logdir from preferences */
@@ -159,12 +180,18 @@ public class AltosPreferences {
 
                telemetries = new Hashtable<Integer,Integer>();
 
+               telemetry_rates = new Hashtable<Integer,Integer>();
+
+               logfiles = new Hashtable<Integer,File>();
+
                voice = backend.getBoolean(voicePreference, true);
 
                callsign = backend.getString(callsignPreference,"N0CALL");
 
                scanning_telemetry = backend.getInt(scanningTelemetryPreference,(1 << AltosLib.ao_telemetry_standard));
 
+               scanning_telemetry_rate = backend.getInt(scanningTelemetryRatePreference,(1 << AltosLib.ao_telemetry_rate_38400));
+
                launcher_serial = backend.getInt(launcherSerialPreference, 0);
 
                launcher_channel = backend.getInt(launcherChannelPreference, 0);
@@ -266,6 +293,46 @@ public class AltosPreferences {
                }
        }
 
+       public static void set_telemetry_rate(int serial, int new_telemetry_rate) {
+               synchronized (backend) {
+                       telemetry_rates.put(serial, new_telemetry_rate);
+                       backend.putInt(String.format(telemetryRatePreferenceFormat, serial), new_telemetry_rate);
+                       flush_preferences();
+               }
+       }
+
+       public static int telemetry_rate(int serial) {
+               synchronized (backend) {
+                       if (telemetry_rates.containsKey(serial))
+                               return telemetry_rates.get(serial);
+                       int telemetry_rate = backend.getInt(String.format(telemetryRatePreferenceFormat, serial),
+                                                           AltosLib.ao_telemetry_rate_38400);
+                       telemetry_rates.put(serial, telemetry_rate);
+                       return telemetry_rate;
+               }
+       }
+
+       public static void set_logfile(int serial, File new_logfile) {
+               synchronized(backend) {
+                       logfiles.put(serial, new_logfile);
+                       backend.putString(String.format(logfilePreferenceFormat, serial), new_logfile.getPath());
+                       flush_preferences();
+               }
+       }
+
+       public static File logfile(int serial) {
+               synchronized(backend) {
+                       if (logfiles.containsKey(serial))
+                               return logfiles.get(serial);
+                       String logfile_string = backend.getString(String.format(logfilePreferenceFormat, serial), null);
+                       if (logfile_string == null)
+                               return null;
+                       File logfile = new File(logfile_string);
+                       logfiles.put(serial, logfile);
+                       return logfile;
+               }
+       }
+
        public static void set_scanning_telemetry(int new_scanning_telemetry) {
                synchronized (backend) {
                        scanning_telemetry = new_scanning_telemetry;
@@ -280,6 +347,20 @@ public class AltosPreferences {
                }
        }
 
+       public static void set_scanning_telemetry_rate(int new_scanning_telemetry_rate) {
+               synchronized (backend) {
+                       scanning_telemetry_rate = new_scanning_telemetry_rate;
+                       backend.putInt(scanningTelemetryRatePreference, scanning_telemetry_rate);
+                       flush_preferences();
+               }
+       }
+
+       public static int scanning_telemetry_rate() {
+               synchronized(backend) {
+                       return scanning_telemetry_rate;
+               }
+       }
+
        public static void set_voice(boolean new_voice) {
                synchronized (backend) {
                        voice = new_voice;
index 461b5c80ec1d409f61917068484dae4788bd9ebe..76a99acbb1ef82187d034d34885e457c37649a5f 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.File;
 
index c96f04ca47da88eb0a16d76169fa3f57e0948c23..443082d50b08f01a8e5c7a450faadbb6c9a24535 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 
index 9e47bc804282f9b6319e1a2b151b81ab03bf5784..60b8fe5242648c14eaccf96fe7133d1fab80a3f8 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.util.*;
 import java.text.*;
index bf7e0e5b0b36dce0a52ce526b84ec042e66aa466..2864e02a272bb0ba60f27407b0fdf03d27803c0d 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 import java.util.*;
@@ -27,6 +27,7 @@ import java.util.*;
 public class AltosReplayReader extends AltosFlightReader {
        Iterator<AltosState>    iterator;
        File    file;
+       boolean real_time;
 
        public AltosState read() {
                if (iterator.hasNext())
@@ -39,16 +40,22 @@ public class AltosReplayReader extends AltosFlightReader {
 
        public void update(AltosState state) throws InterruptedException {
                /* Make it run in realtime after the rocket leaves the pad */
-               if (state.state > AltosLib.ao_flight_pad && state.time_change > 0)
+               if (real_time && state.state > AltosLib.ao_flight_pad && state.time_change > 0)
                        Thread.sleep((int) (Math.min(state.time_change,10) * 1000));
                state.set_received_time(System.currentTimeMillis());
        }
 
        public File backing_file() { return file; }
 
-       public AltosReplayReader(Iterator<AltosState> in_iterator, File in_file) {
+       public AltosReplayReader(Iterator<AltosState> in_iterator, File in_file,
+                                boolean in_real_time) {
                iterator = in_iterator;
                file = in_file;
+               real_time = in_real_time;
                name = file.getName();
        }
+
+       public AltosReplayReader(Iterator<AltosState> in_iterator, File in_file) {
+               this(in_iterator, in_file, false);
+       }
 }
index 10df11afd6cc7c9277dcd63d1475588e7a43fcf8..d0de5492752e9de6ee3f8417d047f764dc4135c4 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 
index 502c6d65ba5fd426a71b0c5b0085dfa4581b0bfb..3ec692132ebfc1999674f5001d841696454baed5 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 
index ee0238f965f8a2b6c68d9ebca523ec35ffc494ef..53a8e998845aab74ccbc70c058ae769dceb5e59d 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.util.concurrent.TimeoutException;
 
index e34e71b7f599a4b363a7b18a027134f8dd901bbb..cdc2ac42ace48eef971dd55ff6ed372f91220f5e 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.util.concurrent.TimeoutException;
 
index 02f3a25622e596ff2749315b05921b2dbbed128a..3c7213eb370b0e40c0e62847ce2b0495dd0d6085 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.util.concurrent.TimeoutException;
 
index e5421ef53d1a79dadade3a63f1954879e92836cf..d977e886c7d762717719b95f241ba2725153e818 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.util.concurrent.TimeoutException;
 
index 2d60d8cfbaf9e33ee3a73807ba1e09c448e4d6ef..344e7449d6ce909abe4666d731f0432af2aa24af 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.util.concurrent.TimeoutException;
 
index b9eeca0cc1d803403d09b5e6283d7a30e5c2ee80..edd76da2e00dcd5c50d3562953f62b7fd772dab5 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.util.concurrent.TimeoutException;
 
index 9134f5f4a59c60c729f1835ccadd10de4eb17502..d2f86214f228b9206ada035f9193d9a60dc10e53 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public class AltosSpeed extends AltosUnits {
 
index b05cd3586061ad111d99084733f84865c360339e..5fce15c43865e63b43447db93f59faf725f838f7 100644 (file)
@@ -19,7 +19,7 @@
  * Track flight state from telemetry or eeprom data stream
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public class AltosState implements Cloneable {
 
@@ -271,6 +271,7 @@ public class AltosState implements Cloneable {
        public int      state;
        public int      flight;
        public int      serial;
+       public int      altitude_32;
        public int      receiver_serial;
        public boolean  landed;
        public boolean  ascent; /* going up? */
@@ -472,15 +473,23 @@ public class AltosState implements Cloneable {
                pressure.set(p, time);
        }
 
+       public double baro_height() {
+               double a = altitude();
+               double g = ground_altitude();
+               if (a != AltosLib.MISSING && g != AltosLib.MISSING)
+                       return a - g;
+               return AltosLib.MISSING;
+       }
+
        public double height() {
                double k = kalman_height.value();
                if (k != AltosLib.MISSING)
                        return k;
 
-               double a = altitude();
-               double g = ground_altitude();
-               if (a != AltosLib.MISSING && g != AltosLib.MISSING)
-                       return a - g;
+               double b = baro_height();
+               if (b != AltosLib.MISSING)
+                       return b;
+
                return gps_height();
        }
 
@@ -762,6 +771,7 @@ public class AltosState implements Cloneable {
                product = null;
                serial = AltosLib.MISSING;
                receiver_serial = AltosLib.MISSING;
+               altitude_32 = AltosLib.MISSING;
 
                baro = null;
                companion = null;
@@ -899,6 +909,7 @@ public class AltosState implements Cloneable {
                product = old.product;
                serial = old.serial;
                receiver_serial = old.receiver_serial;
+               altitude_32 = old.altitude_32;
 
                baro = old.baro;
                companion = old.companion;
@@ -1024,15 +1035,27 @@ public class AltosState implements Cloneable {
                firmware_version = version;
        }
 
+       public int compare_version(String other_version) {
+               if (firmware_version == null)
+                       return AltosLib.MISSING;
+               return AltosLib.compare_version(firmware_version, other_version);
+       }
+
+       private void re_init() {
+               int bt = boost_tick;
+               int rs = receiver_serial;
+               init();
+               boost_tick = bt;
+               receiver_serial = rs;
+       }
+
        public void set_flight(int flight) {
 
                /* When the flight changes, reset the state */
-               if (flight != AltosLib.MISSING && flight != 0) {
+               if (flight != AltosLib.MISSING) {
                        if (this.flight != AltosLib.MISSING &&
                            this.flight != flight) {
-                               int bt = boost_tick;
-                               init();
-                               boost_tick = bt;
+                               re_init();
                        }
                        this.flight = flight;
                }
@@ -1043,9 +1066,7 @@ public class AltosState implements Cloneable {
                if (serial != AltosLib.MISSING) {
                        if (this.serial != AltosLib.MISSING &&
                            this.serial != serial) {
-                               int bt = boost_tick;
-                               init();
-                               boost_tick = bt;
+                               re_init();
                        }
                        this.serial = serial;
                }
@@ -1056,6 +1077,15 @@ public class AltosState implements Cloneable {
                        receiver_serial = serial;
        }
 
+       public boolean altitude_32() {
+               return altitude_32 == 1;
+       }
+
+       public void set_altitude_32(int altitude_32) {
+               if (altitude_32 != AltosLib.MISSING)
+                       this.altitude_32 = altitude_32;
+       }
+
        public int rssi() {
                if (rssi == AltosLib.MISSING)
                        return 0;
index be812095342988dc6f2f889f74d4f2bda5a9cff1..4154b71ceec90a8d77473e0432977b0c47ae6f32 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 import java.util.*;
@@ -26,4 +26,18 @@ public abstract class AltosStateIterable implements Iterable<AltosState> {
        }
 
        public abstract void write(PrintStream out);
+
+       public static AltosStateIterable iterable(File file) {
+               FileInputStream in;
+               try {
+                       in = new FileInputStream(file);
+               } catch (Exception e) {
+                       System.out.printf("Failed to open file '%s'\n", file);
+                       return null;
+               }
+               if (file.getName().endsWith("telem"))
+                       return new AltosTelemetryFile(in);
+               else
+                       return new AltosEepromFile(in);
+       }
 }
index ac4e963e6de6750b21150684745bfc37bd51337f..70530f756623e201c46dfe0bd4dcd3a6ba455bed 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public interface AltosStateUpdate {
        public void     update_state(AltosState state) throws InterruptedException;
index 8182ec6bb67fe9eaefa016b1337a6f9c9bba5d16..a123d7528145471a9944b1fa95fd6c9f7a611bc3 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.text.*;
 
@@ -114,6 +114,29 @@ public abstract class AltosTelemetry implements AltosStateUpdate {
                return telem;
        }
 
+       public static int extend_height(AltosState state, int height_16) {
+               double  compare_height;
+               int     height = height_16;
+
+               if (state.gps != null && state.gps.alt != AltosLib.MISSING) {
+                       compare_height = state.gps_height();
+               } else {
+                       compare_height = state.height();
+               }
+
+               if (compare_height != AltosLib.MISSING) {
+                       int     high_bits = (int) Math.floor (compare_height / 65536.0);
+
+                       height = (high_bits << 16) | (height_16 & 0xffff);
+
+                       if (Math.abs(height + 65536 - compare_height) < Math.abs(height - compare_height))
+                               height += 65536;
+                       else if (Math.abs(height - 65536 - compare_height) < Math.abs(height - compare_height))
+                               height -= 65536;
+               }
+               return height;
+       }
+
        public static AltosTelemetry parse(String line) throws ParseException, AltosCRCException {
                String[] word = line.split("\\s+");
                int i =0;
index e38840519c3f20276c8c9834e0e5fa5cd9a78a61..f578e6adc5404f8e5ce2f99a0ae363a174b6fd9e 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 
 public class AltosTelemetryConfiguration extends AltosTelemetryStandard {
index 3d3fa407085c641dda785a5ee8235e99b31d9033..15344b8dba5f06464f482b13aee3817fc3125990 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 import java.util.*;
index cba97ddc01309ddf9637d6b4ca53f1de4ec6ad4d..ac42597d5935e7a7da957b95a7ef68883828d8ae 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 import java.util.*;
index 3367ece78bc2a50145b3aa84df36c9aae4e24357..72a8bc4a0750b6faeb0c95b12f11f1045f4e49ac 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.text.*;
 
@@ -186,6 +186,7 @@ public class AltosTelemetryLegacy extends AltosTelemetry {
         *      g_v             GPS vertical speed (integer, cm/sec)
         *      g_s             GPS horizontal speed (integer, cm/sec)
         *      g_c             GPS course (integer, 0-359)
+        *      g_pd            GPS pdop (integer * 10)
         *      g_hd            GPS hdop (integer * 10)
         *      g_vd            GPS vdop (integer * 10)
         *      g_he            GPS h error (integer)
@@ -209,6 +210,7 @@ public class AltosTelemetryLegacy extends AltosTelemetry {
        final static String AO_TELEM_GPS_VERTICAL_SPEED         = "g_v";
        final static String AO_TELEM_GPS_HORIZONTAL_SPEED       = "g_g";
        final static String AO_TELEM_GPS_COURSE                 = "g_c";
+       final static String AO_TELEM_GPS_PDOP                   = "g_pd";
        final static String AO_TELEM_GPS_HDOP                   = "g_hd";
        final static String AO_TELEM_GPS_VDOP                   = "g_vd";
        final static String AO_TELEM_GPS_HERROR                 = "g_he";
index 8368188f895492d42b83385babb524836e1a0b68..427ae16ebed3552459ebf5487854201320a568c2 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 
 public class AltosTelemetryLocation extends AltosTelemetryStandard {
@@ -37,11 +37,12 @@ public class AltosTelemetryLocation extends AltosTelemetryStandard {
        int     climb_rate;
        int     course;
 
+       public static final int AO_GPS_MODE_ALTITUDE_24 = (1 << 0);     /* Reports 24-bits of altitude */
+
        public AltosTelemetryLocation(int[] bytes) {
                super(bytes);
 
                flags          = uint8(5);
-               altitude       = int16(6);
                latitude       = uint32(8);
                longitude      = uint32(12);
                year           = uint8(16);
@@ -57,6 +58,11 @@ public class AltosTelemetryLocation extends AltosTelemetryStandard {
                ground_speed   = uint16(26);
                climb_rate     = int16(28);
                course         = uint8(30);
+
+               if ((mode & AO_GPS_MODE_ALTITUDE_24) != 0) {
+                       altitude = (int8(31) << 16) | uint16(6);
+               } else
+                       altitude = int16(6);
        }
 
        public void update_state(AltosState state) {
@@ -80,8 +86,9 @@ public class AltosTelemetryLocation extends AltosTelemetryStandard {
                        gps.ground_speed = ground_speed * 1.0e-2;
                        gps.course = course * 2;
                        gps.climb_rate = climb_rate * 1.0e-2;
-                       gps.hdop = hdop;
-                       gps.vdop = vdop;
+                       gps.pdop = pdop / 10.0;
+                       gps.hdop = hdop / 10.0;
+                       gps.vdop = vdop / 10.0;
                }
                state.set_temp_gps();
        }
index 8d0de355f195346df58079a2849f48cd315eaa87..758311eb21560e0c3affd41416c52d0bb6177139 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 import java.text.*;
 import java.util.HashMap;
 
index fac5695f27fbf6048a5f5d7b994f1e0ffe3ea529..d949c02f3bc233fcc937e17150841f5184daf495 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public class AltosTelemetryMegaData extends AltosTelemetryStandard {
        int     state;
@@ -31,12 +31,12 @@ public class AltosTelemetryMegaData extends AltosTelemetryStandard {
 
        int     acceleration;
        int     speed;
-       int     height;
+       int     height_16;
 
        public AltosTelemetryMegaData(int[] bytes) {
                super(bytes);
 
-               state = int8(5);
+               state = uint8(5);
 
                v_batt = int16(6);
                v_pyro = int16(8);
@@ -44,7 +44,7 @@ public class AltosTelemetryMegaData extends AltosTelemetryStandard {
                sense = new int[6];
 
                for (int i = 0; i < 6; i++) {
-                       sense[i] = int8(10 + i) << 4;
+                       sense[i] = uint8(10 + i) << 4;
                        sense[i] |= sense[i] >> 8;
                }
 
@@ -55,7 +55,8 @@ public class AltosTelemetryMegaData extends AltosTelemetryStandard {
 
                acceleration = int16(26);
                speed = int16(28);
-               height = int16(30);
+
+               height_16 = int16(30);
        }
 
        public void update_state(AltosState state) {
@@ -79,7 +80,13 @@ public class AltosTelemetryMegaData extends AltosTelemetryStandard {
                state.set_ground_pressure(ground_pres);
                state.set_accel_g(accel_plus_g, accel_minus_g);
 
-               state.set_kalman(height, speed/16.0, acceleration / 16.0);
+               /* Fill in the high bits of height from recent GPS
+                * data if available, otherwise guess using the
+                * previous kalman height
+                */
+
+               state.set_kalman(extend_height(state, height_16),
+                                speed/16.0, acceleration / 16.0);
        }
 }
 
index 9e73bc4e2c6b53114b9b43bf7fcaad7a6c801c44..1b568c88cea80b47ca45bc6edc5d63559b32514d 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public class AltosTelemetryMegaSensor extends AltosTelemetryStandard {
        int     accel;
index 966173069e81a8bbe320adc3b5ff69fe7a7e98f8..3377d969b972034fc6e4390cb3544b14cf27ade8 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 
 public class AltosTelemetryMetrumData extends AltosTelemetryStandard {
index e7055404b24fe5b1f6c36309d3ca0e32355f0525..beab6da99f18e9a3180b321e735be57f1c7d2620 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 
 public class AltosTelemetryMetrumSensor extends AltosTelemetryStandard {
@@ -27,7 +27,7 @@ public class AltosTelemetryMetrumSensor extends AltosTelemetryStandard {
 
        int     acceleration;
        int     speed;
-       int     height;
+       int     height_16;
 
        int     v_batt;
        int     sense_a;
@@ -43,7 +43,7 @@ public class AltosTelemetryMetrumSensor extends AltosTelemetryStandard {
 
                acceleration  = int16(14);
                speed         = int16(16);
-               height        = int16(18);
+               height_16     = int16(18);
 
                v_batt        = int16(20);
                sense_a       = int16(22);
@@ -59,7 +59,8 @@ public class AltosTelemetryMetrumSensor extends AltosTelemetryStandard {
                state.set_pressure(pres);
                state.set_temperature(temp/100.0);
 
-               state.set_kalman(height, speed/16.0, acceleration/16.0);
+               state.set_kalman(extend_height(state, height_16),
+                                speed/16.0, acceleration/16.0);
 
                state.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt));
 
index fbfaff8e2cc406ce52397f37670bbbfd87a5664c..221bb67c5fea9535c1808a881f2d888a4dfa0f16 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 
 public class AltosTelemetryMini extends AltosTelemetryStandard {
index 0dca62aa62abf988c0552279732bf04598cd52d0..2a535e84e1de290655e3364f8128f4a1dcdc10d4 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public class AltosTelemetryRaw extends AltosTelemetryStandard {
        public AltosTelemetryRaw(int[] bytes) {
index 3dff661a3e3a91ed876166d32a59b334c17f4cd2..7539452d4ad9cf3cb609a48b58292b197e128911 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 import java.text.*;
 import java.io.*;
@@ -26,11 +26,19 @@ public class AltosTelemetryReader extends AltosFlightReader {
        AltosLog        log;
        double          frequency;
        int             telemetry;
+       int             telemetry_rate;
        AltosState      state = null;
+       AltosFlightReader       stacked;
 
        LinkedBlockingQueue<AltosLine> telem;
 
        public AltosState read() throws InterruptedException, ParseException, AltosCRCException, IOException {
+               if (stacked != null) {
+                       state = stacked.read();
+                       if (state != null)
+                               return state;
+                       stacked = null;
+               }
                AltosLine l = telem.take();
                if (l.line == null)
                        throw new IOException("IO error");
@@ -52,6 +60,12 @@ public class AltosTelemetryReader extends AltosFlightReader {
        }
 
        public void close(boolean interrupted) {
+
+               if (stacked != null) {
+                       stacked.close(interrupted);
+                       stacked = null;
+               }
+
                link.remove_monitor(telem);
                log.close();
                try {
@@ -92,6 +106,23 @@ public class AltosTelemetryReader extends AltosFlightReader {
                }
        }
 
+       public boolean supports_telemetry_rate(int telemetry_rate) {
+               try {
+                       /* Version 1.4.1.1 supports all rates, older versions don't */
+                       if (link.config_data().compare_version("1.4.1.1") >= 0)
+                               return true;
+
+                       if (telemetry_rate == AltosLib.ao_telemetry_rate_38400)
+                               return true;
+                       else
+                               return false;
+               } catch (InterruptedException ie) {
+                       return false;
+               } catch (TimeoutException te) {
+                       return true;
+               }
+       }
+
        public void save_frequency() {
                AltosPreferences.set_frequency(link.serial, frequency);
        }
@@ -105,6 +136,15 @@ public class AltosTelemetryReader extends AltosFlightReader {
                AltosPreferences.set_telemetry(link.serial, telemetry);
        }
 
+       public void set_telemetry_rate(int in_telemetry_rate) {
+               telemetry_rate = in_telemetry_rate;
+               link.set_telemetry_rate(telemetry_rate);
+       }
+
+       public void save_telemetry_rate() {
+               AltosPreferences.set_telemetry_rate(link.serial, telemetry_rate);
+       }
+
        public void set_monitor(boolean monitor) {
                link.set_monitor(monitor);
        }
@@ -121,9 +161,10 @@ public class AltosTelemetryReader extends AltosFlightReader {
                return link.monitor_battery();
        }
 
-       public AltosTelemetryReader (AltosLink in_link)
+       public AltosTelemetryReader (AltosLink in_link, AltosFlightReader in_stacked)
                throws IOException, InterruptedException, TimeoutException {
                link = in_link;
+               stacked = in_stacked;
                boolean success = false;
                try {
                        log = new AltosLog(link);
@@ -133,6 +174,8 @@ public class AltosTelemetryReader extends AltosFlightReader {
                        set_frequency(frequency);
                        telemetry = AltosPreferences.telemetry(link.serial);
                        set_telemetry(telemetry);
+                       telemetry_rate = AltosPreferences.telemetry_rate(link.serial);
+                       set_telemetry_rate(telemetry_rate);
                        link.add_monitor(telem);
                        success = true;
                } finally {
@@ -140,4 +183,22 @@ public class AltosTelemetryReader extends AltosFlightReader {
                                close(true);
                }
        }
+
+       private static AltosFlightReader existing_data(AltosLink link) {
+               if (link == null)
+                       return null;
+
+               File    file = AltosPreferences.logfile(link.serial);
+               if (file != null) {
+                       AltosStateIterable      iterable = AltosStateIterable.iterable(file);
+                       if (iterable != null)
+                               return new AltosReplayReader(iterable.iterator(), file, false);
+               }
+               return null;
+       }
+
+       public AltosTelemetryReader(AltosLink link)
+               throws IOException, InterruptedException, TimeoutException {
+               this(link, existing_data(link));
+       }
 }
index d611e88c004b371b26630beb018aabd8b88c0d69..d1cdaf6de12a54755be85e283c97b2b18d11bd64 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public class AltosTelemetrySatellite extends AltosTelemetryStandard {
        int             channels;
index ad4d92837a955c2ab80019e3bf5e2862f2559f7e..fc3fe8589040c6af8d25a02b3495b451ef3b8061 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 
 public class AltosTelemetrySensor extends AltosTelemetryStandard {
index 23ae9d21fc05894fc76ef14ac29b1493ddbc32a8..f4dfd8e9665953dc58987c972022e313bc176e27 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public abstract class AltosTelemetryStandard extends AltosTelemetry {
        int[]   bytes;
index 5fa71b8683b48cd9f710f6d4a5c4368a4f107e7a..e654fada4c2b235f51ae49388838fb5b0c4c4115 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public class AltosTemperature extends AltosUnits {
 
index d29cfae7450825f7bea624759b1a4c578dfe06ab..dbdb788248ee150826ea272732e72ddb4d693da3 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public abstract class AltosUnits {
 
index ca6faafd34166edf90e192b2a856c15384f46817..664aed67cf77a571c65fc310f53bf5472826f838 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public interface AltosUnitsListener {
        public void units_changed(boolean imperial_units);
index 351bf11575296d6dd50acb4c7152153cda46c210..22bd1aeec201a235353448302e3f47209dba29a1 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public class AltosVoltage extends AltosUnits {
 
index c3479a93dfd2bf18e4709ce643610a3f7eb261a1..fb208b02989bc77590d09a10ef5fd224aff6f3f7 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
 
 public interface AltosWriter {
 
-       public void write(AltosState state);
-
        public void write(AltosStateIterable states);
 
        public void close();
index e81418bb318dad34f82fc9db7c624094229b49bd..0ad9b7dad226236c8d8b1212bb9794c92fa60f65 100644 (file)
@@ -131,7 +131,7 @@ JAR=altoslib_$(ALTOSLIB_VERSION).jar
 all-local: $(JAR)
 
 clean-local:
-       -rm -rf bin $(JAR)
+       -rm -rf $(JAVAROOT) altoslib_*.jar
 
 install-altoslibJAVA: $(JAR)
        @$(NORMAL_INSTALL)
index 10b600e441ca086d4da85f5c90ea13e01e4cf1f9..a9b80aa4dbcbaaf12bf0a44bb286737fbaefb112 100644 (file)
@@ -17,7 +17,7 @@ Altos-Linux-*.tar.bz2
 Altos-Linux-*.sh
 Altos-Mac-*.zip
 Altos-Windows-*.exe
-altos.desktop
+.desktop
 *.dll
 *.dylib
 *.so
index 28038ad687653e5829c756b848103eb8cf18f1b2..74b45f1c97027ac32e1263cb1311798856750303 100644 (file)
@@ -20,8 +20,8 @@ package altosui;
 import java.awt.*;
 import libaltosJNI.*;
 
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class Altos extends AltosUILib {
 
index 3bc804068fef165716cb60686fd70dc5df0deebf..24fc362fb424e2abd6d0d91ba388930a84928b7e 100644 (file)
@@ -21,8 +21,8 @@ import java.util.*;
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class AltosAscent extends AltosUIFlightTab {
        JLabel  cur, max;
index e7b335ac7f6fcc32168e3c0c7cedb08b5928d674..7ac53dd8ca9418ceb56cb184ffff4cbdca4e4c59 100644 (file)
@@ -19,8 +19,8 @@ package altosui;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class AltosCompanionInfo extends JTable implements AltosFlightDisplay {
        private AltosFlightInfoTableModel model;
index 6eb7d40cb34ea88e7a0d60469ed9a179094bbd6a..40f7ebecb4c4635809dfdec7ebc9d068edca3af5 100644 (file)
@@ -22,8 +22,8 @@ import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
 import java.text.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class AltosConfig implements ActionListener {
 
index f0b4f0f998a2cb31de3bc668a81aa5fdd10b52fb..64336c8e06daa1ac0b5d72fedab5960ddd383762 100644 (file)
@@ -21,8 +21,8 @@ import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
 import javax.swing.event.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class AltosConfigPyroUI
        extends AltosUIDialog
@@ -285,9 +285,13 @@ public class AltosConfigPyroUI
                "0.050", "0.100", "0.250", "0.500", "1.0", "2.0"
        };
 
+       boolean initializing;
+
        public void set_pyro_firing_time(double new_pyro_firing_time) {
+               initializing = true;
                pyro_firing_time_value.setSelectedItem(Double.toString(new_pyro_firing_time));
                pyro_firing_time_value.setEnabled(new_pyro_firing_time >= 0);
+               initializing = false;
        }
 
        public double get_pyro_firing_time() throws AltosConfigDataException {
@@ -301,23 +305,28 @@ public class AltosConfigPyroUI
        }
 
        public void set_dirty() {
-               owner.set_dirty();
+               if (!initializing)
+                       owner.set_dirty();
        }
 
        public void itemStateChanged(ItemEvent e) {
-               owner.set_dirty();
+               if (!initializing)
+                       owner.set_dirty();
        }
 
        public void changedUpdate(DocumentEvent e) {
-               owner.set_dirty();
+               if (!initializing)
+                       owner.set_dirty();
        }
 
        public void insertUpdate(DocumentEvent e) {
-               owner.set_dirty();
+               if (!initializing)
+                       owner.set_dirty();
        }
 
        public void removeUpdate(DocumentEvent e) {
-               owner.set_dirty();
+               if (!initializing)
+                       owner.set_dirty();
        }
 
        public void units_changed(boolean imperial_units) {
index bfbd2c7710ef296118724e50a85cce9c625be561..9020ed9ddc874f0d652c39aa491a74b641c2ceb2 100644 (file)
@@ -21,8 +21,8 @@ import java.awt.event.*;
 import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class AltosConfigTD implements ActionListener {
 
@@ -62,6 +62,7 @@ public class AltosConfigTD implements ActionListener {
        int_ref         radio_calibration;
        int_ref         radio_setting;
        int_ref         radio_frequency;
+       int_ref         telemetry_rate;
        string_ref      config_version;
        string_ref      version;
        string_ref      product;
@@ -105,6 +106,7 @@ public class AltosConfigTD implements ActionListener {
                config_ui.set_version(version.get());
                config_ui.set_radio_frequency(frequency());
                config_ui.set_radio_calibration(radio_calibration.get());
+               config_ui.set_telemetry_rate(telemetry_rate.get());
                config_ui.set_clean();
                if (!made_visible) {
                        made_visible = true;
@@ -140,6 +142,7 @@ public class AltosConfigTD implements ActionListener {
                        get_int(line, "Radio cal:", radio_calibration);
                        get_int(line, "Frequency:", radio_frequency);
                        get_int(line, "Radio setting:", radio_setting);
+                       get_int(line, "Telemetry rate:", telemetry_rate);
                        get_string(line,"software-version", version);
                        get_string(line,"product", product);
                }
@@ -151,6 +154,7 @@ public class AltosConfigTD implements ActionListener {
                radio_setting.set(0);
                radio_frequency.set(0);
                radio_calibration.set(1186611);
+               telemetry_rate.set(Altos.ao_telemetry_rate_38400);
                config_version.set("0.0");
                version.set("unknown");
                product.set("unknown");
@@ -178,6 +182,17 @@ public class AltosConfigTD implements ActionListener {
                }
        }
 
+       synchronized int telemetry_rate() {
+               return telemetry_rate.get();
+       }
+
+       synchronized void set_telemetry_rate(int new_telemetry_rate){
+               int     rate = telemetry_rate.get();
+
+               if (rate >= 0)
+                       telemetry_rate.set(new_telemetry_rate);
+       }
+
        final static int        serial_mode_read = 0;
        final static int        serial_mode_save = 1;
        final static int        serial_mode_reboot = 2;
@@ -208,8 +223,10 @@ public class AltosConfigTD implements ActionListener {
                                        if (!config_version.get().equals("0.0"))
                                                break;
                                        been_there = true;
-                                       config.serial_line.printf("C\n ");
-                                       config.serial_line.flush_input();
+                                       if (config != null && config.serial_line != null) {
+                                               config.serial_line.printf("C\n ");
+                                               config.serial_line.flush_input();
+                                       }
                                }
                        } catch (InterruptedException ie) {
                        }
@@ -218,6 +235,7 @@ public class AltosConfigTD implements ActionListener {
                         * available firmware version might place on the actual frequency
                         */
                        config.set_frequency(AltosPreferences.frequency(serial.get()));
+                       config.set_telemetry_rate(AltosPreferences.telemetry_rate(serial.get()));
                        config.process_line("all finished");
                }
 
@@ -226,6 +244,8 @@ public class AltosConfigTD implements ActionListener {
                        if (frequency != 0)
                                AltosPreferences.set_frequency(serial.get(),
                                                               frequency);
+                       AltosPreferences.set_telemetry_rate(serial.get(),
+                                                           telemetry_rate());
                }
 
                public void run () {
@@ -259,8 +279,10 @@ public class AltosConfigTD implements ActionListener {
        }
 
        void abort() {
-               serial_line.close();
-               serial_line = null;
+               if (serial_line != null) {
+                       serial_line.close();
+                       serial_line = null;
+               }
                JOptionPane.showMessageDialog(owner,
                                              String.format("Connection to \"%s\" failed",
                                                            device.toShortString()),
@@ -279,6 +301,8 @@ public class AltosConfigTD implements ActionListener {
        void save_data() {
                double  freq = config_ui.radio_frequency();
                set_frequency(freq);
+               int telemetry_rate = config_ui.telemetry_rate();
+               set_telemetry_rate(telemetry_rate);
                run_serial_thread(serial_mode_save);
        }
 
@@ -311,6 +335,7 @@ public class AltosConfigTD implements ActionListener {
                radio_setting = new int_ref(0);
                radio_frequency = new int_ref(0);
                radio_calibration = new int_ref(1186611);
+               telemetry_rate = new int_ref(AltosLib.ao_telemetry_rate_38400);
                config_version = new string_ref("0.0");
                version = new string_ref("unknown");
                product = new string_ref("unknown");
@@ -340,4 +365,4 @@ public class AltosConfigTD implements ActionListener {
                        }
                }
        }
-}
\ No newline at end of file
+}
index 22b3384d6a995e7a341c6eac16a1f6c4c8f17121..b677ad2388de472cbe0d4bae76279d7cccb8e435 100644 (file)
@@ -21,8 +21,8 @@ import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
 import javax.swing.event.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class AltosConfigTDUI
        extends AltosUIDialog
@@ -37,6 +37,7 @@ public class AltosConfigTDUI
        JLabel          frequency_label;
        JLabel          radio_calibration_label;
        JLabel          radio_frequency_label;
+       JLabel          rate_label;
 
        public boolean          dirty;
 
@@ -44,8 +45,9 @@ public class AltosConfigTDUI
        JLabel          product_value;
        JLabel          version_value;
        JLabel          serial_value;
-       AltosFreqList   radio_frequency_value;
+       AltosUIFreqList radio_frequency_value;
        JLabel          radio_calibration_value;
+       AltosUIRateList rate_value;
 
        JButton         save;
        JButton         reset;
@@ -54,7 +56,6 @@ public class AltosConfigTDUI
 
        ActionListener  listener;
 
-
        /* A window listener to catch closing events and tell the config code */
        class ConfigListener extends WindowAdapter {
                AltosConfigTDUI ui;
@@ -166,7 +167,7 @@ public class AltosConfigTDUI
                c.anchor = GridBagConstraints.LINE_START;
                c.insets = ir;
                c.ipady = 5;
-               radio_frequency_value = new AltosFreqList();
+               radio_frequency_value = new AltosUIFreqList();
                radio_frequency_value.addItemListener(this);
                pane.add(radio_frequency_value, c);
                radio_frequency_value.setToolTipText("Telemetry, RDF and packet frequency");
@@ -193,6 +194,28 @@ public class AltosConfigTDUI
                radio_calibration_value = new JLabel(String.format("%d", 1186611));
                pane.add(radio_calibration_value, c);
 
+               /* Telemetry Rate */
+               c = new GridBagConstraints();
+               c.gridx = 0; c.gridy = 7;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = il;
+               c.ipady = 5;
+               rate_label = new JLabel("Telemetry Rate:");
+               pane.add(rate_label, c);
+
+               c = new GridBagConstraints();
+               c.gridx = 4; c.gridy = 7;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.weightx = 1;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = ir;
+               c.ipady = 5;
+               rate_value = new AltosUIRateList();
+               pane.add(rate_value, c);
+
                /* Buttons */
                c = new GridBagConstraints();
                c.gridx = 0; c.gridy = 12;
@@ -340,6 +363,14 @@ public class AltosConfigTDUI
                radio_calibration_value.setText(String.format("%d", calibration));
        }
 
+       public int telemetry_rate() {
+               return rate_value.getSelectedIndex();
+       }
+
+       public void set_telemetry_rate(int rate) {
+               rate_value.setSelectedIndex(rate);
+       }
+
        public void set_clean() {
                dirty = false;
        }
index 1b5ff9881b0c2ee28458e9ff8772d778fcf3bf5e..9fcace610a7212c604bbe7785fcf13779838aaa8 100644 (file)
@@ -21,8 +21,8 @@ import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
 import javax.swing.event.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class AltosConfigUI
        extends AltosUIDialog
@@ -40,7 +40,9 @@ public class AltosConfigUI
        JLabel                  radio_calibration_label;
        JLabel                  radio_frequency_label;
        JLabel                  radio_enable_label;
+       JLabel                  rate_label;
        JLabel                  aprs_interval_label;
+       JLabel                  aprs_ssid_label;
        JLabel                  flight_log_max_label;
        JLabel                  ignite_mode_label;
        JLabel                  pad_orientation_label;
@@ -58,10 +60,12 @@ public class AltosConfigUI
        JComboBox<String>       main_deploy_value;
        JComboBox<String>       apogee_delay_value;
        JComboBox<String>       apogee_lockout_value;
-       AltosFreqList           radio_frequency_value;
+       AltosUIFreqList         radio_frequency_value;
        JTextField              radio_calibration_value;
        JRadioButton            radio_enable_value;
+       AltosUIRateList         rate_value;
        JComboBox<String>       aprs_interval_value;
+       JComboBox<Integer>      aprs_ssid_value;
        JComboBox<String>       flight_log_max_value;
        JComboBox<String>       ignite_mode_value;
        JComboBox<String>       pad_orientation_value;
@@ -113,6 +117,10 @@ public class AltosConfigUI
                "10"
        };
 
+       static Integer[]        aprs_ssid_values = {
+               0, 1, 2 ,3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+       };
+
        static String[]         beep_values = {
                "3750",
                "4000",
@@ -194,6 +202,13 @@ public class AltosConfigUI
                        radio_enable_value.setToolTipText("Firmware version does not support disabling radio");
        }
 
+       void set_rate_tool_tip() {
+               if (rate_value.isEnabled())
+                       rate_value.setToolTipText("Select telemetry baud rate");
+               else
+                       rate_value.setToolTipText("Firmware version does not support variable telemetry rates");
+       }
+
        void set_aprs_interval_tool_tip() {
                if (aprs_interval_value.isEnabled())
                        aprs_interval_value.setToolTipText("Enable APRS and set the interval between APRS reports");
@@ -201,6 +216,15 @@ public class AltosConfigUI
                        aprs_interval_value.setToolTipText("Hardware doesn't support APRS");
        }
 
+       void set_aprs_ssid_tool_tip() {
+               if (aprs_ssid_value.isEnabled())
+                       aprs_interval_value.setToolTipText("Set the APRS SSID (secondary station identifier)");
+               else if (aprs_interval_value.isEnabled())
+                       aprs_interval_value.setToolTipText("Software version doesn't support setting the APRS SSID");
+               else
+                       aprs_interval_value.setToolTipText("Hardware doesn't support APRS");
+       }
+
        void set_flight_log_max_tool_tip() {
                if (flight_log_max_value.isEnabled())
                        flight_log_max_value.setToolTipText("Size reserved for each flight log (in kB)");
@@ -417,7 +441,7 @@ public class AltosConfigUI
                c.anchor = GridBagConstraints.LINE_START;
                c.insets = ir;
                c.ipady = 5;
-               radio_frequency_value = new AltosFreqList();
+               radio_frequency_value = new AltosUIFreqList();
                radio_frequency_value.addItemListener(this);
                pane.add(radio_frequency_value, c);
                radio_frequency_value.setToolTipText("Telemetry, RDF and packet frequency");
@@ -475,6 +499,31 @@ public class AltosConfigUI
                set_radio_enable_tool_tip();
                row++;
 
+               /* Telemetry Rate */
+               c = new GridBagConstraints();
+               c.gridx = 0; c.gridy = row;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = il;
+               c.ipady = 5;
+               rate_label = new JLabel("Telemetry baud rate:");
+               pane.add(rate_label, c);
+
+               c = new GridBagConstraints();
+               c.gridx = 4; c.gridy = row;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.weightx = 1;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = ir;
+               c.ipady = 5;
+               rate_value = new AltosUIRateList();
+               rate_value.addItemListener(this);
+               pane.add(rate_value, c);
+               set_rate_tool_tip();
+               row++;
+
                /* APRS interval */
                c = new GridBagConstraints();
                c.gridx = 0; c.gridy = row;
@@ -501,6 +550,33 @@ public class AltosConfigUI
                set_aprs_interval_tool_tip();
                row++;
 
+               /* APRS SSID */
+               c = new GridBagConstraints();
+               c.gridx = 0; c.gridy = row;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = il;
+               c.ipady = 5;
+               aprs_ssid_label = new JLabel("APRS SSID:");
+               pane.add(aprs_ssid_label, c);
+
+               c = new GridBagConstraints();
+               c.gridx = 4; c.gridy = row;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.weightx = 1;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = ir;
+               c.ipady = 5;
+               aprs_ssid_value = new JComboBox<Integer>(aprs_ssid_values);
+               aprs_ssid_value.setEditable(false);
+               aprs_ssid_value.addItemListener(this);
+               aprs_ssid_value.setMaximumRowCount(aprs_ssid_values.length);
+               pane.add(aprs_ssid_value, c);
+               set_aprs_ssid_tool_tip();
+               row++;
+
                /* Callsign */
                c = new GridBagConstraints();
                c.gridx = 0; c.gridy = row;
@@ -850,9 +926,16 @@ public class AltosConfigUI
                serial_value.setText(String.format("%d", serial));
        }
 
+       public void set_altitude_32(int altitude_32) {
+       }
+
        public void set_main_deploy(int new_main_deploy) {
                main_deploy_value.setSelectedItem(AltosConvert.height.say(new_main_deploy));
                main_deploy_value.setEnabled(new_main_deploy >= 0);
+
+               main_deploy_value.setVisible(new_main_deploy >= 0);
+               main_deploy_label.setVisible(new_main_deploy >= 0);
+
        }
 
        public int main_deploy() {
@@ -880,6 +963,8 @@ public class AltosConfigUI
        }
 
        public void units_changed(boolean imperial_units) {
+               boolean was_dirty = dirty;
+
                String v = main_deploy_value.getSelectedItem().toString();
                main_deploy_label.setText(get_main_deploy_label());
                set_main_deploy_values();
@@ -892,9 +977,15 @@ public class AltosConfigUI
                        set_tracker_motion_values();
                        set_tracker_motion((int) (AltosConvert.height.parse(motion, !imperial_units) + 0.5));
                }
+
+               if (!was_dirty)
+                       set_clean();
        }
 
        public void set_apogee_delay(int new_apogee_delay) {
+               apogee_delay_value.setVisible(new_apogee_delay >= 0);
+               apogee_delay_label.setVisible(new_apogee_delay >= 0);
+
                apogee_delay_value.setSelectedItem(Integer.toString(new_apogee_delay));
                apogee_delay_value.setEnabled(new_apogee_delay >= 0);
        }
@@ -917,6 +1008,9 @@ public class AltosConfigUI
        public void set_apogee_lockout(int new_apogee_lockout) {
                apogee_lockout_value.setSelectedItem(Integer.toString(new_apogee_lockout));
                apogee_lockout_value.setEnabled(new_apogee_lockout >= 0);
+
+               apogee_lockout_value.setVisible(new_apogee_lockout >= 0);
+               apogee_lockout_label.setVisible(new_apogee_lockout >= 0);
        }
 
        public int apogee_lockout() throws AltosConfigDataException {
@@ -924,6 +1018,7 @@ public class AltosConfigUI
        }
 
        public void set_radio_frequency(double new_radio_frequency) {
+               radio_frequency_label.setVisible(new_radio_frequency >= 0);
                radio_frequency_value.set_frequency(new_radio_frequency);
        }
 
@@ -933,6 +1028,8 @@ public class AltosConfigUI
 
        public void set_radio_calibration(int new_radio_calibration) {
                radio_calibration_value.setVisible(new_radio_calibration >= 0);
+               radio_calibration_label.setVisible(new_radio_calibration >= 0);
+
                if (new_radio_calibration < 0)
                        radio_calibration_value.setText("Disabled");
                else
@@ -944,12 +1041,14 @@ public class AltosConfigUI
        }
 
        public void set_radio_enable(int new_radio_enable) {
+               radio_enable_label.setVisible(new_radio_enable >= 0);
+               radio_enable_value.setVisible(new_radio_enable >= 0);
+
                if (new_radio_enable >= 0) {
                        radio_enable_value.setSelected(new_radio_enable > 0);
                        radio_enable_value.setEnabled(true);
                } else {
                        radio_enable_value.setSelected(true);
-                       radio_enable_value.setVisible(radio_frequency() > 0);
                        radio_enable_value.setEnabled(false);
                }
                set_radio_enable_tool_tip();
@@ -962,8 +1061,20 @@ public class AltosConfigUI
                        return -1;
        }
 
+       public void set_telemetry_rate(int new_rate) {
+               rate_label.setVisible(new_rate >= 0);
+
+               rate_value.set_rate(new_rate);
+       }
+
+       public int telemetry_rate() {
+               return rate_value.rate();
+       }
+
        public void set_callsign(String new_callsign) {
                callsign_value.setVisible(new_callsign != null);
+               callsign_label.setVisible(new_callsign != null);
+
                callsign_value.setText(new_callsign);
        }
 
@@ -985,6 +1096,9 @@ public class AltosConfigUI
        }
 
        public void set_flight_log_max(int new_flight_log_max) {
+               flight_log_max_value.setVisible(new_flight_log_max >= 0);
+               flight_log_max_label.setVisible(new_flight_log_max >= 0);
+
                flight_log_max_value.setSelectedItem(flight_log_max_label(new_flight_log_max));
                flight_log_max = new_flight_log_max;
                set_flight_log_max_tool_tip();
@@ -1011,6 +1125,9 @@ public class AltosConfigUI
        }
 
        public void set_ignite_mode(int new_ignite_mode) {
+               ignite_mode_value.setVisible(new_ignite_mode >= 0);
+               ignite_mode_label.setVisible(new_ignite_mode >= 0);
+
                if (new_ignite_mode >= ignite_mode_values.length)
                        new_ignite_mode = 0;
                if (new_ignite_mode < 0) {
@@ -1032,14 +1149,13 @@ public class AltosConfigUI
 
 
        public void set_pad_orientation(int new_pad_orientation) {
+               pad_orientation_value.setVisible(new_pad_orientation >= 0);
+               pad_orientation_label.setVisible(new_pad_orientation >= 0);
+
                if (new_pad_orientation >= pad_orientation_values.length)
                        new_pad_orientation = 0;
-               if (new_pad_orientation < 0) {
-                       pad_orientation_value.setVisible(false);
+               if (new_pad_orientation < 0)
                        new_pad_orientation = 0;
-               } else {
-                       pad_orientation_value.setVisible(true);
-               }
                pad_orientation_value.setSelectedIndex(new_pad_orientation);
                set_pad_orientation_tool_tip();
        }
@@ -1052,6 +1168,9 @@ public class AltosConfigUI
        }
 
        public void set_beep(int new_beep) {
+               beep_value.setVisible(new_beep >= 0);
+               beep_label.setVisible(new_beep >= 0);
+
                int new_freq = (int) Math.floor (AltosConvert.beep_value_to_freq(new_beep) + 0.5);
                for (int i = 0; i < beep_values.length; i++)
                        if (new_beep == AltosConvert.beep_freq_to_value(Integer.parseInt(beep_values[i]))) {
@@ -1103,12 +1222,13 @@ public class AltosConfigUI
        }
 
        public void set_tracker_motion(int tracker_motion) {
+               tracker_motion_label.setVisible(tracker_motion >= 0);
+               tracker_motion_value.setVisible(tracker_motion >= 0);
+
                if (tracker_motion < 0) {
-                       tracker_motion_label.setVisible(false);
-                       tracker_motion_value.setVisible(false);
+                       tracker_motion_value.setEnabled(false);
                } else {
-                       tracker_motion_label.setVisible(true);
-                       tracker_motion_value.setVisible(true);
+                       tracker_motion_value.setEnabled(true);
                        tracker_motion_value.setSelectedItem(AltosConvert.height.say(tracker_motion));
                }
        }
@@ -1118,12 +1238,13 @@ public class AltosConfigUI
        }
 
        public void set_tracker_interval(int tracker_interval) {
+               tracker_interval_label.setVisible(tracker_interval >= 0);
+               tracker_interval_value.setVisible(tracker_interval >= 0);
+
                if (tracker_interval< 0) {
-                       tracker_interval_label.setVisible(false);
-                       tracker_interval_value.setVisible(false);
+                       tracker_interval_value.setEnabled(false);
                } else {
-                       tracker_interval_label.setVisible(true);
-                       tracker_interval_value.setVisible(true);
+                       tracker_interval_value.setEnabled(true);
                        tracker_interval_value.setSelectedItem(String.format("%d", tracker_interval));
                }
        }
@@ -1159,6 +1280,9 @@ public class AltosConfigUI
        }
 
        public void set_aprs_interval(int new_aprs_interval) {
+               aprs_interval_value.setVisible(new_aprs_interval >= 0);
+               aprs_interval_label.setVisible(new_aprs_interval >= 0);
+
                String  s;
 
                if (new_aprs_interval <= 0)
@@ -1166,7 +1290,6 @@ public class AltosConfigUI
                else
                        s = Integer.toString(new_aprs_interval);
                aprs_interval_value.setSelectedItem(s);
-               aprs_interval_value.setVisible(new_aprs_interval >= 0);
                set_aprs_interval_tool_tip();
        }
 
@@ -1177,4 +1300,17 @@ public class AltosConfigUI
                        return 0;
                return parse_int("aprs interval", s, false);
        }
+
+       public void set_aprs_ssid(int new_aprs_ssid) {
+               aprs_ssid_value.setVisible(new_aprs_ssid >= 0);
+               aprs_ssid_label.setVisible(new_aprs_ssid >= 0);
+
+               aprs_ssid_value.setSelectedItem(Math.max(0,new_aprs_ssid));
+               set_aprs_ssid_tool_tip();
+       }
+
+       public int aprs_ssid() throws AltosConfigDataException {
+               Integer i = (Integer) aprs_ssid_value.getSelectedItem();
+               return i;
+       }
 }
index e61a4a5b191200115596d4c10c5b8090aa86cf84..85a3f6c0d455954253486536e4abddf7b37a1f90 100644 (file)
@@ -22,7 +22,7 @@ import java.awt.event.*;
 import java.beans.*;
 import javax.swing.*;
 import javax.swing.event.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class AltosConfigureUI
        extends AltosUIConfigure
@@ -89,6 +89,8 @@ public class AltosConfigureUI
                row++;
        }
 
+       boolean has_bluetooth;
+
        public void add_bluetooth() {
                JButton manage_bluetooth = new JButton("Manage Bluetooth");
                manage_bluetooth.addActionListener(new ActionListener() {
@@ -98,6 +100,7 @@ public class AltosConfigureUI
                        });
                pane.add(manage_bluetooth, constraints(0, 2));
                /* in the same row as add_frequencies, so don't bump row */
+               has_bluetooth = true;
        }
 
        public void add_frequencies() {
@@ -108,7 +111,10 @@ public class AltosConfigureUI
                                }
                        });
                manage_frequencies.setToolTipText("Configure which values are shown in frequency menus");
-               pane.add(manage_frequencies, constraints(2, 1));
+               if (has_bluetooth)
+                       pane.add(manage_frequencies, constraints(2, 1));
+               else
+                       pane.add(manage_frequencies, constraints(0, 3));
                row++;
        }
 
index 36fc16138c2b81c4c285eb842d4e32c571707c65..e38b35edf305b60d79e1e996238774a2c55fb80d 100644 (file)
@@ -21,8 +21,8 @@ import java.util.*;
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class AltosDescent extends AltosUIFlightTab {
 
index 46c0b38736d5c9d4c53bf1c1519634ebee9765b4..7e7efa64d91a96621b7256c6905e6c676eb00085 100644 (file)
@@ -19,8 +19,8 @@ package altosui;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class AltosFlightStatus extends JComponent implements AltosFlightDisplay {
        GridBagLayout   layout;
index b33f40a4a9cbe760ea1ccc724c7c4782bc7dd290..336b44aa691737ef1eb6e9060212624aa5bde3fd 100644 (file)
@@ -27,7 +27,7 @@ import java.util.*;
 import java.text.*;
 import java.util.prefs.*;
 import java.util.concurrent.LinkedBlockingQueue;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public class AltosFlightStatusTableModel extends AbstractTableModel {
        private String[] columnNames = {
index 0daec04e87d7c4ac7e952fc463f347f96162bcfa..3ba78c19f8e18460e35abca368002a07118b54ed 100644 (file)
@@ -18,7 +18,7 @@
 package altosui;
 
 import java.awt.event.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public class AltosFlightStatusUpdate implements ActionListener {
 
index 43deb631705f86abc30dd5f072570daeb6e3a7ba..6af345ea909068c09fdf1cb887badd0e7532b540 100644 (file)
@@ -22,8 +22,8 @@ import java.awt.event.*;
 import javax.swing.*;
 import java.util.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay {
        AltosVoice              voice;
@@ -169,10 +169,11 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay {
                exit_on_close = true;
        }
 
-       Container       bag;
-       AltosFreqList   frequencies;
-       JComboBox<String>       telemetries;
-       JLabel          telemetry;
+       Container               bag;
+       AltosUIFreqList         frequencies;
+       AltosUIRateList         rates;
+       AltosUITelemetryList    telemetries;
+       JLabel                  telemetry;
 
        ActionListener  show_timer;
 
@@ -193,8 +194,8 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay {
 
                /* Stick channel selector at top of table for telemetry monitoring */
                if (serial >= 0) {
-                       // Channel menu
-                       frequencies = new AltosFreqList(AltosUIPreferences.frequency(serial));
+                       // Frequency menu
+                       frequencies = new AltosUIFreqList(AltosUIPreferences.frequency(serial));
                        frequencies.set_product("Monitor");
                        frequencies.set_serial(serial);
                        frequencies.addActionListener(new ActionListener() {
@@ -217,27 +218,40 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay {
                        c.anchor = GridBagConstraints.WEST;
                        bag.add (frequencies, c);
 
-                       // Telemetry format menu
+                       // Telemetry rate list
+                       rates = new AltosUIRateList(AltosUIPreferences.telemetry_rate(serial));
+                       rates.addActionListener(new ActionListener() {
+                                       public void actionPerformed(ActionEvent e) {
+                                               int rate = rates.rate();
+                                               try {
+                                                       reader.set_telemetry_rate(rate);
+                                               } catch (TimeoutException te) {
+                                               } catch (InterruptedException ie) {
+                                               }
+                                               reader.save_telemetry_rate();
+                                       }
+                               });
+                       rates.setEnabled(reader.supports_telemetry_rate(AltosLib.ao_telemetry_rate_2400));
+                       c.gridx = 1;
+                       c.gridy = 0;
+                       c.weightx = 0;
+                       c.weighty = 0;
+                       c.insets = new Insets(3, 3, 3, 3);
+                       c.fill = GridBagConstraints.NONE;
+                       c.anchor = GridBagConstraints.WEST;
+                       bag.add (rates, c);
+
+                       // Telemetry format list
                        if (reader.supports_telemetry(Altos.ao_telemetry_standard)) {
-                               telemetries = new JComboBox<String>();
-                               for (int i = 1; i <= Altos.ao_telemetry_max; i++)
-                                       telemetries.addItem(Altos.telemetry_name(i));
-                               int telemetry = AltosPreferences.telemetry(serial);
-                               if (telemetry <= Altos.ao_telemetry_off ||
-                                   telemetry > Altos.ao_telemetry_max)
-                                       telemetry = Altos.ao_telemetry_standard;
-                               telemetries.setSelectedIndex(telemetry - 1);
-                               telemetries.setMaximumRowCount(Altos.ao_telemetry_max);
-                               telemetries.setPreferredSize(null);
-                               telemetries.revalidate();
+                               telemetries = new AltosUITelemetryList(serial);
                                telemetries.addActionListener(new ActionListener() {
                                                public void actionPerformed(ActionEvent e) {
-                                                       int telemetry = telemetries.getSelectedIndex() + 1;
+                                                       int telemetry = telemetries.get_selected();
                                                        reader.set_telemetry(telemetry);
                                                        reader.save_telemetry();
                                                }
                                        });
-                               c.gridx = 1;
+                               c.gridx = 2;
                                c.gridy = 0;
                                c.weightx = 0;
                                c.weighty = 0;
@@ -256,7 +270,7 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay {
                                        version = "Telemetry: None";
 
                                telemetry = new JLabel(version);
-                               c.gridx = 1;
+                               c.gridx = 2;
                                c.gridy = 0;
                                c.weightx = 0;
                                c.weighty = 0;
@@ -274,9 +288,8 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay {
                c.gridy = 1;
                c.fill = GridBagConstraints.HORIZONTAL;
                c.weightx = 1;
-               c.gridwidth = 2;
+               c.gridwidth = 3;
                bag.add(flightStatus, c);
-               c.gridwidth = 1;
 
                /* The rest of the window uses a tabbed pane to
                 * show one of the alternate data views
@@ -315,7 +328,6 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay {
                c.fill = GridBagConstraints.BOTH;
                c.weightx = 1;
                c.weighty = 1;
-               c.gridwidth = 2;
                bag.add(pane, c);
 
                setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
index 07fe93176c33dd68d71bfec4f47e7ff8a9222c6a..ddd281a6d41813453cedb2a932211eb99d7d88c9 100644 (file)
@@ -23,8 +23,8 @@ import java.util.ArrayList;
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 import org.jfree.chart.ChartPanel;
 import org.jfree.chart.JFreeChart;
index 042111ec44347c5eb7803aa5fd477ffc6db41c4a..67b7a9897717a2aea529ae383916babb946ffdda 100644 (file)
@@ -24,8 +24,8 @@ import javax.swing.event.*;
 import java.io.*;
 import java.util.concurrent.*;
 import java.util.Arrays;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDisplay, AltosIdleMonitorListener, DocumentListener {
        AltosDevice             device;
@@ -33,9 +33,11 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl
        AltosPad                pad;
        AltosInfoTable          flightInfo;
        AltosFlightStatus       flightStatus;
+       AltosIgnitor            ignitor;
        AltosIdleMonitor        thread;
        int                     serial;
        boolean                 remote;
+       boolean                 has_ignitor;
 
        void stop_display() {
                if (thread != null) {
@@ -70,10 +72,22 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl
 
        public void show(AltosState state, AltosListenerState listener_state) {
                status_update.saved_state = state;
+               if (ignitor.should_show(state)) {
+                       if (!has_ignitor) {
+                               pane.add("Ignitor", ignitor);
+                               has_ignitor = true;
+                       }
+               } else {
+                       if (has_ignitor) {
+                               pane.remove(ignitor);
+                               has_ignitor = false;
+                       }
+               }
 //             try {
                        pad.show(state, listener_state);
                        flightStatus.show(state, listener_state);
                        flightInfo.show(state, listener_state);
+                       ignitor.show(state, listener_state);
 //             } catch (Exception e) {
 //                     System.out.print("Show exception " + e);
 //             }
@@ -89,7 +103,7 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl
        }
 
        Container       bag;
-       AltosFreqList   frequencies;
+       AltosUIFreqList frequencies;
        JTextField      callsign_value;
 
        /* DocumentListener interface methods */
@@ -186,7 +200,7 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl
                /* Stick frequency selector at top of table for telemetry monitoring */
                if (remote && serial >= 0) {
                        // Frequency menu
-                       frequencies = new AltosFreqList(AltosUIPreferences.frequency(serial));
+                       frequencies = new AltosUIFreqList(AltosUIPreferences.frequency(serial));
                        frequencies.addActionListener(new ActionListener() {
                                        public void actionPerformed(ActionEvent e) {
                                                double frequency = frequencies.frequency();
@@ -222,6 +236,8 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl
                flightInfo = new AltosInfoTable();
                pane.add("Table", new JScrollPane(flightInfo));
 
+               ignitor = new AltosIgnitor();
+
                /* Make the tabbed pane use the rest of the window space */
                bag.add(pane, constraints(0, 3, GridBagConstraints.BOTH));
 
index c251bbe219e90a92d7fbaf378c8c4e4ad9a677ac..15a81e57e37a5fd604142123d776e378aed3c1f1 100644 (file)
@@ -24,8 +24,8 @@ import java.io.*;
 import java.text.*;
 import java.util.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class AltosIgniteUI
        extends AltosUIDialog
index 990a87e681775710eb66ceaa13d261e1c24d5ba6..117def093981154c6daaf35baddebafadffefbfd 100644 (file)
@@ -20,8 +20,8 @@ package altosui;
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class AltosIgnitor extends AltosUIFlightTab {
 
index dd5cf9ab827842aae003d620eeadadb944f6436c..7c50adacba874d053c892e913277dc71330083d0 100644 (file)
@@ -21,8 +21,8 @@ import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
 import java.io.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class AltosLanded extends AltosUIFlightTab implements ActionListener {
 
@@ -151,6 +151,12 @@ public class AltosLanded extends AltosUIFlightTab implements ActionListener {
                return "Landed";
        }
 
+       public void show(AltosState state, AltosListenerState listener_state) {
+               super.show(state, listener_state);
+               if (reader.backing_file() != null)
+                       graph.setEnabled(true);
+       }
+
        public AltosLanded(AltosFlightReader in_reader) {
                reader = in_reader;
 
index 9ac1e44c3a11b0fd1c88a6a03f244a56982a7048..1717861698f4c1bbb36a28cb99787cd998e6c612 100644 (file)
@@ -20,7 +20,7 @@ package altosui;
 import java.io.*;
 import java.util.concurrent.*;
 import java.awt.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class AltosLaunch {
        AltosDevice     device;
index cc082542b6f853543e998d20b68258b1171634fd..3320e6751c9207ed725575e460bdea80dbe31d9b 100644 (file)
@@ -23,7 +23,7 @@ import javax.swing.*;
 import java.io.*;
 import java.text.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altosuilib_3.*;
 
 class FireButton extends JButton {
        protected void processMouseEvent(MouseEvent e) {
index 6b5fd1500618edf63a4f8fc818bd90b11b1db57a..eb0c56448eb5a2bbd6a9ade8598797c7781ac7bc 100644 (file)
@@ -18,8 +18,8 @@
 package altosui;
 
 import java.util.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class AltosPad extends AltosUIFlightTab {
 
@@ -117,6 +117,17 @@ public class AltosPad extends AltosUIFlightTab {
                }
        }
 
+       boolean report_pad(AltosState state) {
+               if ((state.state == AltosLib.ao_flight_stateless ||
+                    state.state < AltosLib.ao_flight_pad) &&
+                   state.gps != null &&
+                   state.gps.lat != AltosLib.MISSING)
+               {
+                       return false;
+               }
+               return true;
+       }
+
        class PadLat extends AltosUIIndicator {
 
                double  last_lat = AltosLib.MISSING - 1;
@@ -126,12 +137,12 @@ public class AltosPad extends AltosUIFlightTab {
                        String label = null;
 
                        if (state != null) {
-                               if (state.state < AltosLib.ao_flight_pad && state.gps != null && state.gps.lat != AltosLib.MISSING) {
-                                       lat = state.gps.lat;
-                                       label = "Latitude";
-                               } else {
+                               if (report_pad(state)) {
                                        lat = state.pad_lat;
                                        label = "Pad Latitude";
+                               } else {
+                                       lat = state.gps.lat;
+                                       label = "Latitude";
                                }
                        }
                        if (lat != last_lat) {
@@ -163,12 +174,12 @@ public class AltosPad extends AltosUIFlightTab {
                        String label = null;
 
                        if (state != null) {
-                               if (state.state < AltosLib.ao_flight_pad && state.gps != null && state.gps.lon != AltosLib.MISSING) {
-                                       lon = state.gps.lon;
-                                       label = "Longitude";
-                               } else {
+                               if (report_pad(state)) {
                                        lon = state.pad_lon;
                                        label = "Pad Longitude";
+                               } else {
+                                       lon = state.gps.lon;
+                                       label = "Longitude";
                                }
                        }
                        if (lon != last_lon) {
@@ -200,12 +211,12 @@ public class AltosPad extends AltosUIFlightTab {
                        String label = null;
 
                        if (state != null) {
-                               if (state.state < AltosLib.ao_flight_pad && state.gps != null && state.gps.alt != AltosLib.MISSING) {
-                                       alt = state.gps.alt;
-                                       label = "Altitude";
-                               } else {
+                               if (report_pad(state)) {
                                        alt = state.pad_alt;
                                        label = "Pad Altitude";
+                               } else {
+                                       alt = state.gps.alt;
+                                       label = "Altitude";
                                }
                        }
                        if (alt != last_alt) {
index 6137487c418cb0bf8fc414c292a00b2e77516dde..0aa5d03ce142ef1a420b2c45d4d581b9654ac829 100644 (file)
@@ -22,8 +22,8 @@ import java.awt.event.*;
 import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class AltosUI extends AltosUIFrame {
        public AltosVoice voice = new AltosVoice();
@@ -99,10 +99,25 @@ public class AltosUI extends AltosUIFrame {
                return b;
        }
 
+       /* OSXAdapter interfaces */
+       public void macosx_file_handler(String path) {
+               process_graph(new File(path));
+       }
+
+       public void macosx_quit_handler() {
+               System.exit(0);
+       }
+
+       public void macosx_preferences_handler() {
+               ConfigureAltosUI();
+       }
+
        public AltosUI() {
 
                load_library(null);
 
+               register_for_macosx_events();
+
                AltosUIPreferences.set_component(this);
 
                pane = getContentPane();
index 280470866a4f22df99e45ca6de87158be04991ff..b229d7b2bb7aa0e253668e91acb7072981f410f1 100644 (file)
@@ -19,7 +19,7 @@ package altosui;
 
 import java.io.File;
 import java.util.prefs.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 import javax.swing.filechooser.FileSystemView;
 
 public class AltosUIPreferencesBackend implements AltosPreferencesBackend {
index 46dea171b85cbfefca3a628476a0ef12e2b79603..8dc797d6f92c97e0297d56d17f6f8da995fd7fc2 100644 (file)
        <key>CFBundleInfoDictionaryVersion</key>
        <string>6.0</string>
        <key>CFBundleIconFile</key>
-       <string>AltosUIIcon.icns</string>
+       <string>altusmetrum-altosui.icns</string>
+       <key>CFBundleDocumentTypes</key>
+       <array>
+         <dict>
+           <key>CFBundleTypeName</key>
+           <string>Telemetry</string>
+           <key>CFBundleTypeIconFile</key>
+           <string>application-vnd.altusmetrum.telemetry.icns</string>
+           <key>CFBundleTypeExtensions</key>
+           <array>
+             <string>telem</string>
+           </array>
+           <key>CFBundleTypeRole</key>
+           <string>Editor</string>
+         </dict>
+         <dict>
+           <key>CFBundleTypeName</key>
+           <string>Eeprom</string>
+           <key>CFBundleTypeIconFile</key>
+           <string>application-vnd.altusmetrum.eeprom.icns</string>
+           <key>CFBundleTypeExtensions</key>
+           <array>
+             <string>eeprom</string>
+           </array>
+           <key>CFBundleTypeRole</key>
+           <string>Editor</string>
+         </dict>
+       </array>
        <key>Java</key>
        <dict>
                <key>MainClass</key>
index ebf1c5b96071223146a54f441ed021ecd1884557..cd47c1b53337ff5205256dae4d05c872d7f12f7f 100644 (file)
@@ -32,19 +32,135 @@ Function GetJRE
         Delete $2
 FunctionEnd
 
-Function DetectJRE
+Function DoDetectJRE
+
+  DetailPrint "Desired Java version ${JRE_VERSION}"
+
+  ; Check in HKCU for CurrentVersion
+
+  ClearErrors
+  ReadRegStr $2 HKCU "SOFTWARE\JavaSoft\Java Runtime Environment" \
+             "CurrentVersion"
+
+  IfErrors hklm_version
+
+  DetailPrint "HKEY_CURRENT_USER Java version $2"
+
+  ${VersionCompare} $2 ${JRE_VERSION} $3
+
+  IntCmp $3 1 yes yes no
+
+hklm_version:
+
+  ; Check in HKLM for CurrentVersion
+
+  ClearErrors
   ReadRegStr $2 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment" \
              "CurrentVersion"
+  
+  IfErrors hkcu_any
 
-  DetailPrint "Desired Java version ${JRE_VERSION}"
-  DetailPrint "Actual Java version $2"
+  DetailPrint "HKEY_LOCAL_MACHINE Java version $2"
 
   ${VersionCompare} $2 ${JRE_VERSION} $3
 
-  IntCmp $3 1 done done
+  IntCmp $3 1 yes yes no
 
-  Call GetJRE
+hkcu_any:
+
+  ; Check in HKCU for any Java install
+
+  StrCpy $0 0
+
+hkcu_any_loop:
+  EnumRegKey $1 HKCU "SOFTWARE\JavaSoft" $0
+
+  StrCmp $1 "Java Runtime Environment" found_hkcu
+
+  StrCmp $1 "" hklm_any
+  
+  IntOp $0 $0 + 1
+
+  Goto hkcu_any_loop
+  
+found_hkcu:
+
+  DetailPrint "HKEY_CURRENT_USER has SOFTWARE\JavaSoft\$1"
+
+  Goto maybe
+
+hklm_any:
+
+  ; Check in HKCU for any Java install
+
+  StrCpy $0 0
+
+hklm_any_loop:
+  EnumRegKey $1 HKLM "SOFTWARE\JavaSoft" $0
+
+  StrCmp $1 "Java Runtime Environment" found_hklm
+
+  StrCmp $1 "" no
+  
+  IntOp $0 $0 + 1
+
+  Goto hklm_any_loop
+  
+found_hklm:
+
+  DetailPrint "HKEY_CURRENT_USER has SOFTWARE\JavaSoft\$1"
+
+  Goto maybe
+
+yes:
+  StrCpy $0 2
+  Goto done
+
+maybe:
+  StrCpy $0 1
+  Goto done
+
+no:
+  StrCpy $0 0
+  Goto done  
 
 done:
 
 FunctionEnd
+
+var dialog
+var hwnd
+var null
+
+var install
+var quit
+var skip
+
+Function DetectJRE
+
+  Call DoDetectJRE
+
+  IntCmp $0 1 ask_maybe ask_no yes
+
+ask_no:
+  StrCpy $0 "No Java detected. Download and install?"
+  Goto ask
+
+ask_maybe:
+  StrCpy $0 "Cannot determine installed Java version. Download and install?"
+  Goto ask
+
+ask:
+  MessageBox MB_YESNOCANCEL $0 IDYES do_java IDNO skip_java
+
+bail:
+  Abort
+
+do_java:
+  Call GetJRE
+
+
+skip_java:
+yes:
+
+FunctionEnd
diff --git a/altosui/Instdrv/NSIS/Includes/refresh-sh.nsh b/altosui/Instdrv/NSIS/Includes/refresh-sh.nsh
new file mode 100644 (file)
index 0000000..23d8e5e
--- /dev/null
@@ -0,0 +1,14 @@
+!define SHCNE_ASSOCCHANGED 0x08000000
+!define SHCNF_IDLIST 0
+Function RefreshShellIcons
+  ; By jerome tremblay - april 2003
+  ${DisableX64FSRedirection}
+  System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (${SHCNE_ASSOCCHANGED}, ${SHCNF_IDLIST}, 0, 0)'
+FunctionEnd
+
+Function un.RefreshShellIcons
+  ; By jerome tremblay - april 2003
+  ${DisableX64FSRedirection}
+  System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (${SHCNE_ASSOCCHANGED}, ${SHCNF_IDLIST}, 0, 0)'
+FunctionEnd
index 4cb5df589a306f5ad8b9abbe3d3c6f7936e2e7be..48f58933ec0900e52483b077c0c919bebd767a87 100644 (file)
@@ -64,7 +64,7 @@ LIBALTOS= \
        altos.dll
 
 desktopdir = $(datadir)/applications
-desktop_file = altos.desktop
+desktop_file = altusmetrum-altosui.desktop
 desktop_SCRIPTS = $(desktop_file)
 
 JAR=altosui.jar
@@ -72,26 +72,45 @@ JAR=altosui.jar
 FATJAR=altosui-fat.jar
 
 # Icons
-ICONDIR=$(top_srcdir)/icon
+ICONDIR=../icon
 
 JAVA_ICONS=\
-       $(ICONDIR)/altus-metrum-16.png \
-       $(ICONDIR)/altus-metrum-32.png \
-       $(ICONDIR)/altus-metrum-48.png \
-       $(ICONDIR)/altus-metrum-64.png \
-       $(ICONDIR)/altus-metrum-128.png \
-       $(ICONDIR)/altus-metrum-256.png
+       $(ICONDIR)/altusmetrum-altosui-16.png \
+       $(ICONDIR)/altusmetrum-altosui-32.png \
+       $(ICONDIR)/altusmetrum-altosui-48.png \
+       $(ICONDIR)/altusmetrum-altosui-64.png \
+       $(ICONDIR)/altusmetrum-altosui-128.png\
+       $(ICONDIR)/altusmetrum-altosui-256.png
 
 # icon base names for jar
-ICONJAR= -C $(ICONDIR) altus-metrum-16.png \
-       -C $(ICONDIR) altus-metrum-32.png \
-       -C $(ICONDIR) altus-metrum-48.png \
-       -C $(ICONDIR) altus-metrum-64.png \
-       -C $(ICONDIR) altus-metrum-128.png \
-       -C $(ICONDIR) altus-metrum-256.png
-
-WINDOWS_ICON=$(ICONDIR)/altus-metrum.ico
-MACOSX_ICON=$(ICONDIR)/AltosUIIcon.icns
+ICONJAR= \
+       -C $(ICONDIR) altusmetrum-altosui-16.png \
+       -C $(ICONDIR) altusmetrum-altosui-32.png \
+       -C $(ICONDIR) altusmetrum-altosui-48.png \
+       -C $(ICONDIR) altusmetrum-altosui-64.png \
+       -C $(ICONDIR) altusmetrum-altosui-128.png\
+       -C $(ICONDIR) altusmetrum-altosui-256.png
+
+WINDOWS_ICONS  =\
+       $(ICONDIR)/altusmetrum-altosui.ico \
+       $(ICONDIR)/altusmetrum-altosui.exe
+       $(ICONDIR)/application-vnd.altusmetrum.eeprom.ico \
+       $(ICONDIR)/application-vnd.altusmetrum.eeprom.exe \
+       $(ICONDIR)/application-vnd.altusmetrum.telemetry.ico \
+       $(ICONDIR)/application-vnd.altusmetrum.telemetry.exe
+
+MACOSX_ICONS   =\
+       $(ICONDIR)/altusmetrum-altosui.icns \
+       $(ICONDIR)/application-vnd.altusmetrum.eeprom.icns \
+       $(ICONDIR)/application-vnd.altusmetrum.telemetry.icns
+
+LINUX_ICONS    =\
+       $(ICONDIR)/altusmetrum-altosui.svg \
+       $(ICONDIR)/application-vnd.altusmetrum.eeprom.svg \
+       $(ICONDIR)/application-vnd.altusmetrum.telemetry.svg
+
+LINUX_MIMETYPE =\
+       $(ICONDIR)/org-altusmetrum-mimetypes.xml
 
 # Firmware
 FIRMWARE_TD_0_2=$(top_srcdir)/src/teledongle-v0.2/teledongle-v0.2-$(VERSION).ihx
@@ -115,10 +134,13 @@ FIRMWARE_TMEGA=$(FIRMWARE_TMEGA_1_0)
 FIRMWARE_EMINI_1_0=$(top_srcdir)/src/easymini-v1.0/easymini-v1.0-$(VERSION).ihx
 FIRMWARE_EMINI=$(FIRMWARE_EMINI_1_0)
 
+FIRMWARE_EMEGA_1_0=$(top_srcdir)/src/easymega-v1.0/easymega-v1.0-$(VERSION).ihx
+FIRMWARE_EMEGA=$(FIRMWARE_EMEGA_1_0)
+
 FIRMWARE_TGPS_1_0=$(top_srcdir)/src/telegps-v1.0/telegps-v1.0-$(VERSION).ihx
 FIRMWARE_TGPS=$(FIRMWARE_TGPS_1_0)
 
-FIRMWARE=$(FIRMWARE_TM) $(FIRMWARE_TELEMINI) $(FIRMWARE_TD) $(FIRMWARE_TBT) $(FIRMWARE_TMEGA) $(FIRMWARE_EMINI) $(FIRMWARE_TGPS)
+FIRMWARE=$(FIRMWARE_TM) $(FIRMWARE_TELEMINI) $(FIRMWARE_TD) $(FIRMWARE_TBT) $(FIRMWARE_TMEGA) $(FIRMWARE_EMINI) $(FIRMWARE_TGPS) $(FIRMWARE_EMEGA)
 
 ALTUSMETRUM_DOC=$(top_srcdir)/doc/altusmetrum.pdf
 ALTOS_DOC=$(top_srcdir)/doc/altos.pdf
@@ -141,14 +163,14 @@ FAT_FILES=$(FATJAR) $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) $(FREETTS_CLASS) $(JFR
 
 LINUX_LIBS=libaltos32.so libaltos64.so
 
-LINUX_FILES=$(FAT_FILES) $(LINUX_LIBS) $(FIRMWARE) $(DOC) altos.desktop.in ../icon/altusmetrum.svg
+LINUX_FILES=$(FAT_FILES) $(LINUX_LIBS) $(FIRMWARE) $(DOC) $(desktop_file).in $(LINUX_ICONS) $(LINUX_MIMETYPE)
 LINUX_EXTRA=altosui-fat
 
 MACOSX_INFO_PLIST=Info.plist
-MACOSX_FILES=$(FAT_FILES) libaltos.dylib $(MACOSX_INFO_PLIST) $(DOC) ReadMe-Mac.rtf $(MACOSX_ICON)
+MACOSX_FILES=$(FAT_FILES) libaltos.dylib $(MACOSX_INFO_PLIST) $(DOC) ReadMe-Mac.rtf $(MACOSX_ICONS)
 MACOSX_EXTRA=$(FIRMWARE)
 
-WINDOWS_FILES=$(FAT_FILES) $(FIRMWARE) altos.dll altos64.dll $(top_srcdir)/altusmetrum.inf $(top_srcdir)/altusmetrum.cat $(WINDOWS_ICON)
+WINDOWS_FILES=$(FAT_FILES) $(FIRMWARE) altos.dll altos64.dll $(top_srcdir)/altusmetrum.inf $(top_srcdir)/altusmetrum.cat $(WINDOWS_ICONS)
 
 all-local: classes/altosui $(JAR) altosui altosui-test altosui-jdb
 
@@ -156,12 +178,12 @@ clean-local:
        -rm -rf classes $(JAR) $(FATJAR) \
                $(LINUX_DIST) $(LINUX_SH) $(MACOSX_DIST) windows $(WINDOWS_DIST) $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) $(FREETTS_CLASS) \
                $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) Manifest.txt Manifest-fat.txt altos-windows.log altos-windows.nsi \
-               altosui altosui-test altosui-jdb macosx linux
+               altosui altosui-test altosui-jdb macosx linux *.desktop
 
 EXTRA_DIST = $(desktop_file).in
 
 $(desktop_file): $(desktop_file).in
-       sed -e 's#%bindir%#@bindir@#' -e 's#%icondir%#$(datadir)/icons/hicolor/scalable/apps#' ${srcdir}/altos.desktop.in > $@
+       sed -e 's#%bindir%#@bindir@#' -e 's#%icondir%#$(datadir)/icons/hicolor/scalable/apps#' ${srcdir}/$(desktop_file).in > $@
        chmod +x $@
 
 if FATINSTALL
@@ -195,7 +217,6 @@ else
 fat: $(LINUX_DIST) $(LINUX_SH) $(MACOSX_DIST) $(WINDOWS_DIST)
 endif
 
-
 altosuidir=$(datadir)/java
 
 install-altosuiJAVA: altosui.jar
@@ -325,7 +346,7 @@ $(MACOSX_DIST): $(MACOSX_FILES) $(MACOSX_EXTRA) Makefile
        cp -a $(DOC) macosx/Doc
        cp -p Info.plist macosx/AltosUI.app/Contents
        mkdir -p macosx/AltOS-$(VERSION) macosx/AltosUI.app/Contents/Resources/Java
-       cp -p $(MACOSX_ICON) macosx/AltosUI.app/Contents/Resources
+       cp -p $(MACOSX_ICONS) macosx/AltosUI.app/Contents/Resources
        cp -p $(FATJAR) macosx/AltosUI.app/Contents/Resources/Java/altosui.jar
        cp -p libaltos.dylib macosx/AltosUI.app/Contents/Resources/Java
        cp -p $(ALTOSLIB_CLASS) macosx/AltosUI.app/Contents/Resources/Java
@@ -336,6 +357,6 @@ $(MACOSX_DIST): $(MACOSX_FILES) $(MACOSX_EXTRA) Makefile
        cp -p $(MACOSX_EXTRA) macosx/AltOS-$(VERSION)
        genisoimage -D -V AltOS-$(VERSION) -no-pad -r -apple -o $@ macosx
 
-$(WINDOWS_DIST): $(WINDOWS_FILES) altos-windows.nsi
+$(WINDOWS_DIST): $(WINDOWS_FILES) altos-windows.nsi Instdrv/NSIS/Includes/java.nsh
        -rm -f $@
        makensis -Oaltos-windows.log "-XOutFile $@" "-DVERSION=$(VERSION)" altos-windows.nsi || (cat altos-windows.log && exit 1)
index 2e2a46f17af7343b152d9d83dc0872f08d4cf275..11c1dc0700d0682dae16f1833258c8287ed667b1 100644 (file)
@@ -2,16 +2,24 @@
 !addincludedir Instdrv/NSIS/Includes
 !include x64.nsh
 !include java.nsh
+!include refresh-sh.nsh
 
-!define PRODUCT_NAME "Altus Metrum Windows Software"
+!define REG_NAME       "Altus Metrum"
+!define PROG_ID_TELEM  "altusmetrum.altosui.telem.1"
+!define PROG_ID_EEPROM "altusmetrum.altosui.eeprom.1"
+!define FAT_NAME       "altosui-fat.jar"
+!define WIN_APP_ICON   "altusmetrum-altosui.ico"
+!define WIN_APP_EXE    "altusmetrum-altosui.exe"
+!define WIN_TELEM_EXE  "application-vnd.altusmetrum.telemetry.exe"
+!define WIN_EEPROM_EXE "application-vnd.altusmetrum.eeprom.exe"
 
-Name "Altus Metrum Installer"
+Name "${REG_NAME} Installer"
 
 ; Default install directory
 InstallDir "$PROGRAMFILES\AltusMetrum"
 
 ; Tell the installer where to re-install a new version
-InstallDirRegKey HKLM "Software\AltusMetrum" "Install_Dir"
+InstallDirRegKey HKLM "Software\${REG_NAME}" "Install_Dir"
 
 LicenseText "GNU General Public License Version 2"
 LicenseData "../COPYING"
@@ -21,7 +29,7 @@ RequestExecutionLevel admin
 
 ShowInstDetails Show
 
-ComponentText "Altus Metrum Software and Driver Installer"
+ComponentText "${REG_NAME} Software and Driver Installer"
 
 Function .onInit
        DetailPrint "Checking host operating system"
@@ -33,6 +41,16 @@ Function .onInit
        ${EndIf}
 FunctionEnd
 
+Function un.onInit
+       DetailPrint "Checking host operating system"
+       ${If} ${RunningX64}
+               DetailPrint "Installer running on 64-bit host"
+               SetRegView 64
+               StrCpy $INSTDIR "$PROGRAMFILES64\AltusMetrum"
+               ${DisableX64FSRedirection}
+       ${EndIf}
+FunctionEnd
+
 ; Pages to present
 
 Page license
@@ -68,12 +86,12 @@ done:
 
 SectionEnd
 
-Section "AltosUI Application"
+Section "${REG_NAME} Application"
        Call DetectJRE
 
        SetOutPath $INSTDIR
 
-       File "altosui-fat.jar"
+       File "${FAT_NAME}"
        File "altoslib_@ALTOSLIB_VERSION@.jar"
        File "altosuilib_@ALTOSUILIB_VERSION@.jar"
        File "cmudict04.jar"
@@ -88,16 +106,16 @@ Section "AltosUI Application"
 
        File "*.dll"
 
-       File "../icon/*.ico"
+       File "../icon/${WIN_APP_ICON}"
 
-       CreateShortCut "$SMPROGRAMS\AltusMetrum.lnk" "$SYSDIR\javaw.exe" "-jar altosui-fat.jar" "$INSTDIR\altus-metrum.ico"
+       CreateShortCut "$SMPROGRAMS\${REG_NAME}.lnk" "$SYSDIR\javaw.exe" "-jar ${FAT_NAME}" "$INSTDIR\${WIN_APP_ICON}"
 SectionEnd
 
-Section "AltosUI Desktop Shortcut"
-       CreateShortCut "$DESKTOP\AltusMetrum.lnk" "$INSTDIR\altosui-fat.jar"  "" "$INSTDIR\altus-metrum.ico"
+Section "${REG_NAME} Desktop Shortcut"
+       CreateShortCut "$DESKTOP\${REG_NAME}.lnk" "$INSTDIR\${FAT_NAME}"  "" "$INSTDIR\${WIN_APP_ICON}"
 SectionEnd
 
-Section "TeleMetrum, TeleDongle and TeleBT Firmware"
+Section "Firmware"
 
        SetOutPath $INSTDIR
 
@@ -111,6 +129,7 @@ Section "TeleMetrum, TeleDongle and TeleBT Firmware"
        File "../src/telebt-v1.0/telebt-v1.0-${VERSION}.ihx"
        File "../src/telemega-v1.0/telemega-v1.0-${VERSION}.ihx"
        File "../src/easymini-v1.0/easymini-v1.0-${VERSION}.ihx"
+       File "../src/easymega-v1.0/easymega-v1.0-${VERSION}.ihx"
 
 SectionEnd
 
@@ -127,38 +146,105 @@ Section "Documentation"
        File "../doc/telemini.pdf"
 SectionEnd
 
+Section "File Associations"
+
+       ${DisableX64FSRedirection}
+
+       SetOutPath $INSTDIR
+
+       File "../icon/${WIN_APP_EXE}"
+       File "../icon/${WIN_TELEM_EXE}"
+       File "../icon/${WIN_EEPROM_EXE}"
+
+       DeleteRegKey HKCR "${PROG_ID_TELEM}"
+       DeleteRegKey HKCR "${PROG_ID_EEPROM}"
+
+       DeleteRegKey   HKCR ".eeprom\${PROG_ID_EEPROM}"
+       DeleteRegValue HKCR ".eeprom\OpenWithProgids" "${PROG_ID_EEPROM}"
+       DeleteRegKey   HKCR ".telem\${PROG_ID_EEPROM}"
+       DeleteRegValue HKCR ".telem\OpenWithProgids" "${PROG_ID_EEPROM}"
+
+       ; .eeprom elements
+
+       WriteRegStr HKCR "${PROG_ID_EEPROM}"            ""                              "Altus Metrum Log File"
+       WriteRegStr HKCR "${PROG_ID_EEPROM}"            "FriendlyTypeName"              "Altus Metrum Log File"
+       WriteRegStr HKCR "${PROG_ID_EEPROM}\CurVer"     ""                              "${PROG_ID_EEPROM}"
+       WriteRegStr HKCR "${PROG_ID_EEPROM}\DefaultIcon" ""                             '"$INSTDIR\${WIN_EEPROM_EXE}",-101'
+  WriteRegExpandStr HKCR "${PROG_ID_EEPROM}\shell\open\command" ""                     '"%SYSTEMROOT%\System32\javaw.exe" -Djava.library.path="$INSTDIR" -jar "$INSTDIR\${FAT_NAME}" "%1"'
+
+       WriteRegStr HKCR ".eeprom"                      ""                              "${PROG_ID_EEPROM}"
+       WriteRegStr HKCR ".eeprom"                      "PerceivedType"                 "Altus Metrum Log File"
+       WriteRegStr HKCR ".eeprom"                      "Content Type"                  "application/vnd.altusmetrum.eeprom"
+
+       WriteRegStr HKCR ".eeprom\OpenWithProgids"      "${PROG_ID_EEPROM}"             ""
+       WriteRegStr HKCR ".eeprom\${PROG_ID_EEPROM}"    ""                              "${REG_NAME}"
+       
+       ; .telem elements
+       
+       WriteRegStr HKCR "${PROG_ID_TELEM}"             ""                              "Altus Metrum Telemetry File"
+       WriteRegStr HKCR "${PROG_ID_TELEM}"             "FriendlyTypeName"              "Altus Metrum Telemetry File"
+       WriteRegStr HKCR "${PROG_ID_TELEM}\CurVer"      ""                              "${PROG_ID_TELEM}"
+       WriteRegStr HKCR "${PROG_ID_TELEM}\DefaultIcon" ""                              '"$INSTDIR\${WIN_TELEM_EXE}",-101'
+  WriteRegExpandStr HKCR "${PROG_ID_TELEM}\shell\open\command" ""                      '"%SYSTEMROOT%\System32\javaw.exe" -Djava.library.path="$INSTDIR" -jar "$INSTDIR\${FAT_NAME}" "%1"'
+
+       WriteRegStr HKCR ".telem"                       ""                              "${PROG_ID_TELEM}"
+       WriteRegStr HKCR ".telem"                       "PerceivedType"                 "Altus Metrum Telemetry File"
+       WriteRegStr HKCR ".telem"                       "Content Type"                  "application/vnd.altusmetrum.telemetry"
+
+       WriteRegStr HKCR ".telem\OpenWithProgids"       "${PROG_ID_TELEM}"              ""
+       WriteRegStr HKCR ".telem\${PROG_ID_TELEM}"      ""                              "${REG_NAME}"
+
+       Call RefreshShellIcons
+SectionEnd
+       
 Section "Uninstaller"
 
        ; Deal with the uninstaller
 
+       ${DisableX64FSRedirection}
        SetOutPath $INSTDIR
 
        ; Write the install path to the registry
-       WriteRegStr HKLM SOFTWARE\AltusMetrum "Install_Dir" "$INSTDIR"
+       WriteRegStr HKLM "SOFTWARE\${REG_NAME}" "Install_Dir" "$INSTDIR"
 
        ; Write the uninstall keys for windows
-       WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "DisplayName" "Altus Metrum"
-       WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "UninstallString" '"$INSTDIR\uninstall.exe"'
-       WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "NoModify" "1"
-       WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "NoRepair" "1"
+       WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "DisplayName" "${REG_NAME}"
+       WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "UninstallString" '"$INSTDIR\uninstall-${REG_NAME}.exe"'
+       WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "NoModify" "1"
+       WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "NoRepair" "1"
 
-       WriteUninstaller "uninstall.exe"
+       WriteUninstaller "uninstall-${REG_NAME}.exe"
 SectionEnd
 
 Section "Uninstall"
-       DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum"
-       DeleteRegKey HKLM "Software\AltusMetrum"
 
-       Delete "$INSTDIR\*.*"
-       RMDir "$INSTDIR"
+       ${DisableX64FSRedirection}
 
-       ; Remove devices
-       InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} AltusMetrumSerial
-       InstDrv::DeleteOemInfFiles /NOUNLOAD
-       InstDrv::RemoveAllDevices
+       DeleteRegKey   HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}"
+       DeleteRegKey   HKLM "SOFTWARE\${REG_NAME}"
+
+       DetailPrint "Delete uninstall reg entries"
+
+       DeleteRegKey   HKCR "${PROG_ID_EEPROM}"
+       DeleteRegKey   HKCR "${PROG_ID_TELEM}"
+
+       DeleteRegKey   HKCR ".eeprom\${PROG_ID_EEPROM}"
+       DeleteRegValue HKCR ".eeprom\OpenWithProgids" "${PROG_ID_EEPROM}"
+
+       DeleteRegKey   HKCR ".telem\${PROG_ID_TELEM}"
+       DeleteRegValue HKCR ".telem\OpenWithProgids" "${PROG_ID_TELEM}"
+
+       DetailPrint "Delete file association reg entries"
+
+       Delete "$INSTDIR\${FAT_NAME}"
+       Delete "$INSTDIR\uninstall-${REG_NAME}.exe"
+
+       Delete "$INSTDIR\${WIN_APP_ICON}"
+       Delete "$INSTDIR\${WIN_APP_EXE}"
 
        ; Remove shortcuts, if any
-       Delete "$SMPROGRAMS\AltusMetrum.lnk"
-       Delete "$DESKTOP\AltusMetrum.lnk"
+       Delete "$SMPROGRAMS\${REG_NAME}.lnk"
+       Delete "$DESKTOP\${REG_NAME}.lnk"
        
+       Call un.RefreshShellIcons
 SectionEnd
diff --git a/altosui/altos.desktop.in b/altosui/altos.desktop.in
deleted file mode 100644 (file)
index 6611434..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-[Desktop Entry]
-Type=Application
-Name=AltOS UI
-GenericName=Altus Metrum Ground Station
-Comment=View and log downlink data from Altus Metrum products
-Icon=%icondir%/altusmetrum.svg
-Exec=%bindir%/altosui %f
-Terminal=false
-MimeType=text/plain;
-Categories=Education;Electronics;Science;
diff --git a/altosui/altusmetrum-altosui.desktop.in b/altosui/altusmetrum-altosui.desktop.in
new file mode 100644 (file)
index 0000000..10fd9e9
--- /dev/null
@@ -0,0 +1,11 @@
+[Desktop Entry]
+Type=Application
+Version=1.0
+Name=AltOS UI
+GenericName=Altus Metrum Ground Station
+Comment=View and log downlink data from Altus Metrum products
+Icon=%icondir%/altusmetrum-altosui.svg
+Exec=%bindir%/altosui %f
+Terminal=false
+MimeType=application/vnd.altusmetrum.telemetry;application/vnd.altusmetrum.eeprom
+Categories=Education;Electronics;Science;
index 957b1aadf985ca2d7d19b5538a50bdf6bc0a04ad..2e44c2aacf1b26f83afe2850400a3140d34bdf0e 100644 (file)
@@ -130,6 +130,7 @@ esac
 #
 # Create the .desktop file by editing the paths
 #
+
 case "$target" in
 /*)
     target_abs="$target"
@@ -149,43 +150,46 @@ for infile in "$target"/AltOS/*.desktop.in; do
 done
 
 #
-# Figure out where to install the .desktop files. If we can, write it
-# to the public /usr/share/applications, otherwise, write it to the
-# per-user ~/.local/share/applications
+# Install the .desktop file
 #
 
-public=/usr/share/applications
-private=$HOME/.local/share/applications
-apps=""
+for desktop in "$target"/AltOS/*.desktop; do
+    case `id -u` in
+       0)
+           xdg-desktop-menu install --mode system "$desktop"
+           ;;
+       *)
+           xdg-desktop-menu install --mode user "$desktop"
+           ;;
+    esac
+done
 
-if [ -d "$public" -a -w "$public" ]; then
-    apps="$public"
-else
-    mkdir -p "$private" >/dev/null 2>&1 
-    if [ -d "$private" -a -w "$private" ]; then
-       apps="$private"
-    fi
-fi
-       
-case "$apps" in
-"")
-    echo "Cannot install application icon"
-    finish 1
-    ;;
-esac
+#
+# Install mime type file
+#
+
+for mimetype in "$target"/AltOS/*-mimetypes.xml; do
+    case `id -u` in
+       0)
+           xdg-mime install --mode system "$mimetype"
+           ;;
+       *)
+           xdg-mime install --mode user "$mimetype"
+           ;;
+    esac
+done
 
-echo -n "Installing .desktop files to $apps..."
+#
+# Install icons
+#
 
-cp "$target"/AltOS/*.desktop "$apps"
+for icon_dir in /usr/share/icons/hicolor/scalable/mimetypes "$HOME/.icons" "$HOME/.kde/share/icons"; do
+    if [ -w "$icon_dir" ]; then
+       cp "$target"/AltOS/*.svg "$icon_dir"
+       update-icon-caches "$icon_dir"
+    fi
+done
 
-case "$?" in
-0)
-    echo " done."
-    ;;
-*)
-    echo " failed."
-    ;;
-esac
 
 #
 # Install icon to desktop if desired
@@ -222,13 +226,14 @@ if [ -d $HOME/Desktop ]; then
        esac
     done
 
-    echo -n "Installing desktop icons..."
     case "$do_desktop" in
-    [yY]*)
-       for d in "$target"/AltOS/*.desktop; do
-           ln -f -s "$d" "$HOME/Desktop/"
-       done
-       ;;
+       [yY]*)
+           echo -n "Installing desktop icons..."
+           for d in "$target"/AltOS/*.desktop; do
+               base=`basename $d`
+               cp --remove-destination "$d" "$HOME/Desktop/"
+           done
+           ;;
     esac
 
     echo " done."
index beefa532b0affc86c0194a816b1e7d101738a853..2c0850213627a6083751d984e493ec807d2c68c1 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import libaltosJNI.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public class AltosBTDevice extends altos_bt_device implements AltosDevice {
 
index cad60ffba5216f48f63d1452c47561cf4c106327..c99b27f94e8d0c3b0d309c994960e7405408cbd7 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.util.*;
 import libaltosJNI.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public class AltosBTDeviceIterator implements Iterator<AltosBTDevice> {
        AltosBTDevice   current;
index 02883c759dbe4203b6c4c63b4fde4a1e796afec1..c526269d12ef871b4549b46d14669b285e48e3c1 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.util.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public class AltosBTKnown implements Iterable<AltosBTDevice> {
        LinkedList<AltosBTDevice>       devices = new LinkedList<AltosBTDevice>();
index 6da0a3ebcc22199b14b721506c48d9957913ceba..b953ca923d484f1f6ba4b72b88510443121457ab 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -23,7 +23,7 @@ import javax.swing.*;
 import javax.swing.plaf.basic.*;
 import java.util.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public class AltosBTManage extends AltosUIDialog implements ActionListener, Iterable<AltosBTDevice> {
        LinkedBlockingQueue<AltosBTDevice> found_devices;
index 0a5e4fa28d606bf43b3f242a19d7db65692197e4..6328d37dea1bd67d0934dea8941fdc755840b471 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
 import java.io.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public class AltosCSVUI
        extends AltosUIDialog
index 6dcd63b8dcb35624634814897e4b7c1fa2c8e161..a0525a00886eb7697575680a57032b752c956e56 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
 import java.util.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 class AltosEditFreqUI extends AltosUIDialog implements ActionListener {
        Frame           frame;
index 59891c4a8cecc90226c8ee9a582ab47e36b48651..1990faf1f4d73c2e2af315fcded7691d733a1a73 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import javax.swing.*;
 import javax.swing.filechooser.FileNameExtensionFilter;
 import java.io.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public class AltosDataChooser extends JFileChooser {
        JFrame  frame;
index 251ae994cb21087c417ebd31ae8e96061289bb8e..1f5536ffe4fea88a324494ae1043aec05a83ac00 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import libaltosJNI.*;
 
index 0bedea97b75019ea597cf160a493491fb8ffae7f..d2ccd5e76f15e388daf1d9bae3314ea1b847eea9 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import javax.swing.*;
 import java.awt.*;
@@ -131,7 +131,8 @@ public abstract class AltosDeviceDialog extends AltosUIDialog implements ActionL
                buttonPane.add(cancel_button);
                buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
 
-               add_bluetooth();
+               if (AltosUILib.has_bluetooth)
+                       add_bluetooth();
 
                buttonPane.add(select_button);
 
index 3013612ab9199f5c641f1edc039ac4d91b6645b6..80a76d6d6c2d532abb061cdd0d17b8cb215eb77a 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import javax.swing.*;
 import java.awt.*;
index 06bc68a912003f41e58bc79c4bec53d6c9bbe126..6b6e03e7372baa86c778f52e7946ee54ef914dca 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.*;
 import javax.swing.*;
 import java.io.*;
 import java.text.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public class AltosDisplayThread extends Thread {
 
index 981daddfa708ff01269c9b57cf27879e8a346740..39585dad3793aef24bdc01c7fb56e09f8fc5c06f 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.event.*;
 import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public class AltosEepromDelete implements Runnable {
        AltosEepromList         flights;
index 2b967339ad4bb0d8019df44ae118caea23212fe1..81dd3d13e4eb50a01bb50a6d0408f91f741cc1fc 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.event.*;
 import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public class AltosEepromManage implements ActionListener {
 
index b1e85622cdd690faee717cc0ede6a6abcfe16947..060d0474f888b872b64c3eceb185d921a67621f0 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.*;
 import java.awt.event.*;
index 02c71cd97ccf424d6a3b140cf283c1d24f0c2dea..11dd4adb3f51c062f000a6d9ff8fbb3328eb9d15 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMonitor {
        JFrame          owner;
index 293d3045831a4e2ac0ab4028ec61ba00db1ae268..1adfdab57256df407ff6fbc9e9ec93e22332a888 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import javax.swing.*;
 import javax.swing.border.*;
 import java.awt.*;
 import java.awt.event.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 class AltosEepromItem implements ActionListener {
        AltosEepromLog  log;
index 3f1206170f170deafcece0f0eed349b685139ff1..44be2a9064f6183396b073d208979340fdfc9128 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -23,7 +23,7 @@ import javax.swing.*;
 import javax.swing.filechooser.FileNameExtensionFilter;
 import java.io.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public class AltosFlashUI
        extends AltosUIDialog
@@ -213,6 +213,7 @@ public class AltosFlashUI
                new AltosHexfileFilter(AltosLib.product_teledongle, "teledongle", "TeleDongle Image"),
                new AltosHexfileFilter(AltosLib.product_telemega, "telemega", "TeleMega Image"),
                new AltosHexfileFilter(AltosLib.product_easymini, "easymini", "EasyMini Image"),
+               new AltosHexfileFilter(AltosLib.product_easymega, "easymega", "EasyMega Image"),
        };
 
        boolean select_source_file() {
index 55b74034b7255b9bd11e2aafa0bf892cc3ea6ad5..d0f20bb49d2dd08c86f9499dd7aec473609f41e2 100644 (file)
@@ -15,9 +15,9 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public interface AltosFlightDisplay extends AltosUnitsListener, AltosFontListener {
        void reset();
index 3995efb3125232b6e36cb9b883ed1108bf292f5f..0bc4f847ca1fef7a2c403bf4980dfa744750ecd4 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import javax.swing.table.*;
 
index 703dfb9d46b44c85980731620c6b0c47103e94bb..1ec4a03e5030615a42a2652ef4112b1505b02af3 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.*;
 import javax.swing.*;
 import java.util.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public class AltosFlightStatsTable extends JComponent implements AltosFontListener {
        GridBagLayout   layout;
index a98cc13179c1122f7bfd0ab0a9f7d121172d6b3d..a1b2170bff2561d3057830ebd5014f32cfcd4d24 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 public interface AltosFontListener {
        void font_size_changed(int font_size);
diff --git a/altosuilib/AltosFreqList.java b/altosuilib/AltosFreqList.java
deleted file mode 100644 (file)
index e1299aa..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.altosuilib_2;
-
-import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
-
-public class AltosFreqList extends JComboBox<AltosFrequency> {
-
-       String  product;
-       int     serial;
-       int     calibrate;
-
-       public void set_frequency(double new_frequency) {
-               int i;
-
-               if (new_frequency < 0) {
-                       setVisible(false);
-                       return;
-               }
-
-               for (i = 0; i < getItemCount(); i++) {
-                       AltosFrequency  f = (AltosFrequency) getItemAt(i);
-
-                       if (f.close(new_frequency)) {
-                               setSelectedIndex(i);
-                               return;
-                       }
-               }
-               for (i = 0; i < getItemCount(); i++) {
-                       AltosFrequency  f = (AltosFrequency) getItemAt(i);
-
-                       if (new_frequency < f.frequency)
-                               break;
-               }
-               String  description = String.format("%s serial %d", product, serial);
-               AltosFrequency  frequency = new AltosFrequency(new_frequency, description);
-               AltosUIPreferences.add_common_frequency(frequency);
-               insertItemAt(frequency, i);
-               setMaximumRowCount(getItemCount());
-       }
-
-       public void set_product(String new_product) {
-               product = new_product;
-       }
-
-       public void set_serial(int new_serial) {
-               serial = new_serial;
-       }
-
-       public double frequency() {
-               AltosFrequency  f = (AltosFrequency) getSelectedItem();
-               if (f != null)
-                       return f.frequency;
-               return 434.550;
-       }
-
-       public AltosFreqList () {
-               super(AltosUIPreferences.common_frequencies());
-               setMaximumRowCount(getItemCount());
-               setEditable(false);
-               product = "Unknown";
-               serial = 0;
-       }
-
-       public AltosFreqList(double in_frequency) {
-               this();
-               set_frequency(in_frequency);
-       }
-}
index f8c8b27b762e7b506332b5bd426c6734c9078a7b..522eea1ef65ed1d463a9d84a303e213ef65f1c96 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.io.*;
 import java.util.ArrayList;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 import org.jfree.ui.*;
 import org.jfree.chart.*;
@@ -172,6 +172,29 @@ class AltosMagUnits extends AltosUnits {
        }
 }
 
+class AltosDopUnits extends AltosUnits {
+
+       public double value(double p, boolean imperial_units) {
+               return p;
+       }
+
+       public double inverse(double p, boolean imperial_units) {
+               return p;
+       }
+
+       public String show_units(boolean imperial_units) {
+               return null;
+       }
+
+       public String say_units(boolean imperial_units) {
+               return null;
+       }
+
+       public int show_fraction(int width, boolean imperial_units) {
+               return 1;
+       }
+}
+
 public class AltosGraph extends AltosUIGraph {
 
        static final private Color height_color = new Color(194,31,31);
@@ -191,6 +214,9 @@ public class AltosGraph extends AltosUIGraph {
        static final private Color gps_course_color = new Color (100, 31, 112);
        static final private Color gps_ground_speed_color = new Color (31, 112, 100);
        static final private Color gps_climb_rate_color = new Color (31, 31, 112);
+       static final private Color gps_pdop_color = new Color(50, 194, 0);
+       static final private Color gps_hdop_color = new Color(50, 0, 194);
+       static final private Color gps_vdop_color = new Color(194, 0, 50);
        static final private Color temperature_color = new Color (31, 194, 194);
        static final private Color dbm_color = new Color(31, 100, 100);
        static final private Color state_color = new Color(0,0,0);
@@ -212,11 +238,12 @@ public class AltosGraph extends AltosUIGraph {
        static AltosGyroUnits gyro_units = new AltosGyroUnits();
        static AltosOrient orient_units = new AltosOrient();
        static AltosMagUnits mag_units = new AltosMagUnits();
+       static AltosDopUnits dop_units = new AltosDopUnits();
 
        AltosUIAxis     height_axis, speed_axis, accel_axis, voltage_axis, temperature_axis, nsat_axis, dbm_axis;
        AltosUIAxis     distance_axis, pressure_axis;
        AltosUIAxis     gyro_axis, orient_axis, mag_axis;
-       AltosUIAxis     course_axis;
+       AltosUIAxis     course_axis, dop_axis;
 
        public AltosGraph(AltosUIEnable enable, AltosFlightStats stats, AltosGraphDataSet dataSet) {
                super(enable);
@@ -236,6 +263,7 @@ public class AltosGraph extends AltosUIGraph {
                orient_axis = newAxis("Tilt Angle", orient_units, orient_color, 0);
                mag_axis = newAxis("Magnetic Field", mag_units, mag_x_color, 0);
                course_axis = newAxis("Course", orient_units, gps_course_color, 0);
+               dop_axis = newAxis("Dilution of Precision", dop_units, gps_pdop_color, 0);
 
                addMarker("State", AltosGraphDataPoint.data_state, state_color);
 
@@ -325,6 +353,24 @@ public class AltosGraph extends AltosUIGraph {
                                  gps_climb_rate_color,
                                  enable_gps,
                                  speed_axis);
+                       addSeries("GPS Position DOP",
+                                 AltosGraphDataPoint.data_gps_pdop,
+                                 dop_units,
+                                 gps_pdop_color,
+                                 false,
+                                 dop_axis);
+                       addSeries("GPS Horizontal DOP",
+                                 AltosGraphDataPoint.data_gps_hdop,
+                                 dop_units,
+                                 gps_hdop_color,
+                                 false,
+                                 dop_axis);
+                       addSeries("GPS Vertical DOP",
+                                 AltosGraphDataPoint.data_gps_vdop,
+                                 dop_units,
+                                 gps_vdop_color,
+                                 false,
+                                 dop_axis);
                }
                if (stats.has_rssi)
                        addSeries("Received Signal Strength",
index 3aff1e826b488d7e83306ed628fa0153ae193b7e..56dadb8b49170389975d6063c77ce4cccd2e3539 100644 (file)
@@ -15,9 +15,9 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public class AltosGraphDataPoint implements AltosUIDataPoint {
 
@@ -53,7 +53,10 @@ public class AltosGraphDataPoint implements AltosUIDataPoint {
        public static final int data_gps_course = 27;
        public static final int data_gps_ground_speed = 28;
        public static final int data_gps_climb_rate = 29;
-       public static final int data_ignitor_0 = 30;
+       public static final int data_gps_pdop = 30;
+       public static final int data_gps_hdop = 31;
+       public static final int data_gps_vdop = 32;
+       public static final int data_ignitor_0 = 33;
        public static final int data_ignitor_num = 32;
        public static final int data_ignitor_max = data_ignitor_0 + data_ignitor_num - 1;
        public static final int data_ignitor_fired_0 = data_ignitor_0 + data_ignitor_num;
@@ -194,6 +197,24 @@ public class AltosGraphDataPoint implements AltosUIDataPoint {
                        else
                                y = AltosLib.MISSING;
                        break;
+               case data_gps_pdop:
+                       if (state.gps != null)
+                               y = state.gps.pdop;
+                       else
+                               y = AltosLib.MISSING;
+                       break;
+               case data_gps_hdop:
+                       if (state.gps != null)
+                               y = state.gps.hdop;
+                       else
+                               y = AltosLib.MISSING;
+                       break;
+               case data_gps_vdop:
+                       if (state.gps != null)
+                               y = state.gps.vdop;
+                       else
+                               y = AltosLib.MISSING;
+                       break;
                default:
                        if (data_ignitor_0 <= index && index <= data_ignitor_max) {
                                int ignitor = index - data_ignitor_0;
index 36933e9bf09288f03b69e63baa4e7cea403bfef3..0845f20ecbf87fcc59a8de6d0f83e8fff0efc555 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.lang.*;
 import java.io.*;
 import java.util.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 class AltosGraphIterator implements Iterator<AltosUIDataPoint> {
        AltosGraphDataSet       dataSet;
index 23ae4ae507ce5fd795540abd4971e2dfc74aeeb8..625fe76f6ff33f09416490b057f3fc99a97e4be6 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
 import javax.swing.table.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public class AltosInfoTable extends JTable implements AltosFlightDisplay, HierarchyListener {
        private AltosFlightInfoTableModel model;
@@ -198,24 +198,28 @@ public class AltosInfoTable extends JTable implements AltosFlightDisplay, Hierar
                                if (state.gps_height != AltosLib.MISSING)
                                        info_add_row(1, "GPS height", "%8.1f", state.gps_height);
 
-                               /* The SkyTraq GPS doesn't report these values */
-                               /*
-                                 if (false) {
-                                 info_add_row(1, "GPS ground speed", "%8.1f m/s %3d°",
-                                 state.gps.ground_speed,
-                                 state.gps.course);
-                                 info_add_row(1, "GPS climb rate", "%8.1f m/s",
-                                 state.gps.climb_rate);
-                                 info_add_row(1, "GPS error", "%6d m(h)%3d m(v)",
-                                 state.gps.h_error, state.gps.v_error);
-                                 }
-                               */
-
-                               info_add_row(1, "GPS hdop", "%8.1f", state.gps.hdop);
+                               if (state.gps.ground_speed != AltosLib.MISSING && state.gps.course != AltosLib.MISSING)
+                                       info_add_row(1, "GPS ground speed", "%6.1f m/s %3d°",
+                                                    state.gps.ground_speed,
+                                                    state.gps.course);
+                               if (state.gps.climb_rate != AltosLib.MISSING)
+                                       info_add_row(1, "GPS climb rate", "%6.1f m/s",
+                                                    state.gps.climb_rate);
+
+                               if (state.gps.h_error != AltosLib.MISSING && state.gps.v_error != AltosLib.MISSING)
+                                       info_add_row(1, "GPS error", "%6d m(h)%3d m(v)",
+                                                    state.gps.h_error, state.gps.v_error);
+                               if (state.gps.pdop != AltosLib.MISSING &&
+                                   state.gps.hdop != AltosLib.MISSING &&
+                                   state.gps.vdop != AltosLib.MISSING)
+                                       info_add_row(1, "GPS dop", "%3.1fp/%3.1fh/%3.1fv",
+                                                    state.gps.pdop,
+                                                    state.gps.hdop,
+                                                    state.gps.vdop);
 
                                if (state.npad > 0) {
                                        if (state.from_pad != null) {
-                                               info_add_row(1, "Distance from pad", "%6d m",
+                                               info_add_row(1, "Ground pad dist", "%6d m",
                                                             (int) (state.from_pad.distance + 0.5));
                                                info_add_row(1, "Direction from pad", "%6d°",
                                                             (int) (state.from_pad.bearing + 0.5));
@@ -234,12 +238,12 @@ public class AltosInfoTable extends JTable implements AltosFlightDisplay, Hierar
                                        info_add_row(1, "Pad GPS alt", "%6.0f m", state.pad_alt);
                                }
                                if (state.gps.year != AltosLib.MISSING)
-                                       info_add_row(1, "GPS date", "%04d-%02d-%02d",
+                                       info_add_row(2, "GPS date", "%04d-%02d-%02d",
                                                     state.gps.year,
                                                     state.gps.month,
                                                     state.gps.day);
                                if (state.gps.hour != AltosLib.MISSING)
-                                       info_add_row(1, "GPS time", "  %02d:%02d:%02d",
+                                       info_add_row(2, "GPS time", "  %02d:%02d:%02d",
                                                     state.gps.hour,
                                                     state.gps.minute,
                                                     state.gps.second);
index 2debb62a40f6eddd3e06a596a193fb2999afa984..0dd5740cae3e5ad2e080d0ee4afb58ac98d2e8f6 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import javax.swing.*;
 
index c91b70e9348f65be17e7f475049484594fd37334..30934d96ad84104977c156c574b691ad4776ffac 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.*;
 import javax.swing.*;
index 34cf1650179cb3e95aad061fb56d0679fa06f6ab..dfc3c649c2adf4defc07572b33bb42e11ed239ae 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 public interface AltosPositionListener {
        public void position_changed(int position);
index 8f002c4a2a4b3ff96e47e5342c38d6ce92c88ed5..481ce6565087d8b018d70ab8db062b81c499cd53 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public class AltosRomconfigUI
        extends AltosUIDialog
index b0cde0591c1ab28ba8b78465871da01ffe40a9a0..7e51a55a757d174d8dce0a1ac6566cefbbaf5d8d 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -25,7 +25,7 @@ import java.io.*;
 import java.util.*;
 import java.text.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 class AltosScanResult {
        String          callsign;
@@ -33,32 +33,40 @@ class AltosScanResult {
        int             flight;
        AltosFrequency  frequency;
        int             telemetry;
+       int             rate;
 
        boolean interrupted = false;
 
        public String toString() {
-               return String.format("%-9.9s serial %-4d flight %-4d (%s %s)",
-                                    callsign, serial, flight, frequency.toShortString(), AltosLib.telemetry_name(telemetry));
+               return String.format("%-9.9s serial %-4d flight %-4d (%s %s %d)",
+                                    callsign, serial, flight,
+                                    frequency.toShortString(),
+                                    AltosLib.telemetry_name(telemetry),
+                                    AltosLib.ao_telemetry_rate_values[rate]);
        }
 
        public String toShortString() {
-               return String.format("%s %d %d %7.3f %d",
-                                    callsign, serial, flight, frequency, telemetry);
+               return String.format("%s %d %d %7.3f %d %d",
+                                    callsign, serial, flight, frequency, telemetry, rate);
        }
 
        public AltosScanResult(String in_callsign, int in_serial,
-                              int in_flight, AltosFrequency in_frequency, int in_telemetry) {
+                              int in_flight, AltosFrequency in_frequency,
+                              int in_telemetry,
+                              int in_rate) {
                callsign = in_callsign;
                serial = in_serial;
                flight = in_flight;
                frequency = in_frequency;
                telemetry = in_telemetry;
+               rate = in_rate;
        }
 
        public boolean equals(AltosScanResult other) {
                return (serial == other.serial &&
                        frequency.frequency == other.frequency.frequency &&
-                       telemetry == other.telemetry);
+                       telemetry == other.telemetry &&
+                       rate == other.rate);
        }
 
        public boolean up_to_date(AltosScanResult other) {
@@ -132,15 +140,20 @@ public class AltosScanUI
        private JLabel                  scanning_label;
        private JLabel                  frequency_label;
        private JLabel                  telemetry_label;
+       private JLabel                  rate_label;
        private JButton                 cancel_button;
        private JButton                 monitor_button;
        private JCheckBox[]             telemetry_boxes;
+       private JCheckBox[]             rate_boxes;
        javax.swing.Timer               timer;
        AltosScanResults                results = new AltosScanResults();
 
        int                             telemetry;
        boolean                         select_telemetry = false;
 
+       int                             rate;
+       boolean                         select_rate = false;
+
        final static int                timeout = 1200;
        TelemetryHandler                handler;
        Thread                          thread;
@@ -189,10 +202,11 @@ public class AltosScanUI
                                                        continue;
                                                if (state.flight != AltosLib.MISSING) {
                                                        final AltosScanResult   result = new AltosScanResult(state.callsign,
-                                                                                                    state.serial,
-                                                                                                    state.flight,
-                                                                                                    frequencies[frequency_index],
-                                                                                                    telemetry);
+                                                                                                            state.serial,
+                                                                                                            state.flight,
+                                                                                                            frequencies[frequency_index],
+                                                                                                            telemetry,
+                                                                                                            rate);
                                                        Runnable r = new Runnable() {
                                                                        public void run() {
                                                                                results.add(result);
@@ -217,12 +231,18 @@ public class AltosScanUI
                frequency_label.setText(String.format("Frequency: %s", frequencies[frequency_index].toString()));
                if (select_telemetry)
                        telemetry_label.setText(String.format("Telemetry: %s", AltosLib.telemetry_name(telemetry)));
+               if (select_rate)
+                       rate_label.setText(String.format("Rate: %d baud", AltosLib.ao_telemetry_rate_values[rate]));
        }
 
        void set_telemetry() {
                reader.set_telemetry(telemetry);
        }
 
+       void set_rate() {
+               reader.set_telemetry_rate(rate);
+       }
+
        void set_frequency() throws InterruptedException, TimeoutException {
                reader.set_frequency(frequencies[frequency_index].frequency);
                reader.reset();
@@ -230,24 +250,43 @@ public class AltosScanUI
 
        void next() throws InterruptedException, TimeoutException {
                reader.set_monitor(false);
+
+               /* Let any pending input from the last configuration drain out */
                Thread.sleep(100);
-               ++frequency_index;
+
+               if (select_rate) {
+                       boolean wrapped = false;
+                       do {
+                               ++rate;
+                               if (rate > AltosLib.ao_telemetry_rate_max) {
+                                       wrapped = true;
+                                       rate = 0;
+                               }
+                       } while (!rate_boxes[rate].isSelected());
+                       set_rate();
+                       if (!wrapped) {
+                               set_label();
+                               return;
+                       }
+               }
                if (select_telemetry) {
-                       if (frequency_index >= frequencies.length ||
-                           !telemetry_boxes[telemetry - AltosLib.ao_telemetry_min].isSelected())
-                       {
-                               frequency_index = 0;
-                               do {
-                                       ++telemetry;
-                                       if (telemetry > AltosLib.ao_telemetry_max)
-                                               telemetry = AltosLib.ao_telemetry_min;
-                               } while (!telemetry_boxes[telemetry - AltosLib.ao_telemetry_min].isSelected());
-                               set_telemetry();
+                       boolean wrapped = false;
+                       do {
+                               ++telemetry;
+                               if (telemetry > AltosLib.ao_telemetry_max) {
+                                       wrapped = true;
+                                       telemetry = AltosLib.ao_telemetry_min;
+                               }
+                       } while (!telemetry_boxes[telemetry - AltosLib.ao_telemetry_min].isSelected());
+                       set_telemetry();
+                       if (!wrapped) {
+                               set_label();
+                               return;
                        }
-               } else {
-                       if (frequency_index >= frequencies.length)
-                               frequency_index = 0;
                }
+               ++frequency_index;
+               if (frequency_index >= frequencies.length)
+                       frequency_index = 0;
                set_frequency();
                set_label();
                reader.set_monitor(true);
@@ -297,15 +336,33 @@ public class AltosScanUI
                                AltosUIPreferences.set_scanning_telemetry(scanning_telemetry);
                        }
 
+                       if (cmd.equals("rate")) {
+                               int k;
+                               int scanning_rate = 0;
+                               for (k = 0; k <= AltosLib.ao_telemetry_rate_max; k++) {
+                                       if (rate_boxes[k].isSelected())
+                                               scanning_rate |= (1 << k);
+                               }
+                               if (scanning_rate == 0) {
+                                       scanning_rate = (1 << 0);
+                                       rate_boxes[0].setSelected(true);
+                               }
+                               AltosUIPreferences.set_scanning_telemetry_rate(scanning_rate);
+                       }
+
                        if (cmd.equals("monitor")) {
                                close();
                                AltosScanResult r = (AltosScanResult) (list.getSelectedValue());
                                if (r != null) {
                                        if (device != null) {
                                                if (reader != null) {
+                                                       System.out.printf("frequency %g rate %d\n", r.frequency.frequency, r.rate);
                                                        reader.set_telemetry(r.telemetry);
+                                                       reader.set_telemetry_rate(r.rate);
                                                        reader.set_frequency(r.frequency.frequency);
                                                        reader.save_frequency();
+                                                       reader.save_telemetry();
+                                                       reader.save_telemetry_rate();
                                                        owner.scan_device_selected(device);
                                                }
                                        }
@@ -341,6 +398,7 @@ public class AltosScanUI
                        reader = new AltosTelemetryReader(new AltosSerial(device));
                        set_frequency();
                        set_telemetry();
+                       set_rate();
                        try {
                                Thread.sleep(100);
                        } catch (InterruptedException ie) {
@@ -386,11 +444,13 @@ public class AltosScanUI
 
                owner = in_owner;
                select_telemetry = in_select_telemetry;
+               select_rate = true;
 
                frequencies = AltosUIPreferences.common_frequencies();
                frequency_index = 0;
 
                telemetry = AltosLib.ao_telemetry_standard;
+               rate = 0;
 
                if (!open())
                        return;
@@ -412,18 +472,24 @@ public class AltosScanUI
 
                if (select_telemetry) {
                        telemetry_label = new JLabel("");
+                       telemetry_label.setPreferredSize(new Dimension(100, 16));
                        telemetry = AltosLib.ao_telemetry_min;
                } else {
                        telemetry = AltosLib.ao_telemetry_standard;
                }
 
+               if (select_rate) {
+                       rate_label = new JLabel("");
+                       rate_label.setPreferredSize(new Dimension(100, 16));
+               }
+
                set_label();
 
                c.fill = GridBagConstraints.HORIZONTAL;
-               c.anchor = GridBagConstraints.WEST;
+               c.anchor = GridBagConstraints.LINE_START;
                c.insets = i;
-               c.weightx = 1;
-               c.weighty = 1;
+               c.weightx = 0;
+               c.weighty = 0;
 
                c.gridx = 0;
                c.gridy = 0;
@@ -433,10 +499,35 @@ public class AltosScanUI
                c.gridy = 1;
                pane.add(frequency_label, c);
 
-               int     y_offset = 3;
+               int     y_offset_rate = 3;
+               int     y_offset_telem = 3;
+
+               int     check_x = 0;
+
+               if (select_rate && select_telemetry)
+                       c.gridwidth = 1;
+
+               if (select_rate) {
+                       c.gridy = 2;
+                       c.gridx = check_x++;
+                       pane.add(rate_label, c);
+
+                       int     scanning_rate = AltosUIPreferences.scanning_telemetry_rate();
+                       rate_boxes = new JCheckBox[AltosLib.ao_telemetry_rate_max + 1];
+                       for (int k = 0; k <= AltosLib.ao_telemetry_rate_max; k++) {
+                               rate_boxes[k] = new JCheckBox(String.format("%d baud", AltosLib.ao_telemetry_rate_values[k]));
+                               c.gridy = y_offset_rate + k;
+                               pane.add(rate_boxes[k], c);
+                               rate_boxes[k].setActionCommand("rate");
+                               rate_boxes[k].addActionListener(this);
+                               rate_boxes[k].setSelected((scanning_rate & (1 << k)) != 0);
+                       }
+                       y_offset_rate += AltosLib.ao_telemetry_rate_max + 1;
+               }
 
                if (select_telemetry) {
                        c.gridy = 2;
+                       c.gridx = check_x++;
                        pane.add(telemetry_label, c);
 
                        int     scanning_telemetry = AltosUIPreferences.scanning_telemetry();
@@ -444,15 +535,17 @@ public class AltosScanUI
                        for (int k = AltosLib.ao_telemetry_min; k <= AltosLib.ao_telemetry_max; k++) {
                                int j = k - AltosLib.ao_telemetry_min;
                                telemetry_boxes[j] = new JCheckBox(AltosLib.telemetry_name(k));
-                               c.gridy = 3 + j;
+                               c.gridy = y_offset_telem + j;
                                pane.add(telemetry_boxes[j], c);
                                telemetry_boxes[j].setActionCommand("telemetry");
                                telemetry_boxes[j].addActionListener(this);
                                telemetry_boxes[j].setSelected((scanning_telemetry & (1 << k)) != 0);
                        }
-                       y_offset += (AltosLib.ao_telemetry_max - AltosLib.ao_telemetry_min + 1);
+                       y_offset_telem += (AltosLib.ao_telemetry_max - AltosLib.ao_telemetry_min + 1);
                }
 
+               int y_offset = Math.max(y_offset_rate, y_offset_telem);
+
                list = new JList<AltosScanResult>(results) {
                                //Subclass JList to workaround bug 4832765, which can cause the
                                //scroll pane to not let the user easily scroll up to the beginning
index 60e15bdb094c9b0d664ef8940f587090e34062e1..0eba55fd36f7078d763ef7e7ae9ada1c96686a94 100644 (file)
  * Deal with TeleDongle on a serial port
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.io.*;
 import java.util.*;
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 import libaltosJNI.*;
 
 /*
index 1e8207d1b0daff086cf26ceb97f023498d0285c2..cd19b101105ce3dccdb61a6022356a8c004e07b1 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 public class AltosSerialInUseException extends Exception {
        public AltosDevice      device;
index 74561673fde97f92cb53eee15353d3765259b5a3..9e98ddb77bb7cade58e5132d27352eecbe17387f 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.io.*;
 import java.util.ArrayList;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 import org.jfree.ui.*;
 import org.jfree.chart.*;
@@ -48,7 +48,11 @@ public class AltosUIAxis extends NumberAxis {
        public final static int axis_default = axis_include_zero;
 
        public void set_units() {
-               setLabel(String.format("%s (%s)", label, units.show_units()));
+               String u = units.show_units();
+               if (u != null)
+                       setLabel(String.format("%s (%s)", label, u));
+               else
+                       setLabel(label);
        }
 
        public void set_enable(boolean enable) {
index 0e82cacb3162b6d8cb8fb1ddfc3454c10938b175..9c0f3bc7af933ff9dff2f1241d5c65aadfc31d24 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -223,6 +223,31 @@ public class AltosUIConfigure
                row++;
        }
 
+       static final Integer map_caches[] = { 9, 25, 100 };
+
+       public void add_map_cache() {
+               pane.add(new JLabel("Map Cache Size"), constraints(0, 1));
+
+               final JComboBox<Integer> map_cache = new JComboBox<Integer>(map_caches);
+
+               map_cache.setEditable(true);
+               map_cache.addActionListener(new ActionListener() {
+                               public void actionPerformed(ActionEvent e) {
+                                       try {
+                                               int     size = (Integer) (map_cache.getSelectedItem());
+
+                                               AltosUIPreferences.set_map_cache(size);
+                                       } catch (ClassCastException ce) {
+                                               map_cache.setSelectedItem(new Integer(AltosUIPreferences.map_cache()));
+                                       }
+                               }
+                       });
+
+               map_cache.setSelectedItem (new Integer(AltosUIPreferences.map_cache()));
+               pane.add(map_cache, constraints(1, 2, GridBagConstraints.BOTH));
+               row++;
+       }
+
        public void add_bluetooth() {
        }
 
@@ -257,7 +282,9 @@ public class AltosUIConfigure
                add_font_size();
                add_look_and_feel();
                add_position();
-               add_bluetooth();
+               add_map_cache();
+               if (AltosUILib.has_bluetooth)
+                       add_bluetooth();
                add_frequencies();
 
                /* And a close button at the bottom */
index 353ff30ff308b4b33117a37ad4234099c6614ff3..9a810a41de670e849af16af74d858c70eed13d2b 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 public class AltosUIDataMissing extends Exception {
        public int      id;
index 3f16500e1d17ce5d619ca1225b702ff7e437f859..f72bbcd5e92da902a6f6f3e9677e6ad320e3034b 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 public interface AltosUIDataPoint {
        public abstract double x() throws AltosUIDataMissing;
index ee70a3fd6a57ac52f013bc47c51dcff00e30280c..9e048587c3861799f472dd37d052e03b1827c02a 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 public interface AltosUIDataSet {
        public abstract String name();
index dc737414532718a14c236925f0ce442be200ed2c..9fc5283efebeca4a1c8c5b2ebf6b57ca38aa5a63 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.*;
 import java.awt.event.*;
index da98797a7cfd7ae54f78cc6fe0fa5941bb5c6eab..e227d2b774e283d6a9690f7b7ef614e0437f3672 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -23,7 +23,7 @@ import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
 import java.util.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 import org.jfree.ui.*;
 import org.jfree.chart.*;
index 039d83e09d9c0600be32403d17efb50a86ea9441..74161634193d58b509e11675fa411f28b80d67bd 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.util.*;
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public abstract class AltosUIFlightTab extends JComponent implements AltosFlightDisplay, HierarchyListener {
        public GridBagLayout    layout;
index 6e62c762948d83578814c5b26d4534a0c92ff352..2e886932b8f4ba168622a2280eac52f854d651a2 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -36,12 +36,12 @@ public class AltosUIFrame extends JFrame implements AltosUIListener, AltosPositi
        }
 
        static String[] altos_icon_names = {
-               "/altus-metrum-16.png",
-               "/altus-metrum-32.png",
-               "/altus-metrum-48.png",
-               "/altus-metrum-64.png",
-               "/altus-metrum-128.png",
-               "/altus-metrum-256.png"
+               "/altusmetrum-altosui-16.png",
+               "/altusmetrum-altosui-32.png",
+               "/altusmetrum-altosui-48.png",
+               "/altusmetrum-altosui-64.png",
+               "/altusmetrum-altosui-128.png",
+               "/altusmetrum-altosui-256.png"
        };
 
        static public String[] icon_names;
@@ -157,11 +157,72 @@ public class AltosUIFrame extends JFrame implements AltosUIListener, AltosPositi
                }
        }
 
+       static boolean global_settings_done;
+
+       public String getName() {
+               return "Altus Metrum";
+       }
+
+       public void macosx_quit_handler() {
+               System.out.printf("Got quit handler\n");
+       }
+
+       public void macosx_about_handler() {
+               System.out.printf("Got about handler\n");
+       }
+
+       public void macosx_preferences_handler() {
+               System.out.printf("Got preferences handler\n");
+       }
+
+       public void macosx_file_handler(String path) {
+               System.out.printf("Got file handler with \"%s\"\n", path);
+       }
+
+       /* Check that we are on Mac OS X.  This is crucial to loading and using the OSXAdapter class.
+        */
+       public static boolean MAC_OS_X = (System.getProperty("os.name").toLowerCase().startsWith("mac os x"));
+
+       private static boolean registered_for_macosx_events;
+
+       /* Generic registration with the Mac OS X application menu
+        * Checks the platform, then attempts to register with the Apple EAWT
+        * See OSXAdapter.java to see how this is done without directly referencing any Apple APIs
+        */
+       public synchronized void register_for_macosx_events() {
+               if (registered_for_macosx_events)
+                       return;
+               registered_for_macosx_events = true;
+               if (MAC_OS_X) {
+                       try {
+                               // Generate and register the OSXAdapter, passing it a hash of all the methods we wish to
+                               // use as delegates for various com.apple.eawt.ApplicationListener methods
+                               OSXAdapter.setQuitHandler(this, getClass().getDeclaredMethod("macosx_quit_handler", (Class[])null));
+//                             OSXAdapter.setAboutHandler(this, getClass().getDeclaredMethod("macosx_about_handler", (Class[])null));
+                               OSXAdapter.setPreferencesHandler(this, getClass().getDeclaredMethod("macosx_preferences_handler", (Class[])null));
+                               OSXAdapter.setFileHandler(this, getClass().getDeclaredMethod("macosx_file_handler", new Class[] { String.class }));
+                       } catch (Exception e) {
+                               System.err.println("Error while loading the OSXAdapter:");
+                               e.printStackTrace();
+                       }
+               }
+       }
        void init() {
                AltosUIPreferences.register_ui_listener(this);
                AltosUIPreferences.register_position_listener(this);
                position = AltosUIPreferences.position();
                addWindowListener(new AltosUIFrameListener());
+
+               /* Try to make menus live in the menu bar like regular Mac apps */
+               if (!global_settings_done) {
+                       try {
+                               global_settings_done = true;
+                               System.setProperty("com.apple.mrj.application.apple.menu.about.name", getName());
+                               System.setProperty("com.apple.macos.useScreenMenuBar", "true");
+                               System.setProperty("apple.laf.useScreenMenuBar", "true" ); // for older versions of Java
+                       } catch (Exception e) {
+                       }
+               }
                set_icon();
        }
 
diff --git a/altosuilib/AltosUIFreqList.java b/altosuilib/AltosUIFreqList.java
new file mode 100644 (file)
index 0000000..84e6dce
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altosuilib_3;
+
+import javax.swing.*;
+import org.altusmetrum.altoslib_5.*;
+
+public class AltosUIFreqList extends JComboBox<AltosFrequency> {
+
+       String  product;
+       int     serial;
+       int     calibrate;
+
+       public void set_frequency(double new_frequency) {
+               int i;
+
+               if (new_frequency < 0) {
+                       setVisible(false);
+                       return;
+               }
+
+               for (i = 0; i < getItemCount(); i++) {
+                       AltosFrequency  f = (AltosFrequency) getItemAt(i);
+
+                       if (f.close(new_frequency)) {
+                               setSelectedIndex(i);
+                               return;
+                       }
+               }
+               for (i = 0; i < getItemCount(); i++) {
+                       AltosFrequency  f = (AltosFrequency) getItemAt(i);
+
+                       if (new_frequency < f.frequency)
+                               break;
+               }
+               String  description = String.format("%s serial %d", product, serial);
+               AltosFrequency  frequency = new AltosFrequency(new_frequency, description);
+               AltosUIPreferences.add_common_frequency(frequency);
+               insertItemAt(frequency, i);
+               setMaximumRowCount(getItemCount());
+               setVisible(true);
+       }
+
+       public void set_product(String new_product) {
+               product = new_product;
+       }
+
+       public void set_serial(int new_serial) {
+               serial = new_serial;
+       }
+
+       public double frequency() {
+               AltosFrequency  f = (AltosFrequency) getSelectedItem();
+               if (f != null)
+                       return f.frequency;
+               return 434.550;
+       }
+
+       public AltosUIFreqList () {
+               super(AltosUIPreferences.common_frequencies());
+               setMaximumRowCount(getItemCount());
+               setEditable(false);
+               product = "Unknown";
+               serial = 0;
+       }
+
+       public AltosUIFreqList(double in_frequency) {
+               this();
+               set_frequency(in_frequency);
+       }
+}
index 9cca088de48cfd38d23262f3e26d36618ee90522..870c4e9356de5fd82d468ba2b0e6b4f200900424 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.io.*;
 import java.util.ArrayList;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 import org.jfree.ui.*;
 import org.jfree.chart.*;
index 724fac18de3a9ef39bfb89b8920c81e039fe3e9d..39accab44405b208da65268d651e936665204c3e 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.io.*;
 import java.util.ArrayList;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 import org.jfree.ui.*;
 import org.jfree.chart.*;
index b1626cba8ea29517098529554a297f745c96e8a5..d17078e781b17c1d3f55119796d4311d660d33b2 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public abstract class AltosUIIndicator implements AltosFontListener, AltosUnitsListener {
        JLabel          label;
index 688dd58bdf87ac074b6a6125827eeff07d81b2f5..a15bf19fec5c59f0f9437eb0829e8172c337327b 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -25,7 +25,7 @@ import java.lang.Math;
 import java.awt.geom.*;
 import java.util.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public class AltosUILatLon {
        public double   lat;
index b51c5963314a41dc57d794a86e99b66d26d905c2..8fa7dfe69d937b1833c0452282d112aeeefeb875 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.*;
 import libaltosJNI.*;
 
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public class AltosUILib extends AltosLib {
 
@@ -80,6 +80,7 @@ public class AltosUILib extends AltosLib {
 
        static public boolean initialized = false;
        static public boolean loaded_library = false;
+       static public boolean has_bluetooth = false;
 
        static final String[] library_names = { "altos", "altos32", "altos64" };
 
@@ -96,6 +97,13 @@ public class AltosUILib extends AltosLib {
                                        loaded_library = false;
                                }
                        }
+
+                       String OS = System.getProperty("os.name");
+
+                       if (OS.startsWith("Linux")) {
+                               has_bluetooth = true;
+                       }
+
                        initialized = true;
                }
                return loaded_library;
index 75a0ad949cc7e6b1555acae2874777f7792d29e6..a32d310c4b9c0ec2726009f01776d652c916d423 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 public interface AltosUIListener {
        public void ui_changed(String look_and_feel);
index aaa68f238c893549641585858a12dc291bff6ce0..c22801f8bea098bc022a504c8a9d67022b264c95 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -25,7 +25,7 @@ import java.lang.Math;
 import java.awt.geom.*;
 import java.util.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosUIMapZoomListener {
 
index 55311d8c8ad5ecf29051c0af530ab65ef3a9586e..b9064cf435860fc4b812c6e93c566845f8ed14bc 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import javax.swing.*;
 import javax.imageio.ImageIO;
@@ -24,30 +24,31 @@ import java.awt.*;
 import java.io.*;
 import java.net.*;
 
-public class AltosUIMapCache {
+public class AltosUIMapCache implements AltosUIMapCacheListener {
        static final int        success = 0;
        static final int        loading = 1;
        static final int        failed = 2;
        static final int        bad_request = 3;
        static final int        forbidden = 4;
 
-       static final int        min_cache_size = 9;
-       static final int        max_cache_size = 24;
+       int                     min_cache_size;         /* configured minimum cache size */
+       int                     cache_size;             /* current cache size */
+       int                     requested_cache_size;   /* cache size computed by application */
 
        private Object          fetch_lock = new Object();
        private Object          cache_lock = new Object();
 
-       int                     cache_size = min_cache_size;
-
        AltosUIMapImage[]       images = new AltosUIMapImage[cache_size];
 
        long                    used;
 
        public void set_cache_size(int new_size) {
+
+               requested_cache_size = new_size;
+
                if (new_size < min_cache_size)
                        new_size = min_cache_size;
-               if (new_size > max_cache_size)
-                       new_size = max_cache_size;
+
                if (new_size == cache_size)
                        return;
 
@@ -109,6 +110,28 @@ public class AltosUIMapCache {
                }
        }
 
+       public void map_cache_changed(int map_cache) {
+               min_cache_size = map_cache;
+
+               set_cache_size(requested_cache_size);
+       }
+
+       public void dispose() {
+               AltosUIPreferences.unregister_map_cache_listener(this);
+
+               for (int i = 0; i < cache_size; i++) {
+                       AltosUIMapImage image = images[i];
+
+                       if (image != null)
+                           image.flush();
+               }
+       }
+
        public AltosUIMapCache() {
+               min_cache_size = AltosUIPreferences.map_cache();
+
+               set_cache_size(0);
+
+               AltosUIPreferences.register_map_cache_listener(this);
        }
 }
diff --git a/altosuilib/AltosUIMapCacheListener.java b/altosuilib/AltosUIMapCacheListener.java
new file mode 100644 (file)
index 0000000..680d123
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright © 2014 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altosuilib_3;
+
+public interface AltosUIMapCacheListener {
+       public void map_cache_changed(int map_cache);
+}
index 3819d0790939369fd2ac6cbc9eb0bad0e351371e..77cd4299b3c5fdc0bf60d08c693f6ae1ae15f4ca 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import javax.swing.*;
 import javax.imageio.ImageIO;
index e09a2d9f09eb037db57e8af8f4b43aeaabb06712..32437d4ec513ad7c301784dfeed72ee782e64699 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -25,12 +25,13 @@ import java.lang.Math;
 import java.awt.geom.*;
 import java.util.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public class AltosUIMapLine {
        AltosUILatLon   start, end;
 
        private Font    font = null;
+       static public int stroke_width = 6;
 
        public void set_font(Font font) {
                this.font = font;
@@ -87,19 +88,24 @@ public class AltosUIMapLine {
        }
 
        public void paint(Graphics2D g, AltosUIMapTransform t) {
-               g.setColor(Color.BLUE);
 
                if (start == null || end == null)
                        return;
 
+               g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+
                Line2D.Double line = new Line2D.Double(t.screen(start),
                                                       t.screen(end));
 
+               g.setColor(Color.WHITE);
+               g.setStroke(new BasicStroke(stroke_width+4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
+               g.draw(line);
+
+               g.setColor(Color.BLUE);
+               g.setStroke(new BasicStroke(stroke_width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
                g.draw(line);
 
                String  message = line_dist();
-               g.setFont(font);
-               g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
                Rectangle2D     bounds;
                bounds = font.getStringBounds(message, g.getFontRenderContext());
 
@@ -111,6 +117,13 @@ public class AltosUIMapLine {
                } else {
                        x += 2.0f;
                }
+
+               g.setFont(font);
+               g.setColor(Color.WHITE);
+               for (int dy = -2; dy <= 2; dy += 2)
+                       for (int dx = -2; dx <= 2; dx += 2)
+                               g.drawString(message, x + dx, y + dy);
+               g.setColor(Color.BLUE);
                g.drawString(message, x, y);
        }
 }
index 8c640e5fa6223cf7f3b22a0801facd21badb29f5..47fc4d5e28ab54e6f5be959a7b277eb794f3fe43 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -25,7 +25,7 @@ import java.lang.Math;
 import java.awt.geom.*;
 import java.util.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public class AltosUIMapMark {
 
index ff17be6735604a0c65fe56ee02aa4caf2c2dc14f..705f4b6a8b2c6f2e95c632a1084461f4cf3338d0 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -25,7 +25,7 @@ import java.lang.Math;
 import java.awt.geom.*;
 import java.util.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 class PathPoint {
        AltosUILatLon   lat_lon;
index 56066d70b25764a3ad0fb661112172123c82caa9..1c088a497cf202bbcd031687ed59c0093c2d9359 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -26,7 +26,7 @@ import java.text.*;
 import java.lang.Math;
 import java.net.URL;
 import java.net.URLConnection;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 class AltosUIMapPos extends Box {
        AltosUIFrame    owner;
index 8a5b16e15313635e6e5dc1feb08271ac4993c05a..463ef3f21de7c6d05950b0db4a5ef1ddedbba306 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 public class AltosUIMapRectangle {
        AltosUILatLon   ul, lr;
index 4cecb54f319cbb42b04491ec657f854ae27e1ab9..dd8ace32c7c0800768a19becbb0ebcde4c072b65 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.io.*;
 import java.net.*;
index 91aff00cd5b19cc33a13594d0240bfc32b17fe24..0bbd2bc93c6bebfac7fb1d048c2850be45a7fa28 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 public interface AltosUIMapStoreListener {
        abstract void notify_store(AltosUIMapStore store, int status);
index 7c82318302370320d36a0f1d5203ffd8d5ed6731..8b6a8f0a3862a3f49f0946fc6382fe0daae1822e 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.*;
 import java.awt.image.*;
@@ -25,7 +25,7 @@ import java.awt.geom.*;
 import java.io.*;
 import java.util.*;
 import java.awt.RenderingHints.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public class AltosUIMapTile {
        AltosUIMapTileListener  listener;
index 4ca135392c1864cb5aec2ec7b463f56fae9c3855..f58f55e0defb8662803e5778503118aeb5e071fe 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 public interface AltosUIMapTileListener {
        abstract public void notify_tile(AltosUIMapTile tile, int status);
index e6f1ffe32b1e891b41cc5d4a02182fee331257f2..89a3e9f682b95f6ba88e7848795b92fdbc3e40fe 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -25,7 +25,7 @@ import java.lang.Math;
 import java.awt.geom.*;
 import java.util.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public class AltosUIMapTransform {
 
index a14fde6583e42cb64b938a49168dce22c751897f..70b8e2e92c8fb7772e387ce9d209df809a472145 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -26,7 +26,7 @@ import java.lang.*;
 import java.awt.geom.*;
 import java.util.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public class AltosUIMapView extends Component implements MouseMotionListener, MouseListener, MouseWheelListener, ComponentListener, AltosUIMapTileListener, AltosUIMapStoreListener {
 
@@ -67,7 +67,7 @@ public class AltosUIMapView extends Component implements MouseMotionListener, Mo
        AltosUILatLon           centre;
 
        public void set_font() {
-               line.set_font(AltosUILib.value_font);
+               line.set_font(AltosUILib.status_font);
                for (AltosUIMapTile tile : tiles.values())
                        tile.set_font(AltosUILib.value_font);
                repaint();
@@ -370,7 +370,7 @@ public class AltosUIMapView extends Component implements MouseMotionListener, Mo
                for (Point point : to_remove)
                        tiles.remove(point);
 
-               cache.set_cache_size(((lower_right.y - upper_left.y) / px_size + 1) * ((lower_right.x - upper_left.x) / px_size + 1));
+               cache.set_cache_size((getWidth() / px_size + 2) * (getHeight() / px_size + 2));
                for (int y = upper_left.y; y <= lower_right.y; y += px_size) {
                        for (int x = upper_left.x; x <= lower_right.x; x += px_size) {
                                Point point = new Point(x, y);
index 02e8bb5118a4f5a00da344759b8c53a83efcda56..23498c89c7d41a781f880bad4f6e30917edde7d6 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 public interface AltosUIMapZoomListener {
        abstract public void zoom_changed(int zoom);
index cd6fa589a90dbc33593f4a92347c972f2168aa0e..5e9809ee07660149c6e58fb02e7dcc574cbd8fb6 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.io.*;
 import java.util.ArrayList;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 import org.jfree.ui.*;
 import org.jfree.chart.*;
index 7a582a7d5d3d25bb84f77dd3159a1402378aaabf..ecab20d4ee7e54846660002fe4a5775dad110b5d 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.io.*;
 import java.util.*;
 import java.awt.Component;
 import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public class AltosUIPreferences extends AltosPreferences {
 
@@ -34,6 +34,9 @@ public class AltosUIPreferences extends AltosPreferences {
        /* Window position preference name */
        final static String positionPreference = "POSITION";
 
+       /* Maps cache size preference name */
+       final static String mapCachePreference = "MAP-CACHE";
+
        /* UI Component to pop dialogs up */
        static Component component;
 
@@ -52,6 +55,10 @@ public class AltosUIPreferences extends AltosPreferences {
 
        public static int position = AltosUILib.position_top_left;
 
+       static LinkedList<AltosUIMapCacheListener> map_cache_listeners;
+
+       public static int map_cache = 9;
+
        public static void init() {
                AltosPreferences.init(new AltosUIPreferencesBackend());
 
@@ -68,6 +75,9 @@ public class AltosUIPreferences extends AltosPreferences {
 
                position = backend.getInt(positionPreference, AltosUILib.position_top_left);
                position_listeners = new LinkedList<AltosPositionListener>();
+
+               map_cache = backend.getInt(mapCachePreference, 9);
+               map_cache_listeners = new LinkedList<AltosUIMapCacheListener>();
        }
 
        static { init(); }
@@ -215,4 +225,32 @@ public class AltosUIPreferences extends AltosPreferences {
                        return position;
                }
        }
+
+       public static void register_map_cache_listener(AltosUIMapCacheListener l) {
+               synchronized(backend) {
+                       map_cache_listeners.add(l);
+               }
+       }
+
+       public static void unregister_map_cache_listener(AltosUIMapCacheListener l) {
+               synchronized (backend) {
+                       map_cache_listeners.remove(l);
+               }
+       }
+
+       public static void set_map_cache(int new_map_cache) {
+               synchronized(backend) {
+                       map_cache = new_map_cache;
+                       backend.putInt(mapCachePreference, map_cache);
+                       flush_preferences();
+                       for (AltosUIMapCacheListener l: map_cache_listeners)
+                               l.map_cache_changed(map_cache);
+               }
+       }
+
+       public static int map_cache() {
+               synchronized(backend) {
+                       return map_cache;
+               }
+       }
 }
index da29253dc9e57149eb8c6da774f18df865c70f64..4048fd83b99f4a52b0018c829cb69e8df48d0140 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.io.File;
 import java.util.prefs.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 import javax.swing.filechooser.FileSystemView;
 
 public class AltosUIPreferencesBackend implements AltosPreferencesBackend {
diff --git a/altosuilib/AltosUIRateList.java b/altosuilib/AltosUIRateList.java
new file mode 100644 (file)
index 0000000..ee35ce6
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altosuilib_3;
+
+import javax.swing.*;
+import org.altusmetrum.altoslib_5.*;
+
+public class AltosUIRateList extends JComboBox<String> {
+
+       String  product;
+       int     serial;
+
+       public void set_rate(int new_rate) {
+               int i;
+
+               setVisible(new_rate >= 0);
+               setSelectedIndex(new_rate);
+       }
+
+       public void set_product(String new_product) {
+               product = new_product;
+       }
+
+       public void set_serial(int new_serial) {
+               serial = new_serial;
+       }
+
+       public int rate() {
+               return getSelectedIndex();
+       }
+
+       public AltosUIRateList () {
+               super();
+               for (int i = 0; i < AltosLib.ao_telemetry_rate_values.length; i++)
+                       addItem(String.format("%d baud", AltosLib.ao_telemetry_rate_values[i]));
+               setMaximumRowCount(getItemCount());
+               setEditable(false);
+               product = "Unknown";
+               serial = 0;
+       }
+
+       public AltosUIRateList(int in_rate) {
+               this();
+               set_rate(in_rate);
+       }
+}
index b0632d18937bb2840efbb2cc7fd2c522e59f4f7c..809020c49e79c25d31dc2394dadfdee610490915 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.io.*;
 import java.util.ArrayList;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 import org.jfree.ui.*;
 import org.jfree.chart.*;
diff --git a/altosuilib/AltosUITelemetryList.java b/altosuilib/AltosUITelemetryList.java
new file mode 100644 (file)
index 0000000..facfdcd
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright © 2014 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altosuilib_3;
+
+import java.util.*;
+import javax.swing.*;
+import org.altusmetrum.altoslib_5.*;
+
+
+public class AltosUITelemetryList extends JComboBox<String> {
+       public int get_selected() {
+               return getSelectedIndex() + 1;
+       }
+
+       public void set_selected(int telemetry) {
+               setSelectedIndex(telemetry-1);
+       }
+
+       public AltosUITelemetryList(int serial) {
+               super();
+               for (int i = AltosLib.ao_telemetry_min; i <= AltosLib.ao_telemetry_max; i++)
+                       addItem(AltosLib.telemetry_name(i));
+
+               int telemetry = AltosPreferences.telemetry(serial);
+               if (telemetry < AltosLib.ao_telemetry_min || AltosLib.ao_telemetry_max < telemetry)
+                       telemetry = AltosLib.ao_telemetry_standard;
+               setMaximumRowCount(AltosLib.ao_telemetry_max);
+               set_selected(telemetry);
+               revalidate();
+       }
+}
+
index 2285b6fc046af8f5b8ac3fb6cf8f5b1b712738a0..50c30851fea62ac52e895b403407e7e6a68b51f1 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public abstract class AltosUIUnitsIndicator extends AltosUIIndicator {
 
index 0edb5c04b3ae2fd7d58fea4452a23bf57e7a1ced..9fd5757b76753d021e2875d699f937844843c183 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 public class AltosUIVersion {
        public final static String version = "@VERSION@";
index 3ff17213c8cdb975118634110427eaa27a97174c..8e99185678e971860c53ed831b48c5f0605eb833 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public abstract class AltosUIVoltageIndicator extends AltosUIUnitsIndicator {
 
index b70b5e83bd18911da0862c79c97df48dba93f53f..f4906a73662c4f8f0140c0152ad5e4935f726f78 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.util.*;
 import libaltosJNI.*;
@@ -79,6 +79,7 @@ public class AltosUSBDevice  extends altos_device implements AltosDevice {
                if (want_product == AltosUILib.product_altimeter)
                        return have_product == AltosUILib.product_telemetrum ||
                                have_product == AltosUILib.product_telemega ||
+                               have_product == AltosUILib.product_easymega ||
                                have_product == AltosUILib.product_telegps ||
                                have_product == AltosUILib.product_easymini ||
                                have_product == AltosUILib.product_telemini;
index a3995f680eb52c373ec8d871cd5f2bdef42c0acb..e02730bac7399a357ed662a7479168fac53e0d63 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import com.sun.speech.freetts.Voice;
 import com.sun.speech.freetts.VoiceManager;
index 4426f7a3de35fe436ae2d9211c4af350ed4c6ebe..9bccb808d8e9743222f677a1046b885483bd6072 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
 
 import java.awt.*;
 import java.awt.event.*;
index e08fbe7443e74acbb04814ae03b4ed077607e91f..d51da91de03f636cd81f9539804bcdee0cb42f64 100644 (file)
@@ -36,7 +36,6 @@ altosuilib_JAVA = \
        AltosVoice.java \
        AltosDisplayThread.java \
        AltosDeviceUIDialog.java \
-       AltosFreqList.java \
        AltosSerial.java \
        AltosSerialInUseException.java \
        AltosConfigFreqUI.java \
@@ -68,6 +67,7 @@ altosuilib_JAVA = \
        AltosUIMapPath.java \
        AltosUIMapTile.java \
        AltosUIMapCache.java \
+       AltosUIMapCacheListener.java \
        AltosUIMapImage.java \
        AltosUIMapTransform.java \
        AltosUIMapRectangle.java \
@@ -80,7 +80,11 @@ altosuilib_JAVA = \
        AltosUIFlightTab.java \
        AltosUIIndicator.java \
        AltosUIUnitsIndicator.java \
-       AltosUIVoltageIndicator.java
+       AltosUIVoltageIndicator.java \
+       AltosUIFreqList.java \
+       AltosUITelemetryList.java \
+       AltosUIRateList.java \
+       OSXAdapter.java
 
 JAR=altosuilib_$(ALTOSUILIB_VERSION).jar
 
@@ -99,7 +103,7 @@ ICONJAR= -C $(ICONDIR) redled.png -C $(ICONDIR) redoff.png \
 all-local: $(JAR)
 
 clean-local:
-       -rm -rf $(JAVAROOT) $(JAR)
+       -rm -rf $(JAVAROOT) altosuilib_*.jar
 
 install-altosuilibJAVA: $(JAR)
        @$(NORMAL_INSTALL)
diff --git a/altosuilib/OSXAdapter.java b/altosuilib/OSXAdapter.java
new file mode 100755 (executable)
index 0000000..23aacd7
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+
+File: OSXAdapter.java
+
+Abstract: Hooks existing preferences/about/quit functionality from an
+    existing Java app into handlers for the Mac OS X application menu.
+    Uses a Proxy object to dynamically implement the
+    com.apple.eawt.ApplicationListener interface and register it with the
+    com.apple.eawt.Application object.  This allows the complete project
+    to be both built and run on any platform without any stubs or
+    placeholders. Useful for developers looking to implement Mac OS X
+    features while supporting multiple platforms with minimal impact.
+
+Version: 2.0
+
+Disclaimer: IMPORTANT:  This Apple software is supplied to you by
+Apple Inc. ("Apple") in consideration of your agreement to the
+following terms, and your use, installation, modification or
+redistribution of this Apple software constitutes acceptance of these
+terms.  If you do not agree with these terms, please do not use,
+install, modify or redistribute this Apple software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, Apple grants you a personal, non-exclusive
+license, under Apple's copyrights in this original Apple software (the
+"Apple Software"), to use, reproduce, modify and redistribute the Apple
+Software, with or without modifications, in source and/or binary forms;
+provided that if you redistribute the Apple Software in its entirety and
+without modifications, you must retain this notice and the following
+text and disclaimers in all such redistributions of the Apple Software.
+Neither the name, trademarks, service marks or logos of Apple Inc.
+may be used to endorse or promote products derived from the Apple
+Software without specific prior written permission from Apple.  Except
+as expressly stated in this notice, no other rights or licenses, express
+or implied, are granted by Apple herein, including but not limited to
+any patent rights that may be infringed by your derivative works or by
+other works in which the Apple Software may be incorporated.
+
+The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+Copyright © 2003-2007 Apple, Inc., All Rights Reserved
+
+*/
+
+package org.altusmetrum.altosuilib_3;
+
+import java.lang.reflect.*;
+import java.util.HashMap;
+
+
+public class OSXAdapter implements InvocationHandler {
+
+    protected Object targetObject;
+    protected Method targetMethod;
+    protected String proxySignature;
+
+    static Object macOSXApplication;
+
+    // Pass this method an Object and Method equipped to perform application shutdown logic
+    // The method passed should return a boolean stating whether or not the quit should occur
+    public static void setQuitHandler(Object target, Method quitHandler) {
+        setHandler(new OSXAdapter("handleQuit", target, quitHandler));
+    }
+
+    // Pass this method an Object and Method equipped to display application info
+    // They will be called when the About menu item is selected from the application menu
+    public static void setAboutHandler(Object target, Method aboutHandler) {
+        boolean enableAboutMenu = (target != null && aboutHandler != null);
+        if (enableAboutMenu) {
+            setHandler(new OSXAdapter("handleAbout", target, aboutHandler));
+        }
+        // If we're setting a handler, enable the About menu item by calling
+        // com.apple.eawt.Application reflectively
+        try {
+            Method enableAboutMethod = macOSXApplication.getClass().getDeclaredMethod("setEnabledAboutMenu", new Class[] { boolean.class });
+            enableAboutMethod.invoke(macOSXApplication, new Object[] { Boolean.valueOf(enableAboutMenu) });
+        } catch (Exception ex) {
+            System.err.println("OSXAdapter could not access the About Menu");
+            ex.printStackTrace();
+        }
+    }
+
+    // Pass this method an Object and a Method equipped to display application options
+    // They will be called when the Preferences menu item is selected from the application menu
+    public static void setPreferencesHandler(Object target, Method prefsHandler) {
+        boolean enablePrefsMenu = (target != null && prefsHandler != null);
+        if (enablePrefsMenu) {
+            setHandler(new OSXAdapter("handlePreferences", target, prefsHandler));
+        }
+        // If we're setting a handler, enable the Preferences menu item by calling
+        // com.apple.eawt.Application reflectively
+        try {
+            Method enablePrefsMethod = macOSXApplication.getClass().getDeclaredMethod("setEnabledPreferencesMenu", new Class[] { boolean.class });
+            enablePrefsMethod.invoke(macOSXApplication, new Object[] { Boolean.valueOf(enablePrefsMenu) });
+        } catch (Exception ex) {
+            System.err.println("OSXAdapter could not access the About Menu");
+            ex.printStackTrace();
+        }
+    }
+
+    // Pass this method an Object and a Method equipped to handle document events from the Finder
+    // Documents are registered with the Finder via the CFBundleDocumentTypes dictionary in the
+    // application bundle's Info.plist
+    public static void setFileHandler(Object target, Method fileHandler) {
+        setHandler(new OSXAdapter("handleOpenFile", target, fileHandler) {
+            // Override OSXAdapter.callTarget to send information on the
+            // file to be opened
+            public boolean callTarget(Object appleEvent) {
+                if (appleEvent != null) {
+                    try {
+                        Method getFilenameMethod = appleEvent.getClass().getDeclaredMethod("getFilename", (Class[])null);
+                        String filename = (String) getFilenameMethod.invoke(appleEvent, (Object[])null);
+                        this.targetMethod.invoke(this.targetObject, new Object[] { filename });
+                    } catch (Exception ex) {
+
+                    }
+                }
+                return true;
+            }
+        });
+    }
+
+    // setHandler creates a Proxy object from the passed OSXAdapter and adds it as an ApplicationListener
+    public static void setHandler(OSXAdapter adapter) {
+        try {
+            Class applicationClass = Class.forName("com.apple.eawt.Application");
+            if (macOSXApplication == null) {
+                macOSXApplication = applicationClass.getConstructor((Class[])null).newInstance((Object[])null);
+            }
+            Class applicationListenerClass = Class.forName("com.apple.eawt.ApplicationListener");
+            Method addListenerMethod = applicationClass.getDeclaredMethod("addApplicationListener", new Class[] { applicationListenerClass });
+            // Create a proxy object around this handler that can be reflectively added as an Apple ApplicationListener
+            Object osxAdapterProxy = Proxy.newProxyInstance(OSXAdapter.class.getClassLoader(), new Class[] { applicationListenerClass }, adapter);
+            addListenerMethod.invoke(macOSXApplication, new Object[] { osxAdapterProxy });
+        } catch (ClassNotFoundException cnfe) {
+            System.err.println("This version of Mac OS X does not support the Apple EAWT.  ApplicationEvent handling has been disabled (" + cnfe + ")");
+        } catch (Exception ex) {  // Likely a NoSuchMethodException or an IllegalAccessException loading/invoking eawt.Application methods
+            System.err.println("Mac OS X Adapter could not talk to EAWT:");
+            ex.printStackTrace();
+        }
+    }
+
+    // Each OSXAdapter has the name of the EAWT method it intends to listen for (handleAbout, for example),
+    // the Object that will ultimately perform the task, and the Method to be called on that Object
+    protected OSXAdapter(String proxySignature, Object target, Method handler) {
+        this.proxySignature = proxySignature;
+        this.targetObject = target;
+        this.targetMethod = handler;
+    }
+
+    // Override this method to perform any operations on the event
+    // that comes with the various callbacks
+    // See setFileHandler above for an example
+    public boolean callTarget(Object appleEvent) throws InvocationTargetException, IllegalAccessException {
+        Object result = targetMethod.invoke(targetObject, (Object[])null);
+        if (result == null) {
+            return true;
+        }
+        return Boolean.valueOf(result.toString()).booleanValue();
+    }
+
+    // InvocationHandler implementation
+    // This is the entry point for our proxy object; it is called every time an ApplicationListener method is invoked
+    public Object invoke (Object proxy, Method method, Object[] args) throws Throwable {
+        if (isCorrectMethod(method, args)) {
+            boolean handled = callTarget(args[0]);
+            setApplicationEventHandled(args[0], handled);
+        }
+        // All of the ApplicationListener methods are void; return null regardless of what happens
+        return null;
+    }
+
+    // Compare the method that was called to the intended method when the OSXAdapter instance was created
+    // (e.g. handleAbout, handleQuit, handleOpenFile, etc.)
+    protected boolean isCorrectMethod(Method method, Object[] args) {
+        return (targetMethod != null && proxySignature.equals(method.getName()) && args.length == 1);
+    }
+
+    // It is important to mark the ApplicationEvent as handled and cancel the default behavior
+    // This method checks for a boolean result from the proxy method and sets the event accordingly
+    protected void setApplicationEventHandled(Object event, boolean handled) {
+        if (event != null) {
+            try {
+                Method setHandledMethod = event.getClass().getDeclaredMethod("setHandled", new Class[] { boolean.class });
+                // If the target method returns a boolean, use that as a hint
+                setHandledMethod.invoke(event, new Object[] { Boolean.valueOf(handled) });
+            } catch (Exception ex) {
+                System.err.println("OSXAdapter was unable to handle an ApplicationEvent: " + event);
+                ex.printStackTrace();
+            }
+        }
+    }
+}
diff --git a/ao-bringup/test-easymega b/ao-bringup/test-easymega
new file mode 100755 (executable)
index 0000000..eabe1ee
--- /dev/null
@@ -0,0 +1,68 @@
+#!/bin/sh
+
+VERSION=1.0
+PRODUCT=EasyMega
+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 "\t$PRODUCT v$VERSION powered from USB"
+echo
+
+ret=1
+ao-list | while read product serial dev; do
+    case "$product" in
+       "$PRODUCT-v$VERSION")
+
+           echo "Testing $product $serial $dev"
+
+           for igniter in drogue main 0 1 2 3; do
+               echo "Testing $igniter igniter."
+               echo -n "Press enter to continue..."
+               read foo < /dev/tty
+               ../ao-tools/ao-test-igniter/ao-test-igniter --tty="$dev" $igniter
+
+               case $? in
+                   0)
+                       ;;
+                   *)
+                       echo "failed"
+                       exit 1
+                       ;;
+               esac
+           done
+
+           echo "Testing baro sensor"
+           ../ao-tools/ao-test-baro/ao-test-baro --tty="$dev"
+
+           case $? in
+               0)
+                   ;;
+               *)
+                   echo "failed"
+                   exit 1
+           esac
+
+           FLASHSIZE=8388608
+
+           echo "Testing flash"
+           ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE"
+
+           case $? in
+               0)
+                   ;;
+               *)
+                   echo "failed"
+                   exit 1
+           esac
+
+           echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
+           ret=0
+           ;;
+       *)
+           echo "Skipping $product $serial $dev"
+           ;;
+    esac
+done
index 291393856c567096ed25440fbbe7cc22a31cbed1..17e0095526e3270e735eaccfc28f3445e42ac8aa 100755 (executable)
@@ -19,7 +19,7 @@ ao-list | while read product serial dev; do
            echo "Testing $product $serial $dev"
 
            echo "Testing igniters. Both should flash"
-           ./test-igniter "$dev" drogue main
+           ../ao-tools/ao-test-igniter/ao-test-igniter --tty="$dev" drogue main
 
            case $? in
                0)
@@ -30,7 +30,7 @@ ao-list | while read product serial dev; do
            esac
 
            echo "Testing baro sensor"
-           ./test-baro "$dev"
+           ../ao-tools/ao-test-baro/ao-test-baro --tty="$dev"
 
            case $? in
                0)
@@ -43,7 +43,7 @@ ao-list | while read product serial dev; do
            FLASHSIZE=1048576
 
            echo "Testing flash"
-           ./test-flash "$dev" "$FLASHSIZE"
+           ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE"
 
            case $? in
                0)
index a1e216265ac33f1b1ec780be7ecec69243a25010..04c467b5da343b92fe2a62f11ec8f142eb4d1427 100755 (executable)
@@ -70,6 +70,7 @@ do_gps(file f) {
        string[*] sats = find_gps(i, "Sats:");
 
        int actual_flags = string_to_integer(flags[1]);
+       int actual_sats = string_to_integer(sats[1]);
 
        while ((actual_flags & (1 << 4)) == 0) {
                printf("Flags: %s\n", flags[1]);
index f31744850dddb579e983c632f909582d53b86686..9295dd062db03c698308eb4198530c9e27f79afc 100755 (executable)
@@ -42,7 +42,7 @@ ao-list | while read product serial dev; do
                    exit 1
            esac
 
-           echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
+           echo "$PRODUCT-v$VERSION" serial "$serial" passed functional tests
            ret=0
            ;;
        *)
diff --git a/ao-bringup/turnon_easymega b/ao-bringup/turnon_easymega
new file mode 100755 (executable)
index 0000000..b313e16
--- /dev/null
@@ -0,0 +1,61 @@
+#!/bin/sh
+
+if [ -x /usr/bin/ao-flash-stm ]; then
+       STMLOAD=/usr/bin/ao-flash-stm
+else
+       echo "Can't find ao-flash-stm!  Aborting."
+       exit 1
+fi
+
+if [ -x /usr/bin/ao-usbload ]; then
+       USBLOAD=/usr/bin/ao-usbload
+else
+       echo "Can't find ao-usbload!  Aborting."
+       exit 1
+fi
+
+VERSION=1.0
+REPO=~/altusmetrumllc/Binaries
+
+echo "EasyMega v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2014 by Bdale Garbee.  Released under GPL v2"
+echo
+echo "Expectations:"
+echo "\tEasyMega v$VERSION"
+echo "\t\twith USB cable attached"
+echo "\t\twith ST-Link-V2 cabled to debug header"
+echo
+echo -n "EasyMega-$VERSION serial number: "
+read SERIAL
+
+echo $STMLOAD
+
+$STMLOAD $REPO/loaders/easymega-v$VERSION*.elf || exit 1
+
+sleep 2
+
+$USBLOAD --serial=$SERIAL $REPO/easymega-v$VERSION*.elf || exit 1
+
+sleep 2
+
+dev=`ao-list | awk '/EasyMega-v'"$VERSION"'/ { print $3; exit(0); }'`
+
+case "$dev" in
+/dev/tty*)
+       echo "EasyMega found on $dev"
+       ;;
+*)
+       echo 'No EasyMega-v'"$VERSION"' found'
+       exit 1
+       ;;
+esac
+
+echo 'E 0' > $dev
+
+../ao-tools/ao-cal-accel/ao-cal-accel $dev
+
+echo 'E 1' > $dev
+
+./test-easymega
+
+exit $?
index 39a636420a5ada339aff493498526073208413ac..7745a8e560abcddf71bddf50fc8281c0db75965d 100755 (executable)
@@ -54,4 +54,6 @@ echo 'E 0' > $dev
 
 SERIAL=$SERIAL ./cal-freq $dev
 
-./cal-accel $dev
+../ao-tools/ao-cal-accel/ao-cal-accel $dev
+
+echo 'E 1' > $dev
index 80193c4c448f98700f074d5eff3a211f2fe6ced6..48ff1e276cb6083aeed292821b6e8469b186675f 100755 (executable)
@@ -1,17 +1,13 @@
 #!/bin/sh
 
-if [ -x ../ao-tools/ao-stmload/ao-stmload ]; then
-       STMLOAD=../ao-tools/ao-stmload/ao-stmload
-elif [ -x /usr/bin/ao-stmload ]; then
-       STMLOAD=/usr/bin/ao-stmload
+if [ -x /usr/bin/ao-flash-stm ]; then
+       FLASH_STM=/usr/bin/ao-flash-stm
 else
-       echo "Can't find ao-stmload!  Aborting."
+       echo "Can't find ao-flash-stm!  Aborting."
        exit 1
 fi
 
-if [ -x ../ao-tools/ao-usbload/ao-usbload ]; then
-       USBLOAD=../ao-tools/ao-usbload/ao-usbload
-elif [ -x /usr/bin/ao-usbload ]; then
+if [ -x /usr/bin/ao-usbload ]; then
        USBLOAD=/usr/bin/ao-usbload
 else
        echo "Can't find ao-usbload!  Aborting."
@@ -24,16 +20,16 @@ echo "TeleMetrum v$VERSION Turn-On and Calibration Program"
 echo "Copyright 2014 by Bdale Garbee.  Released under GPL v2"
 echo
 echo "Expectations:"
-echo "\tTeleMetrum v$VERSIOn powered from USB"
+echo "\tTeleMetrum v$VERSION powered from USB"
 echo "\t\twith ST-Link-V2 cabled to debug header"
 echo "\t\twith coax from UHF to frequency counter"
 echo
 echo -n "TeleMetrum-$VERSION serial number: "
 read SERIAL
 
-echo $STMLOAD
+echo $FLASH_STM
 
-$STMLOAD --raw ../src/telemetrum-v$VERSION/flash-loader/*.elf || exit 1
+$FLASH_STM ~/altusmetrumllc/Binaries/loaders/telemetrum-v$VERSION-*.elf || exit 1
 
 sleep 2
 
@@ -57,4 +53,6 @@ echo 'E 0' > $dev
 
 SERIAL=$SERIAL ./cal-freq $dev
 
-./cal-accel $dev
+../ao-tools/ao-cal-accel/ao-cal-accel $dev
+
+echo 'E 1' > $dev
index a42988d6c22f57a45ded73084b1cf8f59f60c9c8..2d873e5049f97c469b1a977991a7d0fb95d98f1a 100644 (file)
@@ -1,7 +1,8 @@
 SUBDIRS=lib ao-rawload ao-dbg ao-bitbang ao-eeprom ao-list \
        ao-load ao-telem ao-send-telem ao-sky-flash \
        ao-dumpflash ao-edit-telem ao-dump-up ao-elftohex \
-       ao-flash ao-usbload
+       ao-flash ao-usbload ao-test-igniter ao-test-baro \
+       ao-test-flash ao-cal-accel
 if LIBSTLINK
 SUBDIRS += ao-stmload
 endif
diff --git a/ao-tools/ao-cal-accel/.gitignore b/ao-tools/ao-cal-accel/.gitignore
new file mode 100644 (file)
index 0000000..73402b2
--- /dev/null
@@ -0,0 +1 @@
+ao-cal-accel
diff --git a/ao-tools/ao-cal-accel/Makefile.am b/ao-tools/ao-cal-accel/Makefile.am
new file mode 100644 (file)
index 0000000..d278097
--- /dev/null
@@ -0,0 +1,11 @@
+bin_PROGRAMS=ao-cal-accel
+
+AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+
+ao_cal_accel_DEPENDENCIES = $(top_builddir)/ao-tools/lib/libao-tools.a
+
+ao_cal_accel_LDADD=$(top_builddir)/ao-tools/lib/libao-tools.a $(LIBUSB_LIBS)
+
+ao_cal_accel_SOURCES=ao-cal-accel.c
+
+man_MANS = ao-cal-accel.1
diff --git a/ao-tools/ao-cal-accel/ao-cal-accel.1 b/ao-tools/ao-cal-accel/ao-cal-accel.1
new file mode 100644 (file)
index 0000000..eb75d7c
--- /dev/null
@@ -0,0 +1,58 @@
+.\"
+.\" Copyright © 2009 Keith Packard <keithp@keithp.com>
+.\"
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful, but
+.\" WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+.\" General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License along
+.\" with this program; if not, write to the Free Software Foundation, Inc.,
+.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+.\"
+.\"
+.TH AO-LOAD 1 "ao-cal-accel" ""
+.SH NAME
+ao-cal-accel \- Calibrate AltOS flight computer accelerometers
+.SH SYNOPSIS
+.B "ao-cal-accel"
+[\-T \fItty-device\fP]
+[\--tty \fItty-device\fP]
+[\-D \fIaltos-device\fP]
+[\--device \fIaltos-device\fP]
+.SH DESCRIPTION
+.I ao-cal-accel
+drives the built-in accelerometer calibration and validates the results.
+.SH OPTIONS
+.TP
+\-T tty-device | --tty tty-device
+This selects which tty device the debugger uses to communicate with
+the target device. The special name 'BITBANG' directs ao-dbg to use
+the cp2103 connection, otherwise this should be a usb serial port
+connected to a suitable cc1111 debug node.
+.TP
+\-D AltOS-device | --device AltOS-device
+Search for a connected device. This requires an argument of one of the
+following forms:
+.IP
+TeleMega:2
+.br
+TeleMega
+.br
+2
+.IP
+Leaving out the product name will cause the tool to select a suitable
+product, leaving out the serial number will cause the tool to match
+one of the available devices.
+.SH USAGE
+.I ao-cal-accel
+opens the target device, executes the accelerometer calibration
+command, verifies that it executed correctly, then shows the resulting
+calibration values and saves them to configuration memory.
+.SH AUTHOR
+Keith Packard
diff --git a/ao-tools/ao-cal-accel/ao-cal-accel.c b/ao-tools/ao-cal-accel/ao-cal-accel.c
new file mode 100644 (file)
index 0000000..9a98864
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+ * Copyright © 2014 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <err.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <string.h>
+#include <stdbool.h>
+#include <termios.h>
+#include "ao-elf.h"
+#include "ccdbg.h"
+#include "cc-usb.h"
+#include "cc.h"
+#include "ao-verbose.h"
+
+static const struct option options[] = {
+       { .name = "tty", .has_arg = 1, .val = 'T' },
+       { .name = "device", .has_arg = 1, .val = 'D' },
+       { .name = "raw", .has_arg = 0, .val = 'r' },
+       { .name = "verbose", .has_arg = 1, .val = 'v' },
+       { 0, 0, 0, 0},
+};
+
+static void usage(char *program)
+{
+       fprintf(stderr, "usage: %s [--verbose=<verbose>] [--device=<device>] [-tty=<tty>]\n", program);
+       exit(1);
+}
+
+void
+done(struct cc_usb *cc, int code)
+{
+       cc_usb_close(cc);
+       exit (code);
+}
+
+static int
+ends_with(char *whole, char *suffix)
+{
+       int whole_len = strlen(whole);
+       int suffix_len = strlen(suffix);
+
+       if (suffix_len > whole_len)
+               return 0;
+       return strcmp(whole + whole_len - suffix_len, suffix) == 0;
+}
+
+static int
+starts_with(char *whole, char *prefix)
+{
+       int whole_len = strlen(whole);
+       int prefix_len = strlen(prefix);
+
+       if (prefix_len > whole_len)
+               return 0;
+       return strncmp(whole, prefix, prefix_len) == 0;
+}
+
+static char **
+tok(char *line) {
+       char    **strs = malloc (sizeof (char *)), *str;
+       int     n = 0;
+
+       while ((str = strtok(line, " \t"))) {
+               line = NULL;
+               strs = realloc(strs, (n + 2) * sizeof (char *));
+               strs[n] = strdup(str);
+               n++;
+       }
+       strs[n] = '\0';
+       return strs;
+}
+
+static void
+free_strs(char **strs) {
+       char    *str;
+       int     i;
+
+       for (i = 0; (str = strs[i]) != NULL; i++)
+               free(str);
+       free(strs);
+}
+
+struct flash {
+       struct flash    *next;
+       char            line[512];
+       char            **strs;
+};
+
+static struct flash *
+flash(struct cc_usb *usb)
+{
+       struct flash    *head = NULL, **tail = &head;
+       cc_usb_printf(usb, "c s\nv\n");
+       for (;;) {
+               char    line[512];
+               struct flash    *b;
+
+               cc_usb_getline(usb, line, sizeof (line));
+               b = malloc (sizeof (struct flash));
+               strcpy(b->line, line);
+               b->strs = tok(line);
+               b->next = NULL;
+               *tail = b;
+               tail = &b->next;
+               if (strstr(line, "software-version"))
+                       break;
+       }
+       return head;
+}
+
+static void
+free_flash(struct flash *b) {
+       struct flash *n;
+
+       while (b) {
+               n = b->next;
+               free_strs(b->strs);
+               free(b);
+               b = n;
+       }
+}
+
+char **
+find_flash(struct flash *b, char *word0) {
+       int i;
+       for (;b; b = b->next) {
+               if (strstr(b->line, word0))
+                       return b->strs;
+       }
+       return NULL;
+}
+
+void
+await_key(void)
+{
+       struct termios  termios, termios_save;
+       char    buf[512];
+
+       tcgetattr(0, &termios);
+       termios_save = termios;
+       cfmakeraw(&termios);
+       tcsetattr(0, TCSAFLUSH, &termios);
+       read(0, buf, sizeof (buf));
+       tcsetattr(0, TCSAFLUSH, &termios_save);
+}
+
+int
+do_cal(struct cc_usb *usb) {
+       struct flash    *b;
+       char    **accel;
+       char    line[1024];
+       int     l;
+       int     running = 0;
+       int     worked = 1;
+
+       cc_usb_printf(usb, "E 1\nc a 0\n");
+
+       for (;;) {
+               int     c = cc_usb_getchar_timeout(usb, 20*1000);
+
+               if (c == '\n')
+                       l = 0;
+               else if (l < sizeof (line) - 1)
+                       line[l++] = c;
+               line[l] = '\0';
+               putchar(c); fflush(stdout);
+               if (strstr(line, "press a key...")) {
+                       await_key();
+                       cc_usb_printf(usb, " ");
+                       l = 0;
+                       running = 1;
+               }
+               else if (strstr(line, "Invalid"))
+                       worked = 0;
+               if (running && strstr(line, ">")) {
+                       printf("\n");
+                       break;
+               }
+       }
+       cc_usb_printf(usb, "E 0\n");
+
+       if (!worked) {
+               printf("Calibration failed\n");
+               return 0;
+       }
+
+       b = flash(usb);
+
+       accel = find_flash(b, "Accel cal");
+       if (!accel) {
+               printf("no response\n");
+               return 0;
+       }
+
+       printf ("Accel cal +1g: %s -1g: %s\n",
+               accel[3], accel[5]);
+
+       printf ("Saving..."); fflush(stdout);
+       cc_usb_printf (usb, "c w\n");
+       cc_usb_sync(usb);
+       b = flash(usb);
+       printf ("done\n");
+
+       return worked;
+}
+
+int
+main (int argc, char **argv)
+{
+       char                    *device = NULL;
+       char                    *filename;
+       Elf                     *e;
+       unsigned int            s;
+       int                     i;
+       int                     c;
+       int                     tries;
+       struct cc_usb           *cc = NULL;
+       char                    *tty = NULL;
+       int                     success;
+       int                     verbose = 0;
+       int                     ret = 0;
+       int                     expected_size;
+
+       while ((c = getopt_long(argc, argv, "rT:D:c:s:v:", options, NULL)) != -1) {
+               switch (c) {
+               case 'T':
+                       tty = optarg;
+                       break;
+               case 'D':
+                       device = optarg;
+                       break;
+               case 'v':
+                       verbose++;
+                       break;
+               default:
+                       usage(argv[0]);
+                       break;
+               }
+       }
+
+       ao_verbose = verbose;
+
+       if (verbose > 1)
+               ccdbg_add_debug(CC_DEBUG_BITBANG);
+
+       if (!tty)
+               tty = cc_usbdevs_find_by_arg(device, "AltosFlash");
+       if (!tty)
+               tty = cc_usbdevs_find_by_arg(device, "TeleMega");
+       if (!tty)
+               tty = getenv("ALTOS_TTY");
+       if (!tty)
+               tty="/dev/ttyACM0";
+
+       cc = cc_usb_open(tty);
+
+       if (!cc)
+               exit(1);
+
+       if (!do_cal(cc))
+               ret = 1;
+       done(cc, ret);
+}
index 3db44542e3095d64fd4afd42867696eb6a6a5275..26c3263e72a193886a248067adb83746c869ba0f 100644 (file)
@@ -85,6 +85,12 @@ packet_state(union ao_telemetry_all *telem)
        case AO_TELEMETRY_MEGA_DATA:
                cur_state = telem->mega_data.state;
                break;
+       case AO_TELEMETRY_METRUM_SENSOR:
+               cur_state = telem->metrum_sensor.state;
+               break;
+       case AO_TELEMETRY_MINI:
+               cur_state = telem->mini.state;
+               break;
        }
        return cur_state;
 }
diff --git a/ao-tools/ao-test-baro/.gitignore b/ao-tools/ao-test-baro/.gitignore
new file mode 100644 (file)
index 0000000..f5fb64d
--- /dev/null
@@ -0,0 +1 @@
+ao-test-baro
diff --git a/ao-tools/ao-test-baro/Makefile.am b/ao-tools/ao-test-baro/Makefile.am
new file mode 100644 (file)
index 0000000..69e4752
--- /dev/null
@@ -0,0 +1,11 @@
+bin_PROGRAMS=ao-test-baro
+
+AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+
+ao_test_baro_DEPENDENCIES = $(top_builddir)/ao-tools/lib/libao-tools.a
+
+ao_test_baro_LDADD=$(top_builddir)/ao-tools/lib/libao-tools.a $(LIBUSB_LIBS)
+
+ao_test_baro_SOURCES=ao-test-baro.c
+
+man_MANS = ao-test-baro.1
diff --git a/ao-tools/ao-test-baro/ao-test-baro.1 b/ao-tools/ao-test-baro/ao-test-baro.1
new file mode 100644 (file)
index 0000000..0004dba
--- /dev/null
@@ -0,0 +1,56 @@
+.\"
+.\" Copyright © 2009 Keith Packard <keithp@keithp.com>
+.\"
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful, but
+.\" WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+.\" General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License along
+.\" with this program; if not, write to the Free Software Foundation, Inc.,
+.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+.\"
+.\"
+.TH AO-LOAD 1 "ao-test-baro" ""
+.SH NAME
+ao-test-baro \- test AltOS flight computer barometric sensor
+.SH SYNOPSIS
+.B "ao-test-baro"
+[\-T \fItty-device\fP]
+[\--tty \fItty-device\fP]
+[\-D \fIaltos-device\fP]
+[\--device \fIaltos-device\fP]
+\fIbaro-name...\fP
+.SH DESCRIPTION
+.I ao-test-baro
+makes sure the altitude is between -50m and 3000m and temperature is
+between 20°C and 30°C.
+.SH OPTIONS
+.TP
+\-T tty-device | --tty tty-device
+This selects which tty device the debugger uses to communicate with
+the target device.
+.TP
+\-D AltOS-device | --device AltOS-device
+Search for a connected device. This requires an argument of one of the
+following forms:
+.IP
+TeleMega:2
+.br
+TeleMega
+.br
+2
+.IP
+Leaving out the product name will cause the tool to select a suitable
+product, leaving out the serial number will cause the tool to match
+one of the available devices.
+.SH USAGE
+.I ao-test-baro
+opens the target device and queries the current barometric data.
+.SH AUTHOR
+Keith Packard
diff --git a/ao-tools/ao-test-baro/ao-test-baro.c b/ao-tools/ao-test-baro/ao-test-baro.c
new file mode 100644 (file)
index 0000000..e883de4
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+ * Copyright © 2014 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <err.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <string.h>
+#include <stdbool.h>
+#include "ao-elf.h"
+#include "ccdbg.h"
+#include "cc-usb.h"
+#include "cc.h"
+#include "ao-verbose.h"
+
+static const struct option options[] = {
+       { .name = "tty", .has_arg = 1, .val = 'T' },
+       { .name = "device", .has_arg = 1, .val = 'D' },
+       { .name = "raw", .has_arg = 0, .val = 'r' },
+       { .name = "verbose", .has_arg = 1, .val = 'v' },
+       { 0, 0, 0, 0},
+};
+
+static void usage(char *program)
+{
+       fprintf(stderr, "usage: %s [--verbose=<verbose>] [--device=<device>] [-tty=<tty>] main|drogue\n", program);
+       exit(1);
+}
+
+void
+done(struct cc_usb *cc, int code)
+{
+/*     cc_usb_printf(cc, "a\n"); */
+       cc_usb_close(cc);
+       exit (code);
+}
+
+static int
+ends_with(char *whole, char *suffix)
+{
+       int whole_len = strlen(whole);
+       int suffix_len = strlen(suffix);
+
+       if (suffix_len > whole_len)
+               return 0;
+       return strcmp(whole + whole_len - suffix_len, suffix) == 0;
+}
+
+static int
+starts_with(char *whole, char *prefix)
+{
+       int whole_len = strlen(whole);
+       int prefix_len = strlen(prefix);
+
+       if (prefix_len > whole_len)
+               return 0;
+       return strncmp(whole, prefix, prefix_len) == 0;
+}
+
+static char **
+tok(char *line) {
+       char    **strs = malloc (sizeof (char *)), *str;
+       int     n = 0;
+
+       while ((str = strtok(line, " \t"))) {
+               line = NULL;
+               strs = realloc(strs, (n + 2) * sizeof (char *));
+               strs[n] = strdup(str);
+               n++;
+       }
+       strs[n] = '\0';
+       return strs;
+}
+
+static void
+free_strs(char **strs) {
+       char    *str;
+       int     i;
+
+       for (i = 0; (str = strs[i]) != NULL; i++)
+               free(str);
+       free(strs);
+}
+
+struct baro {
+       struct baro     *next;
+       char            **strs;
+};
+
+static struct baro *
+baro(struct cc_usb *usb)
+{
+       struct baro     *head = NULL, **tail = &head;
+       cc_usb_printf(usb, "B\n");
+       for (;;) {
+               char    line[512];
+               struct baro     *b;
+
+               cc_usb_getline(usb, line, sizeof (line));
+               b = malloc (sizeof (struct baro));
+               b->strs = tok(line);
+               b->next = NULL;
+               *tail = b;
+               tail = &b->next;
+               if (strstr(line, "Altitude:"))
+                       break;
+       }
+       return head;
+}
+
+static void
+free_baro(struct baro *b) {
+       struct baro *n;
+
+       while (b) {
+               n = b->next;
+               free_strs(b->strs);
+               free(b);
+               b = n;
+       }
+}
+
+char **
+find_baro(struct baro *b, char *word0) {
+       int i;
+       for (;b; b = b->next)
+               if (b->strs[0] && !strcmp(b->strs[0], word0))
+                       return b->strs;
+       return NULL;
+}
+
+int
+do_baro(struct cc_usb *usb) {
+       struct baro *b = baro(usb);
+       char **temp = find_baro(b, "Temperature:");
+       char **alt = find_baro(b, "Altitude:");
+
+       if (!temp || !alt) {
+               printf("no response\n");
+               free_baro(b);
+               return 0;
+       }
+
+       double temperature = strtod(temp[2], NULL) / 100.0;
+       double altitude = strtod(alt[1], NULL);
+
+       if (altitude < -50 || 3000 < altitude) {
+               printf ("weird altitude %f\n", altitude);
+               free_baro(b);
+               return 0;
+       }
+
+       if (temperature < 20 || 35 < temperature) {
+               printf ("weird temperature %f\n", temperature);
+               free_baro(b);
+               return 0;
+       }
+
+       printf ("altitude %f temperature %f\n", altitude, temperature);
+
+       return 1;
+}
+
+int
+main (int argc, char **argv)
+{
+       char                    *device = NULL;
+       char                    *filename;
+       Elf                     *e;
+       unsigned int            s;
+       int                     i;
+       int                     c;
+       int                     tries;
+       struct cc_usb           *cc = NULL;
+       char                    *tty = NULL;
+       int                     success;
+       int                     verbose = 0;
+       int                     ret = 0;
+
+       while ((c = getopt_long(argc, argv, "rT:D:c:s:v:", options, NULL)) != -1) {
+               switch (c) {
+               case 'T':
+                       tty = optarg;
+                       break;
+               case 'D':
+                       device = optarg;
+                       break;
+               case 'v':
+                       verbose++;
+                       break;
+               default:
+                       usage(argv[0]);
+                       break;
+               }
+       }
+
+       ao_verbose = verbose;
+
+       if (verbose > 1)
+               ccdbg_add_debug(CC_DEBUG_BITBANG);
+
+       if (!tty)
+               tty = cc_usbdevs_find_by_arg(device, "AltosFlash");
+       if (!tty)
+               tty = cc_usbdevs_find_by_arg(device, "TeleMega");
+       if (!tty)
+               tty = getenv("ALTOS_TTY");
+       if (!tty)
+               tty="/dev/ttyACM0";
+
+       cc = cc_usb_open(tty);
+
+       if (!cc)
+               exit(1);
+
+       if (!do_baro(cc))
+               ret = 1;
+       done(cc, ret);
+}
diff --git a/ao-tools/ao-test-flash/.gitignore b/ao-tools/ao-test-flash/.gitignore
new file mode 100644 (file)
index 0000000..40ab1ef
--- /dev/null
@@ -0,0 +1 @@
+ao-test-flash
diff --git a/ao-tools/ao-test-flash/Makefile.am b/ao-tools/ao-test-flash/Makefile.am
new file mode 100644 (file)
index 0000000..0323c28
--- /dev/null
@@ -0,0 +1,11 @@
+bin_PROGRAMS=ao-test-flash
+
+AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+
+ao_test_flash_DEPENDENCIES = $(top_builddir)/ao-tools/lib/libao-tools.a
+
+ao_test_flash_LDADD=$(top_builddir)/ao-tools/lib/libao-tools.a $(LIBUSB_LIBS)
+
+ao_test_flash_SOURCES=ao-test-flash.c
+
+man_MANS = ao-test-flash.1
diff --git a/ao-tools/ao-test-flash/ao-test-flash.1 b/ao-tools/ao-test-flash/ao-test-flash.1
new file mode 100644 (file)
index 0000000..155bd1b
--- /dev/null
@@ -0,0 +1,59 @@
+.\"
+.\" Copyright © 2009 Keith Packard <keithp@keithp.com>
+.\"
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful, but
+.\" WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+.\" General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License along
+.\" with this program; if not, write to the Free Software Foundation, Inc.,
+.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+.\"
+.\"
+.TH AO-LOAD 1 "ao-test-igniter" ""
+.SH NAME
+ao-test-igniter \- test AltOS flight computer igniters
+.SH SYNOPSIS
+.B "ao-test-igniter"
+[\-T \fItty-device\fP]
+[\--tty \fItty-device\fP]
+[\-D \fIaltos-device\fP]
+[\--device \fIaltos-device\fP]
+\fIigniter-name...\fP
+.SH DESCRIPTION
+.I ao-test-igniter
+test the status and then fires the specified igniters on the target device
+.SH OPTIONS
+.TP
+\-T tty-device | --tty tty-device
+This selects which tty device the debugger uses to communicate with
+the target device. The special name 'BITBANG' directs ao-dbg to use
+the cp2103 connection, otherwise this should be a usb serial port
+connected to a suitable cc1111 debug node.
+.TP
+\-D AltOS-device | --device AltOS-device
+Search for a connected device. This requires an argument of one of the
+following forms:
+.IP
+TeleMega:2
+.br
+TeleMega
+.br
+2
+.IP
+Leaving out the product name will cause the tool to select a suitable
+product, leaving out the serial number will cause the tool to match
+one of the available devices.
+.SH USAGE
+.I ao-test-igniter
+opens the target device, lists the available igniter and then fires
+the specified ones. And error occurrs if any of the specified igniters
+is not present or not ready.
+.SH AUTHOR
+Keith Packard
diff --git a/ao-tools/ao-test-flash/ao-test-flash.c b/ao-tools/ao-test-flash/ao-test-flash.c
new file mode 100644 (file)
index 0000000..cf44ae6
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * Copyright © 2014 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <err.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <string.h>
+#include <stdbool.h>
+#include "ao-elf.h"
+#include "ccdbg.h"
+#include "cc-usb.h"
+#include "cc.h"
+#include "ao-verbose.h"
+
+static const struct option options[] = {
+       { .name = "tty", .has_arg = 1, .val = 'T' },
+       { .name = "device", .has_arg = 1, .val = 'D' },
+       { .name = "raw", .has_arg = 0, .val = 'r' },
+       { .name = "verbose", .has_arg = 1, .val = 'v' },
+       { 0, 0, 0, 0},
+};
+
+static void usage(char *program)
+{
+       fprintf(stderr, "usage: %s [--verbose=<verbose>] [--device=<device>] [-tty=<tty>] <expected-size>\n", program);
+       exit(1);
+}
+
+void
+done(struct cc_usb *cc, int code)
+{
+       cc_usb_close(cc);
+       exit (code);
+}
+
+static int
+ends_with(char *whole, char *suffix)
+{
+       int whole_len = strlen(whole);
+       int suffix_len = strlen(suffix);
+
+       if (suffix_len > whole_len)
+               return 0;
+       return strcmp(whole + whole_len - suffix_len, suffix) == 0;
+}
+
+static int
+starts_with(char *whole, char *prefix)
+{
+       int whole_len = strlen(whole);
+       int prefix_len = strlen(prefix);
+
+       if (prefix_len > whole_len)
+               return 0;
+       return strncmp(whole, prefix, prefix_len) == 0;
+}
+
+static char **
+tok(char *line) {
+       char    **strs = malloc (sizeof (char *)), *str;
+       int     n = 0;
+
+       while ((str = strtok(line, " \t"))) {
+               line = NULL;
+               strs = realloc(strs, (n + 2) * sizeof (char *));
+               strs[n] = strdup(str);
+               n++;
+       }
+       strs[n] = '\0';
+       return strs;
+}
+
+static void
+free_strs(char **strs) {
+       char    *str;
+       int     i;
+
+       for (i = 0; (str = strs[i]) != NULL; i++)
+               free(str);
+       free(strs);
+}
+
+struct flash {
+       struct flash    *next;
+       char            line[512];
+       char            **strs;
+};
+
+static struct flash *
+flash(struct cc_usb *usb)
+{
+       struct flash    *head = NULL, **tail = &head;
+       cc_usb_printf(usb, "f\nv\n");
+       for (;;) {
+               char    line[512];
+               struct flash    *b;
+
+               cc_usb_getline(usb, line, sizeof (line));
+               b = malloc (sizeof (struct flash));
+               strcpy(b->line, line);
+               b->strs = tok(line);
+               b->next = NULL;
+               *tail = b;
+               tail = &b->next;
+               if (strstr(line, "software-version"))
+                       break;
+       }
+       return head;
+}
+
+static void
+free_flash(struct flash *b) {
+       struct flash *n;
+
+       while (b) {
+               n = b->next;
+               free_strs(b->strs);
+               free(b);
+               b = n;
+       }
+}
+
+char **
+find_flash(struct flash *b, char *word0) {
+       int i;
+       for (;b; b = b->next) {
+               if (strstr(b->line, word0))
+                       return b->strs;
+       }
+       return NULL;
+}
+
+int
+do_flash(struct cc_usb *usb, int expected_size) {
+       struct flash *b = flash(usb);
+       char **size = find_flash(b, "Storage size:");
+       char **erase = find_flash(b, "Storage erase unit:");
+
+       if (!size || !erase) {
+               printf("no response\n");
+               free_flash(b);
+               return 0;
+       }
+
+       int actual_size = atoi(size[2]);
+
+       if (actual_size != expected_size) {
+               printf ("weird flash size %d != %d\n", actual_size, expected_size);
+               free_flash(b);
+               return 0;
+       }
+
+       int actual_erase = atoi(erase[3]);
+
+       if (actual_erase != 65536) {
+               printf ("weird erase size %d\n", actual_erase);
+               free_flash(b);
+               return 0;
+       }
+
+       printf ("flash size %d erase block %d\n", actual_size, actual_erase);
+
+       return 1;
+}
+
+int
+main (int argc, char **argv)
+{
+       char                    *device = NULL;
+       char                    *filename;
+       Elf                     *e;
+       unsigned int            s;
+       int                     i;
+       int                     c;
+       int                     tries;
+       struct cc_usb           *cc = NULL;
+       char                    *tty = NULL;
+       int                     success;
+       int                     verbose = 0;
+       int                     ret = 0;
+       int                     expected_size;
+
+       while ((c = getopt_long(argc, argv, "rT:D:c:s:v:", options, NULL)) != -1) {
+               switch (c) {
+               case 'T':
+                       tty = optarg;
+                       break;
+               case 'D':
+                       device = optarg;
+                       break;
+               case 'v':
+                       verbose++;
+                       break;
+               default:
+                       usage(argv[0]);
+                       break;
+               }
+       }
+
+       if (!argv[optind])
+               usage(argv[0]);
+
+       ao_verbose = verbose;
+
+       if (verbose > 1)
+               ccdbg_add_debug(CC_DEBUG_BITBANG);
+
+       if (!tty)
+               tty = cc_usbdevs_find_by_arg(device, "AltosFlash");
+       if (!tty)
+               tty = cc_usbdevs_find_by_arg(device, "TeleMega");
+       if (!tty)
+               tty = getenv("ALTOS_TTY");
+       if (!tty)
+               tty="/dev/ttyACM0";
+
+       cc = cc_usb_open(tty);
+
+       if (!cc)
+               exit(1);
+
+       if (!do_flash(cc, atoi(argv[optind])))
+               ret = 1;
+       done(cc, ret);
+}
diff --git a/ao-tools/ao-test-igniter/.gitignore b/ao-tools/ao-test-igniter/.gitignore
new file mode 100644 (file)
index 0000000..deee445
--- /dev/null
@@ -0,0 +1 @@
+ao-test-igniter
diff --git a/ao-tools/ao-test-igniter/Makefile.am b/ao-tools/ao-test-igniter/Makefile.am
new file mode 100644 (file)
index 0000000..e24ed46
--- /dev/null
@@ -0,0 +1,11 @@
+bin_PROGRAMS=ao-test-igniter
+
+AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+
+ao_test_igniter_DEPENDENCIES = $(top_builddir)/ao-tools/lib/libao-tools.a
+
+ao_test_igniter_LDADD=$(top_builddir)/ao-tools/lib/libao-tools.a $(LIBUSB_LIBS)
+
+ao_test_igniter_SOURCES=ao-test-igniter.c
+
+man_MANS = ao-test-igniter.1
diff --git a/ao-tools/ao-test-igniter/ao-test-igniter.1 b/ao-tools/ao-test-igniter/ao-test-igniter.1
new file mode 100644 (file)
index 0000000..155bd1b
--- /dev/null
@@ -0,0 +1,59 @@
+.\"
+.\" Copyright © 2009 Keith Packard <keithp@keithp.com>
+.\"
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful, but
+.\" WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+.\" General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License along
+.\" with this program; if not, write to the Free Software Foundation, Inc.,
+.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+.\"
+.\"
+.TH AO-LOAD 1 "ao-test-igniter" ""
+.SH NAME
+ao-test-igniter \- test AltOS flight computer igniters
+.SH SYNOPSIS
+.B "ao-test-igniter"
+[\-T \fItty-device\fP]
+[\--tty \fItty-device\fP]
+[\-D \fIaltos-device\fP]
+[\--device \fIaltos-device\fP]
+\fIigniter-name...\fP
+.SH DESCRIPTION
+.I ao-test-igniter
+test the status and then fires the specified igniters on the target device
+.SH OPTIONS
+.TP
+\-T tty-device | --tty tty-device
+This selects which tty device the debugger uses to communicate with
+the target device. The special name 'BITBANG' directs ao-dbg to use
+the cp2103 connection, otherwise this should be a usb serial port
+connected to a suitable cc1111 debug node.
+.TP
+\-D AltOS-device | --device AltOS-device
+Search for a connected device. This requires an argument of one of the
+following forms:
+.IP
+TeleMega:2
+.br
+TeleMega
+.br
+2
+.IP
+Leaving out the product name will cause the tool to select a suitable
+product, leaving out the serial number will cause the tool to match
+one of the available devices.
+.SH USAGE
+.I ao-test-igniter
+opens the target device, lists the available igniter and then fires
+the specified ones. And error occurrs if any of the specified igniters
+is not present or not ready.
+.SH AUTHOR
+Keith Packard
diff --git a/ao-tools/ao-test-igniter/ao-test-igniter.c b/ao-tools/ao-test-igniter/ao-test-igniter.c
new file mode 100644 (file)
index 0000000..6a699fe
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * Copyright © 2014 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <err.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <string.h>
+#include <stdbool.h>
+#include "ao-elf.h"
+#include "ccdbg.h"
+#include "cc-usb.h"
+#include "cc.h"
+#include "ao-verbose.h"
+
+static const struct option options[] = {
+       { .name = "tty", .has_arg = 1, .val = 'T' },
+       { .name = "device", .has_arg = 1, .val = 'D' },
+       { .name = "raw", .has_arg = 0, .val = 'r' },
+       { .name = "verbose", .has_arg = 1, .val = 'v' },
+       { 0, 0, 0, 0},
+};
+
+static void usage(char *program)
+{
+       fprintf(stderr, "usage: %s [--verbose=<verbose>] [--device=<device>] [-tty=<tty>] main|drogue\n", program);
+       exit(1);
+}
+
+void
+done(struct cc_usb *cc, int code)
+{
+/*     cc_usb_printf(cc, "a\n"); */
+       cc_usb_close(cc);
+       exit (code);
+}
+
+static int
+ends_with(char *whole, char *suffix)
+{
+       int whole_len = strlen(whole);
+       int suffix_len = strlen(suffix);
+
+       if (suffix_len > whole_len)
+               return 0;
+       return strcmp(whole + whole_len - suffix_len, suffix) == 0;
+}
+
+static int
+starts_with(char *whole, char *prefix)
+{
+       int whole_len = strlen(whole);
+       int prefix_len = strlen(prefix);
+
+       if (prefix_len > whole_len)
+               return 0;
+       return strncmp(whole, prefix, prefix_len) == 0;
+}
+
+struct igniter {
+       struct igniter  *next;
+       char            name[512];
+       char            status[512];
+};
+
+static struct igniter *
+igniters(struct cc_usb *usb)
+{
+       struct igniter  *head = NULL, **tail = &head;
+       cc_usb_printf(usb, "t\nv\n");
+       for (;;) {
+               char    line[512];
+               char    name[512];
+               char    status[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));
+                       strcpy(i->name, name);
+                       strcpy(i->status, status);
+                       i->next = NULL;
+                       *tail = i;
+                       tail = &i->next;
+               }
+       }
+       return head;
+}
+
+static void
+free_igniters(struct igniter *i) {
+       struct igniter *n;
+
+       while (i) {
+               n = i->next;
+               free(i);
+               i = n;
+       }
+}
+
+static struct igniter *
+find_igniter(struct igniter *i, char *name)
+{
+       for (; i; i = i->next)
+               if (strcmp(i->name, name) == 0)
+                       return i;
+}
+
+static int
+do_igniter(struct cc_usb *usb, char *name)
+{
+       struct igniter  *all = igniters(usb);
+       struct igniter  *this = find_igniter(all, name);
+       if (!this) {
+               struct igniter  *i;
+               printf("no igniter %s found in");
+               for (i = all; i; i = i->next)
+                       printf(" %s", i->name);
+               printf("\n");
+               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);
+               return 0;
+       }
+       cc_usb_printf(usb, "i DoIt %s\n", this->name);
+       cc_usb_sync(usb);
+       free_igniters(all);
+       usleep(200000);
+       return 1;
+}
+
+int
+main (int argc, char **argv)
+{
+       char                    *device = NULL;
+       char                    *filename;
+       Elf                     *e;
+       unsigned int            s;
+       int                     i;
+       int                     c;
+       int                     tries;
+       struct cc_usb           *cc = NULL;
+       char                    *tty = NULL;
+       int                     success;
+       int                     verbose = 0;
+       int                     ret = 0;
+
+       while ((c = getopt_long(argc, argv, "rT:D:c:s:v:", options, NULL)) != -1) {
+               switch (c) {
+               case 'T':
+                       tty = optarg;
+                       break;
+               case 'D':
+                       device = optarg;
+                       break;
+               case 'v':
+                       verbose++;
+                       break;
+               default:
+                       usage(argv[0]);
+                       break;
+               }
+       }
+
+       ao_verbose = verbose;
+
+       if (verbose > 1)
+               ccdbg_add_debug(CC_DEBUG_BITBANG);
+
+       printf ("device %s\n", device);
+       if (!tty)
+               tty = cc_usbdevs_find_by_arg(device, "TeleMega-v1.0");
+       if (!tty)
+               tty = cc_usbdevs_find_by_arg(device, "TeleMetrum-v2.0");
+       if (!tty)
+               tty = cc_usbdevs_find_by_arg(device, "TeleMini-v2.0");
+       if (!tty)
+               tty = cc_usbdevs_find_by_arg(device, "EasyMega-v1.0");
+       if (!tty)
+               tty = cc_usbdevs_find_by_arg(device, "EasyMetrum-v1.0");
+       if (!tty)
+               tty = cc_usbdevs_find_by_arg(device, "EasyMini-v1.0");
+       if (!tty)
+               tty = getenv("ALTOS_TTY");
+       if (!tty)
+               tty="/dev/ttyACM0";
+
+       cc = cc_usb_open(tty);
+
+       if (!cc)
+               exit(1);
+
+       for (i = optind; i < argc; i++) {
+               char    *name = argv[i];
+
+               if (!do_igniter(cc, name))
+                       ret++;
+       }
+       done(cc, ret);
+}
index 8d6876a064422a202fd7d3de99ea6ecd3cc4174e..b82dd778bc3969140f2270b104fa07ae3a0663ce 100644 (file)
@@ -108,6 +108,29 @@ cc_altitude_to_pressure(double altitude)
    return pressure;
 }
 
+double
+cc_altitude_to_temperature(double altitude)
+{
+
+   double base_temperature = LAYER0_BASE_TEMPERATURE;
+   double temperature;
+
+   int layer_number; /* identifies layer in the atmosphere */
+   double delta_z; /* difference between two altitudes */
+
+   /* calculate the base temperature for the atmospheric layer
+      associated with the inputted altitude */
+   for(layer_number = 0; layer_number < NUMBER_OF_LAYERS - 1 && altitude > base_altitude[layer_number + 1]; layer_number++) {
+      delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number];
+      base_temperature += delta_z * lapse_rate[layer_number];
+   }
+
+   /* calculate the pressure at the inputted altitude */
+   delta_z = altitude - base_altitude[layer_number];
+   temperature = base_temperature + lapse_rate[layer_number] * delta_z;
+
+   return temperature - 273.15;
+}
 
 /* outputs the altitude associated with the given pressure. the altitude
    returned is measured with respect to the mean sea level */
index 88da7f03febfc82f43f9ba05c7db608806bd2ecc..45c10dcb01d636731115927273c6752af6be7a64 100644 (file)
@@ -89,4 +89,3 @@ cc_telemetry_unparse(const union ao_telemetry_all *telemetry, char output_line[C
                p += 2;
        }
 }
-               
index c07f8cd07350f56db32e423d658eae6b315485c1..bff4b2c9992cea601d785cfa08dbac6fc99e44e0 100644 (file)
@@ -346,6 +346,143 @@ struct ao_log_mega {
        } u;
 };
 
+struct ao_log_metrum {
+       char                    type;                   /* 0 */
+       uint8_t                 csum;                   /* 1 */
+       uint16_t                tick;                   /* 2 */
+       union {                                         /* 4 */
+               /* AO_LOG_FLIGHT */
+               struct {
+                       uint16_t        flight;         /* 4 */
+                       int16_t         ground_accel;   /* 6 */
+                       uint32_t        ground_pres;    /* 8 */
+                       uint32_t        ground_temp;    /* 12 */
+               } flight;       /* 16 */
+               /* AO_LOG_STATE */
+               struct {
+                       uint16_t        state;          /* 4 */
+                       uint16_t        reason;         /* 6 */
+               } state;        /* 8 */
+               /* AO_LOG_SENSOR */
+               struct {
+                       uint32_t        pres;           /* 4 */
+                       uint32_t        temp;           /* 8 */
+                       int16_t         accel;          /* 12 */
+               } sensor;       /* 14 */
+               /* AO_LOG_TEMP_VOLT */
+               struct {
+                       int16_t         v_batt;         /* 4 */
+                       int16_t         sense_a;        /* 6 */
+                       int16_t         sense_m;        /* 8 */
+               } volt;         /* 10 */
+               /* AO_LOG_GPS_POS */
+               struct {
+                       int32_t         latitude;       /* 4 */
+                       int32_t         longitude;      /* 8 */
+                       uint16_t        altitude_low;   /* 12 */
+                       int16_t         altitude_high;  /* 14 */
+               } gps;          /* 16 */
+               /* AO_LOG_GPS_TIME */
+               struct {
+                       uint8_t         hour;           /* 4 */
+                       uint8_t         minute;         /* 5 */
+                       uint8_t         second;         /* 6 */
+                       uint8_t         flags;          /* 7 */
+                       uint8_t         year;           /* 8 */
+                       uint8_t         month;          /* 9 */
+                       uint8_t         day;            /* 10 */
+                       uint8_t         pdop;           /* 11 */
+               } gps_time;     /* 12 */
+               /* AO_LOG_GPS_SAT (up to three packets) */
+               struct {
+                       uint8_t channels;               /* 4 */
+                       uint8_t more;                   /* 5 */
+                       struct {
+                               uint8_t svid;
+                               uint8_t c_n;
+                       } sats[4];                      /* 6 */
+               } gps_sat;                              /* 14 */
+               uint8_t         raw[12];                /* 4 */
+       } u;    /* 16 */
+};
+
+struct ao_log_mini {
+       char            type;                           /* 0 */
+       uint8_t         csum;                           /* 1 */
+       uint16_t        tick;                           /* 2 */
+       union {                                         /* 4 */
+               /* AO_LOG_FLIGHT */
+               struct {
+                       uint16_t        flight;         /* 4 */
+                       uint16_t        r6;
+                       uint32_t        ground_pres;    /* 8 */
+               } flight;
+               /* AO_LOG_STATE */
+               struct {
+                       uint16_t        state;          /* 4 */
+                       uint16_t        reason;         /* 6 */
+               } state;
+               /* AO_LOG_SENSOR */
+               struct {
+                       uint8_t         pres[3];        /* 4 */
+                       uint8_t         temp[3];        /* 7 */
+                       int16_t         sense_a;        /* 10 */
+                       int16_t         sense_m;        /* 12 */
+                       int16_t         v_batt;         /* 14 */
+               } sensor;                               /* 16 */
+       } u;                                            /* 16 */
+};                                                     /* 16 */
+
+#define ao_log_pack24(dst,value) do {          \
+               (dst)[0] = (value);             \
+               (dst)[1] = (value) >> 8;        \
+               (dst)[2] = (value) >> 16;       \
+       } while (0)
+
+struct ao_log_gps {
+       char                    type;                   /* 0 */
+       uint8_t                 csum;                   /* 1 */
+       uint16_t                tick;                   /* 2 */
+       union {                                         /* 4 */
+               /* AO_LOG_FLIGHT */
+               struct {
+                       uint16_t        flight;                 /* 4 */
+                       int16_t         start_altitude;         /* 6 */
+                       int32_t         start_latitude;         /* 8 */
+                       int32_t         start_longitude;        /* 12 */
+               } flight;                                       /* 16 */
+               /* AO_LOG_GPS_TIME */
+               struct {
+                       int32_t         latitude;       /* 4 */
+                       int32_t         longitude;      /* 8 */
+                       uint16_t        altitude_low;   /* 12 */
+                       uint8_t         hour;           /* 14 */
+                       uint8_t         minute;         /* 15 */
+                       uint8_t         second;         /* 16 */
+                       uint8_t         flags;          /* 17 */
+                       uint8_t         year;           /* 18 */
+                       uint8_t         month;          /* 19 */
+                       uint8_t         day;            /* 20 */
+                       uint8_t         course;         /* 21 */
+                       uint16_t        ground_speed;   /* 22 */
+                       int16_t         climb_rate;     /* 24 */
+                       uint8_t         pdop;           /* 26 */
+                       uint8_t         hdop;           /* 27 */
+                       uint8_t         vdop;           /* 28 */
+                       uint8_t         mode;           /* 29 */
+                       int16_t         altitude_high;  /* 30 */
+               } gps;  /* 31 */
+               /* AO_LOG_GPS_SAT */
+               struct {
+                       uint16_t        channels;       /* 4 */
+                       struct {
+                               uint8_t svid;
+                               uint8_t c_n;
+                       } sats[12];                     /* 6 */
+               } gps_sat;                              /* 30 */
+       } u;
+};
+
 #define AO_CONFIG_CONFIG               1
 #define AO_CONFIG_MAIN                 2
 #define AO_CONFIG_APOGEE               3
@@ -380,9 +517,30 @@ struct ao_log_mega {
 #define AO_LOG_GPS_ALT         'H'
 #define AO_LOG_GPS_SAT         'V'
 #define AO_LOG_GPS_DATE                'Y'
+#define AO_LOG_GPS_POS         'P'
 
 #define AO_LOG_CONFIG          'c'
 
+#define AO_GPS_NUM_SAT_MASK    (0xf << 0)
+#define AO_GPS_NUM_SAT_SHIFT   (0)
+
+#define AO_GPS_VALID           (1 << 4)
+#define AO_GPS_RUNNING         (1 << 5)
+#define AO_GPS_DATE_VALID      (1 << 6)
+#define AO_GPS_COURSE_VALID    (1 << 7)
+
+#define AO_LOG_FORMAT_UNKNOWN          0       /* unknown; altosui will have to guess */
+#define AO_LOG_FORMAT_FULL             1       /* 8 byte typed log records */
+#define AO_LOG_FORMAT_TINY             2       /* two byte state/baro records */
+#define AO_LOG_FORMAT_TELEMETRY                3       /* 32 byte ao_telemetry records */
+#define AO_LOG_FORMAT_TELESCIENCE      4       /* 32 byte typed telescience records */
+#define AO_LOG_FORMAT_TELEMEGA         5       /* 32 byte typed telemega records */
+#define AO_LOG_FORMAT_EASYMINI         6       /* 16-byte MS5607 baro only, 3.0V supply */
+#define AO_LOG_FORMAT_TELEMETRUM       7       /* 16-byte typed telemetrum records */
+#define AO_LOG_FORMAT_TELEMINI         8       /* 16-byte MS5607 baro only, 3.3V supply */
+#define AO_LOG_FORMAT_TELEGPS          9       /* 32 byte telegps records */
+#define AO_LOG_FORMAT_NONE             127     /* No log at all */
+
 int
 cc_mega_parse(const char *input_line, struct ao_log_mega *l);
 
@@ -398,6 +556,9 @@ cc_pressure_to_altitude(double pressure);
 double
 cc_altitude_to_pressure(double altitude);
 
+double
+cc_altitude_to_temperature(double altitude);
+
 double
 cc_barometer_to_pressure(double baro);
 
index fdae9b6fdce54d559d37ccbfa3c0b14d86395ded..a6a9d3c5234f6537af8c8e1d783b6fc1e0ff5f85 100644 (file)
@@ -18,7 +18,7 @@ dnl
 dnl Process this file with autoconf to create configure.
 
 AC_PREREQ(2.57)
-AC_INIT([altos], 1.4.1)
+AC_INIT([altos], 1.5)
 AC_CONFIG_SRCDIR([src/kernel/ao.h])
 AM_INIT_AUTOMAKE([foreign dist-bzip2])
 AM_MAINTAINER_MODE
@@ -29,8 +29,8 @@ AC_SUBST(VERSION_DASH)
 dnl ==========================================================================
 dnl Java library versions
 
-ALTOSUILIB_VERSION=2
-ALTOSLIB_VERSION=4
+ALTOSUILIB_VERSION=3
+ALTOSLIB_VERSION=5
 
 AC_SUBST(ALTOSLIB_VERSION)
 AC_DEFINE(ALTOSLIB_VERSION,$ALTOSLIB_VERSION,[Version of the AltosLib package])
@@ -459,7 +459,7 @@ xauto)
        xx86_64|xi*86)
                save_CFLAGS="$CFLAGS"
                save_LIBS="$LIBS"
-               LIBS="-lbluetooth"
+               LIBS="-ldl"
                CFLAGS="-m64"
                AC_MSG_CHECKING([if ]$CC[ ]$CFLAGS[ can link programs])
                AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
@@ -534,6 +534,10 @@ ao-tools/ao-dump-up/Makefile
 ao-tools/ao-elftohex/Makefile
 ao-tools/ao-usbload/Makefile
 ao-tools/ao-flash/Makefile
+ao-tools/ao-test-igniter/Makefile
+ao-tools/ao-test-baro/Makefile
+ao-tools/ao-test-flash/Makefile
+ao-tools/ao-cal-accel/Makefile
 ao-utils/Makefile
 src/Version
 ])
index c39450c7ddd100ff4de458beb850efd565292b06..60c63f63524d156f08c2f927ac06493ff202bf17 100644 (file)
@@ -16,7 +16,8 @@ RELNOTES=\
        release-notes-1.3.1.html \
        release-notes-1.3.2.html \
        release-notes-1.4.html \
-       release-notes-1.4.1.html
+       release-notes-1.4.1.html \
+       release-notes-1.5.html
 
 PICTURES=\
        altosui.png \
@@ -61,12 +62,13 @@ SVG=\
        easymini.svg \
        telemega.svg \
        telemetrum.svg \
-       telemini.svg
+       telemini.svg \
+       easymega.svg
 
 RELNOTES_XSL=$(RELNOTES:.html=.xsl)
 HTML=altusmetrum.html altos.html telemetry.html companion.html micropeak.html telegps.html $(RELNOTES)
 PDF=altusmetrum.pdf altos.pdf telemetry.pdf companion.pdf micropeak.pdf telegps.pdf \
-       telemetrum-outline.pdf telemega-outline.pdf easymini-outline.pdf
+       telemetrum-outline.pdf telemega-outline.pdf easymini-outline.pdf easymega-outline.pdf
 HTMLSTYLE=/usr/share/xml/docbook/stylesheet/docbook-xsl/html/docbook.xsl
 FOSTYLE=xorg-fo.xsl
 TEMPLATES=titlepage.templates.xsl
index c68bbac9040b7847fbbdc03688dffad616efd885..0785f65a9a8219ebaae8d4e3ffe553a7234cbd3c 100644 (file)
       </para>
     </legalnotice>
     <revhistory>
+      <revision>
+       <revnumber>1.5</revnumber>
+       <date>6 September 2014</date>
+       <revremark>
+         Major release adding EasyMega support.
+       </revremark>
+      </revision>
       <revision>
        <revnumber>1.4.1</revnumber>
-       <date>24 June 2014</date>
+       <date>20 June 2014</date>
        <revremark>
          Minor release fixing some installation bugs.
        </revremark>
@@ -202,6 +209,11 @@ NAR #88757, TRA #12200
       EasyMini is a dual-deploy altimeter with logging and built-in
       USB data download.
     </para>
+    <para>
+      EasyMega is essentially a TeleMega board with the GPS receiver
+      and telemetry transmitter removed. It offers the same 6 pyro
+      channels and integrated gyroscopes for staging/air-start inhibit.
+    </para>
     <para>
       TeleDongle was our first ground station, providing a USB to RF
       interfaces for communicating with the altimeters. Combined with
@@ -231,7 +243,7 @@ NAR #88757, TRA #12200
       “starter kit” is to charge the battery.
     </para>
     <para>
-      For TeleMetrum and TeleMega, the battery can be charged by plugging it into the
+      For TeleMetrum, TeleMega and EasyMega, the battery can be charged by plugging it into the
       corresponding socket of the device and then using the USB
       cable to plug the flight computer into your computer's USB socket. The
       on-board circuitry will charge the battery whenever it is plugged
@@ -252,7 +264,7 @@ NAR #88757, TRA #12200
       deeply discharged battery.
     </para>
     <para>
-      TeleMetrum v2.0 and TeleMega use a higher power battery charger,
+      TeleMetrum v2.0, TeleMega and EasyMega use a higher power battery charger,
       allowing them to charge the battery while running the board at
       maximum power. When the battery is charging, or when the board
       is consuming a lot of power, the red LED will be lit. When the
@@ -456,7 +468,7 @@ NAR #88757, TRA #12200
          EasyMini and TeleMini v2 are designed to use either a
          lithium polymer battery or any other battery producing
          between 4 and 12 volts, such as a rectangular 9V
-         battery. TeleMega and TeleMetrum are not designed for this,
+         battery. TeleMega, EasyMega and TeleMetrum are not designed for this,
          and must only be powered by a lithium polymer battery. Find
          instructions on how to use other batteries in the EasyMini
          and TeleMini sections below.
@@ -574,6 +586,16 @@ NAR #88757, TRA #12200
              <entry>40mW</entry>
              <entry>3.7V</entry>
            </row>
+           <row>
+             <entry>EasyMega <?linebreak?>v1.0</entry>
+             <entry><para>MS5607 30km (100k')</para></entry>
+             <entry><para>MMA6555 102g</para></entry>
+             <entry>-</entry>
+             <entry><para>MPU6000 HMC5883</para></entry>
+             <entry>8MB</entry>
+             <entry>-</entry>
+             <entry>3.7V</entry>
+           </row>
          </tbody>
        </tgroup>
       </table>
@@ -682,6 +704,25 @@ NAR #88757, TRA #12200
              <entry>3¼ inch (8.26cm)</entry>
              <entry>38mm coupler</entry>
            </row>
+           <row>
+             <entry>EasyMega</entry>
+             <entry><para>
+               Debug<?linebreak?>
+               Companion<?linebreak?>
+               USB<?linebreak?>
+               Battery
+             </para></entry>
+             <entry><para>
+               Apogee pyro <?linebreak?>
+               Main pyro<?linebreak?>
+               Pyro A-D<?linebreak?>
+               Switch<?linebreak?>
+               Pyro battery
+             </para></entry>
+             <entry>1¼ inch (3.18cm)</entry>
+             <entry>2¼ inch (5.62cm)</entry>
+             <entry>38mm coupler</entry>
+           </row>
          </tbody>
        </tgroup>
       </table>
@@ -1361,6 +1402,178 @@ NAR #88757, TRA #12200
        </para>
       </section>
     </section>
+    <section>
+      <title>EasyMega</title>
+      <informalfigure>
+       <mediaobject>
+         <imageobject>
+           <imagedata fileref="easymega-v1.0-top.jpg" width="4.5in" scalefit="1"/>
+         </imageobject>
+       </mediaobject>
+      </informalfigure>
+      <para>
+       EasyMega is a 1¼ inch by 2¼ inch circuit board. It was
+       designed to easily fit in a 38mm coupler. Like TeleMetrum,
+       EasyMega has an accelerometer and so it must be mounted so that
+       the board is aligned with the flight axis. It can be mounted
+       either antenna up or down.
+      </para>
+      <section>
+       <title>EasyMega Screw Terminals</title>
+       <para>
+         EasyMega has two sets of nine screw terminals on the end of
+         the board opposite the telemetry antenna. They are as follows:
+       </para>
+       <table frame='all'>
+         <title>EasyMega Screw Terminals</title>
+         <?dbfo keep-together="always"?>
+         <tgroup cols='3' align='center' colsep='1' rowsep='1'>
+           <colspec align='center' colwidth='*' colname='Pin #'/>
+           <colspec align='center' colwidth='2*' colname='Pin Name'/>
+           <colspec align='left' colwidth='5*' colname='Description'/>
+           <thead>
+             <row>
+               <entry align='center'>Terminal #</entry>
+               <entry align='center'>Terminal Name</entry>
+               <entry align='center'>Description</entry>
+             </row>
+           </thead>
+           <tbody>
+             <row>
+               <entry>Top 1</entry>
+               <entry>Switch Input</entry>
+               <entry>Switch connection to positive battery terminal</entry>
+             </row>
+             <row>
+               <entry>Top 2</entry>
+               <entry>Switch Output</entry>
+               <entry>Switch connection to flight computer</entry>
+             </row>
+             <row>
+               <entry>Top 3</entry>
+               <entry>GND</entry>
+               <entry>Ground connection for use with external active switch</entry>
+             </row>
+             <row>
+               <entry>Top 4</entry>
+               <entry>Main -</entry>
+               <entry>Main pyro channel connection to pyro circuit</entry>
+             </row>
+             <row>
+               <entry>Top 5</entry>
+               <entry>Main +</entry>
+               <entry>Main pyro channel common connection to battery +</entry>
+             </row>
+             <row>
+               <entry>Top 6</entry>
+               <entry>Apogee -</entry>
+               <entry>Apogee pyro channel connection to pyro circuit</entry>
+             </row>
+             <row>
+               <entry>Top 7</entry>
+               <entry>Apogee +</entry>
+               <entry>Apogee pyro channel common connection to battery +</entry>
+             </row>
+             <row>
+               <entry>Top 8</entry>
+               <entry>D -</entry>
+               <entry>D pyro channel connection to pyro circuit</entry>
+             </row>
+             <row>
+               <entry>Top 9</entry>
+               <entry>D +</entry>
+               <entry>D pyro channel common connection to battery +</entry>
+             </row>
+             <row>
+               <entry>Bottom 1</entry>
+               <entry>GND</entry>
+               <entry>Ground connection for negative pyro battery terminal</entry>
+             </row>
+             <row>
+               <entry>Bottom 2</entry>
+               <entry>Pyro</entry>
+               <entry>Positive pyro battery terminal</entry>
+             </row>
+             <row>
+               <entry>Bottom 3</entry>
+               <entry>Lipo</entry>
+               <entry>
+                 Power switch output. Use to connect main battery to
+                 pyro battery input
+               </entry>
+             </row>
+             <row>
+               <entry>Bottom 4</entry>
+               <entry>A -</entry>
+               <entry>A pyro channel connection to pyro circuit</entry>
+             </row>
+             <row>
+               <entry>Bottom 5</entry>
+               <entry>A +</entry>
+               <entry>A pyro channel common connection to battery +</entry>
+             </row>
+             <row>
+               <entry>Bottom 6</entry>
+               <entry>B -</entry>
+               <entry>B pyro channel connection to pyro circuit</entry>
+             </row>
+             <row>
+               <entry>Bottom 7</entry>
+               <entry>B +</entry>
+               <entry>B pyro channel common connection to battery +</entry>
+             </row>
+             <row>
+               <entry>Bottom 8</entry>
+               <entry>C -</entry>
+               <entry>C pyro channel connection to pyro circuit</entry>
+             </row>
+             <row>
+               <entry>Bottom 9</entry>
+               <entry>C +</entry>
+               <entry>C pyro channel common connection to battery +</entry>
+             </row>
+           </tbody>
+         </tgroup>
+       </table>
+      </section>
+      <section>
+       <title>Using a Separate Pyro Battery with EasyMega</title>
+       <para>
+         EasyMega provides explicit support for an external pyro
+         battery. All that is required is to remove the jumper
+         between the lipo terminal (Bottom 3) and the pyro terminal
+         (Bottom 2). Then hook the negative pyro battery terminal to ground
+         (Bottom 1) and the positive pyro battery to the pyro battery
+         input (Bottom 2). You can then use the existing pyro screw
+         terminals to hook up all of the pyro charges.
+       </para>
+      </section>
+      <section>
+       <title>Using Only One Battery With EasyMega</title>
+       <para>
+         Because EasyMega has built-in support for a separate pyro
+         battery, if you want to fly with just one battery running
+         both the computer and firing the charges, you need to
+         connect the flight computer battery to the pyro
+         circuit. EasyMega has two screw terminals for this—hook a
+         wire from the Lipo terminal (Bottom 3) to the Pyro terminal
+         (Bottom 2).
+       </para>
+      </section>
+      <section>
+       <title>Using an Active Switch with EasyMega</title>
+       <para>
+         As explained above, an external active switch requires three
+         connections, one to the positive battery terminal, one to
+         the flight computer positive input and one to ground.
+       </para>
+       <para>
+         The positive battery terminal is available on Top terminal
+         1, the positive flight computer input is on Top terminal
+         2. Ground is on Top terminal 3.
+       </para>
+      </section>
+    </section>
     <section>
       <title>Flight Data Recording</title>
       <para>
@@ -1431,6 +1644,12 @@ NAR #88757, TRA #12200
              <entry>8MB</entry>
              <entry>40</entry>
            </row>
+           <row>
+             <entry>EasyMega</entry>
+             <entry>32</entry>
+             <entry>8MB</entry>
+             <entry>40</entry>
+           </row>
          </tbody>
        </tgroup>
       </table>
@@ -1444,7 +1663,7 @@ NAR #88757, TRA #12200
        Configuration data is also stored in the flash memory on
        TeleMetrum v1.x, TeleMini and EasyMini. This consumes 64kB
        of flash space.  This configuration space is not available
-       for storing flight log data. TeleMetrum v2.0 and TeleMega
+       for storing flight log data. TeleMetrum v2.0, TeleMega and EasyMega
        store configuration data in a bit of eeprom available within
        the processor chip, leaving that space available in flash for
        more flight data.
@@ -1538,7 +1757,7 @@ NAR #88757, TRA #12200
         The AltOS firmware build for the altimeters has two
         fundamental modes, “idle” and “flight”.  Which of these modes
         the firmware operates in is determined at start up time. For
-        TeleMetrum and TeleMega, which have accelerometers, the mode is 
+        TeleMetrum, TeleMega and EasyMega, which have accelerometers, the mode is 
        controlled by the orientation of the
         rocket (well, actually the board, of course...) at the time
         power is switched on.  If the rocket is “nose up”, then
@@ -1803,7 +2022,8 @@ NAR #88757, TRA #12200
        and beep out the maximum height until turned off.
       </para>
       <para>
-        One “neat trick” of particular value when TeleMetrum or TeleMega are used with 
+        One “neat trick” of particular value when TeleMetrum, TeleMega
+       or EasyMega are used with 
         very large air-frames, is that you can power the board up while the 
         rocket is horizontal, such that it comes up in idle mode.  Then you can
         raise the air-frame to launch position, and issue a 'reset' command 
@@ -2049,6 +2269,15 @@ NAR #88757, TRA #12200
        isn't displaying position information, it's possible that this
        is the cause.
       </para>
+      <para>
+       APRS packets include an SSID (Secondary Station Identifier)
+       field that allows one operator to have multiple
+       transmitters. AltOS allows you to set this to a single digit
+       from 0 to 9, allowing you to fly multiple transmitters at the
+       same time while keeping the identify of each one separate in
+       the receiver. By default, the SSID is set to the last digit of
+       the device serial number.
+      </para>
       <para>
        The APRS packet format includes a comment field that can have
        arbitrary text in it. AltOS uses this to send status
@@ -2095,15 +2324,20 @@ NAR #88757, TRA #12200
              <entry>M3.7</entry>
              <entry>Main Igniter Voltage</entry>
            </row>
+           <row>
+             <entry>6</entry>
+             <entry>1286</entry>
+             <entry>Device Serial Number</entry>
+           </row>
          </tbody>
        </tgroup>
       </table>
       <para>
        Here's an example of an APRS comment showing GPS lock with 6
        satellites in view, a primary battery at 4.0V, and
-       apogee and main igniters both at 3.7V.
+       apogee and main igniters both at 3.7V from device 1286.
        <screen>
-         L6 B4.0 A3.7 M3.7
+         L6 B4.0 A3.7 M3.7 1286
        </screen>
       </para>
       <para>
@@ -2166,6 +2400,18 @@ NAR #88757, TRA #12200
          mode.
        </para>
       </section>
+      <section>
+       <title>Telemetry baud rate</title>
+       <para>
+         This sets the modulation bit rate for data transmission for
+         both telemetry and packet link mode. Lower bit
+         rates will increase range while reducing the amount of data
+         that can be sent and increasing battery consumption. All
+         telemetry is done using a rate 1/2 constraint 4 convolution
+         code, so the actual data transmission rate is 1/2 of the
+         modulation bit rate specified here.
+       </para>
+      </section>
       <section>
        <title>APRS Interval</title>
        <para>
@@ -2176,6 +2422,14 @@ NAR #88757, TRA #12200
          recommend sending packets no more than once every 5 seconds.
        </para>
       </section>
+      <section>
+       <title>APRS SSID</title>
+       <para>
+         This selects the SSID reported in APRS packets. By default,
+         it is set to the last digit of the serial number, but you
+         can change this to any value from 0 to 9.
+       </para>
+      </section>
       <section>
         <title>Apogee Delay</title>
         <para>
@@ -2260,7 +2514,7 @@ NAR #88757, TRA #12200
       <section>
        <title>Pad Orientation</title>
        <para>
-         TeleMetrum and TeleMega measure acceleration along the axis
+         TeleMetrum, TeleMega and EasyMega measure acceleration along the axis
          of the board. Which way the board is oriented affects the
          sign of the acceleration value. Instead of trying to guess
          which way the board is mounted in the air frame, the
@@ -2275,7 +2529,7 @@ NAR #88757, TRA #12200
        <title>Configurable Pyro Channels</title>
        <para>
          In addition to the usual Apogee and Main pyro channels,
-         TeleMega has four additional channels that can be configured
+         TeleMega and EasyMega have four additional channels that can be configured
          to activate when various flight conditions are
          satisfied. You can select as many conditions as necessary;
          all of them must be met in order to activate the
@@ -2312,7 +2566,7 @@ NAR #88757, TRA #12200
          </listitem>
          <listitem>
            <para>
-             Orientation. TeleMega contains a 3-axis gyroscope and
+             Orientation. TeleMega and EasyMega contain a 3-axis gyroscope and
              accelerometer which is used to measure the current
              angle. Note that this angle is not the change in angle
              from the launch pad, but rather absolute relative to
@@ -3137,6 +3391,18 @@ NAR #88757, TRA #12200
          at all.
        </para>
       </section>
+      <section>
+       <title>Telemetry baud rate</title>
+       <para>
+         This sets the modulation bit rate for data transmission for
+         both telemetry and packet link mode. Lower bit
+         rates will increase range while reducing the amount of data
+         that can be sent and increasing battery consumption. All
+         telemetry is done using a rate 1/2 constraint 4 convolution
+         code, so the actual data transmission rate is 1/2 of the
+         modulation bit rate specified here.
+       </para>
+      </section>
       <section>
        <title>APRS Interval</title>
        <para>
@@ -3149,6 +3415,14 @@ NAR #88757, TRA #12200
          sending any other telemetry during that time.
        </para>
       </section>
+      <section>
+       <title>APRS SSID</title>
+       <para>
+         Which SSID to report in APRS packets. By default, this is
+         set to the last digit of the serial number, but can be
+         configured to any value from 0 to 9.
+       </para>
+      </section>
       <section>
         <title>Callsign</title>
         <para>
@@ -3211,8 +3485,8 @@ NAR #88757, TRA #12200
       <section>
         <title>Pad Orientation</title>
        <para>
-         Because they include accelerometers, TeleMetrum and
-         TeleMega are sensitive to the orientation of the board. By
+         Because they include accelerometers, TeleMetrum,
+         TeleMega and EasyMega are sensitive to the orientation of the board. By
          default, they expect the antenna end to point forward. This
          parameter allows that default to be changed, permitting the
          board to be mounted with the antenna pointing aft instead.
@@ -3261,7 +3535,7 @@ NAR #88757, TRA #12200
        </informalfigure>
        <para>
          This opens a separate window to configure the additional
-         pyro channels available on TeleMega.  One column is
+         pyro channels available on TeleMega and EasyMega.  One column is
          presented for each channel. Each row represents a single
          parameter, if enabled the parameter must meet the specified
          test for the pyro channel to be fired. See the Pyro Channels
@@ -3409,7 +3683,7 @@ NAR #88757, TRA #12200
        </mediaobject>
       </informalfigure>
       <para>
-        Select this button and then select a TeleDongle Device from the list provided.
+        Select this button and then select a TeleDongle or TeleBT Device from the list provided.
       </para>
       <para>
         The first few lines of the dialog provide information about the
@@ -3418,9 +3692,9 @@ NAR #88757, TRA #12200
         individual configuration entries.
       </para>
       <para>
-       Note that the TeleDongle itself doesn't save any configuration
+       Note that TeleDongle and TeleBT don't save any configuration
        data, the settings here are recorded on the local machine in
-       the Java preferences database. Moving the TeleDongle to
+       the Java preferences database. Moving the device to
        another machine, or using a different user account on the same
        machine will cause settings made here to have no effect.
       </para>
@@ -3472,15 +3746,23 @@ NAR #88757, TRA #12200
         </para>
       </section>
       <section>
-        <title>Radio Calibration</title>
+        <title>RF Calibration</title>
         <para>
           The radios in every Altus Metrum device are calibrated at the
           factory to ensure that they transmit and receive on the
-          specified frequency.  To change a TeleDongle's calibration, 
+          specified frequency.  To change a TeleDongle or TeleBT's calibration, 
          you must reprogram the unit completely, so this entry simply
          shows the current value and doesn't allow any changes.
         </para>
       </section>
+      <section>
+        <title>Telemetry Rate</title>
+        <para>
+          This lets you match the telemetry and packet link rate from
+          the transmitter. If they don't match, the device won't
+          receive any data.
+        </para>
+      </section>
     </section>
     <section>
       <title>Flash Image</title>
@@ -3488,7 +3770,7 @@ NAR #88757, TRA #12200
         This reprograms Altus Metrum devices with new
         firmware. TeleMetrum v1.x, TeleDongle, TeleMini and TeleBT are
         all reprogrammed by using another similar unit as a
-        programming dongle (pair programming). TeleMega, TeleMetrum v2
+        programming dongle (pair programming). TeleMega, EasyMega, TeleMetrum v2
         and EasyMini are all programmed directly over their USB ports
         (self programming).  Please read the directions for flashing
         devices in the Updating Device Firmware chapter below.
@@ -3540,9 +3822,9 @@ NAR #88757, TRA #12200
       <para>
        This listens for telemetry packets on all of the configured
        frequencies, displaying information about each device it
-       receives a packet from. You can select which of the three
-       telemetry formats should be tried; by default, it only listens
-       for the standard telemetry packets used in v1.0 and later
+       receives a packet from. You can select which of the baud rates
+       and telemetry formats should be tried; by default, it only listens
+       at 38400 baud with the standard telemetry format used in v1.0 and later
        firmware.
       </para>
     </section>
@@ -3825,12 +4107,12 @@ NAR #88757, TRA #12200
           In the rocket itself, you just need a flight computer and
           a single-cell, 3.7 volt nominal Li-Po rechargeable battery.  An 
          850mAh battery weighs less than a 9V alkaline battery, and will 
-         run a TeleMetrum or TeleMega for hours.
+         run a TeleMetrum, TeleMega or EasyMega for hours.
          A 110mAh battery weighs less than a triple A battery and is a good
-         choice for use with TeleMini.
+         choice for use with TeleMini or EasyMini.
         </para>
         <para>
-          By default, we ship flight computers with a simple wire antenna.  
+          By default, we ship TeleMini, TeleMetrum and TeleMega flight computers with a simple wire antenna.  
          If your electronics bay or the air-frame it resides within is made 
          of carbon fiber, which is opaque to RF signals, you may prefer to 
          install an SMA connector so that you can run a coaxial cable to an 
@@ -3884,8 +4166,8 @@ NAR #88757, TRA #12200
           if the rocket is hiding in sage brush or a tree, or if the last GPS position
           doesn't get you close enough because the rocket dropped into a canyon, or
           the wind is blowing it across a dry lake bed, or something like that...  Keith
-          currently uses a Yaesu VX-7R, Bdale has a Baofung UV-5R
-         which isn't as nice, but was a whole lot cheaper.
+          currently uses a Yaesu FT1D, Bdale has a Yaesu VX-7R, which
+         is a nicer radio in most ways but doesn't support APRS.
         </para>
         <para>
           So, to recap, on the ground the hardware you'll need includes:
@@ -3951,14 +4233,10 @@ NAR #88757, TRA #12200
       </section>
       <section>
         <title>Future Plans</title>
-       <para>
-         We've designed a simple GPS based radio tracker called TeleGPS.  
-         If all goes well, we hope to introduce this in the first
-         half of 2014.
-       </para>
         <para>
           We have designed and prototyped several “companion boards” that 
-         can attach to the companion connector on TeleMetrum and TeleMega
+         can attach to the companion connector on TeleMetrum,
+         TeleMega and EasyMega
          flight computers to collect more data, provide more pyro channels, 
          and so forth.  We do not yet know if or when any of these boards
          will be produced in enough quantity to sell.  If you have specific
@@ -4007,8 +4285,8 @@ NAR #88757, TRA #12200
       <orderedlist inheritnum='inherit' numeration='arabic'>
        <listitem>
          <para>
-           Make sure accelerometer-equipped products like TeleMetrum and
-           TeleMega are aligned precisely along the axis of
+           Make sure accelerometer-equipped products like TeleMetrum,
+           TeleMega and EasyMega are aligned precisely along the axis of
            acceleration so that the accelerometer can accurately
            capture data during the flight.
          </para>
@@ -4218,7 +4496,7 @@ NAR #88757, TRA #12200
   <chapter>
     <title>Updating Device Firmware</title>
     <para>
-      TeleMega, TeleMetrum v2 and EasyMini are all programmed directly
+      TeleMega, TeleMetrum v2, EasyMega and EasyMini are all programmed directly
       over their USB connectors (self programming). TeleMetrum v1, TeleMini and
       TeleDongle are all programmed by using another device as a
       programmer (pair programming). It's important to recognize which
@@ -4241,12 +4519,12 @@ NAR #88757, TRA #12200
       performance slightly.
     </para>
     <para>
-      Self-programmable devices (TeleMega, TeleMetrum v2 and EasyMini)
+      Self-programmable devices (TeleMega, TeleMetrum v2, EasyMega and EasyMini)
       are reprogrammed by connecting them to your computer over USB
     </para>
     <section>
       <title>
-       Updating TeleMega, TeleMetrum v2 or EasyMini Firmware
+       Updating TeleMega, TeleMetrum v2, EasyMega or EasyMini Firmware
       </title>
       <orderedlist inheritnum='inherit' numeration='arabic'>
        <listitem>
@@ -4327,6 +4605,20 @@ NAR #88757, TRA #12200
              </para>
            </listitem>
          </varlistentry>
+         <varlistentry>
+           <term>EasyMega</term>
+           <listitem>
+             <para>
+               Connect pin 6 and pin 1 of the companion connector. Pin 1
+               can be identified by the square pad around it, and then
+               the pins could sequentially across the board. Be very
+               careful to <emphasis>not</emphasis> short pin 8 to
+               anything as that is connected directly to the battery. Pin
+               7 carries 3.3V and the board will crash if that is
+               connected to pin 1, but shouldn't damage the board.
+             </para>
+           </listitem>
+         </varlistentry>
          <varlistentry>
            <term>TeleMetrum v2</term>
            <listitem>
@@ -4354,6 +4646,50 @@ NAR #88757, TRA #12200
            </listitem>
          </varlistentry>
        </variablelist>
+       <para>
+         Once you've located the right pins:
+       </para>
+       <orderedlist inheritnum='inherit' numeration='arabic'>
+         <listitem>
+           <para>
+             Turn the altimeter power off.
+           </para>
+         </listitem>
+         <listitem>
+           <para>
+             Connect a battery.
+           </para>
+         </listitem>
+         <listitem>
+           <para>
+             Connect the indicated terminals together with a short
+             piece of wire. Take care not to accidentally connect
+             anything else.
+           </para>
+         </listitem>
+         <listitem>
+           <para>
+             Connect USB
+           </para>
+         </listitem>
+         <listitem>
+           <para>
+             Turn the board power on.
+           </para>
+         </listitem>
+         <listitem>
+           <para>
+             The board should now be visible over USB as 'AltosFlash'
+             and be ready to receive firmware.
+           </para>
+         </listitem>
+         <listitem>
+           <para>
+             Once the board has been powered up, you can remove the
+             piece of wire.
+           </para>
+         </listitem>
+       </orderedlist>
       </section>
     </section>
     <section>
@@ -4714,6 +5050,67 @@ NAR #88757, TRA #12200
        </listitem>
       </itemizedlist>
     </section>
+    <section>
+      <title>
+       EasyMega Specifications
+      </title>
+      <itemizedlist>
+       <listitem>
+         <para>
+           Recording altimeter for model rocketry.
+         </para>
+       </listitem>
+       <listitem>
+         <para>
+           Supports dual deployment and four auxiliary pyro channels
+           (a total of 6 events).
+         </para>
+       </listitem>
+       <listitem>
+         <para>
+           Barometric pressure sensor good to 100k feet MSL.
+         </para>
+       </listitem>
+       <listitem>
+         <para>
+           1-axis high-g accelerometer for motor characterization, capable of
+           +/- 102g.
+         </para>
+       </listitem>
+       <listitem>
+         <para>
+           9-axis IMU including integrated 3-axis accelerometer,
+           3-axis gyroscope and 3-axis magnetometer.
+         </para>
+       </listitem>
+       <listitem>
+         <para>
+           On-board 8 Megabyte non-volatile memory for flight data storage.
+         </para>
+       </listitem>
+       <listitem>
+         <para>
+           USB interface for battery charging, configuration, and data recovery.
+         </para>
+       </listitem>
+       <listitem>
+         <para>
+           Fully integrated support for Li-Po rechargeable batteries.
+         </para>
+       </listitem>
+       <listitem>
+         <para>
+           Can use either main system Li-Po or optional separate pyro battery
+           to fire e-matches.
+         </para>
+       </listitem>
+       <listitem>
+         <para>
+           1.25 x 1.25 inch board designed to fit inside 38mm air-frame coupler tube.
+         </para>
+       </listitem>
+      </itemizedlist>
+    </section>
     <section>
       <title>
        TeleMetrum v2 Specifications
@@ -5272,6 +5669,21 @@ NAR #88757, TRA #12200
        </mediaobject>
       </informalfigure>
     </section>
+    <section>
+      <title>EasyMega template</title>
+      <para>
+       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.
+      </para>
+      <informalfigure>
+       <mediaobject id="EasyMegaTemplate">
+         <imageobject>
+           <imagedata format="SVG" fileref="easymega.svg"
+                      scalefit="0" scale="100" align="center" />
+         </imageobject>
+       </mediaobject>
+      </informalfigure>
+    </section>
     <section>
       <title>TeleMetrum template</title>
       <para>
@@ -5322,7 +5734,7 @@ NAR #88757, TRA #12200
       <title>Calibration</title>
       <para>
         There are only two calibrations required for TeleMetrum and
-        TeleMega, and only one for TeleDongle, TeleMini and EasyMini.
+        TeleMega, and only one for EasyMega, TeleDongle, TeleMini and EasyMini.
         All boards are shipped from the factory pre-calibrated, but
         the procedures are documented here in case they are ever
         needed.  Re-calibration is not supported by AltosUI, you must
@@ -5374,7 +5786,7 @@ NAR #88757, TRA #12200
        </para>
       </section>
       <section>
-        <title>TeleMetrum and TeleMega Accelerometers</title>
+        <title>TeleMetrum, TeleMega and EasyMega Accelerometers</title>
         <para>
           While barometric sensors are factory-calibrated,
           accelerometers are not, and so each must be calibrated once
@@ -5401,7 +5813,7 @@ NAR #88757, TRA #12200
         </para>
         <para>
          In the unlikely event an accel cal goes badly, it is possible
-         that TeleMetrum or TeleMega may always come up in 'pad mode'
+         that TeleMetrum, TeleMega or EasyMega may always come up in 'pad mode'
          and as such not be listening to either the USB or radio link.
          If that happens, there is a special hook in the firmware to
          force the board back in to 'idle mode' so you can re-do the
@@ -5421,12 +5833,19 @@ NAR #88757, TRA #12200
   <appendix>
     <title>Release Notes</title>
     <simplesect>
-      <title>Version 1.41</title>
+      <title>Version 1.4.1</title>
       <xi:include
          xmlns:xi="http://www.w3.org/2001/XInclude"
          href="release-notes-1.4.1.xsl"
          xpointer="xpointer(/article/*)"/>
     </simplesect>
+    <simplesect>
+      <title>Version 1.5</title>
+      <xi:include
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         href="release-notes-1.5.xsl"
+         xpointer="xpointer(/article/*)"/>
+    </simplesect>
     <simplesect>
       <title>Version 1.4</title>
       <xi:include
index 514db3eda660b98f93502aa021a311265384f4bb..09a83d16fa725574bc53dd9824939a5976ceb249 100644 (file)
Binary files a/doc/configure-altimeter.png and b/doc/configure-altimeter.png differ
index 9f836e710b88bc6881d212932fbd65530b4f3be7..9e3c98aaf0c350db8dd10583b8a7241f7d3e7266 100644 (file)
Binary files a/doc/configure-groundstation.png and b/doc/configure-groundstation.png differ
diff --git a/doc/easymega-outline.xsl b/doc/easymega-outline.xsl
new file mode 100644 (file)
index 0000000..5796f9c
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+  "/usr/share/xml/docbook/schema/dtd/4.5/docbookx.dtd">
+<article>
+    <title>EasyMega Outline and Hole Pattern</title>
+    <para>
+      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.
+    </para>
+    <informalfigure>
+      <mediaobject id="EasyMegaTemplate">
+       <imageobject>
+         <imagedata format="SVG" fileref="easymega.svg"
+                    scalefit="0" scale="100" align="center" />
+       </imageobject>
+      </mediaobject>
+    </informalfigure>
+</article>
+
+<!-- LocalWords: Altusmetrum
+-->
diff --git a/doc/easymega-v1.0-bottom.jpg b/doc/easymega-v1.0-bottom.jpg
new file mode 100644 (file)
index 0000000..be46f14
Binary files /dev/null and b/doc/easymega-v1.0-bottom.jpg differ
diff --git a/doc/easymega-v1.0-top.jpg b/doc/easymega-v1.0-top.jpg
new file mode 100644 (file)
index 0000000..4526f65
Binary files /dev/null and b/doc/easymega-v1.0-top.jpg differ
diff --git a/doc/easymega.svg b/doc/easymega.svg
new file mode 100644 (file)
index 0000000..6d9d766
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+
+<svg
+       xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   width="2.5in"
+   height="1.5in"
+   viewBox="0 0 250 150"
+   preserveaspectratio="none"
+   id="svg2"
+   version="1.1">
+  <g transform="translate(12.5,12.5)"
+     style="fill:none;stroke:#000000;stroke-width:1;stroke-linejoin:miter;font-size:24">
+    <!-- outline -->
+    <rect width="225" height="125" x="0" y="0"/>
+    <!-- holes -->
+    <path d="M12.5,12.5 m-6.25,0 a6.25,6.25,0,1,0,12.5,0 a6.25,6.25,0,1,0,-12.5,0 l12.5,0 m-6.25,-6.25 l0,12.5"/>
+    <path d="M212.5,12.5 m-6.25,0 a6.25,6.25,0,1,0,12.5,0 a6.25,6.25,0,1,0,-12.5,0 l12.5,0 m-6.25,-6.25 l0,12.5"/>
+    <path d="M12.5,112.5 m-6.25,0 a6.25,6.25,0,1,0,12.5,0 a6.25,6.25,0,1,0,-12.5,0 l12.5,0 m-6.25,-6.25 l0,12.5"/>
+    <path d="M212.5,112.5 m-6.25,0 a6.25,6.25,0,1,0,12.5,0 a6.25,6.25,0,1,0,-12.5,0 l12.5,0 m-6.25,-6.25 l0,12.5"/>
+    <!-- arrow -->
+    <path d="M50,62.5 l125,0"/>
+    <path style="fill:#000000;stroke:none" d="M175,57.5 l10,5 l-10,5 z"/>
+    <!-- label -->
+    <text x="112.5" y="57.5" style="fill:#000000;stroke:none" text-anchor="middle">EasyMega</text>
+    <g transform="rotate(90)">
+      <text x="62.5" y="-190" style="fill:#000000;stroke:none" text-anchor="middle">UP</text>
+    </g>
+  </g>
+</svg>
diff --git a/doc/release-notes-1.5.xsl b/doc/release-notes-1.5.xsl
new file mode 100644 (file)
index 0000000..50d83f7
--- /dev/null
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"/usr/share/xml/docbook/schema/dtd/4.5/docbookx.dtd">
+
+<article>
+  <para>
+    Version 1.5 is a major release. It includes support for our new
+    EasyMega product, new features and bug fixes in in the flight
+    software for all our boards and the AltosUI ground station
+  </para>
+  <para>
+    AltOS New Features
+    <itemizedlist>
+      <listitem>
+       <para>
+         Add support for EasyMega boards.
+       </para>
+      </listitem>
+      <listitem>
+       <para>
+         Make the APRS SSID be configurable. This lets you track
+         different rockets on the same receiver without getting
+         things mixed up.
+       </para>
+      </listitem>
+      <listitem>
+       <para>
+         Report extra pyro channel continuity state on EasyMega and
+         TeleMega via the beeper. This lets you easily verify flight
+         readiness on these boards after powering up the electronics
+         on the rail.
+       </para>
+      </listitem>
+      <listitem>
+       <para>
+         Add lower telemetry data rates (2400 and 9600 bps) to
+         increase telemetry radio range. This reduces the amount of
+         data received as well as increasing battery consumption in
+         the transmitter.
+       </para>
+      </listitem>
+      <listitem>
+       <para>
+         Change TeleGPS to have only a single log, and append new
+         data to it rather than using seperate per-flight logs. This
+         avoids accidentally filling up log storage by turning
+         TeleGPS on/off several times.
+       </para>
+      </listitem>
+    </itemizedlist>
+  </para>
+  <para>
+    AltOS Fixes
+    <itemizedlist>
+      <listitem>
+       <para>
+         Increase the maximum range for altitude values from +/-32767m
+         to +/-2147483647m, allowing the flight computers to function
+         correctly above the 32km level.
+       </para>
+      </listitem>
+      <listitem>
+       <para>
+         Continuously test pyro firing conditions during delay stage,
+         inhibiting the pyro channel if the test fails. This prevents
+         firing pyro charges where the conditions were good before
+         the delay, but become bad before the delay expires.
+       </para>
+      </listitem>
+      <listitem>
+       <para>
+         Allow negative numbers in pyro configuration values. This
+         lets you specify things like descending speed or
+         deceleration.
+       </para>
+      </listitem>
+    </itemizedlist>
+  </para>
+  <para>
+    AltosUI and TeleGPS New Features
+    <itemizedlist>
+      <listitem>
+       <para>
+         Support telemetry baud rate selection. Adds menus to
+         the flight monitoring and configuration for baud rate
+         selection.
+       </para>
+      </listitem>
+      <listitem>
+       <para>
+         Support APRS SSID configuration.
+       </para>
+      </listitem>
+      <listitem>
+       <para>
+         Integrate with file managers. This provides icons for all of
+         our file types and associates our application with the files
+         so that using a file manager to open a AltOS data file
+         results in launching our application.
+       </para>
+      </listitem>
+    </itemizedlist>
+  </para>
+  <para>
+    AltosUI Fixes
+    <itemizedlist>
+      <listitem>
+       <para>
+         Make the 'Graph' button on the landed tab work again.
+       </para>
+      </listitem>
+      <listitem>
+       <para>
+         Make tests for Java on Windows a bit smarter, and also
+         provide the user with the option to skip installing Java for
+         cases where we just can't figure out what version is installed.
+       </para>
+      </listitem>
+    </itemizedlist>
+  </para>
+</article>
index bf6b6e53ea8f1d3e30d58e42fa464f1017140434..e45880cd9f10ddae5040843f8a38b82ec4a952f6 100644 (file)
Binary files a/doc/scan-channels.png and b/doc/scan-channels.png differ
index e89555dee5d4001ebeb60d607bc2e4f0b59da69c..94c7c70cffbeff4ec6ab32b2efacf621d9b9f6ba 100644 (file)
@@ -1,6 +1,7 @@
-altus-metrum-*.png
-micropeak-*.png
-telegps-*.png
+application-*.png
+altusmetrum-*.png
+*.rc
 *.ico
 *.icns
 *.build
+*.exe
index b1c00f4b4e50415ee3b466d431f1ef8f6a05226e..bf147ad37fd33ff12081c42c7a4afe6649a3eb95 100644 (file)
@@ -3,71 +3,157 @@ 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)
 
-AM_FILES=$(shell for i in $(RES); do echo altus-metrum-$$i.png; done)
-MP_FILES=$(shell for i in $(RES); do echo micropeak-$$i.png; done)
-TG_FILES=$(shell for i in $(RES); do echo telegps-$$i.png; done)
+# Application icon base names
 
-MAC_TG_FILES=$(shell for i in $(MAC_RES); do echo telegps-$$i.png; done)
-MAC_MP_FILES=$(shell for i in $(MAC_RES); do echo micropeak-$$i.png; done)
-MAC_AM_FILES=$(shell for i in $(MAC_RES); do echo altus-metrum-$$i.png; done)
+AM_NAME                = altusmetrum-altosui
+MP_NAME                = altusmetrum-micropeak
+TG_NAME                = altusmetrum-telegps
 
-WIN_TG_FILES=$(shell for i in $(WIN_RES); do echo telegps-$$i.png; done)
-WIN_MP_FILES=$(shell for i in $(WIN_RES); do echo micropeak-$$i.png; done)
-WIN_AM_FILES=$(shell for i in $(WIN_RES); do echo altus-metrum-$$i.png; done)
+# File icon base names
 
-ICO_FILES=altus-metrum.ico micro-peak.ico telegps.ico
-ICNS_FILES=AltosUIIcon.icns TeleGPS.icns MicroPeak.icns
+EEPROM_NAME    = application-vnd.altusmetrum.eeprom
+TELEM_NAME     = application-vnd.altusmetrum.telemetry
+MPD_NAME       = application-vnd.altusmetrum.micropeak
 
-icondir = $(datadir)/icons/hicolor/scalable/apps
+# Application icons
 
-AM_ICON = altusmetrum.svg
-MP_ICON = micropeak.svg
-TG_ICON = telegps.svg
+AM_ICON                = $(AM_NAME).svg
+MP_ICON                = $(MP_NAME).svg
+TG_ICON                = $(TG_NAME).svg
 
-icon_DATA = $(AM_ICON) $(MP_ICON) $(TG_ICON)
+# File icons (note that MicroPeak uses the application icon for files)
 
-EXTRA_DIST = $(icon_DATA) $(AM_FILES) $(MP_FILES) $(TG_FILES)
+EEPROM_ICON    = $(EEPROM_NAME).svg
+TELEM_ICON     = $(TELEM_NAME).svg
+MPD_ICON       = $(MPD_NAME).svg
+
+# Files needed for Mac OSX icons
+
+MAC_AM_FILES   = $(shell for i in $(MAC_RES); do echo $(AM_NAME)-$$i.png; done)
+MAC_MP_FILES   = $(shell for i in $(MAC_RES); do echo $(MP_NAME)-$$i.png; done)
+MAC_TG_FILES   = $(shell for i in $(MAC_RES); do echo $(TG_NAME)-$$i.png; done)
+MAC_EEPROM_FILES= $(shell for i in $(MAC_RES); do echo $(EEPROM_NAME)-$$i.png; done)
+MAC_TELEM_FILES        = $(shell for i in $(MAC_RES); do echo $(TELEM_NAME)-$$i.png; done)
+MAC_MPD_FILES  = $(shell for i in $(MAC_RES); do echo $(MPD_NAME)-$$i.png; done)
+
+ICNS_FILES     = $(AM_NAME).icns $(MP_NAME).icns $(TG_NAME).icns \
+                 $(EEPROM_NAME).icns $(TELEM_NAME).icns $(MPD_NAME).icns
+
+# Files needed for Windows icons
+
+WIN_AM_FILES   = $(shell for i in $(WIN_RES); do echo $(AM_NAME)-$$i.png; done)
+WIN_MP_FILES   = $(shell for i in $(WIN_RES); do echo $(MP_NAME)-$$i.png; done)
+WIN_TG_FILES   = $(shell for i in $(WIN_RES); do echo $(TG_NAME)-$$i.png; done)
+WIN_EEPROM_FILES= $(shell for i in $(WIN_RES); do echo $(EEPROM_NAME)-$$i.png; done)
+WIN_TELEM_FILES        = $(shell for i in $(WIN_RES); do echo $(TELEM_NAME)-$$i.png; done)
+WIN_MPD_FILES  = $(shell for i in $(WIN_RES); do echo $(MPD_NAME)-$$i.png; done)
+
+ICO_FILES      = $(AM_NAME).ico $(MP_NAME).ico $(TG_NAME).ico \
+                 $(EEPROM_NAME).ico $(TELEM_NAME).ico $(MPD_NAME).ico
+
+EXE_FILES      = $(AM_NAME).exe $(MP_NAME).exe $(TG_NAME).exe \
+                 $(EEPROM_NAME).exe $(TELEM_NAME).exe $(MPD_NAME).exe
+
+# Files needed for Java internal icons
+
+JAVA_AM_FILES  = $(shell for i in $(JAVA_RES); do echo $(AM_NAME)-$$i.png; done)
+JAVA_MP_FILES  = $(shell for i in $(JAVA_RES); do echo $(MP_NAME)-$$i.png; done)
+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)
+
+# PNG files needed by anyone
+
+AM_FILES       = $(shell for i in $(RES); do echo $(AM_NAME)-$$i.png; done)
+MP_FILES       = $(shell for i in $(RES); do echo $(MP_NAME)-$$i.png; done)
+TG_FILES       = $(shell for i in $(RES); do echo $(TG_NAME)-$$i.png; done)
+EEPROM_FILES   = $(shell for i in $(RES); do echo $(EEPROM_NAME)-$$i.png; done)
+TELEM_FILES    = $(shell for i in $(RES); do echo $(TELEM_NAME)-$$i.png; done)
+IN_MPD_FILES   = $(shell for i in $(RES); do echo $(MPD_NAME)-$$i.png; done)
+
+# XPM file needed by debian
+
+AM_XPM = altusmetrum.xpm
+
+ICON_THEME=$(datadir)/icons/hicolor
+
+appicondir = $(ICON_THEME)/scalable/apps
+appicon_DATA = $(AM_ICON) $(MP_ICON) $(TG_ICON)
+
+MIME_ICONS = $(EEPROM_ICON) $(TELEM_ICON) $(MPD_ICON)
+
+mimeicondir = $(ICON_THEME)/scalable/mimetypes
+mimeicon_DATA = $(MIME_ICONS)
+
+mimedir = $(datadir)/mime/packages
+mime_DATA = org-altusmetrum-mimetypes.xml
+
+pixmapdir = $(datadir)/pixmaps
+pixmap_DATA = altusmetrum.xpm
+
+EXTRA_DIST = $(appicon_DATA) $(mimeicon_DATA) $(mime_DATA) windows-stub.c
 
 res:
        echo $(RES)
 
-all-local: $(ICO_FILES) $(ICNS_FILES)
+java-altosui:
+       @echo $(JAVA_AM_FILES)
+
+java-micropeak:
+       @echo $(JAVA_MP_FILES)
+
+java-telegps:
+       @echo $(JAVA_TG_FILES)
+
+fat: all $(ICO_FILES) $(ICNS_FILES) $(EXE_FILES)
+
+all-local: $(JAVA_FILES) $(AM_XPM)
 
 clean-local:
-       $(RM) altus-metrum-*.png telegps-*.png micropeak-*.png *.build *.ico *.icns
+       $(RM) $(AM_NAME)-*.png $(TG_NAME)-*.png $(MP_NAME)-*.png
+       $(RM) altus-metrum-*.png micropeak-*.png telegps-*.png
+       $(RM) $(EEPROM_NAME)-*.png $(TELEM_NAME)-*.png $(MPD_NAME)-*.png
+       $(RM) *.build *.ico *.rc *.icns *.o *.exe $(MPD_ICON)
+       $(RM) altusmetrum.xpm
+
+install-data-hook:
+       update-mime-database $(datadir)/mime
+       update-icon-caches $(ICON_THEME)
 
-$(AM_FILES): altusmetrum.build
+$(MPD_ICON): $(MP_ICON)
+       $(LN_S) $(MP_ICON) $@
 
-altusmetrum.build: altusmetrum.svg
-       for i in $(RES); do rsvg-convert -w $$i -h $$i -o altus-metrum-$$i.png altusmetrum.svg; done && touch $@
+XPM_SRC=altusmetrum-altosui-32.png
 
-$(TG_FILES): telegps.build
+altusmetrum.xpm: $(XPM_SRC)
+       pngtopnm -alpha $(XPM_SRC) > mask-$@ && \
+               pngtopnm $(XPM_SRC) | \
+               ppmtoxpm -alphamask=mask-$@ > $@ && rm mask-$@
 
-telegps.build: telegps.svg
-       for i in $(RES); do rsvg-convert -w $$i -h $$i -o telegps-$$i.png telegps.svg; done && touch $@
+$(AM_FILES): $(AM_NAME).build
+$(MP_FILES): $(MP_NAME).build
+$(TG_FILES): $(TG_NAME).build
 
-$(MP_FILES): micropeak.build
+SUFFIXES=.svg .build .icns .ico .rc .o .exe
 
-micropeak.build: micropeak.svg
-       for i in $(RES); do rsvg-convert -w $$i -h $$i -o micropeak-$$i.png micropeak.svg; done && touch $@
+.svg.build:
+       for i in $(RES); do rsvg-convert -w $$i -h $$i -o $*-$$i.png $*.svg; done && touch $@
 
-#clean-local:
-#      $(RM) -f $(ICO_FILES)
+.build.icns:
+       png2icns $@ $(shell for i in $(MAC_RES); do echo $*-$$i.png; done)
 
-altus-metrum.ico: $(WIN_AM_FILES)
-       icotool -c -o $@ $(WIN_AM_FILES)
+.build.ico:
+       icotool -c -o $@ $(shell for i in $(WIN_RES); do echo $*-$$i.png; done)
 
-micro-peak.ico: $(WIN_MP_FILES)
-       icotool -c -o $@ $(WIN_MP_FILES)
+.ico.rc:
+       echo '101 ICON "$*.ico"' > $@
 
-telegps.ico: $(WIN_TG_FILES)
-       icotool -c -o $@ $(WIN_TG_FILES)
 
-AltosUIIcon.icns: $(MAC_AM_FILES)
-       png2icns $@ $(MAC_AM_FILES)
+MINGCC32=i686-w64-mingw32-gcc
+MINGWINDRES=i686-w64-mingw32-windres
 
-TeleGPS.icns: $(MAC_TG_FILES)
-       png2icns $@ $(MAC_TG_FILES)
+.rc.o:
+       $(MINGWINDRES) $*.rc $@
 
-MicroPeak.icns: $(MAC_MP_FILES)
-       png2icns $@ $(MAC_MP_FILES)
+.o.exe:
+       $(MINGCC32) -o $@ windows-stub.c $*.o
diff --git a/icon/altusmetrum-altosui.svg b/icon/altusmetrum-altosui.svg
new file mode 100644 (file)
index 0000000..e8935a6
--- /dev/null
@@ -0,0 +1,250 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg2"
+   width="214.27165"
+   height="266.00192"
+   version="1.0"
+   sodipodi:version="0.32"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="altusmetrum.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   inkscape:export-filename="/home/keithp/src/cc1111/altus-logo/bottom.png"
+   inkscape:export-xdpi="119.89881"
+   inkscape:export-ydpi="119.89881">
+  <metadata
+     id="metadata14">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs12">
+    <linearGradient
+       id="linearGradient3165">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop3167" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop3169" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3177">
+      <stop
+         style="stop-color:#da7000;stop-opacity:1;"
+         offset="0"
+         id="stop3179" />
+      <stop
+         id="stop3447"
+         offset="0.24528302"
+         style="stop-color:#a63852;stop-opacity:1;" />
+      <stop
+         style="stop-color:#7200a4;stop-opacity:1;"
+         offset="1"
+         id="stop3181" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3169">
+      <stop
+         style="stop-color:#ff8a00;stop-opacity:1;"
+         offset="0"
+         id="stop3171" />
+      <stop
+         id="stop3445"
+         offset="0.71698111"
+         style="stop-color:#c24573;stop-opacity:0.98039216;" />
+      <stop
+         style="stop-color:#8500e7;stop-opacity:0.96078432;"
+         offset="1"
+         id="stop3173" />
+    </linearGradient>
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 121 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="191 : 121 : 1"
+       inkscape:persp3d-origin="95.5 : 80.666667 : 1"
+       id="perspective16" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3169"
+       id="radialGradient3175"
+       cx="951.68713"
+       cy="2305.2668"
+       fx="951.68713"
+       fy="2305.2668"
+       r="951.68701"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3165"
+       id="radialGradient3171"
+       cx="951.68713"
+       cy="1205.2668"
+       fx="951.68713"
+       fy="1205.2668"
+       r="951.68701"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3169"
+       id="radialGradient3020"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="2305.2668"
+       fx="951.68713"
+       fy="2305.2668"
+       r="951.68701" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3165"
+       id="radialGradient3022"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="1205.2668"
+       fx="951.68713"
+       fy="1205.2668"
+       r="951.68701" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3169"
+       id="radialGradient3024"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="2305.2668"
+       fx="951.68713"
+       fy="2305.2668"
+       r="951.68701" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3165"
+       id="radialGradient3026"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="1205.2668"
+       fx="951.68713"
+       fy="1205.2668"
+       r="951.68701" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3169"
+       id="radialGradient3028"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="2305.2668"
+       fx="951.68713"
+       fy="2305.2668"
+       r="951.68701" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3165"
+       id="radialGradient3030"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="1205.2668"
+       fx="951.68713"
+       fy="1205.2668"
+       r="951.68701" />
+    <filter
+       id="filter3005"
+       inkscape:label="Drop Shadow"
+       color-interpolation-filters="sRGB">
+      <feFlood
+         id="feFlood3007"
+         flood-opacity="0.604"
+         flood-color="rgb(0,0,0)"
+         result="flood" />
+      <feComposite
+         id="feComposite3009"
+         in2="SourceGraphic"
+         in="flood"
+         operator="in"
+         result="composite1" />
+      <feGaussianBlur
+         id="feGaussianBlur3011"
+         stdDeviation="80"
+         result="blur" />
+      <feOffset
+         id="feOffset3013"
+         dx="100"
+         dy="100"
+         result="offset" />
+      <feComposite
+         id="feComposite3015"
+         in2="offset"
+         in="SourceGraphic"
+         operator="over"
+         result="composite2" />
+    </filter>
+  </defs>
+  <sodipodi:namedview
+     inkscape:cy="128.91168"
+     inkscape:cx="271.89232"
+     inkscape:zoom="2.4559706"
+     inkscape:window-height="1177"
+     inkscape:window-width="1462"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     guidetolerance="10.0"
+     gridtolerance="10.0"
+     objecttolerance="10.0"
+     borderopacity="1.0"
+     bordercolor="#666666"
+     pagecolor="#ffffff"
+     id="base"
+     showgrid="false"
+     inkscape:window-x="266"
+     inkscape:window-y="43"
+     inkscape:current-layer="svg2"
+     inkscape:window-maximized="0"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="20"
+     fit-margin-bottom="20" />
+  <g
+     transform="matrix(0.1,0,0,0.1,1.967113,2.4742836)"
+     id="g3"
+     style="fill:url(#radialGradient3175);fill-opacity:1;stroke:url(#radialGradient3171);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;filter:url(#filter3005)">
+    <g
+       transform="translate(20.61545,-27.69425)"
+       style="fill:url(#radialGradient3028);fill-opacity:1;fill-rule:evenodd;stroke:url(#radialGradient3030);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
+       id="g5">
+      <path
+         d="m 931.07168,1164.597 248.86992,-331.80265 416.1687,1338.32935 286.6484,267.1042 -520.4224,0 -270.2797,-262.2181 0,-1033.0627 -160.98492,106.6818 -160.98492,-106.6818 0,1033.0627 -270.2797,262.2181 -520.4224,0 286.6484,-267.1042 416.1687,-1338.32935 248.86992,331.80265 z"
+         id="path7"
+         style="fill:url(#radialGradient3020);fill-opacity:1;stroke:url(#radialGradient3022);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
+         inkscape:connector-curvature="0" />
+      <path
+         d="m 931.07168,27.69425 224.03682,720.46517 -63.341,76.00913 L 931.07168,486.3269 770.37586,824.16855 707.03486,748.15942 931.07168,27.69425 z"
+         id="path9"
+         style="fill:url(#radialGradient3024);fill-opacity:1;stroke:url(#radialGradient3026);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
+         inkscape:connector-curvature="0" />
+    </g>
+  </g>
+</svg>
diff --git a/icon/altusmetrum-micropeak.svg b/icon/altusmetrum-micropeak.svg
new file mode 100644 (file)
index 0000000..d37130f
--- /dev/null
@@ -0,0 +1,219 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="49.03825"
+   height="43.606411"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="micropeak.svg">
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient5343">
+      <stop
+         style="stop-color:#7200a4;stop-opacity:1;"
+         offset="0"
+         id="stop5345" />
+      <stop
+         style="stop-color:#da7000;stop-opacity:1;"
+         offset="1"
+         id="stop5347" />
+    </linearGradient>
+    <marker
+       inkscape:stockid="Arrow2Send"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow2Send"
+       style="overflow:visible">
+      <path
+         id="path3798"
+         style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         transform="matrix(-0.3,0,0,-0.3,0.69,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Send"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Send"
+       style="overflow:visible">
+      <path
+         id="path3780"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+         transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Mend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow2Mend"
+       style="overflow:visible">
+      <path
+         id="path3792"
+         style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         transform="scale(-0.6,-0.6)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Lend"
+       style="overflow:visible">
+      <path
+         id="path3768"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+         transform="matrix(-0.8,0,0,-0.8,-10,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow2Lend"
+       style="overflow:visible">
+      <path
+         id="path3786"
+         style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5343"
+       id="linearGradient5349"
+       x1="255.48561"
+       y1="275.90405"
+       x2="280.61411"
+       y2="275.90405"
+       gradientUnits="userSpaceOnUse" />
+    <filter
+       id="filter3027"
+       inkscape:label="Drop Shadow"
+       color-interpolation-filters="sRGB">
+      <feFlood
+         id="feFlood3029"
+         flood-opacity="0.604"
+         flood-color="rgb(0,0,0)"
+         result="flood" />
+      <feComposite
+         id="feComposite3031"
+         in2="SourceGraphic"
+         in="flood"
+         operator="in"
+         result="composite1" />
+      <feGaussianBlur
+         id="feGaussianBlur3033"
+         stdDeviation="1.6"
+         result="blur" />
+      <feOffset
+         id="feOffset3035"
+         dx="2"
+         dy="2"
+         result="offset" />
+      <feComposite
+         id="feComposite3037"
+         in2="offset"
+         in="SourceGraphic"
+         operator="over"
+         result="composite2" />
+    </filter>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="8.160856"
+     inkscape:cx="33.152671"
+     inkscape:cy="27.859227"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:window-width="1277"
+     inkscape:window-height="894"
+     inkscape:window-x="543"
+     inkscape:window-y="242"
+     inkscape:window-maximized="0"
+     fit-margin-top="-3"
+     fit-margin-left="-4"
+     fit-margin-right="-1"
+     fit-margin-bottom="0" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-241.43522,-252.43073)">
+    <g
+       id="g3000"
+       style="filter:url(#filter3027)">
+      <g
+         id="text2985"
+         style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#7200a4;fill-opacity:1;stroke:none;font-family:Minion Pro;-inkscape-font-specification:Minion Pro">
+        <path
+           inkscape:connector-curvature="0"
+           id="path3003"
+           style="font-size:36px;font-weight:500;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#7200a4;font-family:ITC Benguiat Gothic Std;-inkscape-font-specification:ITC Benguiat Gothic Std Medium"
+           d="m 257.20241,268.30647 c 0,-1.07999 -0.396,-1.872 -1.584,-1.872 -1.188,0 -1.584,0.79201 -1.584,1.872 l 0,8.676 c 0,2.88 -2.052,5.112 -4.824,5.112 -3.06,0 -4.104,-1.872 -4.104,-5.076 l 0,-8.712 c 0,-1.07999 -0.396,-1.872 -1.584,-1.872 -1.188,0 -1.584,0.79201 -1.584,1.872 l 0,21.924 c 0,1.08 0.396,1.872 1.584,1.872 1.188,0 1.584,-0.792 1.584,-1.872 l 0,-6.156 c 0.792,0.612 2.088,0.972 3.564,0.972 2.304,0 4.428,-0.792 5.652,-2.988 l 0.072,0.072 0,1.26 c 0,0.864 0.54,1.44 1.404,1.44 0.864,0 1.404,-0.576 1.404,-1.44 l 0,-15.084" />
+      </g>
+      <path
+         sodipodi:nodetypes="cssc"
+         inkscape:connector-curvature="0"
+         id="path2991"
+         d="m 256.93561,290.70327 c 3.04022,-0.24413 4.30317,-2.66932 5.38268,-5.56604 1.68059,-4.50963 3.67214,-15.86904 8.62227,-20.55527 4.0668,-3.85 8.22354,-3.46656 8.22354,-3.46656"
+         style="fill:none;stroke:url(#linearGradient5349);stroke-width:2.9000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:none" />
+      <path
+         inkscape:transform-center-y="-0.40889198"
+         inkscape:transform-center-x="-0.29194889"
+         d="m 282.7522,267.42614 -3.93403,-2.77705 -4.51792,1.66641 1.42544,-4.59964 -2.98096,-3.78185 4.815,-0.0657 2.67559,-4.00372 1.55039,4.55904 4.63457,1.30742 -3.85681,2.88333 z"
+         inkscape:randomized="0"
+         inkscape:rounded="0"
+         inkscape:flatsided="false"
+         sodipodi:arg2="1.7014539"
+         sodipodi:arg1="1.0731354"
+         sodipodi:r2="3.6257365"
+         sodipodi:r1="7.2514729"
+         sodipodi:cy="261.05426"
+         sodipodi:cx="279.29056"
+         sodipodi:sides="5"
+         id="path5341"
+         style="fill:none;stroke:#da7000;stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+         sodipodi:type="star" />
+    </g>
+  </g>
+</svg>
diff --git a/icon/altusmetrum-telegps.svg b/icon/altusmetrum-telegps.svg
new file mode 100644 (file)
index 0000000..1e390f3
--- /dev/null
@@ -0,0 +1,324 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="151.43401"
+   height="144.50209"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="telegps.svg">
+  <defs
+     id="defs4">
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3169"
+       id="radialGradient3175"
+       cx="951.68713"
+       cy="2305.2668"
+       fx="951.68713"
+       fy="2305.2668"
+       r="951.68701"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       id="linearGradient3169">
+      <stop
+         style="stop-color:#ff8a00;stop-opacity:1;"
+         offset="0"
+         id="stop3171" />
+      <stop
+         id="stop3445"
+         offset="0.71698111"
+         style="stop-color:#c24573;stop-opacity:0.98039216;" />
+      <stop
+         style="stop-color:#8500e7;stop-opacity:0.96078432;"
+         offset="1"
+         id="stop3173" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3165"
+       id="radialGradient3171"
+       cx="951.68713"
+       cy="1205.2668"
+       fx="951.68713"
+       fy="1205.2668"
+       r="951.68701"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       id="linearGradient3165">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop3167" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop3169" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3169"
+       id="radialGradient2838"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="2305.2668"
+       fx="951.68713"
+       fy="2305.2668"
+       r="951.68701" />
+    <linearGradient
+       id="linearGradient3181">
+      <stop
+         style="stop-color:#ff8a00;stop-opacity:1;"
+         offset="0"
+         id="stop3183" />
+      <stop
+         id="stop3185"
+         offset="0.71698111"
+         style="stop-color:#c24573;stop-opacity:0.98039216;" />
+      <stop
+         style="stop-color:#8500e7;stop-opacity:0.96078432;"
+         offset="1"
+         id="stop3187" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3165"
+       id="radialGradient2840"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="1205.2668"
+       fx="951.68713"
+       fy="1205.2668"
+       r="951.68701" />
+    <linearGradient
+       id="linearGradient3190">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop3192" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop3194" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3169"
+       id="radialGradient2830"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="2305.2668"
+       fx="951.68713"
+       fy="2305.2668"
+       r="951.68701" />
+    <linearGradient
+       id="linearGradient3197">
+      <stop
+         style="stop-color:#ff8a00;stop-opacity:1;"
+         offset="0"
+         id="stop3199" />
+      <stop
+         id="stop3201"
+         offset="0.71698111"
+         style="stop-color:#c24573;stop-opacity:0.98039216;" />
+      <stop
+         style="stop-color:#8500e7;stop-opacity:0.96078432;"
+         offset="1"
+         id="stop3203" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3165"
+       id="radialGradient2832"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="1205.2668"
+       fx="951.68713"
+       fy="1205.2668"
+       r="951.68701" />
+    <linearGradient
+       id="linearGradient3206">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop3208" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop3210" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3169"
+       id="radialGradient2834"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="2305.2668"
+       fx="951.68713"
+       fy="2305.2668"
+       r="951.68701" />
+    <linearGradient
+       id="linearGradient3213">
+      <stop
+         style="stop-color:#ff8a00;stop-opacity:1;"
+         offset="0"
+         id="stop3215" />
+      <stop
+         id="stop3217"
+         offset="0.71698111"
+         style="stop-color:#c24573;stop-opacity:0.98039216;" />
+      <stop
+         style="stop-color:#8500e7;stop-opacity:0.96078432;"
+         offset="1"
+         id="stop3219" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3165"
+       id="radialGradient2836"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="1205.2668"
+       fx="951.68713"
+       fy="1205.2668"
+       r="951.68701" />
+    <linearGradient
+       id="linearGradient3222">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop3224" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop3226" />
+    </linearGradient>
+    <radialGradient
+       r="951.68701"
+       fy="2305.2668"
+       fx="951.68713"
+       cy="2305.2668"
+       cx="951.68713"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient3232"
+       xlink:href="#linearGradient3169"
+       inkscape:collect="always" />
+    <radialGradient
+       r="951.68701"
+       fy="1205.2668"
+       fx="951.68713"
+       cy="1205.2668"
+       cx="951.68713"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient3234"
+       xlink:href="#linearGradient3165"
+       inkscape:collect="always" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3169"
+       id="radialGradient4101"
+       cx="194.54575"
+       cy="361.16367"
+       fx="194.54575"
+       fy="361.16367"
+       r="70.597672"
+       gradientTransform="matrix(1,0,0,0.95908583,137.14286,74.776711)"
+       gradientUnits="userSpaceOnUse" />
+    <filter
+       id="filter3238"
+       inkscape:label="Drop Shadow"
+       color-interpolation-filters="sRGB">
+      <feFlood
+         id="feFlood3240"
+         flood-opacity="0.604"
+         flood-color="rgb(0,0,0)"
+         result="flood" />
+      <feComposite
+         id="feComposite3242"
+         in2="SourceGraphic"
+         in="flood"
+         operator="in"
+         result="composite1" />
+      <feGaussianBlur
+         id="feGaussianBlur3244"
+         stdDeviation="4"
+         result="blur" />
+      <feOffset
+         id="feOffset3246"
+         dx="5"
+         dy="5"
+         result="offset" />
+      <feComposite
+         id="feComposite3248"
+         in2="offset"
+         in="SourceGraphic"
+         operator="over"
+         result="composite2" />
+    </filter>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="3.959798"
+     inkscape:cx="91.754359"
+     inkscape:cy="68.172898"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     fit-margin-top="-12"
+     fit-margin-left="-12"
+     fit-margin-right="-6"
+     fit-margin-bottom="-6"
+     inkscape:window-width="996"
+     inkscape:window-height="970"
+     inkscape:window-x="930"
+     inkscape:window-y="553"
+     inkscape:window-maximized="0" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-258.97144,-351.91262)">
+    <path
+       style="fill:url(#radialGradient4101);fill-opacity:1;filter:url(#filter3238)"
+       d="m 261.09094,466.61035 1.9122,-1.69399 39.0721,-36.4688 20.74158,22.05252 -40.71991,38.37279 z m 36.24983,1.34654 -14.08636,-15.38433 -15.33887,14.40857 14.50759,15.23741 z m 18.98704,-17.58715 -14.47613,-15.53942 -14.95191,14.42099 14.19976,15.37575 z m 43.2565,3.24033 -5.69326,-6.00917 -2.76929,1.85727 c -5.01515,3.36349 -10.61773,4.75193 -13.55344,3.35884 -0.90785,-0.4308 -11.20677,-10.85557 -16.46128,-16.61505 -6.3177,-6.92484 -17.77225,-18.68338 -18.08204,-21.53696 l -0.25491,-2.34789 -6.68224,-3.00173 -6.68224,-3.00173 -0.12416,-2.54849 c -0.24316,-4.99109 2.61694,-11.66135 7.10652,-16.57368 6.51922,-7.13306 14.23173,-10.81215 21.4071,-10.21178 l 2.49577,0.20881 2.34108,7.3087 2.34109,7.3087 2.0542,0.21626 c 1.12981,0.11895 2.29245,0.36702 2.58364,0.55127 0.29119,0.18424 11.17756,11.55849 16.63562,17.46044 5.67391,6.13537 16.35301,17.71615 16.74619,18.65715 1.36492,3.26672 -0.56522,9.34479 -4.44838,14.00803 -0.92939,1.1161 -1.6875,2.14976 -1.6847,2.29703 0.003,0.14726 2.44601,2.88431 5.42933,6.08233 2.98332,3.19801 5.42421,6.02814 5.42421,6.28919 0,0.66794 -0.91528,1.72591 -1.73982,2.01104 -0.50334,0.17406 -2.27007,-1.42112 -6.38899,-5.76858 z m -13.8944,-6.52384 c 0.96195,-0.49074 2.46683,-1.3673 3.34417,-1.94791 l 1.59519,-1.05564 -1.69025,-1.72225 c -1.71532,-1.74777 -2.09589,-2.99732 -1.1891,-3.90412 0.98407,-0.98406 2.33559,-0.53387 3.9423,1.31314 l 1.57825,1.81431 1.43638,-1.7099 c 1.7115,-2.03742 3.3933,-5.47555 3.39008,-6.9304 -0.0104,-4.68327 -7.01613,-2.68794 -13.36898,3.80766 -4.26282,4.35861 -6.32786,9.57528 -4.26584,10.77629 1.19252,0.69458 3.36009,0.51166 5.2278,-0.44118 z m -37.53066,-44.39022 c 2.23934,-2.70633 7.29399,-6.99375 10.13666,-8.59806 1.69887,-0.95877 2.21231,-1.46174 2.04152,-1.99985 -0.1255,-0.3954 -1.05734,-3.0661 -2.07077,-5.93487 l -1.84259,-5.21596 -1.60649,0.12825 c -4.1301,0.32972 -9.06228,2.86043 -13.29918,6.82384 -4.03277,3.77245 -7.7843,10.20829 -7.89014,13.53572 l -0.0463,1.4539 5.4085,2.47197 5.4085,2.47197 1.02919,-1.54008 c 0.56606,-0.84704 1.79503,-2.46562 2.73105,-3.59683 z m 32.91039,-10.47213 40.55794,-38.76942 c 7.09795,7.71166 14.5366,15.63755 20.65837,22.2503 l -40.53088,38.2414 z m 35.73645,1.02093 -14.2595,-15.3791 -15.29495,14.35785 14.65467,15.14661 z m 18.6801,-17.55816 -14.10162,-15.40128 -15.32812,14.3973 14.52992,15.24342 z"
+       id="path3063"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccccccccccccccscssascccssscccscasscsssssccssscssssscssscssccccsccccccccccccccccc" />
+  </g>
+</svg>
diff --git a/icon/altusmetrum.svg b/icon/altusmetrum.svg
deleted file mode 100644 (file)
index e8935a6..0000000
+++ /dev/null
@@ -1,250 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   id="svg2"
-   width="214.27165"
-   height="266.00192"
-   version="1.0"
-   sodipodi:version="0.32"
-   inkscape:version="0.48.4 r9939"
-   sodipodi:docname="altusmetrum.svg"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape"
-   inkscape:export-filename="/home/keithp/src/cc1111/altus-logo/bottom.png"
-   inkscape:export-xdpi="119.89881"
-   inkscape:export-ydpi="119.89881">
-  <metadata
-     id="metadata14">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <defs
-     id="defs12">
-    <linearGradient
-       id="linearGradient3165">
-      <stop
-         style="stop-color:#000000;stop-opacity:1;"
-         offset="0"
-         id="stop3167" />
-      <stop
-         style="stop-color:#000000;stop-opacity:0;"
-         offset="1"
-         id="stop3169" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient3177">
-      <stop
-         style="stop-color:#da7000;stop-opacity:1;"
-         offset="0"
-         id="stop3179" />
-      <stop
-         id="stop3447"
-         offset="0.24528302"
-         style="stop-color:#a63852;stop-opacity:1;" />
-      <stop
-         style="stop-color:#7200a4;stop-opacity:1;"
-         offset="1"
-         id="stop3181" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient3169">
-      <stop
-         style="stop-color:#ff8a00;stop-opacity:1;"
-         offset="0"
-         id="stop3171" />
-      <stop
-         id="stop3445"
-         offset="0.71698111"
-         style="stop-color:#c24573;stop-opacity:0.98039216;" />
-      <stop
-         style="stop-color:#8500e7;stop-opacity:0.96078432;"
-         offset="1"
-         id="stop3173" />
-    </linearGradient>
-    <inkscape:perspective
-       sodipodi:type="inkscape:persp3d"
-       inkscape:vp_x="0 : 121 : 1"
-       inkscape:vp_y="0 : 1000 : 0"
-       inkscape:vp_z="191 : 121 : 1"
-       inkscape:persp3d-origin="95.5 : 80.666667 : 1"
-       id="perspective16" />
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3169"
-       id="radialGradient3175"
-       cx="951.68713"
-       cy="2305.2668"
-       fx="951.68713"
-       fy="2305.2668"
-       r="951.68701"
-       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
-       gradientUnits="userSpaceOnUse" />
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3165"
-       id="radialGradient3171"
-       cx="951.68713"
-       cy="1205.2668"
-       fx="951.68713"
-       fy="1205.2668"
-       r="951.68701"
-       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
-       gradientUnits="userSpaceOnUse" />
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3169"
-       id="radialGradient3020"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
-       cx="951.68713"
-       cy="2305.2668"
-       fx="951.68713"
-       fy="2305.2668"
-       r="951.68701" />
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3165"
-       id="radialGradient3022"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
-       cx="951.68713"
-       cy="1205.2668"
-       fx="951.68713"
-       fy="1205.2668"
-       r="951.68701" />
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3169"
-       id="radialGradient3024"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
-       cx="951.68713"
-       cy="2305.2668"
-       fx="951.68713"
-       fy="2305.2668"
-       r="951.68701" />
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3165"
-       id="radialGradient3026"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
-       cx="951.68713"
-       cy="1205.2668"
-       fx="951.68713"
-       fy="1205.2668"
-       r="951.68701" />
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3169"
-       id="radialGradient3028"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
-       cx="951.68713"
-       cy="2305.2668"
-       fx="951.68713"
-       fy="2305.2668"
-       r="951.68701" />
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3165"
-       id="radialGradient3030"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
-       cx="951.68713"
-       cy="1205.2668"
-       fx="951.68713"
-       fy="1205.2668"
-       r="951.68701" />
-    <filter
-       id="filter3005"
-       inkscape:label="Drop Shadow"
-       color-interpolation-filters="sRGB">
-      <feFlood
-         id="feFlood3007"
-         flood-opacity="0.604"
-         flood-color="rgb(0,0,0)"
-         result="flood" />
-      <feComposite
-         id="feComposite3009"
-         in2="SourceGraphic"
-         in="flood"
-         operator="in"
-         result="composite1" />
-      <feGaussianBlur
-         id="feGaussianBlur3011"
-         stdDeviation="80"
-         result="blur" />
-      <feOffset
-         id="feOffset3013"
-         dx="100"
-         dy="100"
-         result="offset" />
-      <feComposite
-         id="feComposite3015"
-         in2="offset"
-         in="SourceGraphic"
-         operator="over"
-         result="composite2" />
-    </filter>
-  </defs>
-  <sodipodi:namedview
-     inkscape:cy="128.91168"
-     inkscape:cx="271.89232"
-     inkscape:zoom="2.4559706"
-     inkscape:window-height="1177"
-     inkscape:window-width="1462"
-     inkscape:pageshadow="2"
-     inkscape:pageopacity="0.0"
-     guidetolerance="10.0"
-     gridtolerance="10.0"
-     objecttolerance="10.0"
-     borderopacity="1.0"
-     bordercolor="#666666"
-     pagecolor="#ffffff"
-     id="base"
-     showgrid="false"
-     inkscape:window-x="266"
-     inkscape:window-y="43"
-     inkscape:current-layer="svg2"
-     inkscape:window-maximized="0"
-     fit-margin-top="0"
-     fit-margin-left="0"
-     fit-margin-right="20"
-     fit-margin-bottom="20" />
-  <g
-     transform="matrix(0.1,0,0,0.1,1.967113,2.4742836)"
-     id="g3"
-     style="fill:url(#radialGradient3175);fill-opacity:1;stroke:url(#radialGradient3171);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;filter:url(#filter3005)">
-    <g
-       transform="translate(20.61545,-27.69425)"
-       style="fill:url(#radialGradient3028);fill-opacity:1;fill-rule:evenodd;stroke:url(#radialGradient3030);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
-       id="g5">
-      <path
-         d="m 931.07168,1164.597 248.86992,-331.80265 416.1687,1338.32935 286.6484,267.1042 -520.4224,0 -270.2797,-262.2181 0,-1033.0627 -160.98492,106.6818 -160.98492,-106.6818 0,1033.0627 -270.2797,262.2181 -520.4224,0 286.6484,-267.1042 416.1687,-1338.32935 248.86992,331.80265 z"
-         id="path7"
-         style="fill:url(#radialGradient3020);fill-opacity:1;stroke:url(#radialGradient3022);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
-         inkscape:connector-curvature="0" />
-      <path
-         d="m 931.07168,27.69425 224.03682,720.46517 -63.341,76.00913 L 931.07168,486.3269 770.37586,824.16855 707.03486,748.15942 931.07168,27.69425 z"
-         id="path9"
-         style="fill:url(#radialGradient3024);fill-opacity:1;stroke:url(#radialGradient3026);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
-         inkscape:connector-curvature="0" />
-    </g>
-  </g>
-</svg>
diff --git a/icon/application-vnd.altusmetrum.eeprom.svg b/icon/application-vnd.altusmetrum.eeprom.svg
new file mode 100644 (file)
index 0000000..7b481cd
--- /dev/null
@@ -0,0 +1,397 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg2"
+   width="214.27165"
+   height="266.00192"
+   version="1.0"
+   sodipodi:version="0.32"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="application-vnd-altusmetrum-eeprom.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   inkscape:export-filename="/home/keithp/src/cc1111/altus-logo/bottom.png"
+   inkscape:export-xdpi="119.89881"
+   inkscape:export-ydpi="119.89881">
+  <metadata
+     id="metadata14">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs12">
+    <linearGradient
+       id="linearGradient3165">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop3167" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop3169" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3177">
+      <stop
+         style="stop-color:#da7000;stop-opacity:1;"
+         offset="0"
+         id="stop3179" />
+      <stop
+         id="stop3447"
+         offset="0.24528302"
+         style="stop-color:#a63852;stop-opacity:1;" />
+      <stop
+         style="stop-color:#7200a4;stop-opacity:1;"
+         offset="1"
+         id="stop3181" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3169">
+      <stop
+         style="stop-color:#ff8a00;stop-opacity:1;"
+         offset="0"
+         id="stop3171" />
+      <stop
+         id="stop3445"
+         offset="0.71698111"
+         style="stop-color:#c24573;stop-opacity:0.98039216;" />
+      <stop
+         style="stop-color:#8500e7;stop-opacity:0.96078432;"
+         offset="1"
+         id="stop3173" />
+    </linearGradient>
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 121 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="191 : 121 : 1"
+       inkscape:persp3d-origin="95.5 : 80.666667 : 1"
+       id="perspective16" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3169"
+       id="radialGradient3175"
+       cx="951.68713"
+       cy="2305.2668"
+       fx="951.68713"
+       fy="2305.2668"
+       r="951.68701"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3165"
+       id="radialGradient3171"
+       cx="951.68713"
+       cy="1205.2668"
+       fx="951.68713"
+       fy="1205.2668"
+       r="951.68701"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3169"
+       id="radialGradient3020"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="2305.2668"
+       fx="951.68713"
+       fy="2305.2668"
+       r="951.68701" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3165"
+       id="radialGradient3022"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="1205.2668"
+       fx="951.68713"
+       fy="1205.2668"
+       r="951.68701" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3169"
+       id="radialGradient3024"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="2305.2668"
+       fx="951.68713"
+       fy="2305.2668"
+       r="951.68701" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3165"
+       id="radialGradient3026"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="1205.2668"
+       fx="951.68713"
+       fy="1205.2668"
+       r="951.68701" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3169"
+       id="radialGradient3028"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="2305.2668"
+       fx="951.68713"
+       fy="2305.2668"
+       r="951.68701" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3165"
+       id="radialGradient3030"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="1205.2668"
+       fx="951.68713"
+       fy="1205.2668"
+       r="951.68701" />
+    <filter
+       id="filter3005"
+       inkscape:label="Drop Shadow"
+       color-interpolation-filters="sRGB">
+      <feFlood
+         id="feFlood3007"
+         flood-opacity="0.604"
+         flood-color="rgb(0,0,0)"
+         result="flood" />
+      <feComposite
+         id="feComposite3009"
+         in2="SourceGraphic"
+         in="flood"
+         operator="in"
+         result="composite1" />
+      <feGaussianBlur
+         id="feGaussianBlur3011"
+         stdDeviation="80"
+         result="blur" />
+      <feOffset
+         id="feOffset3013"
+         dx="100"
+         dy="100"
+         result="offset" />
+      <feComposite
+         id="feComposite3015"
+         in2="offset"
+         in="SourceGraphic"
+         operator="over"
+         result="composite2" />
+    </filter>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3169"
+       id="radialGradient4415"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="2305.2668"
+       fx="951.68713"
+       fy="2305.2668"
+       r="951.68701" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3165"
+       id="radialGradient4417"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="1205.2668"
+       fx="951.68713"
+       fy="1205.2668"
+       r="951.68701" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3169"
+       id="radialGradient4419"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="2305.2668"
+       fx="951.68713"
+       fy="2305.2668"
+       r="951.68701" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3165"
+       id="radialGradient4421"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="1205.2668"
+       fx="951.68713"
+       fy="1205.2668"
+       r="951.68701" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3169"
+       id="radialGradient4423"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="2305.2668"
+       fx="951.68713"
+       fy="2305.2668"
+       r="951.68701" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3165"
+       id="radialGradient4425"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="1205.2668"
+       fx="951.68713"
+       fy="1205.2668"
+       r="951.68701" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3169"
+       id="radialGradient4427"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="2305.2668"
+       fx="951.68713"
+       fy="2305.2668"
+       r="951.68701" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3165"
+       id="radialGradient4429"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="1205.2668"
+       fx="951.68713"
+       fy="1205.2668"
+       r="951.68701" />
+    <filter
+       id="filter4485"
+       style="color-interpolation-filters:sRGB;"
+       inkscape:label="Drop Shadow">
+      <feFlood
+         id="feFlood4487"
+         flood-opacity="0.604"
+         flood-color="rgb(0,0,0)"
+         result="flood" />
+      <feComposite
+         id="feComposite4489"
+         in2="SourceGraphic"
+         in="flood"
+         operator="in"
+         result="composite1" />
+      <feGaussianBlur
+         id="feGaussianBlur4491"
+         in="composite"
+         stdDeviation="8"
+         result="blur" />
+      <feOffset
+         id="feOffset4493"
+         dx="10"
+         dy="10"
+         result="offset" />
+      <feComposite
+         id="feComposite4495"
+         in2="offset"
+         in="SourceGraphic"
+         operator="over"
+         result="composite2" />
+    </filter>
+  </defs>
+  <sodipodi:namedview
+     inkscape:cy="128.91168"
+     inkscape:cx="213.59793"
+     inkscape:zoom="2.4559706"
+     inkscape:window-height="1177"
+     inkscape:window-width="1462"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     guidetolerance="10.0"
+     gridtolerance="10.0"
+     objecttolerance="10.0"
+     borderopacity="1.0"
+     bordercolor="#666666"
+     pagecolor="#ffffff"
+     id="base"
+     showgrid="false"
+     inkscape:window-x="899"
+     inkscape:window-y="94"
+     inkscape:current-layer="svg2"
+     inkscape:window-maximized="0"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="20"
+     fit-margin-bottom="20" />
+  <g
+     id="g4439"
+     style="filter:url(#filter4485)">
+    <g
+       style="fill:url(#radialGradient4427);fill-opacity:1;stroke:url(#radialGradient4429);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;"
+       id="g3"
+       transform="matrix(0.1,0,0,0.1,1.967113,2.4742836)">
+      <g
+         id="g5"
+         style="fill:url(#radialGradient4423);fill-opacity:1;fill-rule:evenodd;stroke:url(#radialGradient4425);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;"
+         transform="translate(20.61545,-27.69425)">
+        <path
+           inkscape:connector-curvature="0"
+           style="fill:url(#radialGradient4415);fill-opacity:1;stroke:url(#radialGradient4417);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;"
+           id="path7"
+           d="m 931.07168,1164.597 248.86992,-331.80265 416.1687,1338.32935 286.6484,267.1042 -520.4224,0 -270.2797,-262.2181 0,-1033.0627 -160.98492,106.6818 -160.98492,-106.6818 0,1033.0627 -270.2797,262.2181 -520.4224,0 286.6484,-267.1042 416.1687,-1338.32935 248.86992,331.80265 z" />
+        <path
+           inkscape:connector-curvature="0"
+           style="fill:url(#radialGradient4419);fill-opacity:1;stroke:url(#radialGradient4421);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;"
+           id="path9"
+           d="m 931.07168,27.69425 224.03682,720.46517 -63.341,76.00913 L 931.07168,486.3269 770.37586,824.16855 707.03486,748.15942 931.07168,27.69425 z" />
+      </g>
+    </g>
+    <g
+       transform="matrix(2.8009121,0,0,2.8009121,97.173402,128.84062)"
+       id="g4373"
+       style="fill-rule:evenodd">
+      <path
+         id="rect3922"
+         d="m 30.19825,5.3569063 c 0.5796,0 1.046698,0.6864133 1.046698,1.5381453 l 0,25.8484734 c 0,0.851692 -0.467114,1.538145 -1.046698,1.538145 l -29.0366268,0 c -0.57960004,0 -1.04669856,-0.686421 -1.04669856,-1.538145 0,0 0.002884,-25.8275138 2.6458e-4,-25.8479191 0,-0.8516925 0.46711441,-1.5381453 1.04669858,-1.5381453 l 29.0366272,0 z"
+         inkscape:connector-curvature="0"
+         style="fill:#333333;stroke:#000000;stroke-width:0.22984983"
+         sodipodi:nodetypes="cssssccscc" />
+      <path
+         style="fill:#999999;stroke:#000000;stroke-width:0.26240885"
+         id="path4952"
+         d="m 4.3596675,0.13120443 0,0.7176181 -1.2452482,3.12200877 0,1.4500325 5.4990161,0 0,-1.4500325 -1.2406962,-3.12200877 0,-0.7176181 -3.0131735,0 z m 6.6261025,0 0,0.7176181 -1.2452487,3.12200877 0,1.4500325 5.4990167,0 0,-1.4500325 -1.240696,-3.12200877 0,-0.7176181 -3.013174,0 z m 6.621594,0 0,0.7176181 -1.240696,3.12200877 0,1.4500325 5.499015,0 0,-1.4500325 -1.240696,-3.12200877 0,-0.7176181 -3.017682,0 z m 6.626102,0 0,0.7176181 -1.240696,3.12200877 0,1.4500325 5.499015,0 0,-1.4500325 -1.240696,-3.12200877 0,-0.7176181 -3.017682,0 z"
+         inkscape:connector-curvature="0"
+         sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccc" />
+      <path
+         style="fill:#999999;stroke:#000000;stroke-width:0.26240885"
+         id="path4974"
+         d="m 3.1147829,34.371248 0,1.450032 1.2452481,3.122009 0,0.717618 3.0131736,0 0,-0.717618 1.2406961,-3.122009 0,-1.450032 -5.499016,0 z m 6.626102,0 0,1.450032 1.2452481,3.122009 0,0.717618 3.013173,0 0,-0.717618 1.240697,-3.122009 0,-1.450032 -5.4990163,0 z m 6.6261021,0 0,1.450032 1.240696,3.122009 0,0.717618 3.017683,0 0,-0.717618 1.240696,-3.122009 0,-1.450032 -5.499017,0 z m 6.626102,0 0,1.450032 1.240696,3.122009 0,0.717618 3.017683,0 0,-0.717618 1.240696,-3.122009 0,-1.450032 -5.499017,0 z"
+         inkscape:connector-curvature="0"
+         sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccc" />
+    </g>
+  </g>
+</svg>
diff --git a/icon/application-vnd.altusmetrum.micropeak.svg b/icon/application-vnd.altusmetrum.micropeak.svg
new file mode 120000 (symlink)
index 0000000..6efd320
--- /dev/null
@@ -0,0 +1 @@
+altusmetrum-micropeak.svg
\ No newline at end of file
diff --git a/icon/application-vnd.altusmetrum.telemetry.svg b/icon/application-vnd.altusmetrum.telemetry.svg
new file mode 100644 (file)
index 0000000..4bcc085
--- /dev/null
@@ -0,0 +1,397 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg2"
+   width="214.27165"
+   height="266.00192"
+   version="1.0"
+   sodipodi:version="0.32"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="application-vnd.altusmetrum.telemetry.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   inkscape:export-filename="/home/keithp/src/cc1111/altus-logo/bottom.png"
+   inkscape:export-xdpi="119.89881"
+   inkscape:export-ydpi="119.89881">
+  <metadata
+     id="metadata14">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs12">
+    <linearGradient
+       id="linearGradient3165">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop3167" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop3169" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3177">
+      <stop
+         style="stop-color:#da7000;stop-opacity:1;"
+         offset="0"
+         id="stop3179" />
+      <stop
+         id="stop3447"
+         offset="0.24528302"
+         style="stop-color:#a63852;stop-opacity:1;" />
+      <stop
+         style="stop-color:#7200a4;stop-opacity:1;"
+         offset="1"
+         id="stop3181" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3169">
+      <stop
+         style="stop-color:#ff8a00;stop-opacity:1;"
+         offset="0"
+         id="stop3171" />
+      <stop
+         id="stop3445"
+         offset="0.71698111"
+         style="stop-color:#c24573;stop-opacity:0.98039216;" />
+      <stop
+         style="stop-color:#8500e7;stop-opacity:0.96078432;"
+         offset="1"
+         id="stop3173" />
+    </linearGradient>
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 121 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="191 : 121 : 1"
+       inkscape:persp3d-origin="95.5 : 80.666667 : 1"
+       id="perspective16" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3169"
+       id="radialGradient3175"
+       cx="951.68713"
+       cy="2305.2668"
+       fx="951.68713"
+       fy="2305.2668"
+       r="951.68701"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3165"
+       id="radialGradient3171"
+       cx="951.68713"
+       cy="1205.2668"
+       fx="951.68713"
+       fy="1205.2668"
+       r="951.68701"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3169"
+       id="radialGradient3020"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="2305.2668"
+       fx="951.68713"
+       fy="2305.2668"
+       r="951.68701" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3165"
+       id="radialGradient3022"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="1205.2668"
+       fx="951.68713"
+       fy="1205.2668"
+       r="951.68701" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3169"
+       id="radialGradient3024"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="2305.2668"
+       fx="951.68713"
+       fy="2305.2668"
+       r="951.68701" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3165"
+       id="radialGradient3026"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="1205.2668"
+       fx="951.68713"
+       fy="1205.2668"
+       r="951.68701" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3169"
+       id="radialGradient3028"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="2305.2668"
+       fx="951.68713"
+       fy="2305.2668"
+       r="951.68701" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3165"
+       id="radialGradient3030"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="1205.2668"
+       fx="951.68713"
+       fy="1205.2668"
+       r="951.68701" />
+    <filter
+       id="filter3005"
+       inkscape:label="Drop Shadow"
+       color-interpolation-filters="sRGB">
+      <feFlood
+         id="feFlood3007"
+         flood-opacity="0.604"
+         flood-color="rgb(0,0,0)"
+         result="flood" />
+      <feComposite
+         id="feComposite3009"
+         in2="SourceGraphic"
+         in="flood"
+         operator="in"
+         result="composite1" />
+      <feGaussianBlur
+         id="feGaussianBlur3011"
+         stdDeviation="80"
+         result="blur" />
+      <feOffset
+         id="feOffset3013"
+         dx="100"
+         dy="100"
+         result="offset" />
+      <feComposite
+         id="feComposite3015"
+         in2="offset"
+         in="SourceGraphic"
+         operator="over"
+         result="composite2" />
+    </filter>
+    <filter
+       id="filter4113"
+       style="color-interpolation-filters:sRGB;"
+       inkscape:label="Drop Shadow">
+      <feFlood
+         id="feFlood4115"
+         flood-opacity="0.604"
+         flood-color="rgb(0,0,0)"
+         result="flood" />
+      <feComposite
+         id="feComposite4117"
+         in2="SourceGraphic"
+         in="flood"
+         operator="in"
+         result="composite1" />
+      <feGaussianBlur
+         id="feGaussianBlur4119"
+         in="composite"
+         stdDeviation="6"
+         result="blur" />
+      <feOffset
+         id="feOffset4121"
+         dx="7.5"
+         dy="7.5"
+         result="offset" />
+      <feComposite
+         id="feComposite4123"
+         in2="offset"
+         in="SourceGraphic"
+         operator="over"
+         result="composite2" />
+    </filter>
+    <filter
+       id="filter4125"
+       style="color-interpolation-filters:sRGB;"
+       inkscape:label="Drop Shadow">
+      <feFlood
+         id="feFlood4127"
+         flood-opacity="0.604"
+         flood-color="rgb(0,0,0)"
+         result="flood" />
+      <feComposite
+         id="feComposite4129"
+         in2="SourceGraphic"
+         in="flood"
+         operator="in"
+         result="composite1" />
+      <feGaussianBlur
+         id="feGaussianBlur4131"
+         in="composite"
+         stdDeviation="6"
+         result="blur" />
+      <feOffset
+         id="feOffset4133"
+         dx="7.5"
+         dy="7.5"
+         result="offset" />
+      <feComposite
+         id="feComposite4135"
+         in2="offset"
+         in="SourceGraphic"
+         operator="over"
+         result="composite2" />
+    </filter>
+    <filter
+       id="filter3082"
+       style="color-interpolation-filters:sRGB;"
+       inkscape:label="Drop Shadow">
+      <feFlood
+         id="feFlood3084"
+         flood-opacity="0.604"
+         flood-color="rgb(0,0,0)"
+         result="flood" />
+      <feComposite
+         id="feComposite3086"
+         in2="SourceGraphic"
+         in="flood"
+         operator="in"
+         result="composite1" />
+      <feGaussianBlur
+         id="feGaussianBlur3088"
+         in="composite"
+         stdDeviation="6"
+         result="blur" />
+      <feOffset
+         id="feOffset3090"
+         dx="7.5"
+         dy="7.5"
+         result="offset" />
+      <feComposite
+         id="feComposite3092"
+         in2="offset"
+         in="SourceGraphic"
+         operator="over"
+         result="composite2" />
+    </filter>
+  </defs>
+  <sodipodi:namedview
+     inkscape:cy="184.51843"
+     inkscape:cx="98.017058"
+     inkscape:zoom="1.7366335"
+     inkscape:window-height="1177"
+     inkscape:window-width="1462"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     guidetolerance="10.0"
+     gridtolerance="10.0"
+     objecttolerance="10.0"
+     borderopacity="1.0"
+     bordercolor="#666666"
+     pagecolor="#ffffff"
+     id="base"
+     showgrid="false"
+     inkscape:window-x="225"
+     inkscape:window-y="54"
+     inkscape:current-layer="svg2"
+     inkscape:window-maximized="0"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="20"
+     fit-margin-bottom="20" />
+  <path
+     sodipodi:type="arc"
+     style="opacity:0.98999999000000005;fill:none;fill-opacity:1;stroke:#8a08e8;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:none;stroke-dashoffset:0"
+     id="path3011"
+     sodipodi:cx="328.79059"
+     sodipodi:cy="127.97095"
+     sodipodi:rx="40.106342"
+     sodipodi:ry="37.459732"
+     d="m 368.89693,127.97095 a 40.106342,37.459732 0 1 1 -80.21268,0 40.106342,37.459732 0 1 1 80.21268,0 z" />
+  <g
+     id="g3032"
+     style="filter:url(#filter3082)">
+    <g
+       style="fill:url(#radialGradient3175);fill-opacity:1;stroke:url(#radialGradient3171);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;"
+       id="g3"
+       transform="matrix(0.1,0,0,0.1,1.967113,2.4742836)">
+      <g
+         id="g5"
+         style="fill:url(#radialGradient3028);fill-opacity:1;fill-rule:evenodd;stroke:url(#radialGradient3030);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;"
+         transform="translate(20.61545,-27.69425)">
+        <path
+           inkscape:connector-curvature="0"
+           style="fill:url(#radialGradient3020);fill-opacity:1;stroke:url(#radialGradient3022);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;"
+           id="path7"
+           d="m 931.07168,1164.597 248.86992,-331.80265 416.1687,1338.32935 286.6484,267.1042 -520.4224,0 -270.2797,-262.2181 0,-1033.0627 -160.98492,106.6818 -160.98492,-106.6818 0,1033.0627 -270.2797,262.2181 -520.4224,0 286.6484,-267.1042 416.1687,-1338.32935 248.86992,331.80265 z" />
+        <path
+           inkscape:connector-curvature="0"
+           style="fill:url(#radialGradient3024);fill-opacity:1;stroke:url(#radialGradient3026);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;"
+           id="path9"
+           d="m 931.07168,27.69425 224.03682,720.46517 -63.341,76.00913 L 931.07168,486.3269 770.37586,824.16855 707.03486,748.15942 931.07168,27.69425 z" />
+      </g>
+    </g>
+    <g
+       transform="translate(16.698976,134.16763)"
+       id="g3916">
+      <path
+         style="fill:#8a0ae8;fill-opacity:1;fill-rule:evenodd;stroke:#8a0ae8;stroke-width:8.48192120000000038;stroke-linecap:round;stroke-opacity:1;"
+         inkscape:connector-curvature="0"
+         d="m 117.80725,-96.247891 c 0,0 5.41921,5.552354 5.41921,16.111148 m -5.41921,16.044574 c 0,0 5.41921,-5.552354 5.41921,-16.111149"
+         id="path14345" />
+      <path
+         style="fill:#8a0ae8;fill-opacity:1;fill-rule:evenodd;stroke:#8a0ae8;stroke-width:8.48192120000000038;stroke-linecap:round;stroke-opacity:1;"
+         inkscape:connector-curvature="0"
+         d="m 136.30179,-112.33241 c 0,0 10.83841,11.11802 10.83841,32.235612 m -10.83841,32.089148 c 0,0 10.83841,-11.104709 10.83841,-32.222298"
+         id="path14347" />
+      <path
+         style="fill:#8a0ae8;fill-opacity:1;fill-rule:evenodd;stroke:#8a0ae8;stroke-width:8.48192120000000038;stroke-linecap:round;stroke-opacity:1;"
+         inkscape:connector-curvature="0"
+         d="m 156.46069,-128.40361 c 0,0 16.27093,16.65706 16.27093,48.333442 m -16.27093,48.147037 c 0,0 16.27093,-16.670379 16.27093,-48.346762"
+         id="path14349" />
+    </g>
+    <g
+       transform="translate(-17.850629,134.16763)"
+       id="g3911">
+      <path
+         style="fill:#8a0ae8;fill-opacity:1;fill-rule:evenodd;stroke:#8a0ae8;stroke-width:8.48192120000000038;stroke-linecap:round;stroke-opacity:1;"
+         inkscape:connector-curvature="0"
+         d="m 77.476121,-96.247891 c 0,0 -5.419205,5.552354 -5.419205,16.111148 m 5.419205,16.044574 c 0,0 -5.419205,-5.552354 -5.419205,-16.111149"
+         id="path14351" />
+      <path
+         style="fill:#8a0ae8;fill-opacity:1;fill-rule:evenodd;stroke:#8a0ae8;stroke-width:8.48192120000000038;stroke-linecap:round;stroke-opacity:1;"
+         inkscape:connector-curvature="0"
+         d="m 59.554132,-112.33241 c 0,0 -10.851724,11.11802 -10.851724,32.235612 m 10.851724,32.089148 c 0,0 -10.851724,-11.104709 -10.851724,-32.222298"
+         id="path14353" />
+      <path
+         style="fill:#8a0ae8;fill-opacity:1;fill-rule:evenodd;stroke:#8a0ae8;stroke-width:8.48192120000000038;stroke-linecap:round;stroke-opacity:1;"
+         inkscape:connector-curvature="0"
+         d="m 39.381908,-128.40361 c 0,0 -16.257613,16.65706 -16.257613,48.333442 m 16.257613,48.147037 c 0,0 -16.257613,-16.670379 -16.257613,-48.346762"
+         id="path14355" />
+    </g>
+  </g>
+</svg>
diff --git a/icon/creating-linux-icons b/icon/creating-linux-icons
new file mode 100644 (file)
index 0000000..5b034c0
--- /dev/null
@@ -0,0 +1,29 @@
+# To create linux icons and file associations
+
+1) Create mime type and install
+
+       http://www.freedesktop.org/wiki/Specifications/AddingMIMETutor/
+
+       # xdg-mime install --mode system org-altusmetrum-mimetypes.xml
+       # update-mime-database /usr/local/share/mime
+
+       On debian, 
+
+2) Create icons and install
+
+       For mime type   application/vnd.altusmetrum.telemetry
+       icon name       application-vnd.altusmetrum.telemetry.svg
+
+       All mime icons go in
+
+       /usr/share/icons/hicolor/scalable/mimetypes
+
+       Update the icon database
+
+       # update-icon-caches /usr/share/icons/hicolor
+
+3) Create .desktop file and install
+
+       # xdg-desktop-menu install --mode system altusmetrum-altosui.desktop
+
+       # update-desktop-database
diff --git a/icon/micropeak.svg b/icon/micropeak.svg
deleted file mode 100644 (file)
index d37130f..0000000
+++ /dev/null
@@ -1,219 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="49.03825"
-   height="43.606411"
-   id="svg2"
-   version="1.1"
-   inkscape:version="0.48.4 r9939"
-   sodipodi:docname="micropeak.svg">
-  <defs
-     id="defs4">
-    <linearGradient
-       id="linearGradient5343">
-      <stop
-         style="stop-color:#7200a4;stop-opacity:1;"
-         offset="0"
-         id="stop5345" />
-      <stop
-         style="stop-color:#da7000;stop-opacity:1;"
-         offset="1"
-         id="stop5347" />
-    </linearGradient>
-    <marker
-       inkscape:stockid="Arrow2Send"
-       orient="auto"
-       refY="0"
-       refX="0"
-       id="Arrow2Send"
-       style="overflow:visible">
-      <path
-         id="path3798"
-         style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
-         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
-         transform="matrix(-0.3,0,0,-0.3,0.69,0)"
-         inkscape:connector-curvature="0" />
-    </marker>
-    <marker
-       inkscape:stockid="Arrow1Send"
-       orient="auto"
-       refY="0"
-       refX="0"
-       id="Arrow1Send"
-       style="overflow:visible">
-      <path
-         id="path3780"
-         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
-         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
-         transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
-         inkscape:connector-curvature="0" />
-    </marker>
-    <marker
-       inkscape:stockid="Arrow2Mend"
-       orient="auto"
-       refY="0"
-       refX="0"
-       id="Arrow2Mend"
-       style="overflow:visible">
-      <path
-         id="path3792"
-         style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
-         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
-         transform="scale(-0.6,-0.6)"
-         inkscape:connector-curvature="0" />
-    </marker>
-    <marker
-       inkscape:stockid="Arrow1Lend"
-       orient="auto"
-       refY="0"
-       refX="0"
-       id="Arrow1Lend"
-       style="overflow:visible">
-      <path
-         id="path3768"
-         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
-         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
-         transform="matrix(-0.8,0,0,-0.8,-10,0)"
-         inkscape:connector-curvature="0" />
-    </marker>
-    <marker
-       inkscape:stockid="Arrow2Lend"
-       orient="auto"
-       refY="0"
-       refX="0"
-       id="Arrow2Lend"
-       style="overflow:visible">
-      <path
-         id="path3786"
-         style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
-         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
-         transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
-         inkscape:connector-curvature="0" />
-    </marker>
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient5343"
-       id="linearGradient5349"
-       x1="255.48561"
-       y1="275.90405"
-       x2="280.61411"
-       y2="275.90405"
-       gradientUnits="userSpaceOnUse" />
-    <filter
-       id="filter3027"
-       inkscape:label="Drop Shadow"
-       color-interpolation-filters="sRGB">
-      <feFlood
-         id="feFlood3029"
-         flood-opacity="0.604"
-         flood-color="rgb(0,0,0)"
-         result="flood" />
-      <feComposite
-         id="feComposite3031"
-         in2="SourceGraphic"
-         in="flood"
-         operator="in"
-         result="composite1" />
-      <feGaussianBlur
-         id="feGaussianBlur3033"
-         stdDeviation="1.6"
-         result="blur" />
-      <feOffset
-         id="feOffset3035"
-         dx="2"
-         dy="2"
-         result="offset" />
-      <feComposite
-         id="feComposite3037"
-         in2="offset"
-         in="SourceGraphic"
-         operator="over"
-         result="composite2" />
-    </filter>
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="8.160856"
-     inkscape:cx="33.152671"
-     inkscape:cy="27.859227"
-     inkscape:document-units="px"
-     inkscape:current-layer="layer1"
-     showgrid="false"
-     inkscape:window-width="1277"
-     inkscape:window-height="894"
-     inkscape:window-x="543"
-     inkscape:window-y="242"
-     inkscape:window-maximized="0"
-     fit-margin-top="-3"
-     fit-margin-left="-4"
-     fit-margin-right="-1"
-     fit-margin-bottom="0" />
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer"
-     id="layer1"
-     transform="translate(-241.43522,-252.43073)">
-    <g
-       id="g3000"
-       style="filter:url(#filter3027)">
-      <g
-         id="text2985"
-         style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#7200a4;fill-opacity:1;stroke:none;font-family:Minion Pro;-inkscape-font-specification:Minion Pro">
-        <path
-           inkscape:connector-curvature="0"
-           id="path3003"
-           style="font-size:36px;font-weight:500;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#7200a4;font-family:ITC Benguiat Gothic Std;-inkscape-font-specification:ITC Benguiat Gothic Std Medium"
-           d="m 257.20241,268.30647 c 0,-1.07999 -0.396,-1.872 -1.584,-1.872 -1.188,0 -1.584,0.79201 -1.584,1.872 l 0,8.676 c 0,2.88 -2.052,5.112 -4.824,5.112 -3.06,0 -4.104,-1.872 -4.104,-5.076 l 0,-8.712 c 0,-1.07999 -0.396,-1.872 -1.584,-1.872 -1.188,0 -1.584,0.79201 -1.584,1.872 l 0,21.924 c 0,1.08 0.396,1.872 1.584,1.872 1.188,0 1.584,-0.792 1.584,-1.872 l 0,-6.156 c 0.792,0.612 2.088,0.972 3.564,0.972 2.304,0 4.428,-0.792 5.652,-2.988 l 0.072,0.072 0,1.26 c 0,0.864 0.54,1.44 1.404,1.44 0.864,0 1.404,-0.576 1.404,-1.44 l 0,-15.084" />
-      </g>
-      <path
-         sodipodi:nodetypes="cssc"
-         inkscape:connector-curvature="0"
-         id="path2991"
-         d="m 256.93561,290.70327 c 3.04022,-0.24413 4.30317,-2.66932 5.38268,-5.56604 1.68059,-4.50963 3.67214,-15.86904 8.62227,-20.55527 4.0668,-3.85 8.22354,-3.46656 8.22354,-3.46656"
-         style="fill:none;stroke:url(#linearGradient5349);stroke-width:2.9000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:none" />
-      <path
-         inkscape:transform-center-y="-0.40889198"
-         inkscape:transform-center-x="-0.29194889"
-         d="m 282.7522,267.42614 -3.93403,-2.77705 -4.51792,1.66641 1.42544,-4.59964 -2.98096,-3.78185 4.815,-0.0657 2.67559,-4.00372 1.55039,4.55904 4.63457,1.30742 -3.85681,2.88333 z"
-         inkscape:randomized="0"
-         inkscape:rounded="0"
-         inkscape:flatsided="false"
-         sodipodi:arg2="1.7014539"
-         sodipodi:arg1="1.0731354"
-         sodipodi:r2="3.6257365"
-         sodipodi:r1="7.2514729"
-         sodipodi:cy="261.05426"
-         sodipodi:cx="279.29056"
-         sodipodi:sides="5"
-         id="path5341"
-         style="fill:none;stroke:#da7000;stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
-         sodipodi:type="star" />
-    </g>
-  </g>
-</svg>
diff --git a/icon/org-altusmetrum-mimetypes.xml b/icon/org-altusmetrum-mimetypes.xml
new file mode 100644 (file)
index 0000000..e8103c0
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<mime-info
+    xmlns="http://www.freedesktop.org/standards/shared-mime-info">
+  <mime-type type="application/vnd.altusmetrum.telemetry">
+    <comment>Altus Metrum Telemetry File</comment>
+    <glob pattern="*.telem"/>
+  </mime-type>
+  <mime-type type="application/vnd.altusmetrum.eeprom">
+    <comment>Altus Metrum Eeprom Log File</comment>
+    <glob pattern="*.eeprom"/>
+  </mime-type>
+  <mime-type type="application/vnd.altusmetrum.micropeak">
+    <comment>Altus Metrum MicroPeak Log File</comment>
+    <glob pattern="*.mpd"/>
+  </mime-type>
+</mime-info>
diff --git a/icon/telegps.svg b/icon/telegps.svg
deleted file mode 100644 (file)
index 1e390f3..0000000
+++ /dev/null
@@ -1,324 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="151.43401"
-   height="144.50209"
-   id="svg2"
-   version="1.1"
-   inkscape:version="0.48.4 r9939"
-   sodipodi:docname="telegps.svg">
-  <defs
-     id="defs4">
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3169"
-       id="radialGradient3175"
-       cx="951.68713"
-       cy="2305.2668"
-       fx="951.68713"
-       fy="2305.2668"
-       r="951.68701"
-       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       id="linearGradient3169">
-      <stop
-         style="stop-color:#ff8a00;stop-opacity:1;"
-         offset="0"
-         id="stop3171" />
-      <stop
-         id="stop3445"
-         offset="0.71698111"
-         style="stop-color:#c24573;stop-opacity:0.98039216;" />
-      <stop
-         style="stop-color:#8500e7;stop-opacity:0.96078432;"
-         offset="1"
-         id="stop3173" />
-    </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3165"
-       id="radialGradient3171"
-       cx="951.68713"
-       cy="1205.2668"
-       fx="951.68713"
-       fy="1205.2668"
-       r="951.68701"
-       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       id="linearGradient3165">
-      <stop
-         style="stop-color:#000000;stop-opacity:1;"
-         offset="0"
-         id="stop3167" />
-      <stop
-         style="stop-color:#000000;stop-opacity:0;"
-         offset="1"
-         id="stop3169" />
-    </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3169"
-       id="radialGradient2838"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
-       cx="951.68713"
-       cy="2305.2668"
-       fx="951.68713"
-       fy="2305.2668"
-       r="951.68701" />
-    <linearGradient
-       id="linearGradient3181">
-      <stop
-         style="stop-color:#ff8a00;stop-opacity:1;"
-         offset="0"
-         id="stop3183" />
-      <stop
-         id="stop3185"
-         offset="0.71698111"
-         style="stop-color:#c24573;stop-opacity:0.98039216;" />
-      <stop
-         style="stop-color:#8500e7;stop-opacity:0.96078432;"
-         offset="1"
-         id="stop3187" />
-    </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3165"
-       id="radialGradient2840"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
-       cx="951.68713"
-       cy="1205.2668"
-       fx="951.68713"
-       fy="1205.2668"
-       r="951.68701" />
-    <linearGradient
-       id="linearGradient3190">
-      <stop
-         style="stop-color:#000000;stop-opacity:1;"
-         offset="0"
-         id="stop3192" />
-      <stop
-         style="stop-color:#000000;stop-opacity:0;"
-         offset="1"
-         id="stop3194" />
-    </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3169"
-       id="radialGradient2830"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
-       cx="951.68713"
-       cy="2305.2668"
-       fx="951.68713"
-       fy="2305.2668"
-       r="951.68701" />
-    <linearGradient
-       id="linearGradient3197">
-      <stop
-         style="stop-color:#ff8a00;stop-opacity:1;"
-         offset="0"
-         id="stop3199" />
-      <stop
-         id="stop3201"
-         offset="0.71698111"
-         style="stop-color:#c24573;stop-opacity:0.98039216;" />
-      <stop
-         style="stop-color:#8500e7;stop-opacity:0.96078432;"
-         offset="1"
-         id="stop3203" />
-    </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3165"
-       id="radialGradient2832"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
-       cx="951.68713"
-       cy="1205.2668"
-       fx="951.68713"
-       fy="1205.2668"
-       r="951.68701" />
-    <linearGradient
-       id="linearGradient3206">
-      <stop
-         style="stop-color:#000000;stop-opacity:1;"
-         offset="0"
-         id="stop3208" />
-      <stop
-         style="stop-color:#000000;stop-opacity:0;"
-         offset="1"
-         id="stop3210" />
-    </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3169"
-       id="radialGradient2834"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
-       cx="951.68713"
-       cy="2305.2668"
-       fx="951.68713"
-       fy="2305.2668"
-       r="951.68701" />
-    <linearGradient
-       id="linearGradient3213">
-      <stop
-         style="stop-color:#ff8a00;stop-opacity:1;"
-         offset="0"
-         id="stop3215" />
-      <stop
-         id="stop3217"
-         offset="0.71698111"
-         style="stop-color:#c24573;stop-opacity:0.98039216;" />
-      <stop
-         style="stop-color:#8500e7;stop-opacity:0.96078432;"
-         offset="1"
-         id="stop3219" />
-    </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3165"
-       id="radialGradient2836"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
-       cx="951.68713"
-       cy="1205.2668"
-       fx="951.68713"
-       fy="1205.2668"
-       r="951.68701" />
-    <linearGradient
-       id="linearGradient3222">
-      <stop
-         style="stop-color:#000000;stop-opacity:1;"
-         offset="0"
-         id="stop3224" />
-      <stop
-         style="stop-color:#000000;stop-opacity:0;"
-         offset="1"
-         id="stop3226" />
-    </linearGradient>
-    <radialGradient
-       r="951.68701"
-       fy="2305.2668"
-       fx="951.68713"
-       cy="2305.2668"
-       cx="951.68713"
-       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
-       gradientUnits="userSpaceOnUse"
-       id="radialGradient3232"
-       xlink:href="#linearGradient3169"
-       inkscape:collect="always" />
-    <radialGradient
-       r="951.68701"
-       fy="1205.2668"
-       fx="951.68713"
-       cy="1205.2668"
-       cx="951.68713"
-       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
-       gradientUnits="userSpaceOnUse"
-       id="radialGradient3234"
-       xlink:href="#linearGradient3165"
-       inkscape:collect="always" />
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3169"
-       id="radialGradient4101"
-       cx="194.54575"
-       cy="361.16367"
-       fx="194.54575"
-       fy="361.16367"
-       r="70.597672"
-       gradientTransform="matrix(1,0,0,0.95908583,137.14286,74.776711)"
-       gradientUnits="userSpaceOnUse" />
-    <filter
-       id="filter3238"
-       inkscape:label="Drop Shadow"
-       color-interpolation-filters="sRGB">
-      <feFlood
-         id="feFlood3240"
-         flood-opacity="0.604"
-         flood-color="rgb(0,0,0)"
-         result="flood" />
-      <feComposite
-         id="feComposite3242"
-         in2="SourceGraphic"
-         in="flood"
-         operator="in"
-         result="composite1" />
-      <feGaussianBlur
-         id="feGaussianBlur3244"
-         stdDeviation="4"
-         result="blur" />
-      <feOffset
-         id="feOffset3246"
-         dx="5"
-         dy="5"
-         result="offset" />
-      <feComposite
-         id="feComposite3248"
-         in2="offset"
-         in="SourceGraphic"
-         operator="over"
-         result="composite2" />
-    </filter>
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="3.959798"
-     inkscape:cx="91.754359"
-     inkscape:cy="68.172898"
-     inkscape:document-units="px"
-     inkscape:current-layer="layer1"
-     showgrid="false"
-     fit-margin-top="-12"
-     fit-margin-left="-12"
-     fit-margin-right="-6"
-     fit-margin-bottom="-6"
-     inkscape:window-width="996"
-     inkscape:window-height="970"
-     inkscape:window-x="930"
-     inkscape:window-y="553"
-     inkscape:window-maximized="0" />
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer"
-     id="layer1"
-     transform="translate(-258.97144,-351.91262)">
-    <path
-       style="fill:url(#radialGradient4101);fill-opacity:1;filter:url(#filter3238)"
-       d="m 261.09094,466.61035 1.9122,-1.69399 39.0721,-36.4688 20.74158,22.05252 -40.71991,38.37279 z m 36.24983,1.34654 -14.08636,-15.38433 -15.33887,14.40857 14.50759,15.23741 z m 18.98704,-17.58715 -14.47613,-15.53942 -14.95191,14.42099 14.19976,15.37575 z m 43.2565,3.24033 -5.69326,-6.00917 -2.76929,1.85727 c -5.01515,3.36349 -10.61773,4.75193 -13.55344,3.35884 -0.90785,-0.4308 -11.20677,-10.85557 -16.46128,-16.61505 -6.3177,-6.92484 -17.77225,-18.68338 -18.08204,-21.53696 l -0.25491,-2.34789 -6.68224,-3.00173 -6.68224,-3.00173 -0.12416,-2.54849 c -0.24316,-4.99109 2.61694,-11.66135 7.10652,-16.57368 6.51922,-7.13306 14.23173,-10.81215 21.4071,-10.21178 l 2.49577,0.20881 2.34108,7.3087 2.34109,7.3087 2.0542,0.21626 c 1.12981,0.11895 2.29245,0.36702 2.58364,0.55127 0.29119,0.18424 11.17756,11.55849 16.63562,17.46044 5.67391,6.13537 16.35301,17.71615 16.74619,18.65715 1.36492,3.26672 -0.56522,9.34479 -4.44838,14.00803 -0.92939,1.1161 -1.6875,2.14976 -1.6847,2.29703 0.003,0.14726 2.44601,2.88431 5.42933,6.08233 2.98332,3.19801 5.42421,6.02814 5.42421,6.28919 0,0.66794 -0.91528,1.72591 -1.73982,2.01104 -0.50334,0.17406 -2.27007,-1.42112 -6.38899,-5.76858 z m -13.8944,-6.52384 c 0.96195,-0.49074 2.46683,-1.3673 3.34417,-1.94791 l 1.59519,-1.05564 -1.69025,-1.72225 c -1.71532,-1.74777 -2.09589,-2.99732 -1.1891,-3.90412 0.98407,-0.98406 2.33559,-0.53387 3.9423,1.31314 l 1.57825,1.81431 1.43638,-1.7099 c 1.7115,-2.03742 3.3933,-5.47555 3.39008,-6.9304 -0.0104,-4.68327 -7.01613,-2.68794 -13.36898,3.80766 -4.26282,4.35861 -6.32786,9.57528 -4.26584,10.77629 1.19252,0.69458 3.36009,0.51166 5.2278,-0.44118 z m -37.53066,-44.39022 c 2.23934,-2.70633 7.29399,-6.99375 10.13666,-8.59806 1.69887,-0.95877 2.21231,-1.46174 2.04152,-1.99985 -0.1255,-0.3954 -1.05734,-3.0661 -2.07077,-5.93487 l -1.84259,-5.21596 -1.60649,0.12825 c -4.1301,0.32972 -9.06228,2.86043 -13.29918,6.82384 -4.03277,3.77245 -7.7843,10.20829 -7.89014,13.53572 l -0.0463,1.4539 5.4085,2.47197 5.4085,2.47197 1.02919,-1.54008 c 0.56606,-0.84704 1.79503,-2.46562 2.73105,-3.59683 z m 32.91039,-10.47213 40.55794,-38.76942 c 7.09795,7.71166 14.5366,15.63755 20.65837,22.2503 l -40.53088,38.2414 z m 35.73645,1.02093 -14.2595,-15.3791 -15.29495,14.35785 14.65467,15.14661 z m 18.6801,-17.55816 -14.10162,-15.40128 -15.32812,14.3973 14.52992,15.24342 z"
-       id="path3063"
-       inkscape:connector-curvature="0"
-       sodipodi:nodetypes="ccccccccccccccccscssascccssscccscasscsssssccssscssssscssscssccccsccccccccccccccccc" />
-  </g>
-</svg>
diff --git a/icon/windows-stub.c b/icon/windows-stub.c
new file mode 100644 (file)
index 0000000..8df3e0a
--- /dev/null
@@ -0,0 +1,2 @@
+__stdcall
+WinMain(int a, int b, int c, int d) { return 0; }
index d2531133d9d1753d4eae555c57a38dbc714fb1a1..1db2d486d2173adf26c6639bbd529e0c79f47b32 100644 (file)
@@ -41,8 +41,7 @@ cjnitest64_LDADD=libaltos64.la
 
 endif
 
-
-LIBS=-lbluetooth
+LIBS=-ldl
 
 HFILES=libaltos.h
 
index b7ec98fc58f5c17994c523955b4e20c6d680f23d..4e3bc2c51b2d5b1f7fcd2eb9c8d090118657a13a 100644 (file)
@@ -643,6 +643,49 @@ altos_list_finish(struct altos_list *usbdevs)
        free(usbdevs);
 }
 
+#include <dlfcn.h>
+
+static void *libbt;
+static int bt_initialized;
+
+static int init_bt(void) {
+       if (!bt_initialized) {
+               bt_initialized = 1;
+               libbt = dlopen("libbluetooth.so.3", RTLD_LAZY);
+               if (!libbt)
+                       printf("failed to find bluetooth library\n");
+       }
+       return libbt != NULL;
+}
+
+#define join(a,b)      a ## b
+#define bt_func(name, ret, fail, formals, actuals)                     \
+       static ret join(altos_, name) formals {                         \
+                                     static ret (*name) formals;       \
+                                     if (!init_bt()) return fail;      \
+                                     name = dlsym(libbt, #name);       \
+                                     if (!name) return fail;           \
+                                     return name actuals;              \
+                                     }
+
+bt_func(ba2str, int, -1, (const bdaddr_t *ba, char *str), (ba, str))
+#define ba2str altos_ba2str
+
+bt_func(str2ba, int, -1, (const char *str, bdaddr_t *ba), (str, ba))
+#define str2ba altos_str2ba
+
+bt_func(hci_read_remote_name, int, -1, (int sock, const bdaddr_t *ba, int len, char *name, int timeout), (sock, ba, len, name, timeout))
+#define hci_read_remote_name altos_hci_read_remote_name
+
+bt_func(hci_open_dev, int, -1, (int dev_id), (dev_id))
+#define hci_open_dev altos_hci_open_dev
+
+bt_func(hci_get_route, int, -1, (bdaddr_t *bdaddr), (bdaddr))
+#define hci_get_route altos_hci_get_route
+
+bt_func(hci_inquiry, int, -1, (int adapter_id, int len, int max_rsp, const uint8_t *lap, inquiry_info **devs, long flags), (adapter_id, len, max_rsp, lap, devs, flags))
+#define hci_inquiry altos_hci_inquiry
+
 struct altos_bt_list {
        inquiry_info    *ii;
        int             sock;
@@ -706,7 +749,8 @@ altos_bt_list_next(struct altos_bt_list *bt_list,
                return 0;
 
        ii = &bt_list->ii[bt_list->rsp];
-       ba2str(&ii->bdaddr, device->addr);
+       if (ba2str(&ii->bdaddr, device->addr) < 0)
+               return 0;
        memset(&device->name, '\0', sizeof (device->name));
        if (hci_read_remote_name(bt_list->sock, &ii->bdaddr,
                                 sizeof (device->name),
@@ -742,11 +786,17 @@ altos_bt_open(struct altos_bt_device *device)
        struct altos_file *file;
 
        file = calloc(1, sizeof (struct altos_file));
-       if (!file)
+       if (!file) {
+               errno = ENOMEM;
+               altos_set_last_posix_error();
                goto no_file;
+       }
        addr.rc_family = AF_BLUETOOTH;
        addr.rc_channel = 1;
-       str2ba(device->addr, &addr.rc_bdaddr);
+       if (str2ba(device->addr, &addr.rc_bdaddr) < 0) {
+               altos_set_last_posix_error();
+               goto no_sock;
+       }
 
        for (i = 0; i < 5; i++) {
                file->fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
index f9a61359672ef4d4ce7f1730d8afe76e8a693893..2cf940a6cf46094b14f540154a847ac71dca04f1 100644 (file)
@@ -11,7 +11,7 @@ micropeak-windows.nsi
 MicroPeak-Linux-*
 MicroPeak-Mac-*
 MicroPeak-Windows-*
-micropeak.desktop
+*.desktop
 *.dll
 *.dylib
 *.so
index 40984c5aa7b887d2aa17c1eee695d719a644a37e..b1dc6cea439768d733c02baa9246a83e58ad043d 100644 (file)
        <key>CFBundleInfoDictionaryVersion</key>
        <string>6.0</string>
        <key>CFBundleIconFile</key>
-       <string>MicroPeak.icns</string>
+       <string>altusmetrum-micropeak.icns</string>
+       <key>CFBundleDocumentTypes</key>
+       <array>
+         <dict>
+           <key>CFBundleTypeName</key>
+           <string>MicroPeak data file</string>
+           <key>CFBundleTypeIconFile</key>
+           <string>application-vnd.altusmetrum.micropeak.icns</string>
+           <key>CFBundleTypeExtensions</key>
+           <array>
+             <string>mpd</string>
+           </array>
+           <key>CFBundleTypeRole</key>
+           <string>Editor</string>
+         </dict>
+       </array>
        <key>Java</key>
        <dict>
                <key>MainClass</key>
index 39ebc43a069df837a49ddf841c6a8783160c7ba4..158656068c963d2f7675cb0621eeee9806a96785 100644 (file)
@@ -56,26 +56,41 @@ ALTOSUILIB_CLASS=\
 ICONDIR=$(top_srcdir)/icon
 
 JAVA_ICONS=\
-       $(ICONDIR)/micropeak-16.png \
-       $(ICONDIR)/micropeak-32.png \
-       $(ICONDIR)/micropeak-48.png \
-       $(ICONDIR)/micropeak-64.png \
-       $(ICONDIR)/micropeak-128.png \
-       $(ICONDIR)/micropeak-256.png
+       $(ICONDIR)/altusmetrum-micropeak-16.png \
+       $(ICONDIR)/altusmetrum-micropeak-32.png \
+       $(ICONDIR)/altusmetrum-micropeak-48.png \
+       $(ICONDIR)/altusmetrum-micropeak-64.png \
+       $(ICONDIR)/altusmetrum-micropeak-128.png\
+       $(ICONDIR)/altusmetrum-micropeak-256.png
 
 # icon base names for jar
-ICONJAR= -C $(ICONDIR) micropeak-16.png \
-       -C $(ICONDIR) micropeak-32.png \
-       -C $(ICONDIR) micropeak-48.png \
-       -C $(ICONDIR) micropeak-64.png \
-       -C $(ICONDIR) micropeak-128.png \
-       -C $(ICONDIR) micropeak-256.png
-
-WINDOWS_ICON=$(ICONDIR)/micro-peak.ico
-MACOSX_ICON=$(ICONDIR)/MicroPeak.icns
+ICONJAR= \
+       -C $(ICONDIR) altusmetrum-micropeak-16.png \
+       -C $(ICONDIR) altusmetrum-micropeak-32.png \
+       -C $(ICONDIR) altusmetrum-micropeak-48.png \
+       -C $(ICONDIR) altusmetrum-micropeak-64.png \
+       -C $(ICONDIR) altusmetrum-micropeak-128.png\
+       -C $(ICONDIR) altusmetrum-micropeak-256.png
+
+WINDOWS_ICONS  =\
+       ../icon/altusmetrum-micropeak.ico \
+       ../icon/altusmetrum-micropeak.exe
+       ../icon/application-vnd.altusmetrum.micropeak.ico \
+       ../icon/application-vnd.altusmetrum.micropeak.ico
+
+MACOSX_ICONS   =\
+       ../icon/altusmetrum-micropeak.icns \
+       ../icon/application-vnd.altusmetrum.micropeak.icns
+
+LINUX_ICONS    =\
+       $(ICONDIR)/altusmetrum-micropeak.svg \
+       $(ICONDIR)/application-vnd.altusmetrum.micropeak.svg
+
+LINUX_MIMETYPE =\
+       $(ICONDIR)/org-altusmetrum-mimetypes.xml
 
 desktopdir = $(datadir)/applications
-desktop_file = micropeak.desktop
+desktop_file = altusmetrum-micropeak.desktop
 desktop_SCRIPTS = $(desktop_file)
 
 all-local: micropeak-test micropeak-jdb $(JAR)
@@ -87,12 +102,12 @@ clean-local:
                $(ALTOSUILIB_CLASS) \
                $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) Manifest.txt Manifest-fat.txt \
                micropeak micropeak-test micropeak-jdb macosx linux windows micropeak-windows.log \
-               micropeak-windows.nsi
+               micropeak-windows.nsi *.desktop
 
 EXTRA_DIST = $(desktop_file).in
 
 $(desktop_file): $(desktop_file).in
-       sed -e 's#%bindir%#@bindir@#' -e 's#%icondir%#$(datadir)/icons/hicolor/scalable/apps#' ${srcdir}/micropeak.desktop.in > $@
+       sed -e 's#%bindir%#@bindir@#' -e 's#%icondir%#$(datadir)/icons/hicolor/scalable/apps#' ${srcdir}/$(desktop_file).in > $@
        chmod +x $@
 
 LINUX_DIST=MicroPeak-Linux-$(VERSION).tar.bz2
@@ -106,14 +121,14 @@ DOC=$(MICROPEAK_DOC)
 
 FAT_FILES=$(FATJAR) $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) $(FREETTS_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS)
 
-LINUX_FILES=$(FAT_FILES) libaltos.so $(FIRMWARE) $(DOC) micropeak.desktop.in ../icon/micropeak.svg
-LINUX_EXTRA=micropeak-fat micropeak.desktop.in
+LINUX_FILES=$(FAT_FILES) libaltos.so $(FIRMWARE) $(DOC) $(desktop_file).in $(LINUX_ICONS) $(LINUX_MIMETYPE)
+LINUX_EXTRA=micropeak-fat $(desktop_file).in
 
 MACOSX_DRIVER_URL=http://www.ftdichip.com/Drivers/VCP/MacOSX/FTDIUSBSerialDriver_v2_2_18.dmg
 MACOSX_DRIVER=FTDIUSBSerialDriver_v2_2_18.dmg
 MACOSX_INFO_PLIST=Info.plist
 MACOSX_README=ReadMe-Mac.rtf
-MACOSX_FILES=$(FAT_FILES) libaltos.dylib $(MACOSX_INFO_PLIST) $(MACOSX_DRIVER) $(MACOSX_README) $(DOC) $(MACOSX_ICON)
+MACOSX_FILES=$(FAT_FILES) libaltos.dylib $(MACOSX_INFO_PLIST) $(MACOSX_DRIVER) $(MACOSX_README) $(DOC) $(MACOSX_ICONS)
 
 $(MACOSX_DRIVER):
        wget $(MACOSX_DRIVER_URL)
@@ -124,7 +139,7 @@ WINDOWS_DRIVER=CDM20824_Setup.exe
 $(WINDOWS_DRIVER):
        wget $(WINDOWS_DRIVER_URL)
 
-WINDOWS_FILES=$(FAT_FILES) altos.dll altos64.dll $(DOC) $(WINDOWS_ICON) $(WINDOWS_DRIVER)
+WINDOWS_FILES=$(FAT_FILES) altos.dll altos64.dll $(DOC) $(WINDOWS_ICONS) $(WINDOWS_DRIVER)
 
 if FATINSTALL
 
@@ -261,7 +276,7 @@ $(MACOSX_DIST): $(MACOSX_FILES)
        cp -p Info.plist macosx/MicroPeak.app/Contents
        cp -p $(MACOSX_DRIVER) macosx
        mkdir -p macosx/MicroPeak.app/Contents/Resources/Java
-       cp -p $(MACOSX_ICON) macosx/MicroPeak.app/Contents/Resources
+       cp -p $(MACOSX_ICONS) macosx/MicroPeak.app/Contents/Resources
        cp -p $(FATJAR) macosx/MicroPeak.app/Contents/Resources/Java/micropeak.jar
        cp -p libaltos.dylib macosx/MicroPeak.app/Contents/Resources/Java
        cp -p $(ALTOSLIB_CLASS) macosx/MicroPeak.app/Contents/Resources/Java
index ca211f16ee33553edfc102a71741582d817ee226..c38ada9151868a8e69e704cec6d6f42f01dabe1f 100644 (file)
@@ -20,8 +20,8 @@ package org.altusmetrum.micropeak;
 import java.lang.*;
 import java.io.*;
 import java.util.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 class MicroIterator implements Iterator<MicroDataPoint> {
        int             i;
@@ -97,9 +97,15 @@ public class MicroData implements AltosUIDataSet {
        private double          time_step;
        private double          ground_altitude;
        private ArrayList<Integer>      bytes;
+       public int              log_id;
        String                  name;
        MicroStats              stats;
-       
+
+       public static final int LOG_ID_MICROPEAK = 0;
+       public static final int LOG_ID_MICROKITE = 1;
+
+       public static final double CLOCK = 0.096;
+
        public class FileEndedException extends Exception {
        }
 
@@ -172,7 +178,7 @@ public class MicroData implements AltosUIDataSet {
                        if (get_nonwhite(f) == 'M' && get_nonwhite(f) == 'P')
                                return true;
                }
-       } 
+       }
 
        private int get_32(InputStream f)  throws IOException, FileEndedException, NonHexcharException {
                int     v = 0;
@@ -345,6 +351,9 @@ public class MicroData implements AltosUIDataSet {
                        ground_pressure = get_32(f);
                        min_pressure = get_32(f);
                        int nsamples = get_16(f);
+
+                       log_id = nsamples >> 12;
+                       nsamples &= 0xfff;
                        pressures = new int[nsamples + 1];
 
                        ground_altitude = AltosConvert.pressure_to_altitude(ground_pressure);
@@ -367,7 +376,7 @@ public class MicroData implements AltosUIDataSet {
                                        else
                                                cur = down;
                                }
-                               
+
                                pressures[i+1] = cur;
                        }
 
@@ -376,7 +385,14 @@ public class MicroData implements AltosUIDataSet {
 
                        crc_valid = crc == current_crc;
 
-                       time_step = 0.192;
+                       switch (log_id) {
+                       case LOG_ID_MICROPEAK:
+                               time_step = 2 * CLOCK;
+                               break;
+                       case LOG_ID_MICROKITE:
+                               time_step = 200 * CLOCK;
+                               break;
+                       }
                        stats = new MicroStats(this);
                } catch (FileEndedException fe) {
                        throw new IOException("File Ended Unexpectedly");
@@ -389,5 +405,5 @@ public class MicroData implements AltosUIDataSet {
                pressures = new int[1];
                pressures[0] = 101000;
        }
-       
+
 }
index 5a5e8c372c2d6788cad7be180e784ab0f984fd50..849ae5365abca7cedcda0b5c41c58ef4603a7da6 100644 (file)
@@ -17,7 +17,7 @@
 
 package org.altusmetrum.micropeak;
 
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class MicroDataPoint implements AltosUIDataPoint {
        public double           time;
index 305421a7b377ac45f2833ba11216baf1c3f95db9..304eac7df05318e4c6c3cb68b7a19c43f907020a 100644 (file)
@@ -21,7 +21,7 @@ import javax.swing.*;
 import java.awt.*;
 import java.awt.event.*;
 import java.util.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class MicroDeviceDialog extends AltosDeviceDialog {
 
index 1c70e1d1515da21cc94aa9bc951ea9cc123cde94..32dd04508d20e50c0e8cbdc1d7c02eb3b47d29c4 100644 (file)
@@ -23,8 +23,8 @@ import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
 import java.util.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class MicroDownload extends AltosUIDialog implements Runnable, ActionListener, MicroSerialLog, WindowListener {
        MicroPeak       owner;
index 87d5499b70417d5e91c6cc906a856f3705698250..8d62ace680d3c4899ae6e277437b49f134b08af3 100644 (file)
@@ -23,8 +23,8 @@ import java.util.ArrayList;
 import java.awt.*;
 import javax.swing.*;
 import javax.swing.filechooser.FileNameExtensionFilter;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class MicroExport extends JFileChooser {
 
index 019346aef29637baaafec278776bfc3a8aa55f84..d6abfcb717869ee3ec7421f4b37aab24fc4d421d 100644 (file)
@@ -19,8 +19,8 @@ package org.altusmetrum.micropeak;
 
 import java.io.*;
 import java.util.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class MicroFile {
 
index 00b6690a37858de5f231315a906667375666c2ac..371c22d0eb9a9a68a0d4e18eedb9faf99181b8b6 100644 (file)
@@ -20,8 +20,8 @@ package org.altusmetrum.micropeak;
 import javax.swing.*;
 import javax.swing.filechooser.FileNameExtensionFilter;
 import java.io.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class MicroFileChooser extends JFileChooser {
        JFrame  frame;
index 5bfe5bf7bd18e30851b01153568909bfeced6231..8b3d49b561629501e6d426d4ce7a80862e014b28 100644 (file)
@@ -21,16 +21,16 @@ import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
 import java.util.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class MicroFrame extends AltosUIFrame {
        static String[] micro_icon_names = {
-               "/micropeak-16.png",
-               "/micropeak-32.png",
-               "/micropeak-48.png",
-               "/micropeak-64.png",
-               "/micropeak-128.png",
-               "/micropeak-256.png"
+               "/altusmetrum-micropeak-16.png",
+               "/altusmetrum-micropeak-32.png",
+               "/altusmetrum-micropeak-48.png",
+               "/altusmetrum-micropeak-64.png",
+               "/altusmetrum-micropeak-128.png",
+               "/altusmetrum-micropeak-256.png"
        };
 
        static { set_icon_names(micro_icon_names); }
index f99689197ffa649ba95f70395965eddad149b8f0..811b1e7c14984c6511e46611285371f9c6a4538a 100644 (file)
@@ -22,8 +22,8 @@ import java.util.ArrayList;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 import org.jfree.ui.*;
 import org.jfree.chart.*;
diff --git a/micropeak/MicroPeak.app/Contents/Resources/MicroPeak.icns b/micropeak/MicroPeak.app/Contents/Resources/MicroPeak.icns
deleted file mode 100644 (file)
index 9ba83bf..0000000
Binary files a/micropeak/MicroPeak.app/Contents/Resources/MicroPeak.icns and /dev/null differ
index 19e91660d6226017cddef42640a748108d2e60e4..1744e8033cc6dd08842b9e1eee36c72d11e749e2 100644 (file)
@@ -23,8 +23,8 @@ import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
 import java.util.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class MicroPeak extends MicroFrame implements ActionListener, ItemListener {
 
@@ -107,7 +107,7 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene
 
        private void DownloadData() {
                AltosDevice     device = MicroDeviceDialog.show(this);
-               
+
                if (device != null)
                        new MicroDownload(this, device);
        }
@@ -128,7 +128,7 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene
                if (save.runDialog())
                        SetName(data.name);
        }
-       
+
        private void Export() {
                if (data == null) {
                        no_data();
@@ -190,10 +190,25 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene
        public void itemStateChanged(ItemEvent e) {
        }
 
+       /* OSXAdapter interfaces */
+       public void macosx_file_handler(String path) {
+               CommandGraph(new File(path));
+       }
+
+       public void macosx_quit_handler() {
+               System.exit(0);
+       }
+
+       public void macosx_preferences_handler() {
+               Preferences();
+       }
+
        public MicroPeak() {
 
                ++number_of_windows;
 
+               register_for_macosx_events();
+
                AltosUIPreferences.set_component(this);
 
                container = getContentPane();
index 26d62012982f097df604e45a93a0249edc0f402d..7a225dcbcc39933c7e557a292516753548889a9c 100644 (file)
@@ -20,8 +20,8 @@ package org.altusmetrum.micropeak;
 import java.awt.*;
 import java.io.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class MicroRaw extends JTextArea {
 
index 7c5d6abe99dcfb093d848d7e266237fe90126707..9497fb33544c8a02c38292c808431e1180074a1e 100644 (file)
@@ -24,8 +24,8 @@ import javax.swing.filechooser.FileNameExtensionFilter;
 import java.io.*;
 import java.util.concurrent.*;
 import java.util.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class MicroSave extends JFileChooser {
 
index 37b68636b73dd639d3e57445b6e4bf6b6fcd5859..f5108c22dee8e5a9a53903b288754d06e426d502 100644 (file)
@@ -20,7 +20,7 @@ package org.altusmetrum.micropeak;
 import java.util.*;
 import java.io.*;
 import libaltosJNI.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class MicroSerial extends InputStream {
        SWIGTYPE_p_altos_file   file;
index 7300f06d33856e8b47a3d43528303a837c29bb96..c49b69ab8130f2b87e58e3cb608c60f3dc58acc3 100644 (file)
@@ -20,7 +20,7 @@ package org.altusmetrum.micropeak;
 import java.util.*;
 import java.io.*;
 import libaltosJNI.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public interface MicroSerialLog {
 
index 45c9f225131b5babf3212622a7d85e4d20984e53..3fc05bd6cc85aa2c5c388627dfd779afdca021fb 100644 (file)
@@ -18,8 +18,8 @@
 package org.altusmetrum.micropeak;
 
 import java.io.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class MicroStats {
        double          coast_height;
index 3b17e731fff1112e1ff093b21e5d0df0d4a946eb..d6265fe8c70a7873361e8d8fcf29bfc7de9eece6 100644 (file)
@@ -19,8 +19,8 @@ package org.altusmetrum.micropeak;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class MicroStatsTable extends JComponent implements AltosFontListener {
        GridBagLayout   layout;
index 437fa0bcde45c54374d2591814d0fca144b47460..24f6722b79a9b69d9e47a2d6ebe9fe210fd17395 100644 (file)
@@ -19,7 +19,7 @@ package org.altusmetrum.micropeak;
 
 import java.util.*;
 import libaltosJNI.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class MicroUSB extends altos_device implements AltosDevice {
 
diff --git a/micropeak/altusmetrum-micropeak.desktop.in b/micropeak/altusmetrum-micropeak.desktop.in
new file mode 100644 (file)
index 0000000..782b470
--- /dev/null
@@ -0,0 +1,10 @@
+[Desktop Entry]
+Type=Application
+Name=MicroPeak
+GenericName=MicroPeak Download and Analysis
+Comment=View and log data from MicroPeak altimeters
+Icon=%icondir%/altusmetrum-micropeak.svg
+Exec=%bindir%/micropeak %f
+Terminal=false
+MimeType=application/vnd.altusmetrum.micropeak
+Categories=Education;Electronics;Science;
index bb5da1bb64e4e33846344a57bb5e3c5c9058e43b..848523b03d79fc34d6b9f5e58a0c202be43235c5 100644 (file)
@@ -1,15 +1,24 @@
-!addplugindir Instdrv/NSIS/Plugins
+!addplugindir ../altosui/Instdrv/NSIS/Plugins
 !addincludedir ../altosui/Instdrv/NSIS/Includes
 !include x64.nsh
 !include java.nsh
+!include refresh-sh.nsh
 
-Name "Altus Metrum MicroPeak Installer"
+!define REG_NAME       "MicroPeak"
+!define PROG_ID                "org.altusmetrum.micropeak.1"
+!define PROG_ID_MPD    "org.altusmetrum.micropeak.mpd.1"
+!define FAT_NAME       "micropeak-fat.jar"
+!define WIN_APP_ICON   "altusmetrum-micropeak.ico"
+!define WIN_APP_EXE    "altusmetrum-micropeak.exe"
+!define WIN_MPD_EXE    "application-vnd.altusmetrum.micropeak.exe"
+
+Name "${REG_NAME} Installer"
 
 ; Default install directory
 InstallDir "$PROGRAMFILES\AltusMetrum"
 
 ; Tell the installer where to re-install a new version
-InstallDirRegKey HKLM "Software\AltusMetrum" "Install_Dir"
+InstallDirRegKey HKLM "Software\${REG_NAME}" "Install_Dir"
 
 LicenseText "GNU General Public License Version 2"
 LicenseData "../COPYING"
@@ -19,7 +28,7 @@ RequestExecutionLevel admin
 
 ShowInstDetails Show
 
-ComponentText "Altus Metrum MicroPeak Software Installer"
+ComponentText "${REG_NAME} Software and Driver Installer"
 
 Function .onInit
        DetailPrint "Checking host operating system"
@@ -31,6 +40,16 @@ Function .onInit
        ${EndIf}
 FunctionEnd
 
+Function un.onInit
+       DetailPrint "Checking host operating system"
+       ${If} ${RunningX64}
+               DetailPrint "Installer running on 64-bit host"
+               SetRegView 64
+               StrCpy $INSTDIR "$PROGRAMFILES64\AltusMetrum"
+               ${DisableX64FSRedirection}
+       ${EndIf}
+FunctionEnd
+
 ; Pages to present
 
 Page license
@@ -43,12 +62,21 @@ UninstPage instfiles
 
 ; And the stuff to install
 
-Section "MicroPeak Application"
+Section "FTDI USB Driver"
+       SetOutPath $INSTDIR
+
+       File "CDM20824_Setup.exe"
+
+       StrCpy $2 "$INSTDIR\CDM20824_Setup.exe"
+       ExecWait $2
+SectionEnd
+
+Section "${REG_NAME} Application"
        Call DetectJRE
 
        SetOutPath $INSTDIR
 
-       File "micropeak-fat.jar"
+       File "${FAT_NAME}"
        File "altoslib_@ALTOSLIB_VERSION@.jar"
        File "altosuilib_@ALTOSUILIB_VERSION@.jar"
        File "jfreechart.jar"
@@ -56,22 +84,13 @@ Section "MicroPeak Application"
 
        File "*.dll"
 
-       File "../icon/*.ico"
-
-       CreateShortCut "$SMPROGRAMS\MicroPeak.lnk" "$SYSDIR\javaw.exe" "-jar micropeak-fat.jar" "$INSTDIR\micro-peak.ico"
-SectionEnd
-
-Section "FTDI USB Driver"
-       SetOutPath $INSTDIR
-
-       File "CDM20824_Setup.exe"
+       File "../icon/${WIN_APP_ICON}"
 
-       StrCpy $2 "$INSTDIR\CDM20824_Setup.exe"
-       ExecWait $2
+       CreateShortCut "$SMPROGRAMS\${REG_NAME}.lnk" "$SYSDIR\javaw.exe" "-jar ${FAT_NAME}" "$INSTDIR\${WIN_APP_ICON}"
 SectionEnd
 
-Section "MicroPeak Desktop Shortcut"
-       CreateShortCut "$DESKTOP\MicroPeak.lnk" "$INSTDIR\micropeak-fat.jar"  "" "$INSTDIR\micro-peak.ico"
+Section "${REG_NAME} Desktop Shortcut"
+       CreateShortCut "$DESKTOP\${REG_NAME}.lnk" "$INSTDIR\${FAT_NAME}"  "" "$INSTDIR\${WIN_APP_ICON}"
 SectionEnd
 
 Section "Documentation"
@@ -81,33 +100,79 @@ Section "Documentation"
        File "../doc/micropeak.pdf"
 SectionEnd
 
+Section "File Associations"
+
+       SetOutPath $INSTDIR
+
+       File "../icon/${WIN_APP_EXE}"
+       File "../icon/${WIN_MPD_EXE}"
+
+       ; application elements
+       
+       DeleteRegKey HKCR "${PROG_ID}"
+       DeleteRegKey HKCR "${PROG_ID_MPD}"
+
+       WriteRegStr HKCR "${PROG_ID_MPD}"               ""                              "MicroPeak Data File"
+       WriteRegStr HKCR "${PROG_ID_MPD}"               "FriendlyTypeName"              "MicroPeak Data File"
+       WriteRegStr HKCR "${PROG_ID_MPD}\CurVer"        ""                              "${PROG_ID_MPD}"
+       WriteRegStr HKCR "${PROG_ID_MPD}\DefaultIcon"   ""                              '"$INSTDIR\${WIN_MPD_EXE}",-101'
+  WriteRegExpandStr HKCR "${PROG_ID_MPD}\shell\play\command" ""                                '"%SYSTEMROOT%\System32\javaw.exe" -Djava.library.path="$INSTDIR" -jar "$INSTDIR\${FAT_NAME}" "%1"'
+
+       ; .mpd elements
+
+       WriteRegStr HKCR ".mpd"                         ""                              "${PROG_ID_MPD}"
+       WriteRegStr HKCR ".mpd"                         "PerceivedType"                 "MicroPeak Data File"
+       WriteRegStr HKCR ".mpd"                         "Content Type"                  "application/vnd.altusmetrum.micropeak"
+
+       WriteRegStr HKCR ".mpd\OpenWithProgids"         "${PROG_ID_MPD}"                        ""
+       WriteRegStr HKCR ".mpd\${PROG_ID_MPD}"          ""                              "${REG_NAME}"
+
+       Call RefreshShellIcons
+SectionEnd
+       
 Section "Uninstaller"
 
        ; Deal with the uninstaller
 
+       ${DisableX64FSRedirection}
        SetOutPath $INSTDIR
 
        ; Write the install path to the registry
-       WriteRegStr HKLM SOFTWARE\AltusMetrum "Install_Dir" "$INSTDIR"
+       WriteRegStr HKLM "SOFTWARE\${REG_NAME}" "Install_Dir" "$INSTDIR"
 
        ; Write the uninstall keys for windows
-       WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "DisplayName" "Altus Metrum"
-       WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "UninstallString" '"$INSTDIR\uninstall.exe"'
-       WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "NoModify" "1"
-       WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "NoRepair" "1"
+       WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "DisplayName" "${REG_NAME}"
+       WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "UninstallString" '"$INSTDIR\uninstall-${REG_NAME}.exe"'
+       WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "NoModify" "1"
+       WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "NoRepair" "1"
 
-       WriteUninstaller "uninstall.exe"
+       WriteUninstaller "uninstall-${REG_NAME}.exe"
 SectionEnd
 
 Section "Uninstall"
-       DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum"
-       DeleteRegKey HKLM "Software\AltusMetrum"
 
-       Delete "$INSTDIR\*.*"
-       RMDir "$INSTDIR"
+       ${DisableX64FSRedirection}
+
+       DeleteRegKey   HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}"
+       DeleteRegKey   HKLM "SOFTWARE\${REG_NAME}"
+
+       DetailPrint "Delete uninstall reg entries"
+
+       DeleteRegKey   HKCR "${PROG_ID}"
+       DeleteRegKey   HKCR "${PROG_ID_MPD}"
+
+       DeleteRegKey   HKCR ".mpd\${PROG_ID_MPD}"
+       DeleteRegValue HKCR ".mpd\OpenWithProgids" "${PROG_ID_MPD}"
+
+       Delete "$INSTDIR\${FAT_NAME}"
+       Delete "$INSTDIR\uninstall-${REG_NAME}.exe"
+
+       Delete "$INSTDIR\${WIN_APP_ICON}"
+       Delete "$INSTDIR\${WIN_APP_EXE}"
 
        ; Remove shortcuts, if any
-       Delete "$SMPROGRAMS\MicroPeak.lnk"
-       Delete "$DESKTOP\MicroPeak.lnk"
+       Delete "$SMPROGRAMS\${REG_NAME}.lnk"
+       Delete "$DESKTOP\${REG_NAME}.lnk"
        
+       Call un.RefreshShellIcons
 SectionEnd
diff --git a/micropeak/micropeak.desktop.in b/micropeak/micropeak.desktop.in
deleted file mode 100644 (file)
index abdf286..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-[Desktop Entry]
-Type=Application
-Name=MicroPeak
-GenericName=MicroPeak download and analysis
-Comment=View and log data from MicroPeak altimeters
-Icon=%icondir%/micropeak.svg
-Exec=%bindir%/micropeak %f
-Terminal=false
-MimeType=text/plain;
-Categories=Education;Electronics;Science;
index 4e8b3c20c6a94562676cd67fffb28606b5b441b8..20126de6771b336f1e54b631496e7a7ab07952c2 100644 (file)
@@ -22,9 +22,11 @@ SDCCDIRS=\
        telemini-v1.0 telemini-v2.0 \
        telebt-v1.0 \
        teleterra-v0.2 teleshield-v0.1 \
-       telefire-v0.1 telefire-v0.2
+       telefire-v0.1 telefire-v0.2 \
+       telerepeat-v1.0
 
 ARMM3DIRS=\
+       easymega-v1.0 easymega-v1.0/flash-loader \
        telemega-v0.1 telemega-v0.1/flash-loader \
        telemega-v1.0 telemega-v1.0/flash-loader \
        telemetrum-v2.0 telemetrum-v2.0/flash-loader \
@@ -39,7 +41,7 @@ ARMM0DIRS=\
        easymini-v1.0 easymini-v1.0/flash-loader
 
 AVRDIRS=\
-       telescience-v0.1 telescience-pwm micropeak nanopeak-v0.1
+       telescience-v0.1 telescience-pwm micropeak nanopeak-v0.1 microkite
 
 SUBDIRS=
 
@@ -98,7 +100,7 @@ uninstall:
 
 all-recursive: all-local
 
-all-local: altitude.h altitude-pa.h ao_kalman.h ao_whiten.h $(PDCLIB)
+all-local: altitude.h altitude-pa.h altitude-pa-small.h ao_kalman.h ao_whiten.h $(PDCLIB)
 
 altitude.h: make-altitude
        nickle $< > $@
@@ -106,7 +108,10 @@ altitude.h: make-altitude
 altitude-pa.h: make-altitude-pa
        nickle $< > $@
 
-ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c
+altitude-pa-small.h: make-altitude-pa
+       nickle $< --sample 3 > $@
+
+ao_kalman.h: make-kalman kalman.5c kalman_micro.5c kalman_filter.5c load_csv.5c matrix.5c
        bash $< kalman > $@
 
 ao_whiten.h: make-whiten
index 632e2a850caa17e8b148717b4200caf08c6aaa54..eb3535c6933f4b42797a6ee0a5932858159a80ec 100644 (file)
@@ -129,6 +129,8 @@ ao_intflash_write_aligned(uint16_t pos, __xdata void *d, uint16_t len) __reentra
                nop
                _endasm;
        }
+       __critical while (!ao_intflash_dma_done)
+                          ao_sleep(&ao_intflash_dma_done);
 }
 
 static void
index 2b19f1f6b4bc20f986443c904e400f6f171f871a..e12f813f8b0b7f8a48fef078252f093de42bb615 100644 (file)
@@ -20,6 +20,8 @@
 
 #define HAS_RADIO              1
 #define DISABLE_LOG_SPACE      1
+#define AO_VALUE_32            0
+#define HAS_WIDE_GPS           0
 
 #if defined(TELEMETRUM_V_1_0)
        /* Discontinued and was never built with CC1111 chips needing this */
@@ -56,6 +58,9 @@
        #define HAS_ACCEL               1
        #define HAS_IGNITE              1
        #define HAS_MONITOR             0
+       #define HAS_TELEMETRY           1
+       #define HAS_RADIO_RATE          0       /* not enough space for this */
+       #define HAS_MUTEX_TRY           0
 #endif
 
 #if defined(TELEMETRUM_V_1_1)
        #define HAS_ACCEL               1
        #define HAS_IGNITE              1
        #define HAS_MONITOR             0
+       #define HAS_TELEMETRY           1
+       #define HAS_RADIO_RATE          0       /* not enough space for this */
+       #define HAS_MUTEX_TRY           0
 #endif
 
 #if defined(TELEMETRUM_V_1_2)
        #define HAS_ACCEL               1
        #define HAS_IGNITE              1
        #define HAS_MONITOR             0
+       #define HAS_TELEMETRY           1
+       #define HAS_RADIO_RATE          0       /* not enough space for this */
+       #define HAS_MUTEX_TRY           0
 #endif
 
 #if defined(TELEDONGLE_V_0_2)
        #define LEGACY_MONITOR          1
        #define HAS_RSSI                1
        #define HAS_AES                 0
+       #define HAS_TELEMETRY           0
+       #define AO_RADIO_REG_TEST       1
 #endif
 
 #if defined(TELEMINI_V_1_0)
        #define HAS_ACCEL               0
        #define HAS_IGNITE              1
        #define HAS_MONITOR             0
+       #define HAS_TELEMETRY           1
+       #define HAS_RADIO_RATE          0       /* not enough space for this */
 #endif
 
 #if defined(TELENANO_V_0_1)
        #define HAS_ACCEL               0
        #define HAS_IGNITE              0
        #define HAS_MONITOR             0
+       #define HAS_TELEMETRY           1
+       #define HAS_RADIO_RATE          0       /* not enough space for this */
 #endif
 
 #if defined(TELEMETRUM_V_0_1)
        #define HAS_ACCEL               1
        #define HAS_IGNITE              1
        #define HAS_MONITOR             0
+       #define HAS_TELEMETRY           1
+       #define HAS_RADIO_RATE          0       /* not enough space for this */
        #define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX        ((uint32_t) 127 * (uint32_t) 1024)
 #endif
 
        #define LEGACY_MONITOR          1
        #define HAS_RSSI                1
        #define HAS_AES                 0
+       #define HAS_TELEMETRY           0
 #endif
 
 #if defined(TIDONGLE)
        #define LEGACY_MONITOR          1
        #define HAS_RSSI                1
        #define HAS_AES                 0
+       #define HAS_TELEMETRY           0
 #endif
 
 #if defined(TELEBT_V_0_0)
        #define LEGACY_MONITOR          1
        #define HAS_RSSI                0
        #define HAS_AES                 0
+       #define HAS_TELEMETRY           0
+       #define AO_RADIO_REG_TEST       1
 #endif
 
 #if defined(TELEBT_V_0_1)
        #define LEGACY_MONITOR          1
        #define HAS_RSSI                0
        #define HAS_AES                 0
+       #define HAS_TELEMETRY           0
+       #define AO_RADIO_REG_TEST       1
 #endif
 
 #if defined(TELELAUNCH_V_0_1)
        #define HAS_IGNITE              1
        #define HAS_MONITOR             0
        #define HAS_AES                 1
+       #define HAS_TELEMETRY           0
 #endif
 
 #if DBG_ON_P1
index 190647ce0dbe432f6a0b4ee5f8428b686110cf69..b9821a4237ab950caecebb6bac85defb30ccbff2 100644 (file)
 #define IF_FREQ_CONTROL        6
 
 /*
+ *  http://www.ntia.doc.gov/files/ntia/publications/84-168.pdf
+ *
+ * Necessary bandwidth for a FSK modulated signal:
+ *
+ *     bw = 2.6d + 0.55b       1.5 < m < 5.5
+ *     bw = 2.1d + 1.9b        5.5 < m < 20
+ *
+ *     b is the modulation rate in bps
+ *     d is the peak deviation (from the center)
+ *
+ *     m = 2d / b
+ *
+ * 20.5 kHz deviation 38.4kbps signal:
+ *
+ *     m = 41 / 38.4, which is < 5.5:
+ *
+ *     bw = 2.6 * 20.5 + 0.55 * 38.4 = 74.42kHz
+ *
+ *     M = 1, E = 3, bw = 75kHz
+ *
+ * 5.125 kHz deviation, 9.6kbps signal
+ *
+ *     m = 10.25 / 9.6, which is < 5.5:
+ *
+ *     bw = 2.6 * 5.125 + 0.55 * 9.6 = 18.6kHz
+ *
+ *     M = 2, E = 3, bw = 53.6kHz
+ *
+ * 1.28125kHz deviation, 2.4kbps signal
+ *
+ *     m = 2.565 / 2.4, which is < 5.5:
+ *
+ *     bw = 2.6 * 20.5 + 1.9 * 2.4 = 47.61kHz
+ *
+ *     M = 3, E = 3, bw = 53.6kHz
+ *
  * For channel bandwidth of 93.75 kHz, the CHANBW_E and CHANBW_M values are
  *
  * BW = 24e6 / (8 * (4 + M) * 2 ** E)
@@ -47,7 +83,9 @@
  * So, M = 0 and E = 3
  */
 
-#define CHANBW_M       0
+#define CHANBW_M_384   1
+#define CHANBW_M_96    3
+#define CHANBW_M_24    3
 #define CHANBW_E       3
 
 /*
  *
  * R = (256 + M) * 2** E * 24e6 / 2**28
  *
- * So M is 163 and E is 10
+ * So for 38360kBaud, M is 163 and E is 10
  */
 
-#define DRATE_E                10
 #define DRATE_M                163
 
+#define DRATE_E_384    10
+
+/* For 9600 baud, M is 163 and E is 8
+ */
+
+#define DRATE_E_96     8
+
+/* For 2400 baud, M is 163 and E is 6
+ */
+
+#define DRATE_E_24     6
+
 /*
  * For a channel deviation of 20.5kHz, the DEVIATION_E and DEVIATION_M values are:
  *
  * F = 24e6/2**17 * (8 + DEVIATION_M) * 2**DEVIATION_E
  *
- * So M is 6 and E is 3
+ * For 20.5kHz deviation, M is 6 and E is 3
+ * For 5.125kHz deviation, M is 6 and E is 1
+ * For 1.28125kHz deviation, M is 0 and E is 0
  */
 
-#define DEVIATION_M    6
-#define DEVIATION_E    3
+#define DEVIATION_M_384        6
+#define DEVIATION_E_384        3
+
+#define DEVIATION_M_96 6
+#define DEVIATION_E_96 1
+
+#define DEVIATION_M_24 0
+#define DEVIATION_E_24 0
 
 /*
  * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone),
@@ -122,13 +179,10 @@ static __code uint8_t radio_setup[] = {
        RF_FSCTRL1_OFF,         (IF_FREQ_CONTROL << RF_FSCTRL1_FREQ_IF_SHIFT),
        RF_FSCTRL0_OFF,         (0 << RF_FSCTRL0_FREQOFF_SHIFT),
 
-       RF_MDMCFG4_OFF,         ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) |
-                                (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) |
-                                (DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)),
        RF_MDMCFG3_OFF,         (DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT),
-       RF_MDMCFG2_OFF,         (RF_MDMCFG2_DEM_DCFILT_OFF |
+       RF_MDMCFG2_OFF,         (RF_MDMCFG2_DEM_DCFILT_ON |
                                 RF_MDMCFG2_MOD_FORMAT_GFSK |
-                                RF_MDMCFG2_SYNC_MODE_15_16_THRES),
+                                RF_MDMCFG2_SYNC_MODE_15_16),
        RF_MDMCFG1_OFF,         (RF_MDMCFG1_FEC_EN |
                                 RF_MDMCFG1_NUM_PREAMBLE_4 |
                                 (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)),
@@ -136,9 +190,6 @@ static __code uint8_t radio_setup[] = {
 
        RF_CHANNR_OFF,          0,
 
-       RF_DEVIATN_OFF,         ((DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) |
-                                (DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)),
-
        /* SmartRF says set LODIV_BUF_CURRENT_TX to 0
         * And, we're not using power ramping, so use PA_POWER 0
         */
@@ -155,8 +206,8 @@ static __code uint8_t radio_setup[] = {
        RF_FSCAL1_OFF,          0x00,
        RF_FSCAL0_OFF,          0x1F,
 
-       RF_TEST2_OFF,           0x88,
-       RF_TEST1_OFF,           0x31,
+       RF_TEST2_OFF,           RF_TEST2_RX_LOW_DATA_RATE_MAGIC,
+       RF_TEST1_OFF,           RF_TEST1_RX_LOW_DATA_RATE_MAGIC,
        RF_TEST0_OFF,           0x09,
 
        /* default sync values */
@@ -187,10 +238,16 @@ static __code uint8_t radio_setup[] = {
                                 RF_BSCFG_BS_POST_KI_PRE_KI|
                                 RF_BSCFG_BS_POST_KP_PRE_KP|
                                 RF_BSCFG_BS_LIMIT_0),
-       RF_AGCCTRL2_OFF,        0x03,
-       RF_AGCCTRL1_OFF,        0x40,
-       RF_AGCCTRL0_OFF,        0x91,
-
+       RF_AGCCTRL2_OFF,        (RF_AGCCTRL2_MAX_DVGA_GAIN_ALL|
+                                RF_AGCCTRL2_MAX_LNA_GAIN_0|
+                                RF_AGCCTRL2_MAGN_TARGET_33dB),
+       RF_AGCCTRL1_OFF,        (RF_AGCCTRL1_AGC_LNA_PRIORITY_0 |
+                                RF_AGCCTRL1_CARRIER_SENSE_REL_THR_DISABLE |
+                                RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_0DB),
+       RF_AGCCTRL0_OFF,        (RF_AGCCTRL0_HYST_LEVEL_NONE |
+                                RF_AGCCTRL0_WAIT_TIME_8 |
+                                RF_AGCCTRL0_AGC_FREEZE_NORMAL |
+                                RF_AGCCTRL0_FILTER_LENGTH_8),
        RF_IOCFG2_OFF,          0x00,
        RF_IOCFG1_OFF,          0x00,
        RF_IOCFG0_OFF,          0x00,
@@ -198,7 +255,7 @@ static __code uint8_t radio_setup[] = {
 
 static __code uint8_t rdf_setup[] = {
        RF_MDMCFG4_OFF,         ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) |
-                                (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) |
+                                (CHANBW_M_384 << RF_MDMCFG4_CHANBW_M_SHIFT) |
                                 (RDF_DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)),
        RF_MDMCFG3_OFF,         (RDF_DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT),
        RF_MDMCFG2_OFF,         (RF_MDMCFG2_DEM_DCFILT_OFF |
@@ -212,26 +269,30 @@ static __code uint8_t rdf_setup[] = {
                                 (RDF_DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)),
 
        /* packet length is set in-line */
-       RF_PKTCTRL1_OFF,        ((1 << PKTCTRL1_PQT_SHIFT)|
+       RF_PKTCTRL1_OFF,        ((0 << PKTCTRL1_PQT_SHIFT)|
                                 PKTCTRL1_ADR_CHK_NONE),
        RF_PKTCTRL0_OFF,        (RF_PKTCTRL0_PKT_FORMAT_NORMAL|
                                 RF_PKTCTRL0_LENGTH_CONFIG_FIXED),
 };
 
 static __code uint8_t fixed_pkt_setup[] = {
+#if !HAS_RADIO_RATE
        RF_MDMCFG4_OFF,         ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) |
-                                (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) |
-                                (DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)),
+                                (CHANBW_M_384 << RF_MDMCFG4_CHANBW_M_SHIFT) |
+                                (DRATE_E_384 << RF_MDMCFG4_DRATE_E_SHIFT)),
+#endif
        RF_MDMCFG3_OFF,         (DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT),
-       RF_MDMCFG2_OFF,         (RF_MDMCFG2_DEM_DCFILT_OFF |
+       RF_MDMCFG2_OFF,         (RF_MDMCFG2_DEM_DCFILT_ON |
                                 RF_MDMCFG2_MOD_FORMAT_GFSK |
-                                RF_MDMCFG2_SYNC_MODE_15_16_THRES),
+                                RF_MDMCFG2_SYNC_MODE_15_16),
        RF_MDMCFG1_OFF,         (RF_MDMCFG1_FEC_EN |
                                 RF_MDMCFG1_NUM_PREAMBLE_4 |
                                 (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)),
 
-       RF_DEVIATN_OFF,         ((DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) |
-                                (DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)),
+#if !HAS_RADIO_RATE
+       RF_DEVIATN_OFF,         ((DEVIATION_E_384 << RF_DEVIATN_DEVIATION_E_SHIFT) |
+                                (DEVIATION_M_384 << RF_DEVIATN_DEVIATION_M_SHIFT)),
+#endif
 
        /* max packet length -- now set inline */
        RF_PKTCTRL1_OFF,        ((1 << PKTCTRL1_PQT_SHIFT)|
@@ -243,6 +304,38 @@ static __code uint8_t fixed_pkt_setup[] = {
                                 RF_PKTCTRL0_LENGTH_CONFIG_FIXED),
 };
 
+#if HAS_RADIO_RATE
+static __code struct {
+       uint8_t         mdmcfg4;
+       uint8_t         deviatn;
+} packet_rate_setup[] = {
+       /* 38400 */
+       {
+               ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) |
+                (CHANBW_M_384 << RF_MDMCFG4_CHANBW_M_SHIFT) |
+                (DRATE_E_384 << RF_MDMCFG4_DRATE_E_SHIFT)),
+               ((DEVIATION_E_384 << RF_DEVIATN_DEVIATION_E_SHIFT) |
+                (DEVIATION_M_384 << RF_DEVIATN_DEVIATION_M_SHIFT)),
+       },
+       /* 9600 */
+       {
+               ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) |
+                (CHANBW_M_96 << RF_MDMCFG4_CHANBW_M_SHIFT) |
+                (DRATE_E_96 << RF_MDMCFG4_DRATE_E_SHIFT)),
+               ((DEVIATION_E_96 << RF_DEVIATN_DEVIATION_E_SHIFT) |
+                (DEVIATION_M_96 << RF_DEVIATN_DEVIATION_M_SHIFT)),
+       },
+       /* 2400 */
+       {
+               ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) |
+                (CHANBW_M_24 << RF_MDMCFG4_CHANBW_M_SHIFT) |
+                (DRATE_E_24 << RF_MDMCFG4_DRATE_E_SHIFT)),
+               ((DEVIATION_E_24 << RF_DEVIATN_DEVIATION_E_SHIFT) |
+                (DEVIATION_M_24 << RF_DEVIATN_DEVIATION_M_SHIFT)),
+       },
+};
+#endif
+
 __xdata uint8_t        ao_radio_dma;
 __xdata uint8_t ao_radio_dma_done;
 __xdata uint8_t ao_radio_done;
@@ -308,6 +401,10 @@ ao_radio_get(uint8_t len)
        RF_FREQ1 = (uint8_t) (ao_config.radio_setting >> 8);
        RF_FREQ0 = (uint8_t) (ao_config.radio_setting);
        RF_PKTLEN = len;
+#if HAS_RADIO_RATE
+       RF_MDMCFG4 = packet_rate_setup[ao_config.radio_rate].mdmcfg4;
+       RF_DEVIATN = packet_rate_setup[ao_config.radio_rate].deviatn;
+#endif
 }
 
 
@@ -551,8 +648,31 @@ ao_radio_test_cmd(void)
                ao_radio_test(0);
 }
 
+#if AO_RADIO_REG_TEST
+static void
+ao_radio_set_reg(void)
+{
+       uint8_t offset;
+       ao_cmd_hex();
+       offset = ao_cmd_lex_i;
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       ao_cmd_hex();
+       printf("RF[%x] %x", offset, RF[offset]);
+       if (ao_cmd_status == ao_cmd_success) {
+               RF[offset] = ao_cmd_lex_i;
+               printf (" -> %x", RF[offset]);
+       }
+       ao_cmd_status = ao_cmd_success;
+       printf("\n");
+}
+#endif
+
 __code struct ao_cmds ao_radio_cmds[] = {
        { ao_radio_test_cmd,    "C <1 start, 0 stop, none both>\0Radio carrier test" },
+#if AO_RADIO_REG_TEST
+       { ao_radio_set_reg,     "V <offset> <value>\0Set radio register" },
+#endif
        { 0,    NULL },
 };
 
index 80d3fb70b7d2219f5218b74b4de2bc2a2e4c3080..ac1e71c971028fc33ac3a822b4660b6c45088ba7 100644 (file)
@@ -1165,12 +1165,73 @@ __xdata __at (0xdf16) uint8_t RF_BSCFG;
 __xdata __at (0xdf17) uint8_t RF_AGCCTRL2;
 #define RF_AGCCTRL2_OFF        0x17
 
+#define RF_AGCCTRL2_MAX_DVGA_GAIN_ALL          (0 << 6)
+#define RF_AGCCTRL2_MAX_DVGA_GAIN_BUT_1                (1 << 6)
+#define RF_AGCCTRL2_MAX_DVGA_GAIN_BUT_2                (2 << 6)
+#define RF_AGCCTRL2_MAX_DVGA_GAIN_BUT_3                (3 << 6)
+#define RF_AGCCTRL2_MAX_LNA_GAIN_0             (0 << 3)
+#define RF_AGCCTRL2_MAX_LNA_GAIN_2_6           (1 << 3)
+#define RF_AGCCTRL2_MAX_LNA_GAIN_6_1           (2 << 3)
+#define RF_AGCCTRL2_MAX_LNA_GAIN_7_4           (3 << 3)
+#define RF_AGCCTRL2_MAX_LNA_GAIN_9_2           (4 << 3)
+#define RF_AGCCTRL2_MAX_LNA_GAIN_11_5          (5 << 3)
+#define RF_AGCCTRL2_MAX_LNA_GAIN_14_6          (6 << 3)
+#define RF_AGCCTRL2_MAX_LNA_GAIN_17_1          (7 << 3)
+#define RF_AGCCTRL2_MAGN_TARGET_24dB           (0 << 0)
+#define RF_AGCCTRL2_MAGN_TARGET_27dB           (1 << 0)
+#define RF_AGCCTRL2_MAGN_TARGET_30dB           (2 << 0)
+#define RF_AGCCTRL2_MAGN_TARGET_33dB           (3 << 0)
+#define RF_AGCCTRL2_MAGN_TARGET_36dB           (4 << 0)
+#define RF_AGCCTRL2_MAGN_TARGET_38dB           (5 << 0)
+#define RF_AGCCTRL2_MAGN_TARGET_40dB           (6 << 0)
+#define RF_AGCCTRL2_MAGN_TARGET_42dB           (7 << 0)
+
 __xdata __at (0xdf18) uint8_t RF_AGCCTRL1;
 #define RF_AGCCTRL1_OFF        0x18
 
+#define RF_AGCCTRL1_AGC_LNA_PRIORITY_0         (0 << 6)
+#define RF_AGCCTRL1_AGC_LNA_PRIORITY_1         (1 << 6)
+#define RF_AGCCTRL1_CARRIER_SENSE_REL_THR_DISABLE      (0 << 4)
+#define RF_AGCCTRL1_CARRIER_SENSE_REL_THR_6DB          (1 << 4)
+#define RF_AGCCTRL1_CARRIER_SENSE_REL_THR_10DB         (2 << 4)
+#define RF_AGCCTRL1_CARRIER_SENSE_REL_THR_14DB         (3 << 4)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_DISABLE      (0x8 << 0)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_7DB_BELOW    (0x9 << 0)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_6DB_BELOW    (0xa << 0)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_5DB_BELOW    (0xb << 0)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_4DB_BELOW    (0xc << 0)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_3DB_BELOW    (0xd << 0)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_2DB_BELOW    (0xe << 0)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_1DB_BELOW    (0xf << 0)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_0DB          (0x0 << 0)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_1DB_ABOVE    (0x1 << 0)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_2DB_ABOVE    (0x2 << 0)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_3DB_ABOVE    (0x3 << 0)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_4DB_ABOVE    (0x4 << 0)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_5DB_ABOVE    (0x5 << 0)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_6DB_ABOVE    (0x6 << 0)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_7DB_ABOVE    (0x7 << 0)
+
 __xdata __at (0xdf19) uint8_t RF_AGCCTRL0;
 #define RF_AGCCTRL0_OFF        0x19
 
+#define RF_AGCCTRL0_HYST_LEVEL_NONE            (0 << 6)
+#define RF_AGCCTRL0_HYST_LEVEL_LOW             (1 << 6)
+#define RF_AGCCTRL0_HYST_LEVEL_MEDIUM          (2 << 6)
+#define RF_AGCCTRL0_HYST_LEVEL_HIGH            (3 << 6)
+#define RF_AGCCTRL0_WAIT_TIME_8                        (0 << 4)
+#define RF_AGCCTRL0_WAIT_TIME_16               (1 << 4)
+#define RF_AGCCTRL0_WAIT_TIME_24               (2 << 4)
+#define RF_AGCCTRL0_WAIT_TIME_32               (3 << 4)
+#define RF_AGCCTRL0_AGC_FREEZE_NORMAL          (0 << 2)
+#define RF_AGCCTRL0_AGC_FREEZE_SYNC            (1 << 2)
+#define RF_AGCCTRL0_AGC_FREEZE_MANUAL_ANALOG   (2 << 2)
+#define RF_AGCCTRL0_AGC_FREEZE_MANUAL_BOTH     (3 << 2)
+#define RF_AGCCTRL0_FILTER_LENGTH_8            (0 << 0)
+#define RF_AGCCTRL0_FILTER_LENGTH_16           (1 << 0)
+#define RF_AGCCTRL0_FILTER_LENGTH_32           (2 << 0)
+#define RF_AGCCTRL0_FILTER_LENGTH_64           (3 << 0)
+
 __xdata __at (0xdf1a) uint8_t RF_FREND1;
 #define RF_FREND1_OFF  0x1a
 
index 8a1b6a4df2763e1e74ec9f61a082dc012f0da082..19beb78f2b51dbf89f1f0f44563d50b203357bc2 100644 (file)
@@ -1,11 +1,11 @@
-/** 
+/**
  * http://ad7zj.net/kd7lmo/aprsbeacon_code.html
  *
  * @mainpage Pico Beacon
  *
  * @section overview_sec Overview
  *
- * The Pico Beacon is an APRS based tracking beacon that operates in the UHF 420-450MHz band.  The device utilizes a 
+ * The Pico Beacon is an APRS based tracking beacon that operates in the UHF 420-450MHz band.  The device utilizes a
  * Microchip PIC 18F2525 embedded controller, Motorola M12+ GPS engine, and Analog Devices AD9954 DDS.  The device is capable
  * of generating a 1200bps A-FSK and 9600 bps FSK AX.25 compliant APRS (Automatic Position Reporting System) message.
 
@@ -24,7 +24,7 @@
  *                                     (4) corrected size of LOG_COORD block when searching for end of log.
  *
  * @subsection v303 V3.03
- * 15 Sep 2005, Change include; (1) removed AD9954 setting SDIO as input pin, 
+ * 15 Sep 2005, Change include; (1) removed AD9954 setting SDIO as input pin,
  *                                     (2) additional comments and Doxygen tags,
  *                                     (3) integration and test code calculates DDS FTW,
  *                                     (4) swapped bus and reference analog input ports (hardware change),
@@ -38,7 +38,7 @@
  *                                    (2) Doxygen documentation clean up and additions, and
  *                                    (3) added integration and test code to baseline.
  *
- * 
+ *
  * @subsection v301 V3.01
  * 13 Jan 2005, Renamed project and files to Pico Beacon.
  *
  *                                     (8) added flight data recorder, and
  *                                     (9) added diagnostics terminal mode.
  *
- * 
+ *
  * @subsection v201 V2.01
- * 30 Jan 2004, Change include; (1) General clean up of in-line documentation, and 
+ * 30 Jan 2004, Change include; (1) General clean up of in-line documentation, and
  *                                     (2) changed temperature resolution to 0.1 degrees F.
  *
- * 
+ *
  * @subsection v200 V2.00
  * 26 Oct 2002, Change include; (1) Micro Beacon II hardware changes including PIC18F252 processor,
- *                                     (2) serial EEPROM, 
- *                                     (3) GPS power control, 
- *                                     (4) additional ADC input, and 
- *                                     (5) LM60 temperature sensor.                            
+ *                                     (2) serial EEPROM,
+ *                                     (3) GPS power control,
+ *                                     (4) additional ADC input, and
+ *                                     (5) LM60 temperature sensor.
  *
  *
  * @subsection v101 V1.01
- * 5 Dec 2001, Change include; (1) Changed startup message, and 
+ * 5 Dec 2001, Change include; (1) Changed startup message, and
  *                                    (2) applied SEPARATE pragma to several methods for memory usage.
  *
  *
  * @subsection v100 V1.00
  * 25 Sep 2001, Initial release.  Flew ANSR-3 and ANSR-4.
- * 
+ *
 
 
  *
  *  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
- *  
+ *
 
 
- * 
- * 
+ *
+ *
  * @section design Design Details
  *
  * Provides design details on a variety of the components that make up the Pico Beacon.
  *  @page power Power Consumption
  *
  *  Measured DC power consumption.
- * 
- *  3VDC prime power current 
+ *
+ *  3VDC prime power current
 
  *
- *    7mA Held in reset 
+ *    7mA Held in reset
 
- *   18mA Processor running, all I/O off 
+ *   18mA Processor running, all I/O off
 
- *  110mA GPS running 
+ *  110mA GPS running
 
- *  120mA GPS running w/antenna 
+ *  120mA GPS running w/antenna
 
- *  250mA DDS running and GPS w/antenna 
+ *  250mA DDS running and GPS w/antenna
 
- *  420mA DDS running, GPS w/antenna, and PA chain on with no RF 
+ *  420mA DDS running, GPS w/antenna, and PA chain on with no RF
 
- *  900mA Transmit 
+ *  900mA Transmit
 
  *
  */
 
 #ifndef AO_APRS_TEST
 #include <ao.h>
+
+#if !HAS_APRS
+#error HAS_APRS not set
+#endif
 #endif
 
 #include <ao_aprs.h>
@@ -176,11 +180,11 @@ static uint16_t sysCRC16(const uint8_t *buffer, uint8_t length, uint16_t crc)
 {
     uint8_t i, bit, value;
 
-    for (i = 0; i < length; ++i) 
+    for (i = 0; i < length; ++i)
     {
         value = buffer[i];
 
-        for (bit = 0; bit < 8; ++bit) 
+        for (bit = 0; bit < 8; ++bit)
         {
             crc ^= (value & 0x01);
             crc = ( crc & 0x01 ) ? ( crc >> 1 ) ^ 0x8408 : ( crc >> 1 );
@@ -253,7 +257,7 @@ typedef enum
 
 /// AX.25 compliant packet header that contains destination, station call sign, and path.
 /// 0x76 for SSID-11, 0x78 for SSID-12
-static uint8_t TNC_AX25_HEADER[] = { 
+static uint8_t TNC_AX25_HEADER[] = {
     'A' << 1, 'P' << 1, 'A' << 1, 'M' << 1, ' ' << 1, ' ' << 1, 0x60,
     'N' << 1, '0' << 1, 'C' << 1, 'A' << 1, 'L' << 1, 'L' << 1, 0x78,
     'W' << 1, 'I' << 1, 'D' << 1, 'E' << 1, '2' << 1, ' ' << 1, 0x65,
@@ -261,6 +265,7 @@ static uint8_t TNC_AX25_HEADER[] = {
 
 #define TNC_CALLSIGN_OFF       7
 #define TNC_CALLSIGN_LEN       6
+#define TNC_SSID_OFF           13
 
 static void
 tncSetCallsign(void)
@@ -275,6 +280,9 @@ tncSetCallsign(void)
        }
        for (; i < TNC_CALLSIGN_LEN; i++)
                TNC_AX25_HEADER[TNC_CALLSIGN_OFF + i] = ' ' << 1;
+
+       /* Fill in the SSID with the low digit of the serial number */
+       TNC_AX25_HEADER[TNC_SSID_OFF] = 0x60 | ((ao_config.aprs_ssid & 0xf) << 1);
 #endif
 }
 
@@ -302,7 +310,7 @@ static uint8_t tncBitStuff;
 /// Buffer to hold the message portion of the AX.25 packet as we prepare it.
 static uint8_t tncBuffer[TNC_BUFFER_SIZE];
 
-/** 
+/**
  *   Initialize the TNC internal variables.
  */
 static void tncInit()
@@ -323,7 +331,7 @@ static void tnc1200TimerTick()
     else
         timeNCOFreq = 0x3aab;
 
-    switch (tncMode) 
+    switch (tncMode)
     {
         case TNC_TX_READY:
             // Generate a test signal alteranting between high and low tones.
@@ -339,16 +347,16 @@ static void tnc1200TimerTick()
                 else
                     tncTxBit = 0;
            }
-                    
+
             // When the flag is done, determine if we need to send more or data.
-            if (++tncBitCount == 8) 
+            if (++tncBitCount == 8)
             {
                 tncBitCount = 0;
                 tncShift = 0x7e;
 
                 // Once we transmit x mS of flags, send the data.
                 // txDelay bytes * 8 bits/byte * 833uS/bit = x mS
-                if (++tncIndex == TNC_TX_DELAY) 
+                if (++tncIndex == TNC_TX_DELAY)
                 {
                     tncIndex = 0;
                     tncShift = TNC_AX25_HEADER[0];
@@ -361,7 +369,7 @@ static void tnc1200TimerTick()
 
         case TNC_TX_HEADER:
             // Determine if we have sent 5 ones in a row, if we have send a zero.
-            if (tncBitStuff == 0x1f) 
+            if (tncBitStuff == 0x1f)
             {
                 if (tncTxBit == 0)
                     tncTxBit = 1;
@@ -381,17 +389,17 @@ static void tnc1200TimerTick()
                     tncTxBit = 0;
            }
 
-            // Save the data stream so we can determine if bit stuffing is 
+            // Save the data stream so we can determine if bit stuffing is
             // required on the next bit time.
             tncBitStuff = ((tncBitStuff << 1) | (tncShift & 0x01)) & 0x1f;
 
             // If all the bits were shifted, get the next byte.
-            if (++tncBitCount == 8) 
+            if (++tncBitCount == 8)
             {
                 tncBitCount = 0;
 
                 // After the header is sent, then send the data.
-                if (++tncIndex == sizeof(TNC_AX25_HEADER)) 
+                if (++tncIndex == sizeof(TNC_AX25_HEADER))
                 {
                     tncIndex = 0;
                     tncShift = tncBuffer[0];
@@ -406,7 +414,7 @@ static void tnc1200TimerTick()
 
         case TNC_TX_DATA:
             // Determine if we have sent 5 ones in a row, if we have send a zero.
-            if (tncBitStuff == 0x1f) 
+            if (tncBitStuff == 0x1f)
             {
                 if (tncTxBit == 0)
                     tncTxBit = 1;
@@ -426,17 +434,17 @@ static void tnc1200TimerTick()
                     tncTxBit = 0;
            }
 
-            // Save the data stream so we can determine if bit stuffing is 
+            // Save the data stream so we can determine if bit stuffing is
             // required on the next bit time.
             tncBitStuff = ((tncBitStuff << 1) | (tncShift & 0x01)) & 0x1f;
 
             // If all the bits were shifted, get the next byte.
-            if (++tncBitCount == 8) 
+            if (++tncBitCount == 8)
             {
                 tncBitCount = 0;
 
                 // If everything was sent, transmit closing flags.
-                if (++tncIndex == tncLength) 
+                if (++tncIndex == tncLength)
                 {
                     tncIndex = 0;
                     tncShift = 0x7e;
@@ -451,7 +459,7 @@ static void tnc1200TimerTick()
 
         case TNC_TX_END:
             // The variable tncShift contains the lastest data byte.
-            // NRZI enocde the data stream. 
+            // NRZI enocde the data stream.
             if ((tncShift & 0x01) == 0x00) {
                 if (tncTxBit == 0)
                     tncTxBit = 1;
@@ -460,13 +468,13 @@ static void tnc1200TimerTick()
            }
 
             // If all the bits were shifted, get the next one.
-            if (++tncBitCount == 8) 
+            if (++tncBitCount == 8)
             {
                 tncBitCount = 0;
                 tncShift = 0x7e;
-    
+
                 // Transmit two closing flags.
-                if (++tncIndex == 2) 
+                if (++tncIndex == 2)
                 {
                     tncMode = TNC_TX_READY;
 
@@ -530,6 +538,7 @@ static int tncComment(uint8_t *buf)
 #ifdef AO_SENSE_MAIN
                       " M%d.%d"
 #endif
+                      " %d"
                       , ao_gps_locked(),
                       ao_num_sats(),
                       battery/10,
@@ -542,6 +551,7 @@ static int tncComment(uint8_t *buf)
                       , main/10,
                       main%10
 #endif
+                      , ao_serial_number
                );
 #else
        return sprintf((char *) buf,
@@ -703,7 +713,7 @@ static int tncPositionPacket(void)
     if (ao_gps_data.flags & AO_GPS_VALID) {
        latitude = ao_gps_data.latitude;
        longitude = ao_gps_data.longitude;
-       altitude = ao_gps_data.altitude;
+       altitude = AO_TELEMETRY_LOCATION_ALTITUDE(&ao_gps_data);
        if (altitude < 0)
            altitude = 0;
     }
@@ -759,7 +769,7 @@ tncFill(uint8_t *buf, int16_t len)
     return l;
 }
 
-/** 
+/**
  *    Prepare an AX.25 data packet.  Each time this method is called, it automatically
  *    rotates through 1 of 3 messages.
  *
index 312259395236429d5a29f1bb90ddd7f7e0dc628f..3ea8b7044b4cecb25f1880f5be5a3b1bbfb066cd 100644 (file)
@@ -41,8 +41,10 @@ extern const uint32_t        ao_radio_cal;
 
 #define FOSC   32000000
 
+#define ao_radio_try_select(task_id)   ao_spi_try_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS,AO_SPI_SPEED_4MHz, task_id)
 #define ao_radio_select()      ao_spi_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS,AO_SPI_SPEED_4MHz)
 #define ao_radio_deselect()    ao_spi_put_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS)
+#define ao_radio_spi_send_sync(d,l)    ao_spi_send_sync((d), (l), AO_CC1120_SPI_BUS)
 #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1120_SPI_BUS)
 #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1120_SPI_BUS)
 #define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC1120_SPI_BUS)
@@ -107,7 +109,7 @@ ao_radio_reg_write(uint16_t addr, uint8_t value)
 }
 
 static void
-ao_radio_burst_read_start (uint16_t addr)
+_ao_radio_burst_read_start (uint16_t addr)
 {
        uint8_t data[2];
        uint8_t d;
@@ -124,8 +126,8 @@ ao_radio_burst_read_start (uint16_t addr)
                           addr);
                d = 1;
        }
-       ao_radio_select();
-       ao_radio_spi_send(data, d);
+
+       ao_radio_spi_send_sync(data, d);
 }
 
 static void
@@ -209,7 +211,7 @@ ao_radio_tx_fifo_space(void)
        return CC1120_FIFO_SIZE - ao_radio_reg_read(CC1120_NUM_TXBYTES);
 }
 
-#if 0
+#if CC1120_DEBUG
 static uint8_t
 ao_radio_status(void)
 {
@@ -245,7 +247,7 @@ ao_radio_check_marc_status(void)
 {
        ao_radio_mcu_wake = 0;
        ao_radio_marc_status = ao_radio_get_marc_status();
-       
+
        /* Anyt other than 'tx/rx finished' means an error occurred */
        if (ao_radio_marc_status & ~(CC1120_MARC_STATUS1_TX_FINISHED|CC1120_MARC_STATUS1_RX_FINISHED))
                ao_radio_abort = 1;
@@ -275,48 +277,102 @@ static void
 ao_radio_idle(void)
 {
        for (;;) {
-               uint8_t state = ao_radio_strobe(CC1120_SIDLE);
-               if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_IDLE)
+               uint8_t state = (ao_radio_strobe(CC1120_SIDLE) >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK;
+               if (state == CC1120_STATUS_STATE_IDLE)
                        break;
-               if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_TX_FIFO_ERROR)
+               if (state == CC1120_STATUS_STATE_TX_FIFO_ERROR)
                        ao_radio_strobe(CC1120_SFTX);
+               if (state == CC1120_STATUS_STATE_RX_FIFO_ERROR)
+                       ao_radio_strobe(CC1120_SFRX);
        }
        /* Flush any pending TX bytes */
        ao_radio_strobe(CC1120_SFTX);
 }
 
 /*
- * Packet deviation is 20.5kHz
+ * Packet deviation
  *
  *     fdev = fosc >> 24 * (256 + dev_m) << dev_e
  *
+ * Deviation for 38400 baud should be 20.5kHz:
+ *
  *             32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz
+ *
+ * Deviation for 9600 baud should be 5.125kHz:
+ *
+ *             32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 3) = 5127Hz
+ *
+ * Deviation for 2400 baud should be 1.28125kHz, but cc1111 and
+ * cc115l can't do that, so we'll use 1.5kHz instead:
+ *
+ *             32e6Hz / (2 ** 24) * (256 + 137) * (2 ** 1) = 1499Hz
  */
 
-#define PACKET_DEV_E   5
-#define PACKET_DEV_M   80
+#define PACKET_DEV_M_384       80
+#define PACKET_DEV_E_384       5
+
+#define PACKET_DEV_M_96                80
+#define PACKET_DEV_E_96                3
+
+#define PACKET_DEV_M_24                137
+#define PACKET_DEV_E_24                1
 
 /*
- * For our packet data, set the symbol rate to 38400 Baud
+ * For our packet data
  *
  *              (2**20 + DATARATE_M) * 2 ** DATARATE_E
  *     Rdata = -------------------------------------- * fosc
  *                          2 ** 39
  *
+ * Given the bit period of the baseband, T, the bandwidth of the
+ * baseband signal is B = 1/(2T).  The overall bandwidth of the
+ * modulated signal is then Channel bandwidth = 2Δf + 2B.
+ *
+ * 38400 -- 2 * 20500 + 38400 = 79.4 kHz
+ *  9600 -- 2 * 5.125 +  9600 = 19.9 kHz
+ *  2400 -- 2 * 1.5   +  2400 =  5.4 khz
+ *
+ * Symbol rate 38400 Baud:
  *
  *     DATARATE_M = 239914
  *     DATARATE_E = 9
+ *     CHANBW = 79.4 (round to 100)
+ *
+ * Symbol rate 9600 Baud:
+ *
+ *     DATARATE_M = 239914
+ *     DATARATE_E = 7
+ *     CHANBW = 19.9 (round to 20)
+ *
+ * Symbol rate 2400 Baud:
+ *
+ *     DATARATE_M = 239914
+ *     DATARATE_E = 5
+ *     CHANBW = 5.0 (round to 8.0)
  */
-#define PACKET_DRATE_E 9
+
 #define PACKET_DRATE_M 239914
 
+#define PACKET_DRATE_E_384     9
+
+/* 200 / 2 = 100 */
+#define PACKET_CHAN_BW_384     ((0 << CC1120_CHAN_BW_CHFILT_BYPASS) | \
+                                (CC1120_CHAN_BW_ADC_CIC_DECFACT_20 << CC1120_CHAN_BW_ADC_CIC_DECFACT) | \
+                                (2 << CC1120_CHAN_BW_BB_CIC_DECFACT))
+
+#define PACKET_DRATE_E_96      7
+/* 200 / 10 = 20 */
+#define PACKET_CHAN_BW_96      ((0 << CC1120_CHAN_BW_CHFILT_BYPASS) | \
+                                (CC1120_CHAN_BW_ADC_CIC_DECFACT_20 << CC1120_CHAN_BW_ADC_CIC_DECFACT) | \
+                                (10 << CC1120_CHAN_BW_BB_CIC_DECFACT))
+
+#define PACKET_DRATE_E_24      5
+/* 200 / 25 = 8 */
+#define PACKET_CHAN_BW_24      ((0 << CC1120_CHAN_BW_CHFILT_BYPASS) | \
+                                (CC1120_CHAN_BW_ADC_CIC_DECFACT_20 << CC1120_CHAN_BW_ADC_CIC_DECFACT) | \
+                                (25 << CC1120_CHAN_BW_BB_CIC_DECFACT))
+
 static const uint16_t packet_setup[] = {
-       CC1120_DEVIATION_M,     PACKET_DEV_M,
-       CC1120_MODCFG_DEV_E,    ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
-                                (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
-                                (PACKET_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
-       CC1120_DRATE2,          ((PACKET_DRATE_E << CC1120_DRATE2_DATARATE_E) |
-                                (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
        CC1120_DRATE1,          ((PACKET_DRATE_M >> 8) & 0xff),
        CC1120_DRATE0,          ((PACKET_DRATE_M >> 0) & 0xff),
        CC1120_PKT_CFG2,        ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
@@ -335,6 +391,39 @@ static const uint16_t packet_setup[] = {
        AO_CC1120_MARC_GPIO_IOCFG,              CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP,
 };
 
+static const uint16_t packet_setup_384[] = {
+       CC1120_DEVIATION_M,     PACKET_DEV_M_384,
+       CC1120_MODCFG_DEV_E,    ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
+                                (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
+                                (PACKET_DEV_E_384 << CC1120_MODCFG_DEV_E_DEV_E)),
+       CC1120_DRATE2,          ((PACKET_DRATE_E_384 << CC1120_DRATE2_DATARATE_E) |
+                                (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
+       CC1120_CHAN_BW,         PACKET_CHAN_BW_384,
+       CC1120_PA_CFG0,         0x7b,
+};
+
+static const uint16_t packet_setup_96[] = {
+       CC1120_DEVIATION_M,     PACKET_DEV_M_96,
+       CC1120_MODCFG_DEV_E,    ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
+                                (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
+                                (PACKET_DEV_E_96 << CC1120_MODCFG_DEV_E_DEV_E)),
+       CC1120_DRATE2,          ((PACKET_DRATE_E_96 << CC1120_DRATE2_DATARATE_E) |
+                                (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
+       CC1120_CHAN_BW,         PACKET_CHAN_BW_96,
+       CC1120_PA_CFG0,         0x7d,
+};
+
+static const uint16_t packet_setup_24[] = {
+       CC1120_DEVIATION_M,     PACKET_DEV_M_24,
+       CC1120_MODCFG_DEV_E,    ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
+                                (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
+                                (PACKET_DEV_E_24 << CC1120_MODCFG_DEV_E_DEV_E)),
+       CC1120_DRATE2,          ((PACKET_DRATE_E_24 << CC1120_DRATE2_DATARATE_E) |
+                                (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
+       CC1120_CHAN_BW,         PACKET_CHAN_BW_24,
+       CC1120_PA_CFG0,         0x7e,
+};
+
 static const uint16_t packet_tx_setup[] = {
        CC1120_PKT_CFG2,        ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
                                 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
@@ -397,6 +486,7 @@ static const uint16_t rdf_setup[] = {
                                 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
         CC1120_PREAMBLE_CFG1,  ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
                                 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
+       CC1120_PA_CFG0,         0x7e,
 };
 
 /*
@@ -443,6 +533,7 @@ static const uint16_t aprs_setup[] = {
                                 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
         CC1120_PREAMBLE_CFG1,  ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
                                 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
+       CC1120_PA_CFG0,         0x7d,
 };
 
 /*
@@ -505,24 +596,49 @@ static uint16_t ao_radio_mode;
 #define AO_RADIO_MODE_APRS_FINISH      (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
 #define AO_RADIO_MODE_TEST             (AO_RADIO_MODE_BITS_TEST | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
 
+static void
+_ao_radio_set_regs(const uint16_t *regs, int nreg)
+{
+       int i;
+
+       for (i = 0; i < nreg; i++) {
+               ao_radio_reg_write(regs[0], regs[1]);
+               regs += 2;
+       }
+}
+
+#define ao_radio_set_regs(setup) _ao_radio_set_regs(setup, (sizeof (setup) / sizeof(setup[0])) >> 1)
+
 static void
 ao_radio_set_mode(uint16_t new_mode)
 {
        uint16_t changes;
-       unsigned int i;
 
        if (new_mode == ao_radio_mode)
                return;
 
        changes = new_mode & (~ao_radio_mode);
-       if (changes & AO_RADIO_MODE_BITS_PACKET)
-               for (i = 0; i < sizeof (packet_setup) / sizeof (packet_setup[0]); i += 2)
-                       ao_radio_reg_write(packet_setup[i], packet_setup[i+1]);
+
+       if (changes & AO_RADIO_MODE_BITS_PACKET) {
+               ao_radio_set_regs(packet_setup);
+
+               switch (ao_config.radio_rate) {
+               default:
+               case AO_RADIO_RATE_38400:
+                       ao_radio_set_regs(packet_setup_384);
+                       break;
+               case AO_RADIO_RATE_9600:
+                       ao_radio_set_regs(packet_setup_96);
+                       break;
+               case AO_RADIO_RATE_2400:
+                       ao_radio_set_regs(packet_setup_24);
+                       break;
+               }
+       }
 
        if (changes & AO_RADIO_MODE_BITS_PACKET_TX)
-               for (i = 0; i < sizeof (packet_tx_setup) / sizeof (packet_tx_setup[0]); i += 2)
-                       ao_radio_reg_write(packet_tx_setup[i], packet_tx_setup[i+1]);
-               
+               ao_radio_set_regs(packet_tx_setup);
+
        if (changes & AO_RADIO_MODE_BITS_TX_BUF)
                ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_TXFIFO_THR);
 
@@ -530,20 +646,16 @@ ao_radio_set_mode(uint16_t new_mode)
                ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG);
 
        if (changes & AO_RADIO_MODE_BITS_PACKET_RX)
-               for (i = 0; i < sizeof (packet_rx_setup) / sizeof (packet_rx_setup[0]); i += 2)
-                       ao_radio_reg_write(packet_rx_setup[i], packet_rx_setup[i+1]);
-               
+               ao_radio_set_regs(packet_rx_setup);
+
        if (changes & AO_RADIO_MODE_BITS_RDF)
-               for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2)
-                       ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]);
+               ao_radio_set_regs(rdf_setup);
 
        if (changes & AO_RADIO_MODE_BITS_APRS)
-               for (i = 0; i < sizeof (aprs_setup) / sizeof (aprs_setup[0]); i += 2)
-                       ao_radio_reg_write(aprs_setup[i], aprs_setup[i+1]);
+               ao_radio_set_regs(aprs_setup);
 
        if (changes & AO_RADIO_MODE_BITS_TEST)
-               for (i = 0; i < sizeof (test_setup) / sizeof (test_setup[0]); i += 2)
-                       ao_radio_reg_write(test_setup[i], test_setup[i+1]);
+               ao_radio_set_regs(test_setup);
 
        if (changes & AO_RADIO_MODE_BITS_INFINITE)
                ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_INFINITE);
@@ -563,12 +675,9 @@ static uint8_t     ao_radio_configured = 0;
 static void
 ao_radio_setup(void)
 {
-       unsigned int    i;
-
        ao_radio_strobe(CC1120_SRES);
 
-       for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2)
-               ao_radio_reg_write(radio_setup[i], radio_setup[i+1]);
+       ao_radio_set_regs(radio_setup);
 
        ao_radio_mode = 0;
 
@@ -592,6 +701,7 @@ static void
 ao_radio_get(uint8_t len)
 {
        static uint32_t last_radio_setting;
+       static uint8_t  last_radio_rate;
 
        ao_mutex_get(&ao_radio_mutex);
 
@@ -603,6 +713,10 @@ ao_radio_get(uint8_t len)
                ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting);
                last_radio_setting = ao_config.radio_setting;
        }
+       if (ao_config.radio_rate != last_radio_rate) {
+               ao_radio_mode &= ~AO_RADIO_MODE_BITS_PACKET;
+               last_radio_rate = ao_config.radio_rate;
+       }
        ao_radio_set_len(len);
 }
 
@@ -696,7 +810,7 @@ ao_radio_test_cmd(void)
                ao_radio_set_mode(AO_RADIO_MODE_TEST);
                ao_radio_strobe(CC1120_STX);
 #if CC1120_TRACE
-               { int t; 
+               { int t;
                        for (t = 0; t < 10; t++) {
                                printf ("status: %02x\n", ao_radio_status());
                                ao_delay(AO_MS_TO_TICKS(100));
@@ -793,7 +907,7 @@ ao_radio_send(const void *d, uint8_t size)
                } else {
                        ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
                }
-                       
+
                fifo_space = ao_radio_wait_tx(encode_len != 0);
                if (ao_radio_abort) {
                        ao_radio_idle();
@@ -881,6 +995,11 @@ static uint16_t    rx_data_consumed;
 static uint16_t rx_data_cur;
 static uint8_t rx_ignore;
 static uint8_t rx_waiting;
+static uint8_t rx_starting;
+static uint8_t rx_task_id;
+static uint32_t        rx_fast_start;
+static uint32_t rx_slow_start;
+static uint32_t        rx_missed;
 
 #if AO_PROFILE
 static uint32_t        rx_start_tick, rx_packet_tick, rx_done_tick, rx_last_done_tick;
@@ -895,13 +1014,34 @@ ao_radio_rx_isr(void)
 {
        uint8_t d;
 
+       if (rx_task_id) {
+               if (ao_radio_try_select(rx_task_id)) {
+                       ++rx_fast_start;
+                       rx_task_id = 0;
+                       _ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
+               } else {
+                       if (rx_ignore)
+                               --rx_ignore;
+                       else {
+                               ao_radio_abort = 1;
+                               rx_missed++;
+                       }
+                       return;
+               }
+       }
+       if (rx_starting) {
+               rx_starting = 0;
+               ao_wakeup(&ao_radio_wake);
+       }
        d = AO_CC1120_SPI.dr;
        AO_CC1120_SPI.dr = 0;
        if (rx_ignore == 0) {
-               if (rx_data_cur >= rx_data_count)
-                       ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
-               else
+               if (rx_data_cur < rx_data_count)
                        rx_data[rx_data_cur++] = d;
+               if (rx_data_cur >= rx_data_count) {
+                       ao_spi_clr_cs(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN));
+                       ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
+               }
                if (rx_waiting && rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) {
 #if AO_PROFILE
                        if (!rx_packet_tick)
@@ -920,24 +1060,20 @@ ao_radio_rx_isr(void)
 static uint16_t
 ao_radio_rx_wait(void)
 {
-       do {
-               if (ao_radio_mcu_wake)
-                       ao_radio_check_marc_status();
-               ao_alarm(AO_MS_TO_TICKS(100));
-               ao_arch_block_interrupts();
-               rx_waiting = 1;
-               while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK &&
-                      !ao_radio_abort &&
-                      !ao_radio_mcu_wake)
-               {
-                       if (ao_sleep(&ao_radio_wake))
-                               ao_radio_abort = 1;
-               }
-               rx_waiting = 0;
-               ao_arch_release_interrupts();
-               ao_clear_alarm();
-       } while (ao_radio_mcu_wake);
-       if (ao_radio_abort)
+       ao_alarm(AO_MS_TO_TICKS(100));
+       ao_arch_block_interrupts();
+       rx_waiting = 1;
+       while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK &&
+              !ao_radio_abort &&
+              !ao_radio_mcu_wake)
+       {
+               if (ao_sleep(&ao_radio_wake))
+                       ao_radio_abort = 1;
+       }
+       rx_waiting = 0;
+       ao_arch_release_interrupts();
+       ao_clear_alarm();
+       if (ao_radio_abort || ao_radio_mcu_wake)
                return 0;
        rx_data_consumed += AO_FEC_DECODE_BLOCK;
 #if AO_PROFILE
@@ -977,48 +1113,67 @@ ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout)
         */
        ao_radio_abort = 0;
 
-       /* configure interrupt pin */
        ao_radio_get(len);
-       ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
 
        ao_radio_wake = 0;
        ao_radio_mcu_wake = 0;
 
-       AO_CC1120_SPI.cr2 = 0;
-
-       /* clear any RXNE */
-       (void) AO_CC1120_SPI.dr;
+       ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
 
-       /* Have the radio signal when the preamble quality goes high */
-       ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_PQT_REACHED);
+       /* configure interrupt pin */
+       ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT);
        ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
-                        AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_HIGH);
-       ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr);
+                        AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
+
+       ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);
        ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
-       ao_exti_enable(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN);
+
+       rx_starting = 1;
+       rx_task_id = ao_cur_task->task_id;
 
        ao_radio_strobe(CC1120_SRX);
 
-       /* Wait for the preamble to appear */
-       ao_radio_wait_isr(timeout);
+       if (timeout)
+               ao_alarm(timeout);
+       ao_arch_block_interrupts();
+       while (rx_starting && !ao_radio_abort) {
+               if (ao_sleep(&ao_radio_wake))
+                       ao_radio_abort = 1;
+       }
+       uint8_t rx_task_id_save = rx_task_id;
+       rx_task_id = 0;
+       rx_starting = 0;
+       ao_arch_release_interrupts();
+       if (timeout)
+               ao_clear_alarm();
+
        if (ao_radio_abort) {
                ret = 0;
+               rx_task_id = 0;
                goto abort;
        }
 
-       ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT);
-       ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
-                        AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
-
-       ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);
-       ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
-
-       ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
+       if (rx_task_id_save) {
+               ++rx_slow_start;
+               ao_radio_select();
+               _ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
+               if (rx_ignore) {
+                       uint8_t ignore = AO_CC1120_SPI.dr;
+                       (void) ignore;
+                       AO_CC1120_SPI.dr = 0;
+                       --rx_ignore;
+               }
+       }
 
        ret = ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait);
 
        ao_radio_burst_read_stop();
 
+       if (ao_radio_mcu_wake)
+               ao_radio_check_marc_status();
+       if (ao_radio_abort)
+               ret = 0;
+
 abort:
        /* Convert from 'real' rssi to cc1111-style values */
 
@@ -1033,7 +1188,7 @@ abort:
                radio_rssi = AO_RADIO_FROM_RSSI (rssi);
        }
 
-       ao_radio_strobe(CC1120_SIDLE);
+       ao_radio_idle();
 
        ao_radio_put();
 
@@ -1072,7 +1227,7 @@ struct ao_cc1120_reg {
        char            *name;
 };
 
-const static struct ao_cc1120_reg ao_cc1120_reg[] = {
+static const struct ao_cc1120_reg ao_cc1120_reg[] = {
        { .addr = CC1120_IOCFG3,        .name = "IOCFG3" },
        { .addr = CC1120_IOCFG2,        .name = "IOCFG2" },
        { .addr = CC1120_IOCFG1,        .name = "IOCFG1" },
@@ -1253,7 +1408,7 @@ const static struct ao_cc1120_reg ao_cc1120_reg[] = {
 
 static void ao_radio_show(void) {
        uint8_t status = ao_radio_status();
-       int     i;
+       unsigned int    i;
 
        ao_radio_get(0xff);
        status = ao_radio_status();
@@ -1264,6 +1419,10 @@ static void ao_radio_show(void) {
 
        for (i = 0; i < AO_NUM_CC1120_REG; i++)
                printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name);
+
+       printf("RX fast start: %u\n", rx_fast_start);
+       printf("RX slow start: %u\n", rx_slow_start);
+       printf("RX missed:     %u\n", rx_missed);
        ao_radio_put();
 }
 
@@ -1287,12 +1446,12 @@ static void ao_radio_packet(void) {
 }
 
 void
-ao_radio_test_recv()
+ao_radio_test_recv(void)
 {
        uint8_t bytes[34];
        uint8_t b;
 
-       if (ao_radio_recv(bytes, 34)) {
+       if (ao_radio_recv(bytes, 34, 0)) {
                if (bytes[33] & 0x80)
                        printf ("CRC OK");
                else
@@ -1308,13 +1467,12 @@ ao_radio_test_recv()
 #include <ao_aprs.h>
 
 static void
-ao_radio_aprs()
+ao_radio_aprs(void)
 {
        ao_packet_slave_stop();
        ao_aprs_send();
 }
 #endif
-
 #endif
 
 static const struct ao_cmds ao_radio_cmds[] = {
index a1d78c01b1d80b145262ad7f04f9bae5750cb1a2..943f344958fcf9337dc1daa6033d48c3733e55d4 100644 (file)
 #define CC1120_FREQ_IF_CFG     0x0f
 #define CC1120_IQIC            0x10
 #define CC1120_CHAN_BW         0x11
+#define  CC1120_CHAN_BW_CHFILT_BYPASS          7
+#define  CC1120_CHAN_BW_ADC_CIC_DECFACT                6
+#define  CC1120_CHAN_BW_ADC_CIC_DECFACT_20             0
+#define  CC1120_CHAN_BW_ADC_CIC_DECFACT_32             1
+#define  CC1120_CHAN_BW_BB_CIC_DECFACT         0
+
 #define CC1120_MDMCFG1         0x12
 #define  CC1120_MDMCFG1_CARRIER_SENSE_GATE     7
 #define  CC1120_MDMCFG1_FIFO_EN                        6
 #define  CC1120_SETTLING_CFG_FS_AUTOCAL_MASK           3
 #define  CC1120_SETTLING_CFG_LOCK_TIME         1
 #define  CC1120_SETTLING_CFG_LOCK_TIME_50_20           0
-#define  CC1120_SETTLING_CFG_LOCK_TIME_70_30           1
+#define  CC1120_SETTLING_CFG_LOCK_TIME_75_30           1
 #define  CC1120_SETTLING_CFG_LOCK_TIME_100_40          2
 #define  CC1120_SETTLING_CFG_LOCK_TIME_150_60          3
 #define  CC1120_SETTLING_CFG_LOCK_TIME_MASK            3
index 399abc4db7b635c321f71f54c447b232735c5a29..21a31a89d16f6c261373b597d03d4cbd25769a61 100644 (file)
         CC1120_SYNC0,                          0x91,       /* Sync Word Configuration [7:0] */\r
 \r
         CC1120_SYNC_CFG1,                                 /* Sync Word Detection Configuration */\r
-               (CC1120_SYNC_CFG1_DEM_CFG_PQT_GATING_ENABLED << CC1120_SYNC_CFG1_DEM_CFG) |\r
-               (0x07 << CC1120_SYNC_CFG1_SYNC_THR),\r
+               (CC1120_SYNC_CFG1_DEM_CFG_PQT_GATING_DISABLED << CC1120_SYNC_CFG1_DEM_CFG) |\r
+               (0xc << CC1120_SYNC_CFG1_SYNC_THR),\r
         CC1120_SYNC_CFG0,\r
                (CC1120_SYNC_CFG0_SYNC_MODE_16_BITS << CC1120_SYNC_CFG0_SYNC_MODE) |\r
-               (CC1120_SYNC_CFG0_SYNC_NUM_ERROR_2 << CC1120_SYNC_CFG0_SYNC_NUM_ERROR),\r
-        CC1120_DCFILT_CFG,                     0x1c,       /* Digital DC Removal Configuration */\r
+               (CC1120_SYNC_CFG0_SYNC_NUM_ERROR_DISABLED << CC1120_SYNC_CFG0_SYNC_NUM_ERROR),\r
+        CC1120_DCFILT_CFG,                     0x15,       /* Digital DC Removal Configuration */\r
         CC1120_PREAMBLE_CFG1,                             /* Preamble Length Configuration */\r
                (CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |\r
                (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD),\r
         CC1120_PREAMBLE_CFG0,\r
-               (1 << CC1120_PREAMBLE_CFG0_PQT_EN) |\r
-               (0x6 << CC1120_PREAMBLE_CFG0_PQT),\r
-        CC1120_FREQ_IF_CFG,                    0x40,       /* RX Mixer Frequency Configuration */\r
-        CC1120_IQIC,                           0x46,       /* Digital Image Channel Compensation Configuration */\r
+               (0 << CC1120_PREAMBLE_CFG0_PQT_EN) |\r
+               (0xe << CC1120_PREAMBLE_CFG0_PQT),\r
+\r
+       /* Adjust PQT lower to accept fewer packets */\r
+\r
+        CC1120_FREQ_IF_CFG,                    0x3a,       /* RX Mixer Frequency Configuration */\r
+        CC1120_IQIC,                           0x00,       /* Digital Image Channel Compensation Configuration */\r
         CC1120_CHAN_BW,                        0x02,       /* Channel Filter Configuration */\r
 \r
         CC1120_MDMCFG1,                                   /* General Modem Parameter Configuration */\r
                (0 << CC1120_MDMCFG1_MANCHESTER_EN) |\r
                (0 << CC1120_MDMCFG1_INVERT_DATA_EN) |\r
                (0 << CC1120_MDMCFG1_COLLISION_DETECT_EN) |\r
-               (CC1120_MDMCFG1_DVGA_GAIN_9 << CC1120_MDMCFG1_DVGA_GAIN) |\r
+               (CC1120_MDMCFG1_DVGA_GAIN_0 << CC1120_MDMCFG1_DVGA_GAIN) |\r
                (0 << CC1120_MDMCFG1_SINGLE_ADC_EN),\r
-        CC1120_MDMCFG0,                        0x05,       /* General Modem Parameter Configuration */\r
+        CC1120_MDMCFG0,                        0x0d,       /* General Modem Parameter Configuration */\r
 \r
        /* AGC reference = 10 * log10(receive BW) - 4 = 10 * log10(100e3) - 4 = 46 */\r
-        CC1120_AGC_REF,                        46,         /* AGC Reference Level Configuration */\r
+        CC1120_AGC_REF,                        0x36,         /* AGC Reference Level Configuration */\r
 \r
        /* Carrier sense threshold - 25dB above the noise */\r
         CC1120_AGC_CS_THR,                     25,         /* Carrier Sense Threshold Configuration */\r
@@ -93,7 +96,7 @@
 \r
         CC1120_SETTLING_CFG,                              /* Frequency Synthesizer Calibration and Settling Configuration */\r
                (CC1120_SETTLING_CFG_FS_AUTOCAL_IDLE_TO_ON << CC1120_SETTLING_CFG_FS_AUTOCAL) |\r
-               (CC1120_SETTLING_CFG_LOCK_TIME_50_20 << CC1120_SETTLING_CFG_LOCK_TIME) |\r
+               (CC1120_SETTLING_CFG_LOCK_TIME_75_30 << CC1120_SETTLING_CFG_LOCK_TIME) |\r
                (CC1120_SETTLING_CFG_FSREG_TIME_60 << CC1120_SETTLING_CFG_FSREG_TIME),\r
 \r
         CC1120_FS_CFG,                                    /* Frequency Synthesizer Configuration */\r
         CC1120_PKT_CFG1,                       0x45,       /* Packet Configuration, Reg 1 */\r
         CC1120_PKT_CFG0,                       0x00,       /* Packet Configuration, Reg 0 */\r
 #endif\r
-        CC1120_RFEND_CFG1,                     0x0f,       /* RFEND Configuration, Reg 1 */\r
+        CC1120_RFEND_CFG1,                     0x0e,       /* RFEND Configuration, Reg 1 */\r
         CC1120_RFEND_CFG0,                     0x00,       /* RFEND Configuration, Reg 0 */\r
        //        CC1120_PA_CFG2,                        0x3f,       /* Power Amplifier Configuration, Reg 2 */\r
        CC1120_PA_CFG2,                        0x3f,       /* Power Amplifier Configuration, Reg 2 */\r
         CC1120_PA_CFG0,                        0x7b,       /* Power Amplifier Configuration, Reg 0 */\r
         CC1120_PKT_LEN,                        0xff,       /* Packet Length Configuration */\r
         CC1120_IF_MIX_CFG,                     0x00,       /* IF Mix Configuration */\r
-        CC1120_FREQOFF_CFG,                    0x22,       /* Frequency Offset Correction Configuration */\r
-        CC1120_TOC_CFG,                        0x0b,       /* Timing Offset Correction Configuration */\r
+        CC1120_FREQOFF_CFG,                    0x20,       /* Frequency Offset Correction Configuration */\r
+        CC1120_TOC_CFG,                        0x0a,       /* Timing Offset Correction Configuration */\r
         CC1120_MARC_SPARE,                     0x00,       /* MARC Spare */\r
         CC1120_ECG_CFG,                        0x00,       /* External Clock Frequency Configuration */\r
         CC1120_SOFT_TX_DATA_CFG,               0x00,       /* Soft TX Data Configuration */\r
         CC1120_XOSC4,                          0xa0,       /* Crystal Oscillator Configuration, Reg 4 */\r
         CC1120_XOSC3,                          0x03,       /* Crystal Oscillator Configuration, Reg 3 */\r
         CC1120_XOSC2,                          0x04,       /* Crystal Oscillator Configuration, Reg 2 */\r
-        CC1120_XOSC1,                          0x01,       /* Crystal Oscillator Configuration, Reg 1 */\r
+        CC1120_XOSC1,                          0x03,       /* Crystal Oscillator Configuration, Reg 1 */\r
         CC1120_XOSC0,                          0x00,       /* Crystal Oscillator Configuration, Reg 0 */\r
         CC1120_ANALOG_SPARE,                   0x00,       /*  */\r
         CC1120_PA_CFG3,                        0x00,       /* Power Amplifier Configuration, Reg 3 */\r
         CC1120_AGC_GAIN2,                      0xd1,       /* AGC Gain, Reg 2 */\r
         CC1120_AGC_GAIN1,                      0x00,       /* AGC Gain, Reg 1 */\r
         CC1120_AGC_GAIN0,                      0x3f,       /* AGC Gain, Reg 0 */\r
-        CC1120_SOFT_RX_DATA_OUT,               0x00,       /* Soft Decision Symbol Data */\r
-        CC1120_SOFT_TX_DATA_IN,                0x00,       /* Soft TX Data Input Register */\r
-        CC1120_ASK_SOFT_RX_DATA,               0x30,       /* AGC ASK Soft Decision Output */\r
         CC1120_RNDGEN,                         0x7f,       /* Random Number Value */\r
-        CC1120_MAGN2,                          0x00,       /* Signal Magnitude after CORDIC [16] */\r
-        CC1120_MAGN1,                          0x00,       /* Signal Magnitude after CORDIC [15:8] */\r
-        CC1120_MAGN0,                          0x00,       /* Signal Magnitude after CORDIC [7:0] */\r
-        CC1120_ANG1,                           0x00,       /* Signal Angular after CORDIC [9:8] */\r
-        CC1120_ANG0,                           0x00,       /* Signal Angular after CORDIC [7:0] */\r
-        CC1120_CHFILT_I2,                      0x08,       /* Channel Filter Data Real Part [18:16] */\r
-        CC1120_CHFILT_I1,                      0x00,       /* Channel Filter Data Real Part [15:8] */\r
-        CC1120_CHFILT_I0,                      0x00,       /* Channel Filter Data Real Part [7:0] */\r
-        CC1120_CHFILT_Q2,                      0x00,       /* Channel Filter Data Imaginary Part [18:16] */\r
-        CC1120_CHFILT_Q1,                      0x00,       /* Channel Filter Data Imaginary Part [15:8] */\r
-        CC1120_CHFILT_Q0,                      0x00,       /* Channel Filter Data Imaginary Part [7:0] */\r
-        CC1120_GPIO_STATUS,                    0x00,       /* GPIO Status */\r
         CC1120_FSCAL_CTRL,                     0x01,       /*  */\r
         CC1120_PHASE_ADJUST,                   0x00,       /*  */\r
-        CC1120_PARTNUMBER,                     0x00,       /* Part Number */\r
-        CC1120_PARTVERSION,                    0x00,       /* Part Revision */\r
         CC1120_SERIAL_STATUS,                  0x00,       /* Serial Status */\r
-        CC1120_RX_STATUS,                      0x01,       /* RX Status */\r
-        CC1120_TX_STATUS,                      0x00,       /* TX Status */\r
-        CC1120_MARC_STATUS1,                   0x00,       /* MARC Status, Reg 1 */\r
-        CC1120_MARC_STATUS0,                   0x00,       /* MARC Status, Reg 0 */\r
         CC1120_PA_IFAMP_TEST,                  0x00,       /*  */\r
         CC1120_FSRF_TEST,                      0x00,       /*  */\r
         CC1120_PRE_TEST,                       0x00,       /*  */\r
index f250e714a98ad5138b5d95ee41d9636613bfe325..cf61acfe9c4ae45a6def0d88caf05c8d3d0dac96 100644 (file)
@@ -249,36 +249,81 @@ ao_radio_idle(void)
 }
 
 /*
- * Packet deviation is 20.5kHz
+ * Packet deviation
  *
  *     fdev = fosc >> 17 * (8 + dev_m) << dev_e
  *
+ * For 38400 baud, use 20.5kHz:
+ *
  *             26e6 / (2 ** 17) * (8 + 5) * (2 ** 3) = 20630Hz
+ *
+ * For 9600 baud, use 5.125kHz:
+ *
+ *             26e6 / (2 ** 17) * (8 + 5) * (2 ** 1) = 5157Hz
+ *
+ * For 2400 baud, use 1.5kHz:
+ *
+ *             26e6 / (2 ** 17) * (8 + 0) * (2 ** 0) = 1587Hz
  */
 
-#define PACKET_DEV_E   3
-#define PACKET_DEV_M   5
+#define PACKET_DEV_E_384       3
+#define PACKET_DEV_M_384       5
+
+#define PACKET_DEV_E_96                1
+#define PACKET_DEV_M_96                5
+
+#define PACKET_DEV_E_24                0
+#define PACKET_DEV_M_24                0
 
 /*
- * For our packet data, set the symbol rate to 38400 Baud
+ * For our packet data:
  *
  *              (256 + DATARATE_M) * 2 ** DATARATE_E
  *     Rdata = -------------------------------------- * fosc
  *                          2 ** 28
  *
+ * For 38400 baud:
+ *
  *             (256 + 131) * (2 ** 10) / (2**28) * 26e6 = 38383
  *
  *     DATARATE_M = 131
- *     DATARATE_E = 10
+ *     DATARATE_E_384 = 10
+ *     DATARATE_E_96 = 8
+ *     DATARATE_E_24 = 6
  */
-#define PACKET_DRATE_E 10
-#define PACKET_DRATE_M 131
+#define PACKET_DRATE_M         131
+
+#define PACKET_DRATE_E_384     10
+#define PACKET_DRATE_E_96      8
+#define PACKET_DRATE_E_24      6
+
+static const struct {
+       uint8_t         mdmcfg4;
+       uint8_t         deviatn;
+} packet_rate_setup[] = {
+       [AO_RADIO_RATE_38400] = {
+               .mdmcfg4 = ((0xf << 4) |
+                           (PACKET_DRATE_E_384 << CC115L_MDMCFG4_DRATE_E)),
+               .deviatn = ((PACKET_DEV_E_384 << CC115L_DEVIATN_DEVIATION_E) |
+                           (PACKET_DEV_M_384 << CC115L_DEVIATN_DEVIATION_M)),
+       },
+
+       [AO_RADIO_RATE_9600] = {
+               .mdmcfg4 = ((0xf << 4) |
+                           (PACKET_DRATE_E_96 << CC115L_MDMCFG4_DRATE_E)),
+               .deviatn = ((PACKET_DEV_E_96 << CC115L_DEVIATN_DEVIATION_E) |
+                           (PACKET_DEV_M_96 << CC115L_DEVIATN_DEVIATION_M)),
+       },
+
+       [AO_RADIO_RATE_2400] = {
+               .mdmcfg4 = ((0xf << 4) |
+                           (PACKET_DRATE_E_24 << CC115L_MDMCFG4_DRATE_E)),
+               .deviatn = ((PACKET_DEV_E_24 << CC115L_DEVIATN_DEVIATION_E) |
+                           (PACKET_DEV_M_24 << CC115L_DEVIATN_DEVIATION_M)),
+       },
+};
 
 static const uint16_t packet_setup[] = {
-       CC115L_DEVIATN,         ((PACKET_DEV_E << CC115L_DEVIATN_DEVIATION_E) |
-                                (PACKET_DEV_M << CC115L_DEVIATN_DEVIATION_M)),
-       CC115L_MDMCFG4,         ((0xf << 4) |
-                                (PACKET_DRATE_E << CC115L_MDMCFG4_DRATE_E)),
        CC115L_MDMCFG3,         (PACKET_DRATE_M),
        CC115L_MDMCFG2,         (0x00 |
                                 (CC115L_MDMCFG2_MOD_FORMAT_GFSK << CC115L_MDMCFG2_MOD_FORMAT) |
@@ -403,9 +448,13 @@ ao_radio_set_mode(uint16_t new_mode)
                return;
 
        changes = new_mode & (~ao_radio_mode);
-       if (changes & AO_RADIO_MODE_BITS_PACKET_TX)
+       if (changes & AO_RADIO_MODE_BITS_PACKET_TX) {
+               ao_radio_reg_write(CC115L_MDMCFG4, packet_rate_setup[ao_config.radio_rate].mdmcfg4);
+               ao_radio_reg_write(CC115L_DEVIATN, packet_rate_setup[ao_config.radio_rate].deviatn);
+
                for (i = 0; i < sizeof (packet_setup) / sizeof (packet_setup[0]); i += 2)
                        ao_radio_reg_write(packet_setup[i], packet_setup[i+1]);
+       }
 
        if (changes & AO_RADIO_MODE_BITS_RDF)
                for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2)
@@ -494,6 +543,7 @@ static void
 ao_radio_get(void)
 {
        static uint32_t last_radio_setting;
+       static uint8_t  last_radio_rate;
 
        ao_mutex_get(&ao_radio_mutex);
        if (!ao_radio_configured)
@@ -504,6 +554,10 @@ ao_radio_get(void)
                ao_radio_reg_write(CC115L_FREQ0, ao_config.radio_setting);
                last_radio_setting = ao_config.radio_setting;
        }
+       if (ao_config.radio_rate != last_radio_rate) {
+               ao_radio_mode &= ~AO_RADIO_MODE_BITS_PACKET_TX;
+               last_radio_rate = ao_config.radio_rate;
+       }
 }
 
 static void
index 944a37f9b38400a05ccc3d2a437f332141af8a79..066df6fff628a39b0680b69e8cf1d34a27b1fe84 100644 (file)
@@ -278,16 +278,17 @@ ao_nmea_gga(void)
 
        ao_gps_lexchar();
        i = ao_gps_decimal(0xff);
-       if (i <= 50) {
-               i = (uint8_t) 5 * i;
+       if (i <= 25) {
+               i = (uint8_t) 10 * i;
                if (ao_gps_char == '.')
-                       i = (i + ((uint8_t) ao_gps_decimal(1) >> 1));
+                       i = (i + ((uint8_t) ao_gps_decimal(1)));
        } else
                i = 255;
        ao_gps_next.hdop = i;
        ao_gps_skip_field();
 
-       ao_gps_next.altitude = ao_gps_decimal(0xff);
+       AO_TELEMETRY_LOCATION_SET_ALTITUDE(&ao_gps_next, ao_gps_decimal(0xff));
+
        ao_gps_skip_field();    /* skip any fractional portion */
 
        ao_nmea_finish();
index 077698a90d514a24672b3d990d867118a1c67a9c..74c29e0a0e74e20af16436e66ffd2de3ab4d12b5 100644 (file)
@@ -728,7 +728,7 @@ ao_gps(void) __reentrant
                                if (nav_timeutc.valid & (1 << NAV_TIMEUTC_VALID_UTC))
                                        ao_gps_data.flags |= AO_GPS_DATE_VALID;
 
-                               ao_gps_data.altitude = nav_posllh.alt_msl / 1000;
+                               AO_TELEMETRY_LOCATION_SET_ALTITUDE(&ao_gps_data, nav_posllh.alt_msl / 1000);
                                ao_gps_data.latitude = nav_posllh.lat;
                                ao_gps_data.longitude = nav_posllh.lon;
 
@@ -740,11 +740,11 @@ ao_gps(void) __reentrant
                                ao_gps_data.minute = nav_timeutc.min;
                                ao_gps_data.second = nav_timeutc.sec;
 
-                               ao_gps_data.pdop = nav_dop.pdop;
-                               ao_gps_data.hdop = nav_dop.hdop;
-                               ao_gps_data.vdop = nav_dop.vdop;
-
-                               /* mode is not set */
+                               /* we report dop scaled by 10, but ublox provides dop scaled by 100
+                                */
+                               ao_gps_data.pdop = nav_dop.pdop / 10;
+                               ao_gps_data.hdop = nav_dop.hdop / 10;
+                               ao_gps_data.vdop = nav_dop.vdop / 10;
 
                                ao_gps_data.ground_speed = nav_velned.g_speed;
                                ao_gps_data.climb_rate = -nav_velned.vel_d;
index 9e64283696eaf3c25c68510764e57c79750ca1f4..32c00068a58d9d89b0a5c29358458afc6c332c1d 100644 (file)
@@ -28,7 +28,21 @@ ao_lco_query(uint16_t box, struct ao_pad_query *query, uint16_t *tick_offset)
 {
        int8_t          r;
        uint16_t        sent_time;
+       uint16_t        timeout = AO_MS_TO_TICKS(10);
 
+#if HAS_RADIO_RATE
+       switch (ao_config.radio_rate) {
+       case AO_RADIO_RATE_38400:
+       default:
+               break;
+       case AO_RADIO_RATE_9600:
+               timeout = AO_MS_TO_TICKS(20);
+               break;
+       case AO_RADIO_RATE_2400:
+               timeout = AO_MS_TO_TICKS(80);
+               break;
+       }
+#endif
        ao_mutex_get(&ao_lco_mutex);
        command.tick = ao_time() - *tick_offset;
        command.box = box;
@@ -36,7 +50,7 @@ ao_lco_query(uint16_t box, struct ao_pad_query *query, uint16_t *tick_offset)
        command.channels = 0;
        ao_radio_cmac_send(&command, sizeof (command));
        sent_time = ao_time();
-       r = ao_radio_cmac_recv(query, sizeof (*query), AO_MS_TO_TICKS(10));
+       r = ao_radio_cmac_recv(query, sizeof (*query), timeout);
        if (r == AO_RADIO_CMAC_OK)
                *tick_offset = sent_time - query->tick;
        ao_mutex_put(&ao_lco_mutex);
index d6c99cbd89defb62b07a2def1b7964f8be2f9df9..2354504981d6f09d3b51046d02fab1e300bc6b3a 100644 (file)
@@ -57,6 +57,12 @@ static __xdata uint16_t              ao_packet_master_time;
 #define AO_PACKET_MASTER_DELAY_LONG    AO_MS_TO_TICKS(1000)
 #define AO_PACKET_MASTER_DELAY_TIMEOUT AO_MS_TO_TICKS(2000)
 
+#if HAS_RADIO_RATE
+#define AO_PACKET_MASTER_RECV_DELAY    AO_MS_TO_TICKS(100) << (ao_config.radio_rate << 1)
+#else
+#define AO_PACKET_MASTER_RECV_DELAY    AO_MS_TO_TICKS(100)
+#endif
+
 static void
 ao_packet_master_busy(void)
 {
@@ -91,7 +97,7 @@ ao_packet_master(void)
                if (ao_tx_packet.len)
                        ao_packet_master_busy();
                ao_packet_master_check_busy();
-               ao_alarm(ao_packet_master_delay);
+               ao_alarm(AO_PACKET_MASTER_RECV_DELAY);
                r = ao_packet_recv();
                ao_clear_alarm();
                if (r) {
index 144cbd70a8834e4053e67c6bebec423e68ae8175..dc2c83fe0cf3c668668dfbf354cbae020d14533f 100644 (file)
@@ -362,14 +362,26 @@ ao_pad_test(void)
 void
 ao_pad_manual(void)
 {
+       uint8_t ignite;
+       int     repeat;
        ao_cmd_white();
        if (!ao_match_word("DoIt"))
                return;
        ao_cmd_decimal();
        if (ao_cmd_status != ao_cmd_success)
                return;
-       ao_pad_ignite = 1 << ao_cmd_lex_i;
-       ao_wakeup(&ao_pad_ignite);
+       ignite = 1 << ao_cmd_lex_i;
+       ao_cmd_decimal();
+       if (ao_cmd_status != ao_cmd_success) {
+               repeat = 1;
+               ao_cmd_status = ao_cmd_success;
+       } else
+               repeat = ao_cmd_lex_i;
+       while (repeat-- > 0) {
+               ao_pad_ignite = ignite;
+               ao_wakeup(&ao_pad_ignite);
+               ao_delay(AO_PAD_FIRE_TIME>>1);
+       }
 }
 
 static __xdata struct ao_task ao_pad_task;
diff --git a/src/easymega-v0.1/.gitignore b/src/easymega-v0.1/.gitignore
deleted file mode 100644 (file)
index 410943d..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-ao_product.h
-easymega-*.elf
diff --git a/src/easymega-v0.1/Makefile b/src/easymega-v0.1/Makefile
deleted file mode 100644 (file)
index 6661985..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-#
-# 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_hmc5883.h \
-       ao_mpu6000.h \
-       ao_mma655x.h \
-       ao_profile.h \
-       ao_task.h \
-       ao_whiten.h \
-       ao_sample_profile.h \
-       ao_quaternion.h \
-       math.h \
-       ao_mpu.h \
-       stm32l.h \
-       math.h \
-       Makefile
-
-#
-# Common AltOS sources
-#
-#      ao_hmc5883.c
-
-#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
-
-MATH_SRC=\
-       ef_acos.c \
-       ef_sqrt.c \
-       ef_rem_pio2.c \
-       kf_cos.c \
-       kf_sin.c \
-       kf_rem_pio2.c \
-       sf_copysign.c \
-       sf_cos.c \
-       sf_fabs.c \
-       sf_floor.c \
-       sf_scalbn.c \
-       sf_sin.c \
-       ef_log.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.c \
-       ao_stdio.c \
-       ao_panic.c \
-       ao_timer.c \
-       ao_mutex.c \
-       ao_ignite.c \
-       ao_freq.c \
-       ao_dma_stm.c \
-       ao_spi_stm.c \
-       ao_data.c \
-       ao_ms5607.c \
-       ao_mma655x.c \
-       ao_hmc5883.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_i2c_stm.c \
-       ao_mpu6000.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_companion.c \
-       ao_pyro.c \
-       $(MATH_SRC) \
-       $(PROFILE) \
-       $(SAMPLE_PROFILE) \
-       $(STACK_GUARD)
-
-PRODUCT=EasyMega-v0.1
-PRODUCT_DEF=-DEASYMEGA
-IDPRODUCT=0x0023
-
-CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g
-
-PROGNAME=easymega-v0.1
-PROG=$(PROGNAME)-$(VERSION).elf
-HEX=$(PROGNAME)-$(VERSION).ihx
-
-SRC=$(ALTOS_SRC) ao_easymega.c
-OBJ=$(SRC:.c=.o)
-
-all: $(PROG) $(HEX)
-
-$(PROG): Makefile $(OBJ) altos.ld
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
-
-../altitude-pa.h: make-altitude-pa
-       nickle $< > $@
-
-$(OBJ): $(INC)
-
-ao_product.h: ao-make-product.5c ../Version
-       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
-
-distclean:     clean
-
-clean:
-       rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
-       rm -f ao_product.h
-
-install:
-
-uninstall:
diff --git a/src/easymega-v0.1/ao_easymega.c b/src/easymega-v0.1/ao_easymega.c
deleted file mode 100644 (file)
index e217c33..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright © 2014 Bdale Garbee <bdale@gag.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include <ao.h>
-#include <ao_hmc5883.h>
-#include <ao_mpu6000.h>
-#include <ao_mma655x.h>
-#include <ao_log.h>
-#include <ao_exti.h>
-#include <ao_companion.h>
-#include <ao_profile.h>
-#include <ao_eeprom.h>
-#if HAS_SAMPLE_PROFILE
-#include <ao_sample_profile.h>
-#endif
-#include <ao_pyro.h>
-#if HAS_STACK_GUARD
-#include <ao_mpu.h>
-#endif
-
-int
-main(void)
-{
-       ao_clock_init();
-       
-#if HAS_STACK_GUARD
-       ao_mpu_init();
-#endif
-
-       ao_task_init();
-       ao_led_init(LEDS_AVAILABLE);
-       ao_led_on(AO_LED_GREEN);
-       ao_timer_init();
-
-       ao_i2c_init();
-       ao_spi_init();
-       ao_dma_init();
-       ao_exti_init();
-
-       ao_adc_init();
-#if HAS_BEEP
-       ao_beep_init();
-#endif
-       ao_cmd_init();
-
-#if HAS_MS5607
-       ao_ms5607_init();
-#endif
-#if HAS_HMC5883
-       ao_hmc5883_init();
-#endif
-#if HAS_MPU6000
-       ao_mpu6000_init();
-#endif
-#if HAS_MMA655X
-       ao_mma655x_init();
-#endif
-
-       ao_eeprom_init();
-       ao_storage_init();
-       
-       ao_flight_init();
-       ao_log_init();
-       ao_report_init();
-
-       ao_usb_init();
-       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_start_scheduler();
-       return 0;
-}
diff --git a/src/easymega-v0.1/ao_pins.h b/src/easymega-v0.1/ao_pins.h
deleted file mode 100644 (file)
index cb6e398..0000000
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * Copyright © 2014 Bdale Garbee <bdale@gag.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef _AO_PINS_H_
-#define _AO_PINS_H_
-
-#define HAS_TASK_QUEUE         1
-
-/* 8MHz High speed external crystal */
-#define AO_HSE                 8000000
-
-/* PLLVCO = 96MHz (so that USB will work) */
-#define AO_PLLMUL              12
-#define AO_RCC_CFGR_PLLMUL     (STM_RCC_CFGR_PLLMUL_12)
-
-/* 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           0
-#define USE_SERIAL_2_STDIN     0
-#define SERIAL_2_PA2_PA3       0
-#define SERIAL_2_PD5_PD6       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_serial1_getchar
-#define ao_gps_putchar         ao_serial1_putchar
-#define ao_gps_set_speed       ao_serial1_set_speed
-#define ao_gps_fifo            (ao_stm_usart1.rx_fifo)
-
-#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX       (1024 * 1024)
-#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 HAS_BATTERY_REPORT     1
-#define HAS_RADIO              0
-#define HAS_TELEMETRY          0
-#define HAS_APRS               0
-
-#define HAS_SPI_1              1
-#define SPI_1_PA5_PA6_PA7      1       /* Barometer */
-#define SPI_1_PB3_PB4_PB5      1       /* Accelerometer, Gyro */
-#define SPI_1_PE13_PE14_PE15   0       
-#define SPI_1_OSPEEDR          STM_OSPEEDR_10MHz
-
-#define HAS_SPI_2              1
-#define SPI_2_PB13_PB14_PB15   1       /* Flash, Companion */
-#define SPI_2_PD1_PD3_PD4      0
-#define SPI_2_OSPEEDR          STM_OSPEEDR_10MHz
-
-#define SPI_2_PORT             (&stm_gpiob)
-#define SPI_2_SCK_PIN          13
-#define SPI_2_MISO_PIN         14
-#define SPI_2_MOSI_PIN         15
-
-#define HAS_I2C_1              1
-#define I2C_1_PB8_PB9          1
-
-#define HAS_I2C_2              0
-#define I2C_2_PB10_PB11                0
-
-#define PACKET_HAS_SLAVE       0
-#define PACKET_HAS_MASTER      0
-
-#define LOW_LEVEL_DEBUG                0
-
-#define LED_PORT_ENABLE                STM_RCC_AHBENR_GPIOAEN
-#define LED_PORT               (&stm_gpioa)
-#define LED_PIN_RED            9
-#define LED_PIN_GREEN          10
-#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                        0
-#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_gpioa)
-#define AO_PYRO_PIN_0  15
-
-/* Pyro B */
-#define AO_PYRO_PORT_1 (&stm_gpioc)
-#define AO_PYRO_PIN_1  10
-
-/* Pyro C */
-#define AO_PYRO_PORT_2 (&stm_gpiob)
-#define AO_PYRO_PIN_2  11
-
-/* Pyro D */
-#define AO_PYRO_PORT_3 (&stm_gpiob)
-#define AO_PYRO_PIN_3  10
-
-/* Drogue */
-#define AO_IGNITER_DROGUE_PORT (&stm_gpioa)
-#define AO_IGNITER_DROGUE_PIN  0
-
-/* Main */
-#define AO_IGNITER_MAIN_PORT   (&stm_gpioa)
-#define AO_IGNITER_MAIN_PIN    1
-
-/* Number of general purpose pyro channels available */
-#define AO_PYRO_NUM    4
-
-#define AO_IGNITER_SET_DROGUE(v)       stm_gpio_set(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, v)
-#define AO_IGNITER_SET_MAIN(v)         stm_gpio_set(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, v)
-
-/*
- * 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         14
-#define AO_ADC_SENSE_A_PORT    (&stm_gpioc)
-#define AO_ADC_SENSE_A_PIN     4
-
-#define AO_ADC_SENSE_B         15
-#define AO_ADC_SENSE_B_PORT    (&stm_gpioc)
-#define AO_ADC_SENSE_B_PIN     5
-
-#define AO_ADC_SENSE_C         13
-#define AO_ADC_SENSE_C_PORT    (&stm_gpioc)
-#define AO_ADC_SENSE_C_PIN     3
-
-#define AO_ADC_SENSE_D         12
-#define AO_ADC_SENSE_D_PORT    (&stm_gpioc)
-#define AO_ADC_SENSE_D_PIN     2
-
-#define AO_ADC_SENSE_DROGUE    11
-#define AO_ADC_SENSE_DROGUE_PORT       (&stm_gpioc)
-#define AO_ADC_SENSE_DROGUE_PIN        1
-
-#define AO_ADC_SENSE_MAIN      10
-#define AO_ADC_SENSE_MAIN_PORT (&stm_gpioc)
-#define AO_ADC_SENSE_MAIN_PIN  0
-
-#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_gpioa)
-#define AO_MS5607_CS_PIN       3
-#define AO_MS5607_CS_MASK      (1 << AO_MS5607_CS_PIN)
-#define AO_MS5607_MISO_PORT    (&stm_gpioa)
-#define AO_MS5607_MISO_PIN     6
-#define AO_MS5607_MISO_MASK    (1 << AO_MS5607_MISO_PIN)
-#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_gpiob)
-#define AO_M25_SPI_CS_PIN      12
-#define AO_M25_SPI_CS_MASK     (1 << AO_M25_SPI_CS_PIN)
-#define AO_M25_SPI_BUS         AO_SPI_2_PB13_PB14_PB15
-
-/*
- * Mag sensor (hmc5883)
- */
-
-#define HAS_HMC5883            1
-#define AO_HMC5883_INT_PORT    (&stm_gpioc)
-#define AO_HMC5883_INT_PIN     14
-#define AO_HMC5883_I2C_INDEX   STM_I2C_INDEX(1)
-
-/*
- * mpu6000
- */
-
-#define HAS_MPU6000            1
-#define AO_MPU6000_INT_PORT    (&stm_gpioc)
-#define AO_MPU6000_INT_PIN     15
-#define AO_MPU6000_SPI_BUS     AO_SPI_1_PB3_PB4_PB5
-#define AO_MPU6000_SPI_CS_PORT (&stm_gpioc)
-#define AO_MPU6000_SPI_CS_PIN  13
-#define HAS_IMU                        1
-
-/*
- * mma655x
- */
-
-#define HAS_MMA655X            1
-#define AO_MMA655X_SPI_INDEX   AO_SPI_1_PB3_PB4_PB5
-#define AO_MMA655X_CS_PORT     (&stm_gpioc)
-#define AO_MMA655X_CS_PIN      12
-
-#define NUM_CMDS               16
-
-/*
- * Companion
- */
-
-#define AO_COMPANION_CS_PORT   (&stm_gpiob)
-#define AO_COMPANION_CS_PIN    (6)
-#define AO_COMPANION_SPI_BUS   AO_SPI_2_PB13_PB14_PB15
-
-/*
- * Monitor
- */
-
-#define HAS_MONITOR            0
-#define LEGACY_MONITOR         0
-#define HAS_MONITOR_PUT                0
-#define AO_MONITOR_LED         0
-#define HAS_RSSI               0
-
-/*
- * Profiling Viterbi decoding
- */
-
-#ifndef AO_PROFILE
-#define AO_PROFILE             0
-#endif
-
-#endif /* _AO_PINS_H_ */
diff --git a/src/easymega-v0.1/flash-loader/Makefile b/src/easymega-v0.1/flash-loader/Makefile
deleted file mode 100644 (file)
index 35312fd..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# AltOS flash loader build
-#
-#
-
-TOPDIR=../..
-HARDWARE=easymega-v0.1
-include $(TOPDIR)/stm/Makefile-flash.defs
diff --git a/src/easymega-v0.1/flash-loader/ao_pins.h b/src/easymega-v0.1/flash-loader/ao_pins.h
deleted file mode 100644 (file)
index 445289b..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright © 2013 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef _AO_PINS_H_
-#define _AO_PINS_H_
-
-/* External crystal at 8MHz */
-#define AO_HSE         8000000
-
-#include <ao_flash_stm_pins.h>
-
-/* Companion port cs_companion0 PD0 */
-
-#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/easymega-v1.0/.gitignore b/src/easymega-v1.0/.gitignore
new file mode 100644 (file)
index 0000000..410943d
--- /dev/null
@@ -0,0 +1,2 @@
+ao_product.h
+easymega-*.elf
diff --git a/src/easymega-v1.0/Makefile b/src/easymega-v1.0/Makefile
new file mode 100644 (file)
index 0000000..c3b360b
--- /dev/null
@@ -0,0 +1,144 @@
+#
+# 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_hmc5883.h \
+       ao_mpu6000.h \
+       ao_mma655x.h \
+       ao_profile.h \
+       ao_task.h \
+       ao_whiten.h \
+       ao_sample_profile.h \
+       ao_quaternion.h \
+       math.h \
+       ao_mpu.h \
+       stm32l.h \
+       math.h \
+       Makefile
+
+#
+# Common AltOS sources
+#
+#      ao_hmc5883.c
+
+#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
+
+MATH_SRC=\
+       ef_acos.c \
+       ef_sqrt.c \
+       ef_rem_pio2.c \
+       kf_cos.c \
+       kf_sin.c \
+       kf_rem_pio2.c \
+       sf_copysign.c \
+       sf_cos.c \
+       sf_fabs.c \
+       sf_floor.c \
+       sf_scalbn.c \
+       sf_sin.c \
+       ef_log.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.c \
+       ao_stdio.c \
+       ao_panic.c \
+       ao_timer.c \
+       ao_mutex.c \
+       ao_ignite.c \
+       ao_freq.c \
+       ao_dma_stm.c \
+       ao_spi_stm.c \
+       ao_data.c \
+       ao_ms5607.c \
+       ao_mma655x.c \
+       ao_hmc5883.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_i2c_stm.c \
+       ao_mpu6000.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_companion.c \
+       ao_pyro.c \
+       $(MATH_SRC) \
+       $(PROFILE) \
+       $(SAMPLE_PROFILE) \
+       $(STACK_GUARD)
+
+PRODUCT=EasyMega-v1.0
+PRODUCT_DEF=-DEASYMEGA
+IDPRODUCT=0x0028
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g
+
+PROGNAME=easymega-v1.0
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_easymega.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+../altitude-pa.h: make-altitude-pa
+       nickle $< > $@
+
+$(OBJ): $(INC)
+
+ao_product.h: ao-make-product.5c ../Version
+       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+distclean:     clean
+
+clean:
+       rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+       rm -f ao_product.h
+
+install:
+
+uninstall:
diff --git a/src/easymega-v1.0/ao_easymega.c b/src/easymega-v1.0/ao_easymega.c
new file mode 100644 (file)
index 0000000..e217c33
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright © 2014 Bdale Garbee <bdale@gag.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_hmc5883.h>
+#include <ao_mpu6000.h>
+#include <ao_mma655x.h>
+#include <ao_log.h>
+#include <ao_exti.h>
+#include <ao_companion.h>
+#include <ao_profile.h>
+#include <ao_eeprom.h>
+#if HAS_SAMPLE_PROFILE
+#include <ao_sample_profile.h>
+#endif
+#include <ao_pyro.h>
+#if HAS_STACK_GUARD
+#include <ao_mpu.h>
+#endif
+
+int
+main(void)
+{
+       ao_clock_init();
+       
+#if HAS_STACK_GUARD
+       ao_mpu_init();
+#endif
+
+       ao_task_init();
+       ao_led_init(LEDS_AVAILABLE);
+       ao_led_on(AO_LED_GREEN);
+       ao_timer_init();
+
+       ao_i2c_init();
+       ao_spi_init();
+       ao_dma_init();
+       ao_exti_init();
+
+       ao_adc_init();
+#if HAS_BEEP
+       ao_beep_init();
+#endif
+       ao_cmd_init();
+
+#if HAS_MS5607
+       ao_ms5607_init();
+#endif
+#if HAS_HMC5883
+       ao_hmc5883_init();
+#endif
+#if HAS_MPU6000
+       ao_mpu6000_init();
+#endif
+#if HAS_MMA655X
+       ao_mma655x_init();
+#endif
+
+       ao_eeprom_init();
+       ao_storage_init();
+       
+       ao_flight_init();
+       ao_log_init();
+       ao_report_init();
+
+       ao_usb_init();
+       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_start_scheduler();
+       return 0;
+}
diff --git a/src/easymega-v1.0/ao_pins.h b/src/easymega-v1.0/ao_pins.h
new file mode 100644 (file)
index 0000000..d6490ba
--- /dev/null
@@ -0,0 +1,355 @@
+/*
+ * Copyright © 2014 Bdale Garbee <bdale@gag.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define HAS_TASK_QUEUE         1
+
+/* 8MHz High speed external crystal */
+#define AO_HSE                 8000000
+
+/* PLLVCO = 96MHz (so that USB will work) */
+#define AO_PLLMUL              12
+#define AO_RCC_CFGR_PLLMUL     (STM_RCC_CFGR_PLLMUL_12)
+
+/* 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           0
+#define USE_SERIAL_2_STDIN     0
+#define SERIAL_2_PA2_PA3       0
+#define SERIAL_2_PD5_PD6       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_serial1_getchar
+#define ao_gps_putchar         ao_serial1_putchar
+#define ao_gps_set_speed       ao_serial1_set_speed
+#define ao_gps_fifo            (ao_stm_usart1.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 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 HAS_BATTERY_REPORT     1
+#define HAS_RADIO              0
+#define HAS_TELEMETRY          0
+#define HAS_APRS               0
+
+#define HAS_SPI_1              1
+#define SPI_1_PA5_PA6_PA7      1       /* Barometer */
+#define SPI_1_PB3_PB4_PB5      1       /* Accelerometer, Gyro */
+#define SPI_1_PE13_PE14_PE15   0       
+#define SPI_1_OSPEEDR          STM_OSPEEDR_10MHz
+
+#define HAS_SPI_2              1
+#define SPI_2_PB13_PB14_PB15   1       /* Flash, Companion */
+#define SPI_2_PD1_PD3_PD4      0
+#define SPI_2_OSPEEDR          STM_OSPEEDR_10MHz
+
+#define SPI_2_PORT             (&stm_gpiob)
+#define SPI_2_SCK_PIN          13
+#define SPI_2_MISO_PIN         14
+#define SPI_2_MOSI_PIN         15
+
+#define HAS_I2C_1              1
+#define I2C_1_PB8_PB9          1
+
+#define HAS_I2C_2              0
+#define I2C_2_PB10_PB11                0
+
+#define PACKET_HAS_SLAVE       0
+#define PACKET_HAS_MASTER      0
+
+#define LOW_LEVEL_DEBUG                0
+
+#define LED_PORT_ENABLE                STM_RCC_AHBENR_GPIOAEN
+#define LED_PORT               (&stm_gpioa)
+#define LED_PIN_RED            9
+#define LED_PIN_GREEN          10
+#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                        0
+#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_gpioa)
+#define AO_PYRO_PIN_0  15
+
+/* Pyro B */
+#define AO_PYRO_PORT_1 (&stm_gpioc)
+#define AO_PYRO_PIN_1  10
+
+/* Pyro C */
+#define AO_PYRO_PORT_2 (&stm_gpiob)
+#define AO_PYRO_PIN_2  11
+
+/* Pyro D */
+#define AO_PYRO_PORT_3 (&stm_gpiob)
+#define AO_PYRO_PIN_3  10
+
+/* Drogue */
+#define AO_IGNITER_DROGUE_PORT (&stm_gpioa)
+#define AO_IGNITER_DROGUE_PIN  0
+
+/* Main */
+#define AO_IGNITER_MAIN_PORT   (&stm_gpioa)
+#define AO_IGNITER_MAIN_PIN    1
+
+/* Number of general purpose pyro channels available */
+#define AO_PYRO_NUM    4
+
+#define AO_IGNITER_SET_DROGUE(v)       stm_gpio_set(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, v)
+#define AO_IGNITER_SET_MAIN(v)         stm_gpio_set(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, v)
+
+/*
+ * 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         14
+#define AO_ADC_SENSE_A_PORT    (&stm_gpioc)
+#define AO_ADC_SENSE_A_PIN     4
+
+#define AO_ADC_SENSE_B         15
+#define AO_ADC_SENSE_B_PORT    (&stm_gpioc)
+#define AO_ADC_SENSE_B_PIN     5
+
+#define AO_ADC_SENSE_C         13
+#define AO_ADC_SENSE_C_PORT    (&stm_gpioc)
+#define AO_ADC_SENSE_C_PIN     3
+
+#define AO_ADC_SENSE_D         12
+#define AO_ADC_SENSE_D_PORT    (&stm_gpioc)
+#define AO_ADC_SENSE_D_PIN     2
+
+#define AO_ADC_SENSE_DROGUE    11
+#define AO_ADC_SENSE_DROGUE_PORT       (&stm_gpioc)
+#define AO_ADC_SENSE_DROGUE_PIN        1
+
+#define AO_ADC_SENSE_MAIN      10
+#define AO_ADC_SENSE_MAIN_PORT (&stm_gpioc)
+#define AO_ADC_SENSE_MAIN_PIN  0
+
+#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_gpioa)
+#define AO_MS5607_CS_PIN       3
+#define AO_MS5607_CS_MASK      (1 << AO_MS5607_CS_PIN)
+#define AO_MS5607_MISO_PORT    (&stm_gpioa)
+#define AO_MS5607_MISO_PIN     6
+#define AO_MS5607_MISO_MASK    (1 << AO_MS5607_MISO_PIN)
+#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_gpiob)
+#define AO_M25_SPI_CS_PIN      12
+#define AO_M25_SPI_CS_MASK     (1 << AO_M25_SPI_CS_PIN)
+#define AO_M25_SPI_BUS         AO_SPI_2_PB13_PB14_PB15
+
+/*
+ * Mag sensor (hmc5883)
+ */
+
+#define HAS_HMC5883            1
+#define AO_HMC5883_INT_PORT    (&stm_gpioc)
+#define AO_HMC5883_INT_PIN     14
+#define AO_HMC5883_I2C_INDEX   STM_I2C_INDEX(1)
+
+/*
+ * mpu6000
+ */
+
+#define HAS_MPU6000            1
+#define AO_MPU6000_INT_PORT    (&stm_gpioc)
+#define AO_MPU6000_INT_PIN     15
+#define AO_MPU6000_SPI_BUS     AO_SPI_1_PB3_PB4_PB5
+#define AO_MPU6000_SPI_CS_PORT (&stm_gpioc)
+#define AO_MPU6000_SPI_CS_PIN  13
+#define HAS_IMU                        1
+
+/*
+ * mma655x
+ */
+
+#define HAS_MMA655X            1
+#define AO_MMA655X_SPI_INDEX   AO_SPI_1_PB3_PB4_PB5
+#define AO_MMA655X_CS_PORT     (&stm_gpioc)
+#define AO_MMA655X_CS_PIN      12
+
+#define NUM_CMDS               16
+
+/*
+ * Companion
+ */
+
+#define AO_COMPANION_CS_PORT   (&stm_gpiob)
+#define AO_COMPANION_CS_PIN    (6)
+#define AO_COMPANION_SPI_BUS   AO_SPI_2_PB13_PB14_PB15
+
+/*
+ * Monitor
+ */
+
+#define HAS_MONITOR            0
+#define LEGACY_MONITOR         0
+#define HAS_MONITOR_PUT                0
+#define AO_MONITOR_LED         0
+#define HAS_RSSI               0
+
+/*
+ * Profiling Viterbi decoding
+ */
+
+#ifndef AO_PROFILE
+#define AO_PROFILE             0
+#endif
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/easymega-v1.0/flash-loader/Makefile b/src/easymega-v1.0/flash-loader/Makefile
new file mode 100644 (file)
index 0000000..d83cb70
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=easymega-v1.0
+include $(TOPDIR)/stm/Makefile-flash.defs
diff --git a/src/easymega-v1.0/flash-loader/ao_pins.h b/src/easymega-v1.0/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..445289b
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+/* External crystal at 8MHz */
+#define AO_HSE         8000000
+
+#include <ao_flash_stm_pins.h>
+
+/* Companion port cs_companion0 PD0 */
+
+#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_ */
index 46fa8e1fdefecbcd9dad65a9e1208c4bb2df306a..55fde04cc658d55c87816cae1217dc0cae2e6e7a 100755 (executable)
@@ -457,7 +457,7 @@ void main() {
                                        name = sprintf("%s_K%d_%d", prefix, i, time_inc);
                                else
                                        name = sprintf("%s_K%d%d_%d", prefix, i, j, time_inc);
-                               printf ("#define %s to_fix32(%12.10f)\n", name, k[i,j]);
+                               printf ("#define %s to_fix_k(%12.10f)\n", name, k[i,j]);
                        }
                printf ("\n");
                exit(0);
index 266a118264a385ca073fb02f74dc5e8db540791a..1b0803845864cb6883ad3b37fba96d3381002671 100644 (file)
@@ -307,7 +307,7 @@ void main() {
                                        name = sprintf("%s_K%d_%d", prefix, i, time_inc);
                                else
                                        name = sprintf("%s_K%d%d_%d", prefix, i, j, time_inc);
-                               printf ("#define %s to_fix32(%12.10f)\n", name, k[i,j]);
+                               printf ("#define %s to_fix_k(%12.10f)\n", name, k[i,j]);
                        }
                printf ("\n");
                exit(0);
index 5ff9b5185c51c8c498583d2fe3f67f8ad476cb9e..ad5bbf8e76ae152fefaed06eed6758963b8ec0da 100644 (file)
@@ -132,6 +132,9 @@ ao_clock_init(void);
  */
 
 #ifndef ao_mutex_get
+uint8_t
+ao_mutex_try(__xdata uint8_t *ao_mutex, uint8_t task_id) __reentrant;
+
 void
 ao_mutex_get(__xdata uint8_t *ao_mutex) __reentrant;
 
@@ -275,15 +278,17 @@ ao_report_init(void);
  * Given raw data, convert to SI units
  */
 
+#if HAS_BARO
 /* pressure from the sensor to altitude in meters */
-int16_t
-ao_pres_to_altitude(int16_t pres) __reentrant;
+alt_t
+ao_pres_to_altitude(pres_t pres) __reentrant;
 
-int16_t
-ao_altitude_to_pres(int16_t alt) __reentrant;
+pres_t
+ao_altitude_to_pres(alt_t alt) __reentrant;
 
 int16_t
 ao_temp_to_dC(int16_t temp) __reentrant;
+#endif
 
 /*
  * ao_convert_pa.c
@@ -293,11 +298,13 @@ ao_temp_to_dC(int16_t temp) __reentrant;
 
 #include <ao_data.h>
 
+#if HAS_BARO
 alt_t
-ao_pa_to_altitude(int32_t pa);
+ao_pa_to_altitude(pres_t pa);
 
 int32_t
 ao_altitude_to_pa(alt_t alt);
+#endif
 
 #if HAS_DBG
 #include <ao_dbg.h>
@@ -521,6 +528,9 @@ struct ao_telemetry_raw_recv {
 #define AO_TELEMETRY_INTERVAL_RECOVER  AO_MS_TO_TICKS(1000)
 #endif
 
+void
+ao_telemetry_reset_interval(void);
+
 void
 ao_telemetry_set_interval(uint16_t interval);
 
@@ -558,6 +568,15 @@ extern __xdata int8_t      ao_radio_rssi;
 #define HAS_RADIO_XMIT HAS_RADIO
 #endif
 
+#define AO_RADIO_RATE_38400    0
+#define AO_RADIO_RATE_9600     1
+#define AO_RADIO_RATE_2400     2
+#define AO_RADIO_RATE_MAX      AO_RADIO_RATE_2400
+
+#if defined(HAS_RADIO) && !defined(HAS_RADIO_RATE)
+#define HAS_RADIO_RATE HAS_RADIO
+#endif
+
 void
 ao_radio_general_isr(void) ao_arch_interrupt(16);
 
@@ -757,11 +776,13 @@ extern __xdata uint8_t ao_force_freq;
  * ao_rssi.c
  */
 
+#ifdef AO_LED_TYPE
 void
-ao_rssi_set(int rssi_value);
+ao_rssi_set(int16_t rssi_value);
 
 void
-ao_rssi_init(uint8_t rssi_led);
+ao_rssi_init(AO_LED_TYPE rssi_led);
+#endif
 
 /*
  * ao_product.c
index 0052bdce916be3fc93245f7812db33ed004c4fcf..d2f583ef7d8c795bf6cafe18bd6db3faebf9a164 100644 (file)
@@ -289,6 +289,9 @@ version(void)
 #endif
 #if defined(AO_BOOT_APPLICATION_BASE) && defined(AO_BOOT_APPLICATION_BOUND)
               "program-space    %u\n"
+#endif
+#if AO_VALUE_32
+              "altitude-32      1\n"
 #endif
               , ao_manufacturer
               , ao_product
index 71445335a7a39901c98b91c4346f1cbd1e6686e1..6b8a1813509e5bb5634cef96e0d6e7456bce22bb 100644 (file)
@@ -50,17 +50,25 @@ __xdata uint8_t ao_config_mutex;
 #error Please define USE_INTERNAL_FLASH
 #endif
 #endif
+
 #ifndef AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX
-#if USE_INTERNAL_FLASH
-#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX       ao_storage_config
-#else
-#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX       ((uint32_t) 192 * (uint32_t) 1024)
-#endif
+# if FLIGHT_LOG_APPEND
+#  define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX     ao_storage_log_max
+# else
+#  if USE_INTERNAL_FLASH
+#   define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX    ao_storage_config
+#  else
+#   define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX    ((uint32_t) 192 * (uint32_t) 1024)
+#  endif
+# endif
 #endif
+
 #ifndef AO_CONFIG_DEFAULT_RADIO_POWER
 #define AO_CONFIG_DEFAULT_RADIO_POWER          0x60
 #endif
 #define AO_CONFIG_DEFAULT_RADIO_AMP            0
+#define AO_CONFIG_DEFAULT_APRS_SSID            (ao_serial_number % 10)
+#define AO_CONFIG_DEFAULT_RADIO_RATE           AO_RADIO_RATE_38400
 
 #if HAS_EEPROM
 static void
@@ -85,10 +93,18 @@ ao_config_put(void)
 #endif
 
 #if HAS_RADIO
+
+#if HAS_RADIO_FORWARD
+__xdata uint32_t       ao_send_radio_setting;
+#endif
+
 void
 ao_config_set_radio(void)
 {
        ao_config.radio_setting = ao_freq_to_set(ao_config.frequency, ao_config.radio_cal);
+#if HAS_RADIO_FORWARD
+       ao_send_radio_setting = ao_freq_to_set(ao_config.send_frequency, ao_config.radio_cal);
+#endif
 }
 #endif /* HAS_RADIO */
 
@@ -191,6 +207,18 @@ _ao_config_get(void)
 #if AO_PYRO_NUM
                if (minor < 18)
                        ao_config.pyro_time = AO_CONFIG_DEFAULT_PYRO_TIME;
+#endif
+#if HAS_APRS
+               if (minor < 19)
+                       ao_config.aprs_ssid = AO_CONFIG_DEFAULT_APRS_SSID;
+#endif
+#if HAS_RADIO_RATE
+               if (minor < 20)
+                       ao_config.radio_rate = AO_CONFIG_DEFAULT_RADIO_RATE;
+#endif
+#if HAS_RADIO_FORWARD
+               if (minor < 21)
+                       ao_config.send_frequency = 434550;
 #endif
                ao_config.minor = AO_CONFIG_MINOR;
                ao_config_dirty = 1;
@@ -283,6 +311,32 @@ ao_config_frequency_set(void) __reentrant
        ao_radio_recv_abort();
 #endif
 }
+
+#endif
+
+#if HAS_RADIO_FORWARD
+void
+ao_config_send_frequency_show(void) __reentrant
+{
+       printf("Send frequency: %ld\n",
+              ao_config.send_frequency);
+}
+
+void
+ao_config_send_frequency_set(void) __reentrant
+{
+       ao_cmd_decimal();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       _ao_config_edit_start();
+       ao_config.send_frequency = ao_cmd_lex_u32;
+       ao_config_set_radio();
+       _ao_config_edit_finish();
+#if HAS_RADIO_RECV
+       ao_radio_recv_abort();
+#endif
+}
+
 #endif
 
 #if HAS_FLIGHT
@@ -477,18 +531,73 @@ ao_config_radio_cal_set(void) __reentrant
        ao_config_set_radio();
        _ao_config_edit_finish();
 }
+
+#endif
+
+#if HAS_RADIO_RATE
+#ifndef HAS_TELEMETRY
+#error Please define HAS_TELEMETRY
+#endif
+
+void
+ao_config_radio_rate_show(void) __reentrant
+{
+       printf("Telemetry rate: %d\n", ao_config.radio_rate);
+}
+
+void
+ao_config_radio_rate_set(void) __reentrant
+{
+       ao_cmd_decimal();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       if (AO_RADIO_RATE_MAX < ao_cmd_lex_i) {
+               ao_cmd_status = ao_cmd_lex_error;
+               return;
+       }
+       _ao_config_edit_start();
+       ao_config.radio_rate = ao_cmd_lex_i;
+#if HAS_TELEMETRY
+       ao_telemetry_reset_interval();
+#endif
+       _ao_config_edit_finish();
+#if HAS_RADIO_RECV
+       ao_radio_recv_abort();
+#endif
+}
 #endif
 
 #if HAS_LOG
+
 void
 ao_config_log_show(void) __reentrant
 {
        printf("Max flight log: %d kB\n", (int16_t) (ao_config.flight_log_max >> 10));
+#if FLIGHT_LOG_APPEND
+       printf("Log fixed: 1\n");
+#endif
 }
 
+#if FLIGHT_LOG_APPEND
+void
+ao_config_log_fix_append(void)
+{
+       _ao_config_edit_start();
+       ao_config.flight_log_max = ao_storage_log_max;
+       _ao_config_edit_finish();
+       ao_mutex_get(&ao_config_mutex);
+       _ao_config_put();
+       ao_config_dirty = 0;
+       ao_mutex_put(&ao_config_mutex);
+}
+#endif
+
 void
 ao_config_log_set(void) __reentrant
 {
+#if FLIGHT_LOG_APPEND
+       printf("Flight log fixed size %d kB\n", ao_storage_log_max >> 10);
+#else
        uint16_t        block = (uint16_t) (ao_storage_block >> 10);
        uint16_t        log_max = (uint16_t) (ao_storage_log_max >> 10);
 
@@ -506,6 +615,7 @@ ao_config_log_set(void) __reentrant
                ao_config.flight_log_max = (uint32_t) ao_cmd_lex_i << 10;
                _ao_config_edit_finish();
        }
+#endif
 }
 #endif /* HAS_LOG */
 
@@ -737,6 +847,30 @@ ao_config_pyro_time_set(void)
 }
 #endif
 
+#if HAS_APRS
+void
+ao_config_aprs_ssid_show(void)
+{
+       printf ("APRS SSID: %d\n",
+               ao_config.aprs_ssid);
+}
+
+void
+ao_config_aprs_ssid_set(void)
+{
+       ao_cmd_decimal();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       if (15 < ao_cmd_lex_i) {
+               ao_cmd_status = ao_cmd_lex_error;
+               return;
+       }
+       _ao_config_edit_start();
+       ao_config.aprs_ssid = ao_cmd_lex_i;
+       _ao_config_edit_finish();
+}
+#endif /* HAS_APRS */
+
 struct ao_config_var {
        __code char     *str;
        void            (*set)(void) __reentrant;
@@ -766,12 +900,20 @@ __code struct ao_config_var ao_config_vars[] = {
 #if HAS_RADIO
        { "F <freq>\0Frequency (kHz)",
          ao_config_frequency_set, ao_config_frequency_show },
+#if HAS_RADIO_FORWARD
+       { "R <freq>\0Repeater output frequency (kHz)",
+         ao_config_send_frequency_set, ao_config_send_frequency_show },
+#endif
        { "c <call>\0Callsign (8 char max)",
          ao_config_callsign_set,       ao_config_callsign_show },
        { "e <0 disable, 1 enable>\0Enable telemetry and RDF",
          ao_config_radio_enable_set, ao_config_radio_enable_show },
        { "f <cal>\0Radio calib (cal = rf/(xtal/2^16))",
          ao_config_radio_cal_set,      ao_config_radio_cal_show },
+#if HAS_RADIO_RATE
+       { "T <rate>\0Telemetry rate (0=38.4, 1=9.6, 2=2.4)",
+         ao_config_radio_rate_set,     ao_config_radio_rate_show },
+#endif
 #if HAS_RADIO_POWER
        { "p <setting>\0Radio power setting (0-255)",
          ao_config_radio_power_set,    ao_config_radio_power_show },
@@ -816,6 +958,10 @@ __code struct ao_config_var ao_config_vars[] = {
 #if HAS_TRACKER
        { "t <motion> <interval>\0Tracker configuration",
          ao_config_tracker_set, ao_config_tracker_show },
+#endif
+#if HAS_APRS
+       { "S <ssid>\0Set APRS SSID (0-15)",
+         ao_config_aprs_ssid_set, ao_config_aprs_ssid_show },
 #endif
        { "s\0Show",
          ao_config_show,               0 },
index 2b5cd352300fed22d9c89ceb7fb0b4dbdeb73aee..164584a53fcf042725f00be1488101644e34ae83 100644 (file)
 #define USE_EEPROM_CONFIG 0
 #endif
 
+#ifndef FLIGHT_LOG_APPEND
+#define FLIGHT_LOG_APPEND 0
+#endif
+
 #if USE_STORAGE_CONFIG
 
 #include <ao_storage.h>
@@ -53,7 +57,7 @@
 #endif
 
 #define AO_CONFIG_MAJOR        1
-#define AO_CONFIG_MINOR        18
+#define AO_CONFIG_MINOR        21
 
 #define AO_AES_LEN 16
 
@@ -102,8 +106,21 @@ struct ao_config {
 #if AO_PYRO_NUM
        uint16_t        pyro_time;              /* minor version 18 */
 #endif
+#if HAS_APRS
+       uint8_t         aprs_ssid;              /* minor version 19 */
+#endif
+#if HAS_RADIO_RATE
+       uint8_t         radio_rate;             /* minor version 20 */
+#endif
+#if HAS_RADIO_FORWARD
+       uint32_t        send_frequency;         /* minor version 21 */
+#endif
 };
 
+#if HAS_RADIO_FORWARD
+extern __xdata uint32_t        ao_send_radio_setting;
+#endif
+
 #define AO_IGNITE_MODE_DUAL            0
 #define AO_IGNITE_MODE_APOGEE          1
 #define AO_IGNITE_MODE_MAIN            2
@@ -140,6 +157,9 @@ ao_config_put(void);
 void
 ao_config_set_radio(void);
 
+void
+ao_config_log_fix_append(void);
+
 void
 ao_config_init(void);
 
index aa9b5f484b438e0871aa395a1cd37d7979237a11..db1f2301d2c9ecaffc18b0f67f661b08b74d683a 100644 (file)
 #include "ao.h"
 #endif
 
-static const int16_t altitude_table[] = {
+#include <ao_sample.h>
+
+static const ao_v_t altitude_table[] = {
 #include "altitude.h"
 };
 
 #define ALT_FRAC_SCALE (1 << ALT_FRAC_BITS)
 #define ALT_FRAC_MASK  (ALT_FRAC_SCALE - 1)
 
-int16_t
+ao_v_t
 ao_pres_to_altitude(int16_t pres) __reentrant
 {
        uint8_t o;
@@ -43,9 +45,9 @@ ao_pres_to_altitude(int16_t pres) __reentrant
 
 #if AO_NEED_ALTITUDE_TO_PRES
 int16_t
-ao_altitude_to_pres(int16_t alt) __reentrant
+ao_altitude_to_pres(ao_v_t alt) __reentrant
 {
-       int16_t span, sub_span;
+       ao_v_t span, sub_span;
        uint8_t l, h, m;
        int32_t pres;
 
index fe6e0ef699b803de2b6109e088ee638ac1be0431..410815b68bcdabac38d417a75d70910b0de91578 100644 (file)
 #endif
 
 static const alt_t altitude_table[] AO_CONST_ATTRIB = {
+#if AO_SMALL_ALTITUDE_TABLE
+#include "altitude-pa-small.h"
+#else
 #include "altitude-pa.h"
+#endif
 };
 
 #ifndef FETCH_ALT
@@ -35,11 +39,11 @@ static const alt_t altitude_table[] AO_CONST_ATTRIB = {
 #define ALT_MASK       (ALT_SCALE - 1)
 
 alt_t
-ao_pa_to_altitude(int32_t pa)
+ao_pa_to_altitude(pres_t pa)
 {
        int16_t o;
        int16_t part;
-       int32_t low, high;
+       alt_t low, high;
 
        if (pa < 0)
                pa = 0;
@@ -48,16 +52,16 @@ ao_pa_to_altitude(int32_t pa)
        o = pa >> ALT_SHIFT;
        part = pa & ALT_MASK;
 
-       low = (int32_t) FETCH_ALT(o) * (ALT_SCALE - part);
-       high = (int32_t) FETCH_ALT(o+1) * part + (ALT_SCALE >> 1);
+       low = (alt_t) FETCH_ALT(o) * (ALT_SCALE - part);
+       high = (alt_t) FETCH_ALT(o+1) * part + (ALT_SCALE >> 1);
        return (low + high) >> ALT_SHIFT;
 }
 
 #ifdef AO_CONVERT_TEST
-int32_t
-ao_altitude_to_pa(int32_t alt)
+pres_t
+ao_altitude_to_pa(alt_t alt)
 {
-       int32_t         span, sub_span;
+       alt_t   span, sub_span;
        uint16_t        l, h, m;
        int32_t         pa;
 
@@ -72,7 +76,7 @@ ao_altitude_to_pa(int32_t alt)
        }
        span = altitude_table[l] - altitude_table[h];
        sub_span = altitude_table[l] - alt;
-       pa = ((((int32_t) l * (span - sub_span) + (int32_t) h * sub_span) << ALT_SHIFT) + (span >> 1)) / span;
+       pa = ((((alt_t) l * (span - sub_span) + (alt_t) h * sub_span) << ALT_SHIFT) + (span >> 1)) / span;
        if (pa > 120000)
                pa = 120000;
        if (pa < 0)
index 7d5b1922a69a56abc29982a653c6d2a827abded9..954228621e2ed10f45493b4bfea8d93005c8833a 100644 (file)
@@ -18,6 +18,7 @@
 #include <stdint.h>
 #define AO_CONVERT_TEST
 typedef int32_t alt_t;
+typedef int32_t pres_t;
 #include "ao_host.h"
 #include "ao_convert_pa.c"
 
index c4b062fdb1d0f9f4631354ada9b2baa30df9910a..8f75ad876b612e3cc1480e1fc9aa9fc8024908bd 100644 (file)
@@ -117,9 +117,7 @@ extern volatile __data uint8_t              ao_data_count;
 
 typedef int32_t        pres_t;
 
-#ifndef AO_ALT_TYPE
 #define AO_ALT_TYPE    int32_t
-#endif
 
 typedef AO_ALT_TYPE    alt_t;
 
@@ -146,10 +144,6 @@ typedef int16_t alt_t;
 
 #endif
 
-#if !HAS_BARO
-typedef int16_t alt_t;
-#endif
-
 /*
  * Need a few macros to pull data from the sensors:
  *
index 2b433ee9b9bd998ba7325be82e62e21643299255..251dbc02a7f35eaa7994c1541af5be3800205f84 100644 (file)
@@ -60,10 +60,10 @@ __xdata uint8_t                     ao_sensor_errors;
  * resting
  */
 static __data uint16_t         ao_interval_end;
-static __data int16_t          ao_interval_min_height;
-static __data int16_t          ao_interval_max_height;
+static __data ao_v_t           ao_interval_min_height;
+static __data ao_v_t           ao_interval_max_height;
 #if HAS_ACCEL
-static __data int16_t          ao_coast_avg_accel;
+static __data ao_v_t           ao_coast_avg_accel;
 #endif
 
 __pdata uint8_t                        ao_flight_force_idle;
@@ -398,14 +398,14 @@ ao_flight(void)
 }
 
 #if HAS_FLIGHT_DEBUG
-static inline int int_part(int16_t i)  { return i >> 4; }
-static inline int frac_part(int16_t i) { return ((i & 0xf) * 100 + 8) / 16; }
+static inline int int_part(ao_v_t i)   { return i >> 4; }
+static inline int frac_part(ao_v_t i)  { return ((i & 0xf) * 100 + 8) / 16; }
 
 static void
 ao_flight_dump(void)
 {
 #if HAS_ACCEL
-       int16_t accel;
+       ao_v_t  accel;
 
        accel = ((ao_config.accel_plus_g - ao_sample_accel) * ao_accel_scale) >> 16;
 #endif
diff --git a/src/kernel/ao_forward.c b/src/kernel/ao_forward.c
new file mode 100644 (file)
index 0000000..2a93718
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright © 2014 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+#include "ao_telem.h"
+
+static void
+ao_monitor_forward(void)
+{
+       uint32_t                                        recv_radio_setting;
+       static __xdata struct ao_telemetry_all_recv     packet;
+
+       for (;;) {
+               while (ao_monitoring)
+                       ao_sleep(DATA_TO_XDATA(&ao_monitoring));
+
+               if (!ao_radio_recv(&packet, sizeof(packet), 0))
+                       continue;
+               if (!(packet.status & PKT_APPEND_STATUS_1_CRC_OK))
+                       continue;
+               recv_radio_setting = ao_config.radio_setting;
+               ao_config.radio_setting = ao_send_radio_setting;
+               ao_radio_send(&packet.telemetry, sizeof (packet.telemetry));
+               ao_config.radio_setting = recv_radio_setting;
+       }
+}
+
+static __xdata struct ao_task ao_monitor_forward_task;
+
+void
+ao_monitor_forward_init(void) __reentrant
+{
+       ao_add_task(&ao_monitor_forward_task, ao_monitor_forward, "monitor_forward");
+}
diff --git a/src/kernel/ao_forward.h b/src/kernel/ao_forward.h
new file mode 100644 (file)
index 0000000..1897dc0
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright © 2014 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_FORWARD_H_
+#define _AO_FORWARD_H_
+
+void
+ao_monitor_forward_init(void) __reentrant;
+
+#endif /* _AO_FORWARD_H_ */
index 47c945d78b80f578622505f770af284dacf5a7d1..d26021da86b9511f340d9fbd203b730b3436b99d 100644 (file)
 #endif
 #include "ao_telem.h"
 
+#ifndef AO_TELEMETRY_LOCATION_ALTITUDE
+#define AO_TELEMETRY_LOCATION_ALTITUDE(l)      ((l)->altitude)
+#endif
+
 void
 ao_gps_print(__xdata struct ao_gps_orig *gps_data) __reentrant
 {
@@ -42,7 +46,7 @@ ao_gps_print(__xdata struct ao_gps_orig *gps_data) __reentrant
               AO_TELEM_GPS_ALTITUDE " %d ",
               (long) gps_data->latitude,
               (long) gps_data->longitude,
-              gps_data->altitude);
+              AO_TELEMETRY_LOCATION_ALTITUDE(gps_data));
 
        if (gps_data->flags & AO_GPS_DATE_VALID)
                printf(AO_TELEM_GPS_YEAR " %d "
index 07201ac235b69cd1656979fae18aaa94327c2d73..7ef98a972aefc7661166084aba65ebd05030ba02 100644 (file)
@@ -52,8 +52,12 @@ ao_gps_report(void)
                        gps_log.u.gps_longitude = gps_data.longitude;
                        ao_log_data(&gps_log);
                        gps_log.type = AO_LOG_GPS_ALT;
-                       gps_log.u.gps_altitude.altitude = gps_data.altitude;
-                       gps_log.u.gps_altitude.unused = 0xffff;
+                       gps_log.u.gps_altitude.altitude_low = gps_data.altitude_low;
+#if HAS_WIDE_GPS
+                       gps_log.u.gps_altitude.altitude_high = gps_data.altitude_high;
+#else
+                       gps_log.u.gps_altitude.altitude_high = 0xffff;
+#endif
                        ao_log_data(&gps_log);
                        if (!date_reported && (gps_data.flags & AO_GPS_DATE_VALID)) {
                                gps_log.type = AO_LOG_GPS_DATE;
index cb0c0fd99722eb38efc3d949f79306970e501d42..f3711fb19a9603390b8a9cc52b82a2c195c78897 100644 (file)
@@ -78,7 +78,8 @@ ao_gps_report_mega(void)
 #if GPS_SPARSE_LOG
                /* Don't log data if GPS has a fix and hasn't moved for a while */
                if ((gps_data.flags & AO_GPS_VALID) &&
-                   !ao_gps_sparse_should_log(gps_data.latitude, gps_data.longitude, gps_data.altitude))
+                   !ao_gps_sparse_should_log(gps_data.latitude, gps_data.longitude,
+                                             AO_TELEMETRY_LOCATION_ALTITUDE(&gps_data))
                        continue;
 #endif
                if ((new & AO_GPS_NEW_DATA) && (gps_data.flags & AO_GPS_VALID)) {
@@ -87,8 +88,8 @@ ao_gps_report_mega(void)
                        gps_log.type = AO_LOG_GPS_TIME;
                        gps_log.u.gps.latitude = gps_data.latitude;
                        gps_log.u.gps.longitude = gps_data.longitude;
-                       gps_log.u.gps.altitude = gps_data.altitude;
-
+                       gps_log.u.gps.altitude_low = gps_data.altitude_low;
+                       gps_log.u.gps.altitude_high = gps_data.altitude_high;
                        gps_log.u.gps.hour = gps_data.hour;
                        gps_log.u.gps.minute = gps_data.minute;
                        gps_log.u.gps.second = gps_data.second;
index 696a833b8147afd45d23dbbba2e9a9b0cdefed2e..8ce074fe33f97bb2ba7bc4d9119bce940ac06d8c 100644 (file)
@@ -44,7 +44,8 @@ ao_gps_report_metrum(void)
                        gps_log.type = AO_LOG_GPS_POS;
                        gps_log.u.gps.latitude = gps_data.latitude;
                        gps_log.u.gps.longitude = gps_data.longitude;
-                       gps_log.u.gps.altitude = gps_data.altitude;
+                       gps_log.u.gps.altitude_low = gps_data.altitude_low;
+                       gps_log.u.gps.altitude_high = gps_data.altitude_high;
                        ao_log_metrum(&gps_log);
 
                        gps_log.type = AO_LOG_GPS_TIME;
@@ -55,6 +56,7 @@ ao_gps_report_metrum(void)
                        gps_log.u.gps_time.year = gps_data.year;
                        gps_log.u.gps_time.month = gps_data.month;
                        gps_log.u.gps_time.day = gps_data.day;
+                       gps_log.u.gps_time.pdop = gps_data.pdop;
                        ao_log_metrum(&gps_log);
                }
 
index 3a05e35acd66260d5826513663d1653a04714bd7..e45cd795bbbd14aaf0ec967a85d5a1856f5786e8 100644 (file)
@@ -19,6 +19,8 @@
 #include <ao.h>
 #endif
 
+#include <ao_data.h>
+
 void
 ao_gps_show(void) __reentrant
 {
@@ -27,7 +29,11 @@ ao_gps_show(void) __reentrant
        printf ("Date: %02d/%02d/%02d\n", ao_gps_data.year, ao_gps_data.month, ao_gps_data.day);
        printf ("Time: %02d:%02d:%02d\n", ao_gps_data.hour, ao_gps_data.minute, ao_gps_data.second);
        printf ("Lat/Lon: %ld %ld\n", (long) ao_gps_data.latitude, (long) ao_gps_data.longitude);
-       printf ("Alt: %d\n", ao_gps_data.altitude);
+#if HAS_WIDE_GPS
+       printf ("Alt: %ld\n", (long) AO_TELEMETRY_LOCATION_ALTITUDE(&ao_gps_data));
+#else
+       printf ("Alt: %d\n", AO_TELEMETRY_LOCATION_ALTITUDE(&ao_gps_data));
+#endif
        printf ("Flags: 0x%x\n", ao_gps_data.flags);
        printf ("Sats: %d", ao_gps_tracking_data.channels);
        for (i = 0; i < ao_gps_tracking_data.channels; i++)
index 9aea1f14762f6139d9fb8dce932b98a6c946068d..7b0f8145d807ce74bd5db66c0d23408251a8d745 100644 (file)
 #include "ao_sample.h"
 #include "ao_kalman.h"
 
+static __pdata ao_k_t          ao_k_height;
+static __pdata ao_k_t          ao_k_speed;
+static __pdata ao_k_t          ao_k_accel;
 
-static __pdata int32_t         ao_k_height;
-static __pdata int32_t         ao_k_speed;
-static __pdata int32_t         ao_k_accel;
+#define AO_K_STEP_100          to_fix_v(0.01)
+#define AO_K_STEP_2_2_100      to_fix_v(0.00005)
 
-#define AO_K_STEP_100          to_fix16(0.01)
-#define AO_K_STEP_2_2_100      to_fix16(0.00005)
+#define AO_K_STEP_10           to_fix_v(0.1)
+#define AO_K_STEP_2_2_10       to_fix_v(0.005)
 
-#define AO_K_STEP_10           to_fix16(0.1)
-#define AO_K_STEP_2_2_10       to_fix16(0.005)
+#define AO_K_STEP_1            to_fix_v(1)
+#define AO_K_STEP_2_2_1                to_fix_v(0.5)
 
-#define AO_K_STEP_1            to_fix16(1)
-#define AO_K_STEP_2_2_1                to_fix16(0.5)
+__pdata ao_v_t                 ao_height;
+__pdata ao_v_t                 ao_speed;
+__pdata ao_v_t                 ao_accel;
+__xdata ao_v_t                 ao_max_height;
+static __pdata ao_k_t          ao_avg_height_scaled;
+__xdata ao_v_t                 ao_avg_height;
 
-__pdata int16_t                        ao_height;
-__pdata int16_t                        ao_speed;
-__pdata int16_t                        ao_accel;
-__xdata int16_t                        ao_max_height;
-static __pdata int32_t         ao_avg_height_scaled;
-__xdata int16_t                        ao_avg_height;
-
-__pdata int16_t                        ao_error_h;
-__pdata int16_t                        ao_error_h_sq_avg;
+__pdata ao_v_t                 ao_error_h;
+__pdata ao_v_t                 ao_error_h_sq_avg;
 
 #if HAS_ACCEL
-__pdata int16_t                        ao_error_a;
+__pdata ao_v_t                 ao_error_a;
 #endif
 
 static void
@@ -56,40 +55,40 @@ ao_kalman_predict(void)
 {
 #ifdef AO_FLIGHT_TEST
        if (ao_sample_tick - ao_sample_prev_tick > 50) {
-               ao_k_height += ((int32_t) ao_speed * AO_K_STEP_1 +
-                               (int32_t) ao_accel * AO_K_STEP_2_2_1) >> 4;
-               ao_k_speed += (int32_t) ao_accel * AO_K_STEP_1;
+               ao_k_height += ((ao_k_t) ao_speed * AO_K_STEP_1 +
+                               (ao_k_t) ao_accel * AO_K_STEP_2_2_1) >> 4;
+               ao_k_speed += (ao_k_t) ao_accel * AO_K_STEP_1;
 
                return;
        }
        if (ao_sample_tick - ao_sample_prev_tick > 5) {
-               ao_k_height += ((int32_t) ao_speed * AO_K_STEP_10 +
-                               (int32_t) ao_accel * AO_K_STEP_2_2_10) >> 4;
-               ao_k_speed += (int32_t) ao_accel * AO_K_STEP_10;
+               ao_k_height += ((ao_k_t) ao_speed * AO_K_STEP_10 +
+                               (ao_k_t) ao_accel * AO_K_STEP_2_2_10) >> 4;
+               ao_k_speed += (ao_k_t) ao_accel * AO_K_STEP_10;
 
                return;
        }
        if (ao_flight_debug) {
                printf ("predict speed %g + (%g * %g) = %g\n",
                        ao_k_speed / (65536.0 * 16.0), ao_accel / 16.0, AO_K_STEP_100 / 65536.0,
-                       (ao_k_speed + (int32_t) ao_accel * AO_K_STEP_100) / (65536.0 * 16.0));
+                       (ao_k_speed + (ao_k_t) ao_accel * AO_K_STEP_100) / (65536.0 * 16.0));
        }
 #endif
-       ao_k_height += ((int32_t) ao_speed * AO_K_STEP_100 +
-                       (int32_t) ao_accel * AO_K_STEP_2_2_100) >> 4;
-       ao_k_speed += (int32_t) ao_accel * AO_K_STEP_100;
+       ao_k_height += ((ao_k_t) ao_speed * AO_K_STEP_100 +
+                       (ao_k_t) ao_accel * AO_K_STEP_2_2_100) >> 4;
+       ao_k_speed += (ao_k_t) ao_accel * AO_K_STEP_100;
 }
 
 static void
 ao_kalman_err_height(void)
 {
-       int16_t e;
-       int16_t height_distrust;
+       ao_v_t  e;
+       ao_v_t height_distrust;
 #if HAS_ACCEL
-       int16_t speed_distrust;
+       ao_v_t  speed_distrust;
 #endif
 
-       ao_error_h = ao_sample_height - (int16_t) (ao_k_height >> 16);
+       ao_error_h = ao_sample_height - (ao_v_t) (ao_k_height >> 16);
 
        e = ao_error_h;
        if (e < 0)
@@ -123,7 +122,7 @@ ao_kalman_err_height(void)
 #endif
                if (height_distrust > 0x100)
                        height_distrust = 0x100;
-               ao_error_h = (int16_t) (((int32_t) ao_error_h * (0x100 - height_distrust)) >> 8);
+               ao_error_h = (ao_v_t) (((ao_k_t) ao_error_h * (0x100 - height_distrust)) >> 8);
 #ifdef AO_FLIGHT_TEST
                if (ao_flight_debug) {
                        printf("over height %g over speed %g distrust: %g height: error %d -> %d\n",
@@ -142,21 +141,21 @@ ao_kalman_correct_baro(void)
        ao_kalman_err_height();
 #ifdef AO_FLIGHT_TEST
        if (ao_sample_tick - ao_sample_prev_tick > 50) {
-               ao_k_height += (int32_t) AO_BARO_K0_1 * ao_error_h;
-               ao_k_speed  += (int32_t) AO_BARO_K1_1 * ao_error_h;
-               ao_k_accel  += (int32_t) AO_BARO_K2_1 * ao_error_h;
+               ao_k_height += (ao_k_t) AO_BARO_K0_1 * ao_error_h;
+               ao_k_speed  += (ao_k_t) AO_BARO_K1_1 * ao_error_h;
+               ao_k_accel  += (ao_k_t) AO_BARO_K2_1 * ao_error_h;
                return;
        }
        if (ao_sample_tick - ao_sample_prev_tick > 5) {
-               ao_k_height += (int32_t) AO_BARO_K0_10 * ao_error_h;
-               ao_k_speed  += (int32_t) AO_BARO_K1_10 * ao_error_h;
-               ao_k_accel  += (int32_t) AO_BARO_K2_10 * ao_error_h;
+               ao_k_height += (ao_k_t) AO_BARO_K0_10 * ao_error_h;
+               ao_k_speed  += (ao_k_t) AO_BARO_K1_10 * ao_error_h;
+               ao_k_accel  += (ao_k_t) AO_BARO_K2_10 * ao_error_h;
                return;
        }
 #endif
-       ao_k_height += (int32_t) AO_BARO_K0_100 * ao_error_h;
-       ao_k_speed  += (int32_t) AO_BARO_K1_100 * ao_error_h;
-       ao_k_accel  += (int32_t) AO_BARO_K2_100 * ao_error_h;
+       ao_k_height += (ao_k_t) AO_BARO_K0_100 * ao_error_h;
+       ao_k_speed  += (ao_k_t) AO_BARO_K1_100 * ao_error_h;
+       ao_k_accel  += (ao_k_t) AO_BARO_K2_100 * ao_error_h;
 }
 
 #if HAS_ACCEL
@@ -164,7 +163,7 @@ ao_kalman_correct_baro(void)
 static void
 ao_kalman_err_accel(void)
 {
-       int32_t accel;
+       ao_k_t  accel;
 
        accel = (ao_config.accel_plus_g - ao_sample_accel) * ao_accel_scale;
 
@@ -187,18 +186,18 @@ ao_kalman_correct_both(void)
                                (double) ao_error_h, AO_BOTH_K10_1 / 65536.0,
                                (double) ao_error_a, AO_BOTH_K11_1 / 65536.0,
                                (ao_k_speed +
-                                (int32_t) AO_BOTH_K10_1 * ao_error_h +
-                                (int32_t) AO_BOTH_K11_1 * ao_error_a) / (65536.0 * 16.0));
+                                (ao_k_t) AO_BOTH_K10_1 * ao_error_h +
+                                (ao_k_t) AO_BOTH_K11_1 * ao_error_a) / (65536.0 * 16.0));
                }
                ao_k_height +=
-                       (int32_t) AO_BOTH_K00_1 * ao_error_h +
-                       (int32_t) AO_BOTH_K01_1 * ao_error_a;
+                       (ao_k_t) AO_BOTH_K00_1 * ao_error_h +
+                       (ao_k_t) AO_BOTH_K01_1 * ao_error_a;
                ao_k_speed +=
-                       (int32_t) AO_BOTH_K10_1 * ao_error_h +
-                       (int32_t) AO_BOTH_K11_1 * ao_error_a;
+                       (ao_k_t) AO_BOTH_K10_1 * ao_error_h +
+                       (ao_k_t) AO_BOTH_K11_1 * ao_error_a;
                ao_k_accel +=
-                       (int32_t) AO_BOTH_K20_1 * ao_error_h +
-                       (int32_t) AO_BOTH_K21_1 * ao_error_a;
+                       (ao_k_t) AO_BOTH_K20_1 * ao_error_h +
+                       (ao_k_t) AO_BOTH_K21_1 * ao_error_a;
                return;
        }
        if (ao_sample_tick - ao_sample_prev_tick > 5) {
@@ -208,18 +207,18 @@ ao_kalman_correct_both(void)
                                (double) ao_error_h, AO_BOTH_K10_10 / 65536.0,
                                (double) ao_error_a, AO_BOTH_K11_10 / 65536.0,
                                (ao_k_speed +
-                                (int32_t) AO_BOTH_K10_10 * ao_error_h +
-                                (int32_t) AO_BOTH_K11_10 * ao_error_a) / (65536.0 * 16.0));
+                                (ao_k_t) AO_BOTH_K10_10 * ao_error_h +
+                                (ao_k_t) AO_BOTH_K11_10 * ao_error_a) / (65536.0 * 16.0));
                }
                ao_k_height +=
-                       (int32_t) AO_BOTH_K00_10 * ao_error_h +
-                       (int32_t) AO_BOTH_K01_10 * ao_error_a;
+                       (ao_k_t) AO_BOTH_K00_10 * ao_error_h +
+                       (ao_k_t) AO_BOTH_K01_10 * ao_error_a;
                ao_k_speed +=
-                       (int32_t) AO_BOTH_K10_10 * ao_error_h +
-                       (int32_t) AO_BOTH_K11_10 * ao_error_a;
+                       (ao_k_t) AO_BOTH_K10_10 * ao_error_h +
+                       (ao_k_t) AO_BOTH_K11_10 * ao_error_a;
                ao_k_accel +=
-                       (int32_t) AO_BOTH_K20_10 * ao_error_h +
-                       (int32_t) AO_BOTH_K21_10 * ao_error_a;
+                       (ao_k_t) AO_BOTH_K20_10 * ao_error_h +
+                       (ao_k_t) AO_BOTH_K21_10 * ao_error_a;
                return;
        }
        if (ao_flight_debug) {
@@ -228,19 +227,19 @@ ao_kalman_correct_both(void)
                        (double) ao_error_h, AO_BOTH_K10_100 / 65536.0,
                        (double) ao_error_a, AO_BOTH_K11_100 / 65536.0,
                        (ao_k_speed +
-                        (int32_t) AO_BOTH_K10_100 * ao_error_h +
-                        (int32_t) AO_BOTH_K11_100 * ao_error_a) / (65536.0 * 16.0));
+                        (ao_k_t) AO_BOTH_K10_100 * ao_error_h +
+                        (ao_k_t) AO_BOTH_K11_100 * ao_error_a) / (65536.0 * 16.0));
        }
 #endif
        ao_k_height +=
-               (int32_t) AO_BOTH_K00_100 * ao_error_h +
-               (int32_t) AO_BOTH_K01_100 * ao_error_a;
+               (ao_k_t) AO_BOTH_K00_100 * ao_error_h +
+               (ao_k_t) AO_BOTH_K01_100 * ao_error_a;
        ao_k_speed +=
-               (int32_t) AO_BOTH_K10_100 * ao_error_h +
-               (int32_t) AO_BOTH_K11_100 * ao_error_a;
+               (ao_k_t) AO_BOTH_K10_100 * ao_error_h +
+               (ao_k_t) AO_BOTH_K11_100 * ao_error_a;
        ao_k_accel +=
-               (int32_t) AO_BOTH_K20_100 * ao_error_h +
-               (int32_t) AO_BOTH_K21_100 * ao_error_a;
+               (ao_k_t) AO_BOTH_K20_100 * ao_error_h +
+               (ao_k_t) AO_BOTH_K21_100 * ao_error_a;
 }
 
 #else
@@ -251,14 +250,14 @@ ao_kalman_correct_accel(void)
        ao_kalman_err_accel();
 
        if (ao_sample_tick - ao_sample_prev_tick > 5) {
-               ao_k_height +=(int32_t) AO_ACCEL_K0_10 * ao_error_a;
-               ao_k_speed  += (int32_t) AO_ACCEL_K1_10 * ao_error_a;
-               ao_k_accel  += (int32_t) AO_ACCEL_K2_10 * ao_error_a;
+               ao_k_height +=(ao_k_t) AO_ACCEL_K0_10 * ao_error_a;
+               ao_k_speed  += (ao_k_t) AO_ACCEL_K1_10 * ao_error_a;
+               ao_k_accel  += (ao_k_t) AO_ACCEL_K2_10 * ao_error_a;
                return;
        }
-       ao_k_height += (int32_t) AO_ACCEL_K0_100 * ao_error_a;
-       ao_k_speed  += (int32_t) AO_ACCEL_K1_100 * ao_error_a;
-       ao_k_accel  += (int32_t) AO_ACCEL_K2_100 * ao_error_a;
+       ao_k_height += (ao_k_t) AO_ACCEL_K0_100 * ao_error_a;
+       ao_k_speed  += (ao_k_t) AO_ACCEL_K1_100 * ao_error_a;
+       ao_k_accel  += (ao_k_t) AO_ACCEL_K2_100 * ao_error_a;
 }
 
 #endif /* else FORCE_ACCEL */
index 91617d93531842dfe50b8469d0304817c254eb04..40a96ef7f259fa4811d6faa11c9567fbd323b6ec 100644 (file)
@@ -142,19 +142,39 @@ ao_log_max_flight(void)
        return max_flight;
 }
 
-void
-ao_log_scan(void) __reentrant
+static void
+ao_log_erase(uint8_t slot) __reentrant
 {
-       uint8_t         log_slot;
-       uint8_t         log_slots;
-       uint8_t         log_want;
+       uint32_t log_current_pos, log_end_pos;
 
-       ao_config_get();
+       ao_log_erase_mark();
+       log_current_pos = ao_log_pos(slot);
+       log_end_pos = log_current_pos + ao_config.flight_log_max;
+       while (log_current_pos < log_end_pos) {
+               uint8_t i;
+               static __xdata uint8_t b;
+
+               /*
+                * Check to see if we've reached the end of
+                * the used memory to avoid re-erasing the same
+                * memory over and over again
+                */
+               for (i = 0; i < 16; i++) {
+                       if (ao_storage_read(log_current_pos + i, &b, 1))
+                               if (b != 0xff)
+                                       break;
+               }
+               if (i == 16)
+                       break;
+               ao_storage_erase(log_current_pos);
+               log_current_pos += ao_storage_block;
+       }
+}
 
-       ao_flight_number = ao_log_max_flight();
-       if (ao_flight_number)
-               if (++ao_flight_number == 0)
-                       ao_flight_number = 1;
+static void
+ao_log_find_max_erase_flight(void) __reentrant
+{
+       uint8_t log_slot;
 
        /* Now look through the log of flight numbers from erase operations and
         * see if the last one is bigger than what we found above
@@ -170,6 +190,80 @@ ao_log_scan(void) __reentrant
        }
        if (ao_flight_number == 0)
                ao_flight_number = 1;
+}
+
+uint8_t
+ao_log_scan(void) __reentrant
+{
+       uint8_t         log_slot;
+       uint8_t         log_slots;
+#if FLIGHT_LOG_APPEND
+       uint8_t         ret;
+#else
+       uint8_t         log_want;
+#endif
+
+       ao_config_get();
+
+       /* Get any existing flight number */
+       ao_flight_number = ao_log_max_flight();
+
+#if FLIGHT_LOG_APPEND
+
+       /* Deal with older OS versions which stored multiple
+        * flights in rom by erasing everything after the first
+        * slot
+        */
+       if (ao_config.flight_log_max != ao_storage_log_max) {
+               log_slots = ao_log_slots();
+               for (log_slot = 1; log_slot < log_slots; log_slot++) {
+                       if (ao_log_flight(log_slot) != 0)
+                               ao_log_erase(log_slot);
+               }
+               ao_config_log_fix_append();
+       }
+       ao_log_current_pos = ao_log_pos(0);
+       ao_log_end_pos = ao_log_current_pos + ao_storage_log_max;
+
+       if (ao_flight_number) {
+               uint32_t        full = ao_log_current_pos;
+               uint32_t        empty = ao_log_end_pos - ao_log_size;
+
+               /* If there's already a flight started, then find the
+                * end of it
+                */
+               for (;;) {
+                       ao_log_current_pos = (full + empty) >> 1;
+                       ao_log_current_pos -= ao_log_current_pos % ao_log_size;
+
+                       if (ao_log_current_pos == full) {
+                               if (ao_log_check(ao_log_current_pos))
+                                       ao_log_current_pos += ao_log_size;
+                               break;
+                       }
+                       if (ao_log_current_pos == empty)
+                               break;
+
+                       if (ao_log_check(ao_log_current_pos)) {
+                               full = ao_log_current_pos;
+                       } else {
+                               empty = ao_log_current_pos;
+                       }
+               }
+               ret = 1;
+       } else {
+               ao_log_find_max_erase_flight();
+               ret = 0;
+       }
+       ao_wakeup(&ao_flight_number);
+       return ret;
+#else
+
+       if (ao_flight_number)
+               if (++ao_flight_number == 0)
+                       ao_flight_number = 1;
+
+       ao_log_find_max_erase_flight();
 
        /* With a flight number in hand, find a place to write a new log,
         * use the target flight number to index the available log slots so
@@ -190,8 +284,9 @@ ao_log_scan(void) __reentrant
                if (++log_slot >= log_slots)
                        log_slot = 0;
        } while (log_slot != log_want);
-
        ao_wakeup(&ao_flight_number);
+       return 0;
+#endif
 }
 
 void
@@ -254,7 +349,6 @@ ao_log_delete(void) __reentrant
 {
        uint8_t slot;
        uint8_t slots;
-       uint32_t log_current_pos, log_end_pos;
 
        ao_cmd_decimal();
        if (ao_cmd_status != ao_cmd_success)
@@ -268,28 +362,7 @@ ao_log_delete(void) __reentrant
 #if HAS_TRACKER
                                ao_tracker_erase_start(ao_cmd_lex_i);
 #endif
-                               ao_log_erase_mark();
-                               log_current_pos = ao_log_pos(slot);
-                               log_end_pos = log_current_pos + ao_config.flight_log_max;
-                               while (log_current_pos < log_end_pos) {
-                                       uint8_t i;
-                                       static __xdata uint8_t b;
-
-                                       /*
-                                        * Check to see if we've reached the end of
-                                        * the used memory to avoid re-erasing the same
-                                        * memory over and over again
-                                        */
-                                       for (i = 0; i < 16; i++) {
-                                               if (ao_storage_read(log_current_pos + i, &b, 1))
-                                                       if (b != 0xff)
-                                                               break;
-                                       }
-                                       if (i == 16)
-                                               break;
-                                       ao_storage_erase(log_current_pos);
-                                       log_current_pos += ao_storage_block;
-                               }
+                               ao_log_erase(slot);
 #if HAS_TRACKER
                                ao_tracker_erase_end();
 #endif
index 33cda3eb3560303f2a3d9030ebc0f76ed7fc89b9..c13a2580f71e3bdae2af7be7d978b71d6d921eff 100644 (file)
@@ -51,11 +51,16 @@ extern __pdata enum ao_flight_state ao_log_state;
 #define AO_LOG_FORMAT_NONE             127     /* No log at all */
 
 extern __code uint8_t ao_log_format;
+extern __code uint8_t ao_log_size;
 
 /* Return the flight number from the given log slot, 0 if none */
 uint16_t
 ao_log_flight(uint8_t slot);
 
+/* Check if there is valid log data at the specified location */
+uint8_t
+ao_log_check(uint32_t pos);
+
 /* Flush the log */
 void
 ao_log_flush(void);
@@ -67,7 +72,7 @@ ao_log(void);
 /* functions provided in ao_log.c */
 
 /* Figure out the current flight number */
-void
+uint8_t
 ao_log_scan(void) __reentrant;
 
 /* Return the position of the start of the given log slot */
@@ -176,8 +181,8 @@ struct ao_log_record {
                int32_t         gps_latitude;
                int32_t         gps_longitude;
                struct {
-                       int16_t         altitude;
-                       uint16_t        unused;
+                       uint16_t        altitude_low;
+                       int16_t         altitude_high;
                } gps_altitude;
                struct {
                        uint16_t        svid;
@@ -246,7 +251,7 @@ struct ao_log_mega {
                struct {
                        int32_t         latitude;       /* 4 */
                        int32_t         longitude;      /* 8 */
-                       int16_t         altitude;       /* 12 */
+                       uint16_t        altitude_low;   /* 12 */
                        uint8_t         hour;           /* 14 */
                        uint8_t         minute;         /* 15 */
                        uint8_t         second;         /* 16 */
@@ -261,7 +266,8 @@ struct ao_log_mega {
                        uint8_t         hdop;           /* 27 */
                        uint8_t         vdop;           /* 28 */
                        uint8_t         mode;           /* 29 */
-               } gps;  /* 30 */
+                       int16_t         altitude_high;  /* 30 */
+               } gps;  /* 32 */
                /* AO_LOG_GPS_SAT */
                struct {
                        uint16_t        channels;       /* 4 */
@@ -273,6 +279,11 @@ struct ao_log_mega {
        } u;
 };
 
+#define AO_LOG_MEGA_GPS_ALTITUDE(l)    ((int32_t) ((l)->u.gps.altitude_high << 16) | ((l)->u.gps.altitude_low))
+#define AO_LOG_MEGA_SET_GPS_ALTITUDE(l,a)      (((l)->u.gps.mode |= AO_GPS_MODE_ALTITUDE_24), \
+                                                ((l)->u.gps.altitude_high = (a) >> 16), \
+                                                (l)->u.gps.altitude_low = (a))
+
 struct ao_log_metrum {
        char                    type;                   /* 0 */
        uint8_t                 csum;                   /* 1 */
@@ -306,8 +317,9 @@ struct ao_log_metrum {
                struct {
                        int32_t         latitude;       /* 4 */
                        int32_t         longitude;      /* 8 */
-                       int16_t         altitude;       /* 12 */
-               } gps;          /* 14 */
+                       uint16_t        altitude_low;   /* 12 */
+                       int16_t         altitude_high;  /* 14 */
+               } gps;          /* 16 */
                /* AO_LOG_GPS_TIME */
                struct {
                        uint8_t         hour;           /* 4 */
@@ -317,7 +329,7 @@ struct ao_log_metrum {
                        uint8_t         year;           /* 8 */
                        uint8_t         month;          /* 9 */
                        uint8_t         day;            /* 10 */
-                       uint8_t         pad;            /* 11 */
+                       uint8_t         pdop;           /* 11 */
                } gps_time;     /* 12 */
                /* AO_LOG_GPS_SAT (up to three packets) */
                struct {
@@ -381,7 +393,7 @@ struct ao_log_gps {
                struct {
                        int32_t         latitude;       /* 4 */
                        int32_t         longitude;      /* 8 */
-                       int16_t         altitude;       /* 12 */
+                       uint16_t        altitude_low;   /* 12 */
                        uint8_t         hour;           /* 14 */
                        uint8_t         minute;         /* 15 */
                        uint8_t         second;         /* 16 */
@@ -396,7 +408,7 @@ struct ao_log_gps {
                        uint8_t         hdop;           /* 27 */
                        uint8_t         vdop;           /* 28 */
                        uint8_t         mode;           /* 29 */
-                       uint8_t         state;          /* 30 */
+                       int16_t         altitude_high;  /* 30 */
                } gps;  /* 31 */
                /* AO_LOG_GPS_SAT */
                struct {
index 3b728c25f1f7887f8d5db5d9403218e0550bbe5f..7643091cdaa759964cdb5b3e7a214eb8c2df55f5 100644 (file)
@@ -26,6 +26,7 @@
 static __xdata struct ao_log_gps log;
 
 __code uint8_t ao_log_format = AO_LOG_FORMAT_TELEGPS;
+__code uint8_t ao_log_size = sizeof (struct ao_log_gps);
 
 static uint8_t
 ao_log_csum(__xdata uint8_t *b) __reentrant
@@ -75,7 +76,8 @@ ao_log_gps_data(uint16_t tick, struct ao_telemetry_location *gps_data)
        log.type = AO_LOG_GPS_TIME;
        log.u.gps.latitude = gps_data->latitude;
        log.u.gps.longitude = gps_data->longitude;
-       log.u.gps.altitude = gps_data->altitude;
+       log.u.gps.altitude_low = gps_data->altitude_low;
+       log.u.gps.altitude_high = gps_data->altitude_high;
 
        log.u.gps.hour = gps_data->hour;
        log.u.gps.minute = gps_data->minute;
@@ -135,3 +137,16 @@ ao_log_flight(uint8_t slot)
                return log.u.flight.flight;
        return 0;
 }
+
+uint8_t
+ao_log_check(uint32_t pos)
+{
+       if (!ao_storage_read(pos,
+                            &log,
+                            sizeof (struct ao_log_gps)))
+               return 0;
+
+       if (ao_log_dump_check_data())
+               return 1;
+       return 0;
+}
index 5851f4d1fadbeedbe83d57a9fa797cab85cbf3a3..a9e8c83168be867353df51be4b8ece3a4cef40bd 100644 (file)
@@ -21,9 +21,6 @@
 #ifndef _AO_LOG_GPS_H_
 #define _AO_LOG_GPS_H_
 
-uint8_t
-ao_log_gps_should_log(int32_t lat, int32_t lon, int16_t alt);
-
 void
 ao_log_gps_flight(void);
 
index d665efb5b56f94e1123afe8df306ad02dc53bbca..aef78def446d7fe09f7fb13ee4407629d0ddd249 100644 (file)
 
 static uint16_t ao_log_offset = STARTING_LOG_OFFSET;
 
+#define AO_LOG_ID_SHIFT        12
+#define AO_LOG_ID_MASK ((1 << AO_LOG_ID_SHIFT) - 1)
+
 void
 ao_log_micro_save(void)
 {
        uint16_t        n_samples = (ao_log_offset - STARTING_LOG_OFFSET) / sizeof (uint16_t);
+
+#if AO_LOG_ID
+       n_samples |= AO_LOG_ID << AO_LOG_ID_SHIFT;
+#endif
        ao_eeprom_write(PA_GROUND_OFFSET, &pa_ground, sizeof (pa_ground));
        ao_eeprom_write(PA_MIN_OFFSET, &pa_min, sizeof (pa_min));
        ao_eeprom_write(N_SAMPLES_OFFSET, &n_samples, sizeof (n_samples));
@@ -99,8 +106,12 @@ ao_log_micro_dump(void)
        uint16_t        crc = 0xffff;
 
        ao_eeprom_read(N_SAMPLES_OFFSET, &n_samples, sizeof (n_samples));
+
        if (n_samples == 0xffff)
                n_samples = 0;
+#if AO_LOG_ID
+       n_samples &= AO_LOG_ID_MASK;
+#endif
        nbytes = STARTING_LOG_OFFSET + sizeof (uint16_t) * n_samples;
        ao_async_start();
        ao_async_byte('M');
index f680e4005c98a5cf9be432ed61509f79d1239863..f7521f218cbb376b662c10bb82174a6ad1c75c58 100644 (file)
@@ -43,10 +43,12 @@ void
 ao_microflight(void)
 {
        int16_t         sample_count;
+       int16_t         log_count;
        uint16_t        time;
        uint32_t        pa_interval_min, pa_interval_max;
        int32_t         pa_diff;
-       uint8_t         h, i;
+       uint8_t         h;
+       uint8_t         i;
        uint8_t         accel_lock = 0;
        uint32_t        pa_sum = 0;
 
@@ -60,19 +62,25 @@ ao_microflight(void)
        h = 0;
        for (;;) {
                time += SAMPLE_SLEEP;
+#if BOOST_DETECT
                if ((sample_count & 0x1f) == 0)
                        ao_led_on(AO_LED_REPORT);
+#endif
                ao_delay_until(time);
                ao_microsample();
+#if BOOST_DETECT
                if ((sample_count & 0x1f) == 0)
                        ao_led_off(AO_LED_REPORT);
+#endif
                pa_hist[h] = pa;
                h = SKIP_PA_HIST(h,1);
                pa_diff = pa_ground - ao_pa;
 
+#if BOOST_DETECT
                /* Check for a significant pressure change */
                if (pa_diff > BOOST_DETECT)
                        break;
+#endif
 
                if (sample_count < GROUND_AVG * 2) {
                        if (sample_count < GROUND_AVG)
@@ -82,6 +90,9 @@ ao_microflight(void)
                        pa_ground = pa_sum >> GROUND_AVG_SHIFT;
                        pa_sum = 0;
                        sample_count = 0;
+#if !BOOST_DETECT
+                       break;
+#endif
                }
        }
 
@@ -93,7 +104,10 @@ ao_microflight(void)
        }
 
        /* Log the remaining samples so we get a complete history since leaving the ground */
-       for (; i != h; i = SKIP_PA_HIST(i,2)) {
+#if LOG_INTERVAL < NUM_PA_HIST
+       for (; i != h; i = SKIP_PA_HIST(i,2))
+#endif
+       {
                pa = pa_hist[i];
                ao_log_micro_data();
        }
@@ -101,6 +115,7 @@ ao_microflight(void)
        /* Now sit around until the pressure is stable again and record the max */
 
        sample_count = 0;
+       log_count = 0;
        pa_min = ao_pa;
        pa_interval_min = ao_pa;
        pa_interval_max = ao_pa;
@@ -112,8 +127,11 @@ ao_microflight(void)
                ao_microsample();
                if ((sample_count & 3) == 0)
                        ao_led_off(AO_LED_REPORT);
-               if (sample_count & 1)
+               if (log_count == LOG_INTERVAL - 1) {
                        ao_log_micro_data();
+                       log_count = 0;
+               } else
+                       log_count++;
 
                /* If accelerating upwards, don't look for min pressure */
                if (ao_pa_accel < ACCEL_LOCK_PA)
index 0684ea2bbaad4b03e747ab6421b83dce885a78b3..75a29cc41d9d7a43e1a817f3d7289717e479a742 100644 (file)
 
 #define FIX_BITS       16
 
-#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5))
-#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5))
+#define to_fix_v(x) ((int16_t) ((x) * 65536.0 + 0.5))
+#define to_fix_k(x) ((int32_t) ((x) * 65536.0 + 0.5))
 #define from_fix8(x)   ((x) >> 8)
 #define from_fix(x)    ((x) >> 16)
-#define fix8_to_fix16(x)       ((x) << 8)
+#define fix8_to_fix_v(x)       ((x) << 8)
 #define fix16_to_fix8(x)       ((x) >> 8)
 
 #include <ao_kalman.h>
 
 /* Basic time step (96ms) */
-#define AO_MK_STEP     to_fix16(0.096)
+#define AO_MK_STEP     to_fix_v(0.096)
 /* step ** 2 / 2 */
-#define AO_MK_STEP_2_2 to_fix16(0.004608)
+#define AO_MK_STEP_2_2 to_fix_v(0.004608)
 
 uint32_t       ao_k_pa;                /* 24.8 fixed point */
 int32_t                ao_k_pa_speed;          /* 16.16 fixed point */
@@ -49,7 +49,7 @@ ao_microkalman_init(void)
 {
        ao_pa = pa;
        ao_k_pa = pa << 8;
-}      
+}
 
 void
 ao_microkalman_predict(void)
index 18f170b49912af18c707e2e8780a03db522f2419..2d75c41c2c786bf98d7c03c05e4a09f9a58b70a0 100644 (file)
@@ -115,6 +115,8 @@ ao_monitor_put(void)
 {
 #if LEGACY_MONITOR
        __xdata char callsign[AO_MAX_CALLSIGN+1];
+#endif
+#if LEGACY_MONITOR || HAS_RSSI
        int16_t rssi;
 #endif
        uint8_t ao_monitor_tail;
@@ -240,7 +242,7 @@ ao_monitor_put(void)
                        hex(sum);
                        putchar ('\n');
 #if HAS_RSSI
-                       if (recv_raw.packet[ao_monitoring + 1] & PKT_APPEND_STATUS_1_CRC_OK) {
+                       if (recv_raw.packet[ao_monitoring + 1] & AO_RADIO_STATUS_CRC_OK) {
                                rssi = AO_RSSI_FROM_RADIO(recv_raw.packet[ao_monitoring]);
                                ao_rssi_set(rssi);
                        }
index 952ff46214a69db9b3e293992ee4f2e602576f46..a36fe93940906efdefaa37e616e0fa762f9daa88 100644 (file)
 
 #include "ao.h"
 
+#ifndef HAS_MUTEX_TRY
+#define HAS_MUTEX_TRY 1
+#endif
+
+#if HAS_MUTEX_TRY
+
+uint8_t
+ao_mutex_try(__xdata uint8_t *mutex, uint8_t task_id) __reentrant
+{
+       uint8_t ret;
+       if (*mutex == task_id)
+               ao_panic(AO_PANIC_MUTEX);
+       ao_arch_critical(
+               if (*mutex)
+                       ret = 0;
+               else {
+                       *mutex = task_id;
+                       ret = 1;
+               });
+       return ret;
+}
+#endif
+
 void
 ao_mutex_get(__xdata uint8_t *mutex) __reentrant
 {
index 85d88d98962006c5f78425d5ab8a0334f8faad19..3044d56517aa06fceaf198fb31a4165e5d6b9370 100644 (file)
@@ -69,6 +69,16 @@ ao_pyro_print_status(void)
 
 uint16_t       ao_pyro_fired;
 
+#ifndef PYRO_DBG
+#define PYRO_DBG       0
+#endif
+
+#if PYRO_DBG
+#define DBG(...)       do { printf("\t%d: ", (int) (pyro - ao_config.pyro)); printf(__VA_ARGS__); } while (0)
+#else
+#define DBG(...)
+#endif
+
 /*
  * Given a pyro structure, figure out
  * if the current flight state satisfies all
@@ -88,63 +98,73 @@ ao_pyro_ready(struct ao_pyro *pyro)
                case ao_pyro_accel_less:
                        if (ao_accel <= pyro->accel_less)
                                continue;
+                       DBG("accel %d > %d\n", ao_accel, pyro->accel_less);
                        break;
                case ao_pyro_accel_greater:
                        if (ao_accel >= pyro->accel_greater)
                                continue;
+                       DBG("accel %d < %d\n", ao_accel, pyro->accel_greater);
                        break;
-
-
                case ao_pyro_speed_less:
                        if (ao_speed <= pyro->speed_less)
                                continue;
+                       DBG("speed %d > %d\n", ao_speed, pyro->speed_less);
                        break;
                case ao_pyro_speed_greater:
                        if (ao_speed >= pyro->speed_greater)
                                continue;
+                       DBG("speed %d < %d\n", ao_speed, pyro->speed_greater);
                        break;
-
                case ao_pyro_height_less:
                        if (ao_height <= pyro->height_less)
                                continue;
+                       DBG("height %d > %d\n", ao_height, pyro->height_less);
                        break;
                case ao_pyro_height_greater:
                        if (ao_height >= pyro->height_greater)
                                continue;
+                       DBG("height %d < %d\n", ao_height, pyro->height_greater);
                        break;
 
 #if HAS_GYRO
                case ao_pyro_orient_less:
                        if (ao_sample_orient <= pyro->orient_less)
                                continue;
+                       DBG("orient %d > %d\n", ao_sample_orient, pyro->orient_less);
                        break;
                case ao_pyro_orient_greater:
                        if (ao_sample_orient >= pyro->orient_greater)
                                continue;
+                       DBG("orient %d < %d\n", ao_sample_orient, pyro->orient_greater);
                        break;
 #endif
 
                case ao_pyro_time_less:
                        if ((int16_t) (ao_time() - ao_boost_tick) <= pyro->time_less)
                                continue;
+                       DBG("time %d > %d\n", (int16_t)(ao_time() - ao_boost_tick), pyro->time_less);
                        break;
                case ao_pyro_time_greater:
                        if ((int16_t) (ao_time() - ao_boost_tick) >= pyro->time_greater)
                                continue;
+                       DBG("time %d < %d\n", (int16_t)(ao_time() - ao_boost_tick), pyro->time_greater);
                        break;
 
                case ao_pyro_ascending:
                        if (ao_speed > 0)
                                continue;
+                       DBG("not ascending speed %d\n", ao_speed);
                        break;
                case ao_pyro_descending:
                        if (ao_speed < 0)
                                continue;
+                       DBG("not descending speed %d\n", ao_speed);
                        break;
 
                case ao_pyro_after_motor:
                        if (ao_motor_number == pyro->motor)
                                continue;
+                       DBG("motor %d != %d\n", ao_motor_number, pyro->motor);
                        break;
 
                case ao_pyro_delay:
@@ -154,10 +174,12 @@ ao_pyro_ready(struct ao_pyro *pyro)
                case ao_pyro_state_less:
                        if (ao_flight_state < pyro->state_less)
                                continue;
+                       DBG("state %d >= %d\n", ao_flight_state, pyro->state_less);
                        break;
                case ao_pyro_state_greater_or_equal:
                        if (ao_flight_state >= pyro->state_greater_or_equal)
                                continue;
+                       DBG("state %d >= %d\n", ao_flight_state, pyro->state_less);
                        break;
 
                default:
@@ -230,7 +252,7 @@ ao_pyro_check(void)
        struct ao_pyro  *pyro;
        uint8_t         p, any_waiting;
        uint16_t        fire = 0;
-       
+
        any_waiting = 0;
        for (p = 0; p < AO_PYRO_NUM; p++) {
                pyro = &ao_config.pyro[p];
@@ -266,6 +288,16 @@ ao_pyro_check(void)
                 * the delay to expire
                 */
                if (pyro->delay_done) {
+
+                       /* Check to make sure the required conditions
+                        * remain valid. If not, inhibit the channel
+                        * by setting the fired bit
+                        */
+                       if (!ao_pyro_ready(pyro)) {
+                               pyro->fired = 1;
+                               continue;
+                       }
+
                        if ((int16_t) (ao_time() - pyro->delay_done) < 0)
                                continue;
                }
@@ -443,7 +475,7 @@ ao_pyro_set(void)
                printf ("invalid pyro channel %d\n", p);
                return;
        }
-       pyro_tmp.flags = 0;
+       memset(&pyro_tmp, '\0', sizeof (pyro_tmp));
        for (;;) {
                ao_cmd_white();
                if (ao_cmd_lex_c == '\n')
@@ -467,13 +499,26 @@ ao_pyro_set(void)
                }
                pyro_tmp.flags |= ao_pyro_values[v].flag;
                if (ao_pyro_values[v].offset != NO_VALUE) {
+                       uint8_t negative = 0;
+                       ao_cmd_white();
+                       if (ao_cmd_lex_c == '-') {
+                               negative = 1;
+                               ao_cmd_lex();
+                       }
                        ao_cmd_decimal();
                        if (ao_cmd_status != ao_cmd_success)
                                return;
-                       if (ao_pyro_values[v].flag & AO_PYRO_8_BIT_VALUE)
+                       if (ao_pyro_values[v].flag & AO_PYRO_8_BIT_VALUE) {
+                               if (negative) {
+                                       ao_cmd_status = ao_cmd_syntax_error;
+                                       return;
+                               }
                                *((uint8_t *) ((char *) &pyro_tmp + ao_pyro_values[v].offset)) = ao_cmd_lex_i;
-                       else
+                       } else {
+                               if (negative)
+                                       ao_cmd_lex_i = -ao_cmd_lex_i;
                                *((int16_t *) ((char *) &pyro_tmp + ao_pyro_values[v].offset)) = ao_cmd_lex_i;
+                       }
                }
        }
        _ao_config_edit_start();
index b37aaeb1707554559265ccee59ad0a5c3fee9e91..0fde725a617ce42b2df60797b246535aec8a4e62 100644 (file)
@@ -83,6 +83,9 @@ ao_pyro_init(void);
 void
 ao_pyro_manual(uint8_t p);
 
+enum ao_igniter_status
+ao_pyro_status(uint8_t p);
+
 void
 ao_pyro_print_status(void);
 
index f22631547473d7de341bff5c91d85107ec8d133f..5314fc8fb82fa7a698dd3743939ef23fe54dbeda 100644 (file)
@@ -211,12 +211,23 @@ ao_report_continuity(void) __reentrant
                        pause(AO_MS_TO_TICKS(100));
                }
        } else {
-               c = 10;
+               c = 5;
                while (c--) {
                        high(AO_MS_TO_TICKS(20));
                        low(AO_MS_TO_TICKS(20));
                }
        }
+#if AO_PYRO_NUM
+       pause(AO_MS_TO_TICKS(250));
+       for(c = 0; c < AO_PYRO_NUM; c++) {
+               enum ao_igniter_status  status = ao_pyro_status(c);
+               if (status == ao_igniter_ready)
+                       mid(AO_MS_TO_TICKS(25));
+               else
+                       low(AO_MS_TO_TICKS(25));
+               pause(AO_MS_TO_TICKS(200));
+       }
+#endif
 #if HAS_LOG
        if (ao_log_full()) {
                pause(AO_MS_TO_TICKS(100));
index 244a84fe3f68c76e7c83371cc3683f2d9b57c18c..793b190b0430ebe47abf510be23e6cbc4c1b3a81 100644 (file)
@@ -17,9 +17,9 @@
 
 #include "ao.h"
 
-static __xdata uint16_t        ao_rssi_time;
-static __pdata uint16_t        ao_rssi_delay;
-static __pdata uint8_t ao_rssi_led;
+static __xdata uint16_t                ao_rssi_time;
+static __pdata uint16_t                ao_rssi_delay;
+static __pdata AO_LED_TYPE     ao_rssi_led;
 
 void
 ao_rssi(void)
@@ -33,7 +33,7 @@ ao_rssi(void)
 }
 
 void
-ao_rssi_set(int rssi_value)
+ao_rssi_set(int16_t rssi_value)
 {
        if (rssi_value > 0)
                rssi_value = 0;
@@ -45,7 +45,7 @@ ao_rssi_set(int rssi_value)
 __xdata struct ao_task ao_rssi_task;
 
 void
-ao_rssi_init(uint8_t rssi_led)
+ao_rssi_init(AO_LED_TYPE rssi_led)
 {
        ao_rssi_led = rssi_led;
        ao_rssi_delay = 0;
index 34658951724e7166dbc3008a9079a2f7a1df8e59..29bf2bf6ed0661a98aab90182b903977c1148880 100644 (file)
@@ -245,7 +245,7 @@ ao_sample_preflight(void)
        } else {
 #if HAS_ACCEL
                ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g;
-               ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g;
+               ao_accel_scale = to_fix_32(GRAVITY * 2 * 16) / ao_accel_2g;
 #endif
                ao_sample_preflight_set();
                ao_preflight = FALSE;
index 16d4c5076774d04ad6adefc70064f1dae43d6626..2ec998bd257adb4a9274447d4111504526c3d829 100644 (file)
  * ao_sample.c
  */
 
+#ifndef AO_VALUE_32
+#define AO_VALUE_32    1
+#endif
+
+#if AO_VALUE_32
+/*
+ * For 32-bit computed values, use 64-bit intermediates.
+ */
+typedef int64_t                        ao_k_t;
+typedef int32_t                        ao_v_t;
+#else
+/*
+ * For 16-bit computed values, use 32-bit intermediates.
+ */
+typedef int32_t                        ao_k_t;
+typedef int16_t                        ao_v_t;
+#endif
+
 /*
  * Barometer calibration
  *
  * 2047m/s² (over 200g)
  */
 
-#define AO_M_TO_HEIGHT(m)      ((int16_t) (m))
-#define AO_MS_TO_SPEED(ms)     ((int16_t) ((ms) * 16))
-#define AO_MSS_TO_ACCEL(mss)   ((int16_t) ((mss) * 16))
+#define AO_M_TO_HEIGHT(m)      ((ao_v_t) (m))
+#define AO_MS_TO_SPEED(ms)     ((ao_v_t) ((ms) * 16))
+#define AO_MSS_TO_ACCEL(mss)   ((ao_v_t) ((mss) * 16))
 
 extern __pdata uint16_t        ao_sample_tick;         /* time of last data */
 extern __data uint8_t  ao_sample_adc;          /* Ring position of last processed sample */
@@ -134,21 +152,33 @@ uint8_t ao_sample(void);
  * ao_kalman.c
  */
 
-#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5))
-#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5))
+#define to_fix_16(x) ((int16_t) ((x) * 65536.0 + 0.5))
+#define to_fix_32(x) ((int32_t) ((x) * 65536.0 + 0.5))
+#define to_fix_64(x) ((int64_t) ((x) * 65536.0 + 0.5))
+
+#ifdef AO_VALUE_32
+#if AO_VALUE_32
+#define to_fix_v(x)    to_fix_32(x)
+#define to_fix_k(x)    to_fix_64(x)
+#else
+#define to_fix_v(x)    to_fix_16(x)
+#define to_fix_k(x)    to_fix_32(x)
+#endif
+
 #define from_fix(x)    ((x) >> 16)
 
-extern __pdata int16_t                 ao_height;      /* meters */
-extern __pdata int16_t                 ao_speed;       /* m/s * 16 */
-extern __pdata int16_t                 ao_accel;       /* m/s² * 16 */
-extern __xdata int16_t                 ao_max_height;  /* max of ao_height */
-extern __xdata int16_t                 ao_avg_height;  /* running average of height */
+extern __pdata ao_v_t                  ao_height;      /* meters */
+extern __pdata ao_v_t                  ao_speed;       /* m/s * 16 */
+extern __pdata ao_v_t                  ao_accel;       /* m/s² * 16 */
+extern __xdata ao_v_t                  ao_max_height;  /* max of ao_height */
+extern __xdata ao_v_t                  ao_avg_height;  /* running average of height */
 
-extern __pdata int16_t                 ao_error_h;
-extern __pdata int16_t                 ao_error_h_sq_avg;
+extern __pdata ao_v_t                  ao_error_h;
+extern __pdata ao_v_t                  ao_error_h_sq_avg;
 
 #if HAS_ACCEL
-extern __pdata int16_t                 ao_error_a;
+extern __pdata ao_v_t                  ao_error_a;
+#endif
 #endif
 
 void ao_kalman(void);
index 9f778b0905b8448e51d58a321ea21cc186d67a4d..56bd715e7b690d15a800f677db7b87b37897e5af 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ * Copyright © 2011 Keth 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
 
 static __pdata uint16_t ao_telemetry_interval;
 
+#if HAS_RADIO_RATE
+static __xdata uint16_t ao_telemetry_desired_interval;
+#endif
+
 #if HAS_RDF
 static __pdata uint8_t ao_rdf = 0;
 static __pdata uint16_t ao_rdf_time;
@@ -64,7 +68,7 @@ static void
 ao_send_sensor(void)
 {
        __xdata struct ao_data *packet = (__xdata struct ao_data *) &ao_data_ring[ao_data_ring_prev(ao_sample_data)];
-                       
+
        telemetry.generic.tick = packet->tick;
        telemetry.generic.type = AO_TELEMETRY_SENSOR;
 
@@ -106,12 +110,13 @@ ao_send_sensor(void)
 
 
 #ifdef AO_SEND_MEGA
+
 /* Send mega sensor packet */
 static void
 ao_send_mega_sensor(void)
 {
        __xdata struct ao_data *packet = (__xdata struct ao_data *) &ao_data_ring[ao_data_ring_prev(ao_sample_data)];
-                       
+
        telemetry.generic.tick = packet->tick;
        telemetry.generic.type = AO_TELEMETRY_MEGA_SENSOR;
 
@@ -240,7 +245,7 @@ static void
 ao_send_mini(void)
 {
        __xdata struct ao_data *packet = (__xdata struct ao_data *) &ao_data_ring[ao_data_ring_prev(ao_sample_data)];
-                       
+
        telemetry.generic.tick = packet->tick;
        telemetry.generic.type = AO_TELEMETRY_MINI;
 
@@ -339,7 +344,7 @@ ao_send_location(void)
                ao_mutex_get(&ao_gps_mutex);
                ao_xmemcpy(&telemetry.location.flags,
                       &ao_gps_data.flags,
-                      26);
+                      27);
                telemetry.location.tick = ao_gps_tick;
                ao_mutex_put(&ao_gps_mutex);
                ao_radio_send(&telemetry, sizeof (telemetry));
@@ -490,12 +495,33 @@ ao_telemetry(void)
        }
 }
 
+#if HAS_RADIO_RATE
+void
+ao_telemetry_reset_interval(void)
+{
+       ao_telemetry_set_interval(ao_telemetry_desired_interval);
+}
+#endif
+
 void
 ao_telemetry_set_interval(uint16_t interval)
 {
        int8_t  cur = 0;
+
+#if HAS_RADIO_RATE
+       /* Limit max telemetry rate based on available radio bandwidth.
+        */
+       static __xdata const uint16_t min_interval[] = {
+               /* [AO_RADIO_RATE_38400] = */ AO_MS_TO_TICKS(100),
+               /* [AO_RADIO_RATE_9600] = */ AO_MS_TO_TICKS(500),
+               /* [AO_RADIO_RATE_2400] = */ AO_MS_TO_TICKS(1000)
+       };
+
+       ao_telemetry_desired_interval = interval;
+       if (interval < min_interval[ao_config.radio_rate])
+               interval = min_interval[ao_config.radio_rate];
+#endif
        ao_telemetry_interval = interval;
-       
 #if AO_SEND_MEGA
        if (interval > 1)
                ao_telemetry_mega_data_max = 1;
@@ -521,7 +547,7 @@ ao_telemetry_set_interval(uint16_t interval)
        ao_telemetry_companion_cur = cur;
 #endif
 
-       ao_telemetry_config_max = AO_SEC_TO_TICKS(1) / interval;
+       ao_telemetry_config_max = AO_SEC_TO_TICKS(5) / interval;
 #if HAS_COMPANION
        if (ao_telemetry_config_max > cur)
                cur++;
index be7d0340745352d20505dc265a00e1f8390cf8da..83d432cf95f39db62dc9f602d8011c58a46f49ae 100644 (file)
@@ -86,12 +86,9 @@ struct ao_telemetry_configuration {
 
 #define AO_TELEMETRY_LOCATION          0x05
 
-#define AO_GPS_MODE_NOT_VALID          'N'
-#define AO_GPS_MODE_AUTONOMOUS         'A'
-#define AO_GPS_MODE_DIFFERENTIAL       'D'
-#define AO_GPS_MODE_ESTIMATED          'E'
-#define AO_GPS_MODE_MANUAL             'M'
-#define AO_GPS_MODE_SIMULATED          'S'
+/* Mode bits */
+
+#define AO_GPS_MODE_ALTITUDE_24                (1 << 0)        /* reports 24-bits of altitude */
 
 struct ao_telemetry_location {
        uint16_t        serial;         /*  0 */
@@ -99,7 +96,7 @@ struct ao_telemetry_location {
        uint8_t         type;           /*  4 */
 
        uint8_t         flags;          /*  5 Number of sats and other flags */
-       int16_t         altitude;       /*  6 GPS reported altitude (m) */
+       uint16_t        altitude_low;   /*  6 GPS reported altitude (m) */
        int32_t         latitude;       /*  8 latitude (degrees * 10⁷) */
        int32_t         longitude;      /* 12 longitude (degrees * 10⁷) */
        uint8_t         year;           /* 16 (- 2000) */
@@ -115,10 +112,31 @@ struct ao_telemetry_location {
        uint16_t        ground_speed;   /* 26 cm/s */
        int16_t         climb_rate;     /* 28 cm/s */
        uint8_t         course;         /* 30 degrees / 2 */
-       uint8_t         unused;         /* 31 unused */
+       int8_t          altitude_high;  /* 31 high byte of altitude */
        /* 32 */
 };
 
+#if HAS_GPS
+
+#ifndef HAS_WIDE_GPS
+#define HAS_WIDE_GPS   1
+#endif
+
+#if HAS_WIDE_GPS
+typedef int32_t                gps_alt_t;
+#define AO_TELEMETRY_LOCATION_ALTITUDE(l)      (((gps_alt_t) (l)->altitude_high << 16) | ((l)->altitude_low))
+#define AO_TELEMETRY_LOCATION_SET_ALTITUDE(l,a) (((l)->mode |= AO_GPS_MODE_ALTITUDE_24), \
+                                                ((l)->altitude_high = (a) >> 16), \
+                                                ((l)->altitude_low = (a)))
+#else
+typedef int16_t                gps_alt_t;
+#define AO_TELEMETRY_LOCATION_ALTITUDE(l)      ((gps_alt_t) (l)->altitude_low)
+#define AO_TELEMETRY_LOCATION_SET_ALTITUDE(l,a)        (((l)->mode = 0, \
+                                                 (l)->altitude_low = (a)))
+#endif /* HAS_WIDE_GPS */
+
+#endif /* HAS_GPS */
+
 #define AO_TELEMETRY_SATELLITE         0x06
 
 struct ao_telemetry_satellite_info {
index 9febc7f090cb6ac33197b40cc054b9ee216e8a39..9b007af82109defdc752e56cfcd375a374c5b1e6 100644 (file)
@@ -36,9 +36,9 @@ ao_usb_connected(void)
 #endif
 
 struct gps_position {
-       int32_t latitude;
-       int32_t longitude;
-       int16_t altitude;
+       int32_t         latitude;
+       int32_t         longitude;
+       gps_alt_t       altitude;
 };
 
 #define GPS_RING       16
@@ -72,7 +72,7 @@ ao_tracker(void)
 #if !HAS_USB_CONNECT
        ao_tracker_force_telem = 1;
 #endif
-       ao_log_scan();
+       log_started = ao_log_scan();
 
        ao_rdf_set(1);
 
@@ -122,12 +122,13 @@ ao_tracker(void)
                        {
                                uint8_t ring;
                                uint8_t moving = 0;
+                               gps_alt_t altitude = AO_TELEMETRY_LOCATION_ALTITUDE(&gps_data);
 
                                for (ring = ao_gps_ring_next(gps_head); ring != gps_head; ring = ao_gps_ring_next(ring)) {
                                        ground_distance = ao_distance(gps_data.latitude, gps_data.longitude,
                                                                      gps_position[ring].latitude,
                                                                      gps_position[ring].longitude);
-                                       height = gps_position[ring].altitude - gps_data.altitude;
+                                       height = gps_position[ring].altitude - altitude;
                                        if (height < 0)
                                                height = -height;
 
@@ -153,7 +154,7 @@ ao_tracker(void)
                                        ao_log_gps_data(gps_tick, &gps_data);
                                        gps_position[gps_head].latitude = gps_data.latitude;
                                        gps_position[gps_head].longitude = gps_data.longitude;
-                                       gps_position[gps_head].altitude = gps_data.altitude;
+                                       gps_position[gps_head].altitude = altitude;
                                        gps_head = ao_gps_ring_next(gps_head);
                                        ao_mutex_put(&tracker_mutex);
                                }
@@ -180,8 +181,7 @@ void
 ao_tracker_erase_end(void)
 {
        if (erasing_current) {
-               ao_log_scan();
-               log_started = 0;
+               log_started = ao_log_scan();
                ao_mutex_put(&tracker_mutex);
        }
 }
@@ -203,7 +203,7 @@ ao_tracker_set_telem(void)
        printf ("log_started: %d\n", log_started);
        printf ("latitude: %ld\n", (long) gps_data.latitude);
        printf ("longitude: %ld\n", (long) gps_data.longitude);
-       printf ("altitude: %d\n", gps_data.altitude);
+       printf ("altitude: %ld\n", AO_TELEMETRY_LOCATION_ALTITUDE(&gps_data));
        printf ("log_running: %d\n", ao_log_running);
        printf ("log_start_pos: %ld\n", (long) ao_log_start_pos);
        printf ("log_cur_pos: %ld\n", (long) ao_log_current_pos);
index 0891903ea5f00cb2adae5dbf57506fcdcb81a5c5..21a7a8e5702f779fd2ddce6e164e89a8bf77ab9e 100644 (file)
@@ -161,16 +161,17 @@ static inline void ao_arch_restore_stack(void) {
 
 #endif /* HAS_TASK */
 
-#define ao_arch_wait_interrupt() do {                  \
-               asm(".global ao_idle_loc\n\twfi\nao_idle_loc:");        \
-               ao_arch_release_interrupts();                           \
-               ao_arch_block_interrupts();                             \
+#define ao_arch_wait_interrupt() do {                          \
+               asm("\twfi\n");                                 \
+               ao_arch_release_interrupts();                   \
+               asm(".global ao_idle_loc\n\nao_idle_loc:");     \
+               ao_arch_block_interrupts();                     \
        } while (0)
 
-#define ao_arch_critical(b) do {                               \
-               ao_arch_block_interrupts();                     \
-               do { b } while (0);                             \
-               ao_arch_release_interrupts();                   \
+#define ao_arch_critical(b) do {                       \
+               uint32_t __mask = ao_arch_irqsave();    \
+               do { b } while (0);                     \
+               ao_arch_irqrestore(__mask);             \
        } while (0)
 
 /*
index ade8e4964341f7d684f6efc3dc61e9f4d58de7f0..bbe2ea587e254bad422db666ddd49ef284601a04 100644 (file)
@@ -53,6 +53,7 @@ ALTOS_SRC = \
        ao_rssi.c \
        ao_send_packet.c \
        ao_packet_master.c \
+       ao_eeprom_stm.c \
        ao_packet.c
 
 PRODUCT=MegaDongle-v0.1
index 2792af22e4df9586ca893bef6c78faa2ab2e9352..68d6de60c9d979eec0bf072484772aa8d798e2a3 100644 (file)
@@ -24,7 +24,7 @@ int
 main(void)
 {
        ao_clock_init();
-       
+
 #if HAS_STACK_GUARD
        ao_mpu_init();
 #endif
@@ -48,7 +48,7 @@ main(void)
        ao_send_packet_init();
 
        ao_config_init();
-       
+
        ao_start_scheduler();
        return 0;
 }
index d460a49095b9a38fdd3fd93cb05cdbf122f91f37..9edd91f443047b2892bc4e9e26789249779d9d41 100644 (file)
@@ -15,6 +15,8 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
+/* Using TeleMetrum v1.9 board */
+
 #ifndef _AO_PINS_H_
 #define _AO_PINS_H_
 
@@ -46,7 +48,7 @@
 #define HAS_SERIAL_1           0
 #define USE_SERIAL_1_STDIN     0
 #define SERIAL_1_PB6_PB7       0
-#define SERIAL_1_PA9_PA10      1
+#define SERIAL_1_PA9_PA10      0
 
 #define HAS_SERIAL_2           0
 #define USE_SERIAL_2_STDIN     0
 #define HAS_SERIAL_3           0
 #define USE_SERIAL_3_STDIN     0
 #define SERIAL_3_PB10_PB11     0
-#define SERIAL_3_PC10_PC11     1
+#define SERIAL_3_PC10_PC11     0
 #define SERIAL_3_PD8_PD9       0
 
-#define ao_gps_getchar         ao_serial3_getchar
-#define ao_gps_putchar         ao_serial3_putchar
-#define ao_gps_set_speed       ao_serial3_set_speed
-
-#define HAS_EEPROM             0
-#define USE_INTERNAL_FLASH     0
+#define HAS_EEPROM             1
+#define USE_INTERNAL_FLASH     1
+#define USE_STORAGE_CONFIG     0
+#define USE_EEPROM_CONFIG      1
 #define HAS_USB                        1
 #define HAS_BEEP               0
 #define HAS_RADIO              1
 #define HAS_TELEMETRY          0
+#define HAS_RSSI               1
 
 #define HAS_SPI_1              0
 #define SPI_1_PA5_PA6_PA7      0       /* Barometer */
@@ -76,7 +77,7 @@
 #define SPI_1_PE13_PE14_PE15   0       /* Accelerometer */
 
 #define HAS_SPI_2              1
-#define SPI_2_PB13_PB14_PB15   1       /* Flash, Companion */
+#define SPI_2_PB13_PB14_PB15   1       /* Radio */
 #define SPI_2_PD1_PD3_PD4      0
 #define SPI_2_OSPEEDR          STM_OSPEEDR_10MHz
 
 #define SPI_2_MISO_PIN         14
 #define SPI_2_MOSI_PIN         15
 
-#define HAS_I2C_1              0
-#define I2C_1_PB8_PB9          1
-
-#define HAS_I2C_2              0
-#define I2C_2_PB10_PB11                1
-
 #define PACKET_HAS_SLAVE       0
 #define PACKET_HAS_MASTER      1
 
 #define LOW_LEVEL_DEBUG                0
 
-#define LED_PORT_0_ENABLE      STM_RCC_AHBENR_GPIOAEN
-#define LED_PORT_1_ENABLE      STM_RCC_AHBENR_GPIOBEN
-#define LED_PORT_0             (&stm_gpioa)
-#define LED_PORT_0_MASK                (0xff)
+#define LED_PORT_0_ENABLE      STM_RCC_AHBENR_GPIOCEN
+#define LED_PORT_0             (&stm_gpioc)
+#define LED_PORT_0_MASK                (0xffff)
 #define LED_PORT_0_SHIFT       0
-#define LED_PORT_1_MASK                (0xff00)
-#define LED_PORT_1_SHIFT       0
-#define LED_PORT_1             (&stm_gpiob)
-#define LED_PIN_RED            1
-#define LED_PIN_GREEN          12
+#define LED_PIN_RED            14
+#define LED_PIN_GREEN          15
 #define AO_LED_RED             (1 << LED_PIN_RED)
 #define AO_LED_GREEN           (1 << LED_PIN_GREEN)
 
 
 #define AO_FEC_DEBUG           0
 #define AO_CC1120_SPI_CS_PORT  (&stm_gpioa)
-#define AO_CC1120_SPI_CS_PIN   0
+#define AO_CC1120_SPI_CS_PIN   2
 #define AO_CC1120_SPI_BUS      AO_SPI_2_PB13_PB14_PB15
 #define AO_CC1120_SPI          stm_spi2
 
-#define AO_CC1120_INT_PORT     (&stm_gpioc)
-#define AO_CC1120_INT_PIN      13
+#define AO_CC1120_INT_PORT     (&stm_gpioa)
+#define AO_CC1120_INT_PIN      3
 
-#define AO_CC1120_MCU_WAKEUP_PORT      (&stm_gpioc)
-#define AO_CC1120_MCU_WAKEUP_PIN       (0)
+#define AO_CC1120_MCU_WAKEUP_PORT      (&stm_gpioa)
+#define AO_CC1120_MCU_WAKEUP_PIN       (4)
 
 #define AO_CC1120_INT_GPIO     2
 #define AO_CC1120_INT_GPIO_IOCFG       CC1120_IOCFG2
diff --git a/src/microkite/.gitignore b/src/microkite/.gitignore
new file mode 100644 (file)
index 0000000..7a5d0a1
--- /dev/null
@@ -0,0 +1,2 @@
+ao_product.h
+microkite-*
diff --git a/src/microkite/Makefile b/src/microkite/Makefile
new file mode 100644 (file)
index 0000000..b752375
--- /dev/null
@@ -0,0 +1,134 @@
+#
+# Tiny AltOS build
+#
+#
+vpath % ../attiny:../drivers:../kernel:../product:..
+vpath ao-make-product.5c ../util
+vpath make-altitude-pa ../util
+
+include ../avr/Makefile.defs
+
+PROGNAME=microkite-v0.1
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SCRIPT=microkite-load
+
+PUBLISH_DIR=$(HOME)/altusmetrumllc/Binaries
+PUBLISH_HEX=$(PUBLISH_DIR)/$(HEX)
+PUBLISH_SCRIPT=$(PUBLISH_DIR)/$(SCRIPT)
+
+MCU=attiny85
+DUDECPUTYPE=t85
+#PROGRAMMER=stk500v2 -P usb
+LOADSLOW=-i 32 -B 32
+LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w:
+
+#LDFLAGS=-L$(LDSCRIPTS) -Tavr25.x
+
+ALTOS_SRC = \
+       ao_micropeak.c \
+       ao_spi_attiny.c \
+       ao_led.c \
+       ao_clock.c \
+       ao_ms5607.c \
+       ao_exti.c \
+       ao_convert_pa.c \
+       ao_report_micro.c \
+       ao_notask.c \
+       ao_eeprom_tiny.c \
+       ao_panic.c \
+       ao_log_micro.c \
+       ao_async.c \
+       ao_microflight.c \
+       ao_microkalman.c
+
+INC=\
+       ao.h \
+       ao_pins.h \
+       ao_arch.h \
+       ao_arch_funcs.h \
+       ao_exti.h \
+       ao_ms5607.h \
+       ao_log_micro.h \
+       ao_micropeak.h \
+       altitude-pa.h
+
+IDPRODUCT=0
+PRODUCT=MicroKite-v0.1
+PRODUCT_DEF=-DMICROPEAK
+CFLAGS = $(PRODUCT_DEF) -I. -I../attiny -I../kernel -I.. -I../drivers -I../product
+CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O2 -mcall-prologues -DATTINY
+
+NICKLE=nickle
+
+SRC=$(ALTOS_SRC)
+OBJ=$(SRC:.c=.o)
+
+V=0
+# The user has explicitly enabled quiet compilation.
+ifeq ($(V),0)
+quiet = @printf "  $1 $2 $@\n"; $($1)
+endif
+# Otherwise, print the full command line.
+quiet ?= $($1)
+
+all: $(PROG) $(HEX) microkite-load
+
+CHECK=sh ../util/check-avr-mem
+
+$(PROG): Makefile $(OBJ)
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ)
+       $(call quiet,CHECK) $(PROG) || ($(RM) -f $(PROG); exit 1)
+
+$(HEX): $(PROG)
+       avr-size $(PROG)
+       $(OBJCOPY) -R .eeprom -O ihex $(PROG) $@
+
+
+load: $(HEX)
+       $(LOADCMD) $(LOADARG)$(HEX)
+
+load-slow: $(HEX)
+       $(LOADCMD) $(LOADSLOW) $(LOADARG)$(HEX)
+
+ao_product.h: ao-make-product.5c ../Version
+       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+ao_product.o: ao_product.c ao_product.h
+
+%.o : %.c $(INC)
+       $(call quiet,CC) -c $(CFLAGS) $<
+
+distclean:     clean
+
+clean:
+       rm -f *.o $(PROG) $(HEX) $(SCRIPT)
+       rm -f ao_product.h
+
+publish: $(PUBLISH_HEX) $(PUBLISH_SCRIPT)
+
+$(PUBLISH_HEX): $(HEX)
+       cp -a $(HEX) $@
+
+$(PUBLISH_SCRIPT): $(SCRIPT)
+       cp -a $(SCRIPT) $@
+
+load-product:
+       ./$(SCRIPT) fast
+
+load-product-slow:
+       ./$(SCRIPT) slow
+
+../altitude-pa.h: make-altitude-pa
+       nickle $< > $@
+
+$(SCRIPT): $(SCRIPT).tmpl Makefile ../Version
+       sed -e 's/%HEX%/$(HEX)/' -e 's/%LOADCMD%/$(LOADCMD)/' -e 's/%LOADARG%/$(LOADARG)/' -e 's/%LOADSLOW%/$(LOADSLOW)/' $(SCRIPT).tmpl > $@ || (rm $@ && exit 1)
+       chmod +x $@
+
+install:
+
+uninstall:
+
+$(OBJ): ao_product.h $(INC)
diff --git a/src/microkite/ao_pins.h b/src/microkite/ao_pins.h
new file mode 100644 (file)
index 0000000..346b63a
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+#include <avr/pgmspace.h>
+
+#define AO_LED_ORANGE          (1<<4)
+#define AO_LED_SERIAL          4
+#define AO_LED_PANIC           AO_LED_ORANGE
+#define AO_LED_REPORT          AO_LED_ORANGE
+#define LEDS_AVAILABLE         (AO_LED_ORANGE)
+#define USE_SERIAL_1_STDIN     0
+#define HAS_USB                        0
+#define PACKET_HAS_SLAVE       0
+#define HAS_SERIAL_1           0
+#define HAS_TASK               0
+#define HAS_MS5607             1
+#define HAS_MS5611             0
+#define HAS_EEPROM             0
+#define HAS_BEEP               0
+#define AVR_CLOCK              250000UL
+
+/* SPI */
+#define SPI_PORT               PORTB
+#define SPI_PIN                        PINB
+#define SPI_DIR                        DDRB
+#define AO_MS5607_CS_PORT      PORTB
+#define AO_MS5607_CS_PIN       3
+
+/* MS5607 */
+#define AO_MS5607_SPI_INDEX    0
+#define AO_MS5607_MISO_PORT    PORTB
+#define AO_MS5607_MISO_PIN     0
+#define AO_MS5607_BARO_OVERSAMPLE      4096
+#define AO_MS5607_TEMP_OVERSAMPLE      1024
+
+/* I2C */
+#define I2C_PORT               PORTB
+#define I2C_PIN                        PINB
+#define I2C_DIR                        DDRB
+#define I2C_PIN_SCL            PINB2
+#define I2C_PIN_SDA            PINB0
+
+#define AO_CONST_ATTRIB                PROGMEM
+typedef int32_t alt_t;
+#define FETCH_ALT(o)           ((alt_t) pgm_read_dword(&altitude_table[o]))
+
+#define AO_ALT_VALUE(x)                ((x) * (alt_t) 10)
+
+#define BOOST_DETECT              0    /* none */
+#define LOG_INTERVAL            200    /* 19.2 seconds */
+#define BOOST_DELAY            0
+
+#define AO_LOG_ID              AO_LOG_ID_MICROKITE
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/microkite/microkite-load.tmpl b/src/microkite/microkite-load.tmpl
new file mode 100644 (file)
index 0000000..08236a1
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/sh
+dir=`dirname $0`
+
+HEX="$dir"/"%HEX%"
+LOADCMD="%LOADCMD%"
+LOADARG="%LOADARG%"
+LOADSLOW="%LOADSLOW%"
+LOADFAST=""
+
+case "$1" in
+fast)
+       LOADSPEED="$LOADFAST"
+       ;;
+*)
+       LOADSPEED="$LOADSLOW"
+       ;;
+esac
+
+echo ${LOADCMD} ${LOADSPEED} ${LOADARG}${HEX}
+${LOADCMD} ${LOADSPEED} ${LOADARG}${HEX}
index 6ae3d0be2acb08611b2119bfe611d3b7d659f02d..ac00f635e77d5d23a581b520a207a0ef4b024a4d 100644 (file)
@@ -8,8 +8,15 @@ vpath make-altitude-pa ../util
 
 include ../avr/Makefile.defs
 
+PROGNAME=micropeak-v0.1
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SCRIPT=micropeak-load
+
 PUBLISH_DIR=$(HOME)/altusmetrumllc/Binaries
-PUBLISH_FILE=$(PUBLISH_DIR)/$(PROG)-$(VERSION).hex
+PUBLISH_HEX=$(PUBLISH_DIR)/$(HEX)
+PUBLISH_SCRIPT=$(PUBLISH_DIR)/$(SCRIPT)
 
 MCU=attiny85
 DUDECPUTYPE=t85
@@ -55,8 +62,6 @@ CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O2 -mcall-prologues -DATTIN
 
 NICKLE=nickle
 
-PROG=micropeak-v0.1
-
 SRC=$(ALTOS_SRC)
 OBJ=$(SRC:.c=.o)
 
@@ -68,7 +73,7 @@ endif
 # Otherwise, print the full command line.
 quiet ?= $($1)
 
-all: $(PROG) $(PROG).hex
+all: $(PROG) $(HEX) micropeak-load
 
 CHECK=sh ../util/check-avr-mem
 
@@ -76,16 +81,16 @@ $(PROG): Makefile $(OBJ)
        $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ)
        $(call quiet,CHECK) $(PROG) || ($(RM) -f $(PROG); exit 1)
 
-$(PROG).hex: $(PROG)
+$(HEX): $(PROG)
        avr-size $(PROG)
        $(OBJCOPY) -R .eeprom -O ihex $(PROG) $@
 
 
-load: $(PROG).hex
-       $(LOADCMD) $(LOADARG)$(PROG).hex
+load: $(HEX)
+       $(LOADCMD) $(LOADARG)$(HEX)
 
-load-slow: $(PROG).hex
-       $(LOADCMD) $(LOADSLOW) $(LOADARG)$(PROG).hex
+load-slow: $(HEX)
+       $(LOADCMD) $(LOADSLOW) $(LOADARG)$(HEX)
 
 ao_product.h: ao-make-product.5c ../Version
        $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
@@ -98,22 +103,30 @@ ao_product.o: ao_product.c ao_product.h
 distclean:     clean
 
 clean:
-       rm -f *.o $(PROG) $(PROG).hex
+       rm -f *.o $(PROG) $(HEX) $(SCRIPT)
        rm -f ao_product.h
 
+publish: $(PUBLISH_HEX) $(PUBLISH_SCRIPT)
 
-publish: $(PROG).hex
-       cp -a $(PROG).hex $(PUBLISH_FILE)
+$(PUBLISH_HEX): $(HEX)
+       cp -a $(HEX) $@
+
+$(PUBLISH_SCRIPT): $(SCRIPT)
+       cp -a $(SCRIPT) $@
 
 load-product:
-       $(LOADCMD) $(LOADARG)$(PUBLISH_FILE)
+       ./$(SCRIPT) fast
 
 load-product-slow:
-       $(LOADCMD) $(LOADSLOW) $(LOADARG)$(PUBLISH_FILE)
+       ./$(SCRIPT) slow
 
 ../altitude-pa.h: make-altitude-pa
        nickle $< > $@
 
+$(SCRIPT): $(SCRIPT).tmpl Makefile ../Version
+       sed -e 's/%HEX%/$(HEX)/' -e 's/%LOADCMD%/$(LOADCMD)/' -e 's/%LOADARG%/$(LOADARG)/' -e 's/%LOADSLOW%/$(LOADSLOW)/' $(SCRIPT).tmpl > $@ || (rm $@ && exit 1)
+       chmod +x $@
+
 install:
 
 uninstall:
diff --git a/src/micropeak/micropeak-load.tmpl b/src/micropeak/micropeak-load.tmpl
new file mode 100644 (file)
index 0000000..08236a1
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/sh
+dir=`dirname $0`
+
+HEX="$dir"/"%HEX%"
+LOADCMD="%LOADCMD%"
+LOADARG="%LOADARG%"
+LOADSLOW="%LOADSLOW%"
+LOADFAST=""
+
+case "$1" in
+fast)
+       LOADSPEED="$LOADFAST"
+       ;;
+*)
+       LOADSPEED="$LOADSLOW"
+       ;;
+esac
+
+echo ${LOADCMD} ${LOADSPEED} ${LOADARG}${HEX}
+${LOADCMD} ${LOADSPEED} ${LOADARG}${HEX}
index 81151364da6557e3cf45ae13562f14286fd74142..b7c289877e110d49f7696ee9a1e18c424d2ee334 100644 (file)
@@ -83,7 +83,7 @@ quiet ?= $($1)
 all: $(PROG)
 
 $(PROG): $(REL) Makefile
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) ..
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL)
        $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@
 
 ao_product.h: ao-make-product.5c ../Version
index 90fe7833f4d239f3b72f9175abace26d8b13a203..7311c21e3ed489dd9030d0adcfbc6af2bc65ed99 100644 (file)
@@ -85,7 +85,7 @@ quiet ?= $($1)
 all: $(PROG)
 
 $(PROG): $(REL) Makefile
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) ..
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL)
        $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM)  || rm $@
 
 ao_product.h: ao-make-product.5c ../Version
index dbbf57d80437e25b6f259ce7ea1aa996935f861a..e9b144c02dca1dd23e16b68b4278523d6ef9c67a 100644 (file)
@@ -24,6 +24,7 @@ INC = \
        altitude.h \
        ao_kalman.h \
        ao_product.h \
+       ao_telemetry.h \
        $(TM_INC)
 
 CORE_SRC = \
index d2fcb6d8b8ca5d45f4e9929f834cad9a4c50849c..e1e350a610e332915108fdda0b9217cb4e8bd4ab 100644 (file)
@@ -85,7 +85,7 @@ quiet ?= $($1)
 all: $(PROG)
 
 $(PROG): $(REL) Makefile
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) ..
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL)
        $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@
 
 ao_product.h: ao-make-product.5c ../Version
index 10f0d19206e436e08912fc69616a41c453a1ca25..54522d869aa1a8e8f895b73b46fae1b518a80b09 100644 (file)
@@ -73,8 +73,9 @@ main(void)
        ao_report_altitude();
        ao_pips();
        ao_log_micro_dump();
-       
+#if BOOST_DELAY        
        ao_delay(BOOST_DELAY);
+#endif
 
        ao_microflight();
 
index 0ec407d7bad503c15d2e37148b4e02ef3156f818..622f5a69700a13eda68311b8a0114691556c5efc 100644 (file)
 #define BOOST_DETECT           360     /* 30m at sea level, 36m at 2000m */
 #endif
 
+#ifndef LOG_INTERVAL
+#define LOG_INTERVAL            2      /* 192 ms */
+#endif
+
+#define AO_LOG_ID_MICROPEAK    0
+#define AO_LOG_ID_MICROKITE    1
+
+#ifndef AO_LOG_ID
+#define AO_LOG_ID              AO_LOG_ID_MICROPEAK
+#endif
+
 /* Wait after power on before doing anything to give the user time to assemble the rocket */
+#ifndef BOOST_DELAY
 #define BOOST_DELAY            AO_SEC_TO_TICKS(60)
+#endif
 
 /* Pressure change (in Pa) to detect landing */
 #define LAND_DETECT            24      /* 2m at sea level, 2.4m at 2000m */
index b461cd3fbf81dd9f32dac82894ea96d7c5bdaad7..7ad3b4b8d97cffd47bac2cf83484d9942cafb892 100644 (file)
@@ -64,6 +64,9 @@
 #define AO_SPI_INDEX(id)       ((id) & AO_SPI_INDEX_MASK)
 #define AO_SPI_CONFIG(id)      ((id) & AO_SPI_CONFIG_MASK)
 
+uint8_t
+ao_spi_try_get(uint8_t spi_index, uint32_t speed, uint8_t task_id);
+
 void
 ao_spi_get(uint8_t spi_index, uint32_t speed);
 
@@ -76,6 +79,9 @@ ao_spi_send(void *block, uint16_t len, uint8_t spi_index);
 void
 ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index);
 
+void
+ao_spi_send_sync(void *block, uint16_t len, uint8_t spi_index);
+
 void
 ao_spi_recv(void *block, uint16_t len, uint8_t spi_index);
 
@@ -95,6 +101,15 @@ ao_spi_init(void);
                ao_spi_set_cs(reg,mask);                        \
        } while (0)
 
+static inline uint8_t
+ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t speed, uint8_t task_id)
+{
+       if (!ao_spi_try_get(bus, speed, task_id))
+               return 0;
+       ao_spi_set_cs(reg, mask);
+       return 1;
+}
+
 #define ao_spi_put_mask(reg,mask,bus) do {     \
                ao_spi_clr_cs(reg,mask);        \
                ao_spi_put(bus);                \
@@ -252,6 +267,8 @@ extern struct ao_stm_usart  ao_stm_usart3;
 
 #define ARM_PUSH32(stack, val) (*(--(stack)) = (val))
 
+typedef uint32_t       ao_arch_irq_t;
+
 static inline uint32_t
 ao_arch_irqsave(void) {
        uint32_t        primask;
@@ -369,10 +386,10 @@ static inline void ao_arch_start_scheduler(void) {
                ao_arch_block_interrupts();                     \
        } while (0)
 
-#define ao_arch_critical(b) do {                               \
-               ao_arch_block_interrupts();                     \
-               do { b } while (0);                             \
-               ao_arch_release_interrupts();                   \
+#define ao_arch_critical(b) do {                       \
+               uint32_t __mask = ao_arch_irqsave();    \
+               do { b } while (0);                     \
+               ao_arch_irqrestore(__mask);             \
        } while (0)
 
 #endif /* _AO_ARCH_FUNCS_H_ */
index 56329c2446c43f6188a6f29dc3ae4d596a93c0df..885af54466a8f41567604f336fce8da0bcf03477 100644 (file)
@@ -153,6 +153,28 @@ ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index)
        ao_dma_done_transfer(miso_dma_index);
 }
 
+void
+ao_spi_send_sync(void *block, uint16_t len, uint8_t spi_index)
+{
+       uint8_t         *b = block;
+       struct stm_spi  *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
+
+       stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
+                       (0 << STM_SPI_CR2_RXNEIE) |
+                       (0 << STM_SPI_CR2_ERRIE) |
+                       (0 << STM_SPI_CR2_SSOE) |
+                       (0 << STM_SPI_CR2_TXDMAEN) |
+                       (0 << STM_SPI_CR2_RXDMAEN));
+
+       /* Clear RXNE */
+       (void) stm_spi->dr;
+
+       while (len--) {
+               while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE)));
+               stm_spi->dr = *b++;
+       }
+}
+
 void
 ao_spi_recv(void *block, uint16_t len, uint8_t spi_index)
 {
@@ -356,13 +378,11 @@ ao_spi_enable_index(uint8_t spi_index)
        }
 }
 
-void
-ao_spi_get(uint8_t spi_index, uint32_t speed)
+static void
+ao_spi_config(uint8_t spi_index, uint32_t speed)
 {
        uint8_t         id = AO_SPI_INDEX(spi_index);
        struct stm_spi  *stm_spi = ao_spi_stm_info[id].stm_spi;
-
-       ao_mutex_get(&ao_spi_mutex[id]);
        stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) |                   /* Three wire mode */
                        (0 << STM_SPI_CR1_BIDIOE) |
                        (0 << STM_SPI_CR1_CRCEN) |                      /* CRC disabled */
@@ -378,7 +398,7 @@ ao_spi_get(uint8_t spi_index, uint32_t speed)
                        (0 << STM_SPI_CR1_CPOL) |                       /* Format 0 */
                        (0 << STM_SPI_CR1_CPHA));
        if (spi_index != ao_spi_index[id]) {
-               
+
                /* Disable old config
                 */
                ao_spi_disable_index(ao_spi_index[id]);
@@ -386,13 +406,32 @@ ao_spi_get(uint8_t spi_index, uint32_t speed)
                /* Enable new config
                 */
                ao_spi_enable_index(spi_index);
-               
+
                /* Remember current config
                 */
                ao_spi_index[id] = spi_index;
        }
 }
 
+uint8_t
+ao_spi_try_get(uint8_t spi_index, uint32_t speed, uint8_t task_id)
+{
+       uint8_t         id = AO_SPI_INDEX(spi_index);
+
+       if (!ao_mutex_try(&ao_spi_mutex[id], task_id))
+               return 0;
+       ao_spi_config(spi_index, speed);
+       return 1;
+}
+
+void
+ao_spi_get(uint8_t spi_index, uint32_t speed)
+{
+       uint8_t         id = AO_SPI_INDEX(spi_index);
+       ao_mutex_get(&ao_spi_mutex[id]);
+       ao_spi_config(spi_index, speed);
+}
+
 void
 ao_spi_put(uint8_t spi_index)
 {
index 9e47f3b839d497c65129e7d4490fef352642d0e4..4181ef35a782d0c0ae58f4810c3a16089853aae9 100644 (file)
@@ -48,6 +48,8 @@
 #define BT_LINK_PIN            P1_7
 #define HAS_MONITOR            1
 #define LEGACY_MONITOR         0
+#define HAS_TELEMETRY          0
+#define AO_RADIO_REG_TEST      1
 
 #define HAS_ADC                        1
 #define AO_PAD_ADC_BATT                0
index 25267268e3a5dd0c67ec409983c46338884af147..99d29826fe972bb16c2391a5f2e14ab280b871f8 100644 (file)
@@ -25,7 +25,6 @@ INC = \
 CORE_SRC = \
        ao_cmd.c \
        ao_config.c \
-       ao_convert.c \
        ao_mutex.c \
        ao_panic.c \
        ao_stdio.c \
index f7a3ff2cea2dc40b7e31866da843d139aac494f7..47ae663f1811af6be510d52913c9fd01e30125fd 100644 (file)
@@ -18,7 +18,8 @@
 #ifndef _AO_PINS_H_
 #define _AO_PINS_H_
 
-#define HAS_RADIO      1
+#define HAS_RADIO              1
+#define HAS_TELEMETRY          0
 
 #define HAS_FLIGHT             0
 #define HAS_USB                        1
index ad5065c175d5f6a738ad0b7bfabe5f5da9bf5be0..944543c5d77a16e3919e6cc71d20a053563c4569 100644 (file)
@@ -25,7 +25,6 @@ INC = \
 CORE_SRC = \
        ao_cmd.c \
        ao_config.c \
-       ao_convert.c \
        ao_mutex.c \
        ao_panic.c \
        ao_stdio.c \
index 96e6b066081e47801310c428f644efe86ad700da..28cc65b92799e9ebd7672621571e8afa7b216648 100644 (file)
@@ -18,7 +18,9 @@
 #ifndef _AO_PINS_H_
 #define _AO_PINS_H_
 
-#define HAS_RADIO      1
+#define HAS_RADIO              1
+#define HAS_RADIO_RATE         1
+#define HAS_TELEMETRY          0
 
 #define HAS_FLIGHT             0
 #define HAS_USB                        1
 #define AO_PAD_ALL_PINS                ((1 << AO_PAD_PIN_0) | (1 << AO_PAD_PIN_1) | (1 << AO_PAD_PIN_2) | (1 << AO_PAD_PIN_3))
 #define AO_PAD_ALL_CHANNELS    ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3))
 
+/* Alarm 2 */
 #define AO_SIREN_PORT          P2
 #define AO_SIREN_DIR           P2DIR
 #define AO_SIREN_PIN           3
 #define AO_SIREN               P2_3
 
+/* Alarm 1 */
 #define AO_STROBE_PORT         P2
 #define AO_STROBE_DIR          P2DIR
 #define AO_STROBE_PIN          4
index 5f53dd9dd39dc745ba2396b9d7b17c61f4ff16a5..d2382a56318c3075e76f636a8cddb1164a346ff9 100644 (file)
 #define HAS_GPS                        1
 #define HAS_FLIGHT             0
 #define HAS_LOG                        1
+#define FLIGHT_LOG_APPEND      1
 #define HAS_TRACKER            1
 
 #define AO_CONFIG_DEFAULT_APRS_INTERVAL                0
 #define AO_CONFIG_DEFAULT_RADIO_POWER          0xc0
-#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX       496 * 1024
 
 /*
  * GPS
index b3f5bb169cab5bf7a8a573672c1baf87d37f7991..4b5f7a9bbec58205ff7bf24d4a881563fad42f61 100644 (file)
@@ -258,7 +258,7 @@ ao_lco_search(void)
        for (box = 0; box < AO_PAD_MAX_BOXES; box++) {
                if ((box % 10) == 0)
                        ao_lco_set_box(box);
-               for (try = 0; try < 5; try++) {
+               for (try = 0; try < 3; try++) {
                        tick_offset = 0;
                        r = ao_lco_query(box, &ao_pad_query, &tick_offset);
                        PRINTD("box %d result %d\n", box, r);
index a6fd4ff8fc2c681412025d8a03795c4fd5dfb434..da790b142e9b0990f1566bc30c2e87e157e816ea 100644 (file)
@@ -48,6 +48,7 @@
 #define HAS_USB                        1
 #define HAS_BEEP               1
 #define HAS_RADIO              1
+#define HAS_RADIO_RATE         1
 #define HAS_TELEMETRY          0
 #define HAS_AES                        1
 
index 46c768e47c0c0901ba6f96671c35cb5cd19a3f85..4a1b3908ab3cbcf2dea2b8a7942b3c10e93e99d1 100644 (file)
@@ -31,6 +31,7 @@ INC = \
        ao_mpu.h \
        stm32l.h \
        math.h \
+       ao_ms5607_convert.c \
        Makefile
 
 #
index ca69dc415eaf2f1a78ef2e5d4db4b98199b36f21..8657e9a90c82f10d30ca87094ac39ece8bcdbcfd 100644 (file)
@@ -25,7 +25,8 @@ INC = \
        ao_int64.h \
        ao_sample.h \
        ao_exti.h \
-       ao_task.h
+       ao_task.h \
+       altitude-pa-small.h
 
 CORE_SRC = \
        ao_cmd.c \
index f202ccd1c31488608a412dd95aa08a8ed9b138ff..ed911798930537292a1177ff48db3478a60f18b5 100644 (file)
 
 #define HAS_FLIGHT             1
 #define HAS_USB                        1
+#define AO_VALUE_32            0
 
 #define HAS_USB_PULLUP 1
 #define AO_USB_PULLUP_PORT     P1
 #define AO_USB_PULLUP_PIN      0
 #define AO_USB_PULLUP          P1_0
 
+#define AO_SMALL_ALTITUDE_TABLE        1
+
 #define USB_FORCE_FLIGHT_IDLE  1
 #define HAS_BEEP               1
-#define HAS_BEEP_CONFIG                0
+#define HAS_BEEP_CONFIG                1
 #define HAS_BATTERY_REPORT     1
 #define HAS_GPS                        0
 #define HAS_SERIAL_1           0
@@ -39,6 +42,8 @@
 #define USE_INTERNAL_FLASH     0
 #define HAS_DBG                        0
 #define PACKET_HAS_SLAVE       1
+#define HAS_RADIO_RATE         1
+#define HAS_TELEMETRY          1
 
 #define AO_LED_RED             2
 #define LEDS_AVAILABLE         AO_LED_RED
diff --git a/src/telerepeat-v1.0/Makefile b/src/telerepeat-v1.0/Makefile
new file mode 100644 (file)
index 0000000..17f6837
--- /dev/null
@@ -0,0 +1,100 @@
+#
+# TeleRepeat build file
+#
+
+TELEREPEAT_VER=1.0
+TELEREPEAT_DEF=1_0
+
+vpath %.c ..:../kernel:../cc1111:../drivers:../product
+vpath %.h ..:../kernel:../cc1111:../drivers:../product
+vpath ao-make-product.5c ../util
+
+ifndef VERSION
+include ../Version
+endif
+
+INC = \
+       ao.h \
+       ao_pins.h \
+       ao_arch.h \
+       ao_arch_funcs.h \
+       cc1111.h \
+       ao_product.h
+
+CORE_SRC = \
+       ao_cmd.c \
+       ao_config.c \
+       ao_monitor.c \
+       ao_mutex.c \
+       ao_panic.c \
+       ao_state.c \
+       ao_stdio.c \
+       ao_task.c \
+       ao_forward.c \
+       ao_storage.c \
+       ao_freq.c
+
+CC1111_SRC = \
+       ao_dbg.c \
+       ao_adc.c \
+       ao_dma.c \
+       ao_led.c \
+       ao_packet.c \
+       ao_intflash.c \
+       ao_packet_master.c \
+       ao_radio.c \
+       ao_romconfig.c \
+       ao_serial.c \
+       ao_string.c \
+       ao_timer.c \
+       ao_usb.c \
+       _bp.c
+
+DRIVER_SRC = \
+       ao_btm.c
+
+PRODUCT_SRC = \
+       ao_telerepeat.c
+
+SRC = \
+       $(CORE_SRC) \
+       $(CC1111_SRC) \
+       $(DRIVER_SRC) \
+       $(PRODUCT_SRC)
+
+PROGNAME = telerepeat-v$(TELEREPEAT_VER)
+PROG = $(PROGNAME)-$(VERSION).ihx
+PRODUCT=TeleRepeat-v$(TELEREPEAT_VER)
+PRODUCT_DEF=-DTELEREPEAT_V_$(TELEREPEAT_DEF)
+IDPRODUCT=0x000e
+CODESIZE=0x7800
+
+include ../cc1111/Makefile.cc1111
+
+NICKLE=nickle
+CHECK_STACK=sh ../util/check-stack
+
+V=0
+# The user has explicitly enabled quiet compilation.
+ifeq ($(V),0)
+quiet = @printf "  $1 $2 $@\n"; $($1)
+endif
+# Otherwise, print the full command line.
+quiet ?= $($1)
+
+all: $(PROG)
+
+$(PROG): $(REL) Makefile
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL)
+       $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@
+
+ao_product.h: ao-make-product.5c ../Version
+       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+distclean:     clean
+
+clean: clean-cc1111
+
+install:
+
+uninstall:
diff --git a/src/telerepeat-v1.0/ao_pins.h b/src/telerepeat-v1.0/ao_pins.h
new file mode 100644 (file)
index 0000000..2a7dbd3
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define HAS_RADIO              1
+#define HAS_RADIO_FORWARD      1
+#define HAS_FLIGHT             0
+#define HAS_USB                        1
+#define HAS_BEEP               0
+#define HAS_SERIAL_1           1
+#define HAS_SERIAL_1_ALT_1     1
+#define HAS_SERIAL_1_ALT_2     0
+#define HAS_SERIAL_1_HW_FLOW   1
+#define USE_SERIAL_1_STDIN     1
+#define DELAY_SERIAL_1_STDIN   1
+#define HAS_DBG                        1
+#define HAS_EEPROM             1
+#define HAS_LOG                        0
+#define USE_INTERNAL_FLASH     1
+#define HAS_BTM                        1
+#define DBG_ON_P1              1
+#define DBG_ON_P0              0
+#define PACKET_HAS_MASTER      1
+#define PACKET_HAS_SLAVE       0
+#define AO_LED_RED             1
+#define AO_LED_BLUE            2
+#define LEDS_AVAILABLE         (AO_LED_RED|AO_LED_BLUE)
+#define AO_MONITOR_LED         AO_LED_RED
+#define AO_BT_LED              AO_LED_BLUE
+#define BT_LINK_ON_P2          0
+#define BT_LINK_ON_P1          1
+#define BT_LINK_PIN_INDEX      7
+#define BT_LINK_PIN            P1_7
+#define HAS_MONITOR            1
+#define HAS_MONITOR_PUT                1
+#define LEGACY_MONITOR         0
+#define HAS_TELEMETRY          0
+#define AO_RADIO_REG_TEST      1
+
+#define HAS_ADC                        1
+#define AO_PAD_ADC_BATT                0
+#define AO_ADC_PINS            (1 << AO_PAD_ADC_BATT)
+
+struct ao_adc {
+       int16_t         batt;
+};
+
+#define AO_ADC_DUMP(p)                                                 \
+       printf ("tick: %5u batt %5d\n",                                 \
+               (p)->tick,                                              \
+               (p)->adc.batt)
+
+#define FETCH_ADC() do {                                               \
+               a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].adc.batt); \
+               a[0] = ADCL;                                            \
+               a[1] = ADCH;                                            \
+       } while (0)
+
+#if DBG_ON_P1
+
+       #define DBG_CLOCK       (1 << 4)        /* mi0 */
+       #define DBG_DATA        (1 << 5)        /* mo0 */
+       #define DBG_RESET_N     (1 << 3)        /* c0 */
+
+       #define DBG_CLOCK_PIN   (P1_4)
+       #define DBG_DATA_PIN    (P1_5)
+       #define DBG_RESET_N_PIN (P1_3)
+
+       #define DBG_PORT_NUM    1
+       #define DBG_PORT        P1
+       #define DBG_PORT_SEL    P1SEL
+       #define DBG_PORT_INP    P1INP
+       #define DBG_PORT_DIR    P1DIR
+
+#endif /* DBG_ON_P1 */
+
+#if DBG_ON_P0
+
+       #define DBG_CLOCK       (1 << 3)
+       #define DBG_DATA        (1 << 4)
+       #define DBG_RESET_N     (1 << 5)
+
+       #define DBG_CLOCK_PIN   (P0_3)
+       #define DBG_DATA_PIN    (P0_4)
+       #define DBG_RESET_N_PIN (P0_5)
+
+       #define DBG_PORT_NUM    0
+       #define DBG_PORT        P0
+       #define DBG_PORT_SEL    P0SEL
+       #define DBG_PORT_INP    P0INP
+       #define DBG_PORT_DIR    P0DIR
+
+#endif /* DBG_ON_P0 */
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/telerepeat-v1.0/ao_telerepeat.c b/src/telerepeat-v1.0/ao_telerepeat.c
new file mode 100644 (file)
index 0000000..21bf8a7
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+#include "ao_forward.h"
+
+void
+main(void)
+{
+       ao_clock_init();
+
+       /* Turn on the LED until the system is stable */
+       ao_led_init(LEDS_AVAILABLE);
+       ao_led_on(AO_LED_RED);
+
+       ao_task_init();
+
+       ao_timer_init();
+       ao_cmd_init();
+       ao_usb_init();
+       ao_monitor_init();
+       ao_radio_init();
+       ao_packet_master_init();
+       ao_adc_init();
+       ao_btm_init();
+       ao_monitor_forward_init();
+       ao_storage_init();
+#if HAS_DBG
+       ao_dbg_init();
+#endif
+       ao_config_init();
+       ao_start_scheduler();
+}
index 30239afccf57bc71377860a837be3e7ddac8a9d8..68bb44eee20fbeacc0c7ee5a1dd5815481d82425 100644 (file)
@@ -62,6 +62,7 @@
        #define HAS_RSSI                0
        #define HAS_AES                 0
        #define HAS_RADIO               1
+       #define HAS_TELEMETRY           0
 #endif
 
 #if DBG_ON_P1
index 1c12c437b8651900b5741aed428bd5ae52f37802..472af53430cfa21dac9e846a0429444562813702 100644 (file)
@@ -71,7 +71,9 @@
        #define HAS_P2_ISR              1
 
        #define BATTERY_PIN             5
-       
+       #define HAS_TELEMETRY           0
+
+       #define AO_VALUE_32             0
 #endif
 
 #if DBG_ON_P1
index 017f7f71788d24fc3fb46a0f675e2fb34e64e084..02e1d22b6c1b502ff92c71a11498084b5ed8c518 100644 (file)
@@ -1,6 +1,7 @@
 vpath % ..:../kernel:../drivers:../util:../micropeak:../aes:../product
 
 PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_flight_test_mm \
+       ao_flight_test_metrum \
        ao_gps_test ao_gps_test_skytraq ao_gps_test_ublox ao_convert_test ao_convert_pa_test ao_fec_test \
        ao_aprs_test ao_micropeak_test ao_fat_test ao_aes_test ao_int64_test \
        ao_ms5607_convert_test ao_quaternion_test
@@ -33,6 +34,9 @@ ao_flight_test_accel: ao_flight_test.c ao_host.h ao_flight.c  ao_sample.c ao_kal
 ao_flight_test_mm: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c ao_pyro.c ao_pyro.h $(INCS)
        cc -DTELEMEGA=1 $(CFLAGS) -o $@ $< -lm
 
+ao_flight_test_metrum: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c ao_pyro.c ao_pyro.h $(INCS)
+       cc -DTELEMETRUM_V2=1 $(CFLAGS) -o $@ $< -lm
+
 ao_gps_test: ao_gps_test.c ao_gps_sirf.c ao_gps_print.c ao_host.h
        cc $(CFLAGS) -o $@ $<
 
index 86cf527ae2f4c7219e376135b357aad327a6f14d..ae505dea77e7e732a81bcc995624ff8adef4b959 100644 (file)
@@ -21,6 +21,8 @@
 #include <stdint.h>
 #include <stdarg.h>
 
+#define HAS_GPS        1
+
 #include <ao_telemetry.h>
 
 #define AO_GPS_NUM_SAT_MASK    (0xf << 0)
@@ -97,41 +99,14 @@ audio_gap(int secs)
 #endif
 }
 
-#include <math.h>
-
-int
-ao_aprs_encode_altitude_expensive(int meters)
-{
-       double  feet = meters / 0.3048;
-
-       double  encode = log(feet) / log(1.002);
-       return floor(encode + 0.5);
-}
-
 // This is where we go after reset.
 int main(int argc, char **argv)
 {
-       int     e, x;
-       int     a;
-
-       for (a = 1; a < 100000; a++) {
-               e = ao_aprs_encode_altitude(a);
-               x = ao_aprs_encode_altitude_expensive(a);
-
-               if (e != x) {
-                       double  back_feet, back_meters;
-                       back_feet = pow(1.002, e);
-                       back_meters = back_feet * 0.3048;
-                       fprintf (stderr, "APRS altitude encoding failure: altitude %d actual %d expected %d actual meters %f\n",
-                                a, e, x, back_meters);
-               }
-       }
-
     audio_gap(1);
 
     ao_gps_data.latitude = (45.0 + 28.25 / 60.0) * 10000000;
     ao_gps_data.longitude = (-(122 + 44.2649 / 60.0)) * 10000000;
-    ao_gps_data.altitude = 84;
+    AO_TELEMETRY_LOCATION_SET_ALTITUDE(&ao_gps_data, 84);
     ao_gps_data.flags = (AO_GPS_VALID|AO_GPS_RUNNING);
 
     /* Transmit one packet */
index 0647fc6c3e97206381af8c6814484216706bd052..8b737ca1e71a9b123f720da3ad5c0b249a91d0c3 100644 (file)
 #define ao_data_ring_next(n)   (((n) + 1) & (AO_DATA_RING - 1))
 #define ao_data_ring_prev(n)   (((n) - 1) & (AO_DATA_RING - 1))
 
+#if 0
 #define AO_M_TO_HEIGHT(m)      ((int16_t) (m))
 #define AO_MS_TO_SPEED(ms)     ((int16_t) ((ms) * 16))
 #define AO_MSS_TO_ACCEL(mss)   ((int16_t) ((mss) * 16))
+#endif
 
 #define AO_GPS_NEW_DATA                1
 #define AO_GPS_NEW_TRACKING    2
 
 int ao_gps_new;
 
+#if !defined(TELEMEGA) && !defined(TELEMETRUM_V2)
+#define TELEMETRUM_V1 1
+#endif
+
 #if TELEMEGA
 #define AO_ADC_NUM_SENSE       6
 #define HAS_MS5607             1
@@ -50,6 +56,7 @@ int ao_gps_new;
 #define HAS_MMA655X            1
 #define HAS_HMC5883            1
 #define HAS_BEEP               1
+#define AO_CONFIG_MAX_SIZE     1024
 
 struct ao_adc {
        int16_t                 sense[AO_ADC_NUM_SENSE];
@@ -57,7 +64,25 @@ struct ao_adc {
        int16_t                 v_pbatt;
        int16_t                 temp;
 };
-#else
+#endif
+
+#if TELEMETRUM_V2
+#define AO_ADC_NUM_SENSE       2
+#define HAS_MS5607             1
+#define HAS_MMA655X            1
+#define HAS_BEEP               1
+#define AO_CONFIG_MAX_SIZE     1024
+
+struct ao_adc {
+       int16_t                 sense_a;
+       int16_t                 sense_m;
+       int16_t                 v_batt;
+       int16_t                 temp;
+};
+#endif
+
+
+#if TELEMETRUM_V1
 /*
  * One set of samples read from the A/D converter
  */
@@ -92,6 +117,7 @@ struct ao_adc {
 #include <ao_data.h>
 #include <ao_log.h>
 #include <ao_telemetry.h>
+#include <ao_sample.h>
 
 #if TELEMEGA
 int ao_gps_count;
@@ -174,7 +200,7 @@ ao_gps_angle(void)
                        ao_gps_static.latitude / 1e7,
                        ao_gps_static.longitude / 1e7,
                        &dist, &bearing);
-       height = ao_gps_static.altitude - ao_gps_prev.altitude;
+       height = AO_TELEMETRY_LOCATION_ALTITUDE(&ao_gps_static) - AO_TELEMETRY_LOCATION_ALTITUDE(&ao_gps_prev);
 
        angle = atan2(dist, height);
        return angle * 180/M_PI;
@@ -185,17 +211,6 @@ ao_gps_angle(void)
 #define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5))
 #define from_fix(x)    ((x) >> 16)
 
-/*
- * Above this height, the baro sensor doesn't work
- */
-#define AO_BARO_SATURATE       13000
-#define AO_MIN_BARO_VALUE      ao_altitude_to_pres(AO_BARO_SATURATE)
-
-/*
- * Above this speed, baro measurements are unreliable
- */
-#define AO_MAX_BARO_SPEED      200
-
 #define ACCEL_NOSE_UP  (ao_accel_2g >> 2)
 
 extern enum ao_flight_state ao_flight_state;
@@ -233,7 +248,7 @@ double      main_time;
 
 int    tick_offset;
 
-static int32_t ao_k_height;
+static ao_k_t  ao_k_height;
 
 int16_t
 ao_time(void)
@@ -305,7 +320,7 @@ struct ao_cmds {
 #define ao_xmemcmp(d,s,c) memcmp(d,s,c)
 
 #define AO_NEED_ALTITUDE_TO_PRES 1
-#if TELEMEGA
+#if TELEMEGA || TELEMETRUM_V2
 #include "ao_convert_pa.c"
 #include <ao_ms5607.h>
 struct ao_ms5607_prom  ao_ms5607_prom;
@@ -455,7 +470,7 @@ ao_insert(void)
 #else
                double  accel = 0.0;
 #endif
-#if TELEMEGA
+#if TELEMEGA || TELEMETRUM_V2
                double  height;
 
                ao_ms5607_convert(&ao_data_static.ms5607_raw, &ao_data_static.ms5607_cooked);
@@ -550,6 +565,7 @@ ao_insert(void)
                                mag_azel.el,
                                mag_azel.az);
 #endif
+#if 0
                        printf ("%7.2f state %-8.8s height %8.4f tilt %4d rot %4d dist %12.2f gps_tilt %4d gps_sats %2d\n",
                                time,
                                ao_state_names[ao_flight_state],
@@ -559,6 +575,7 @@ ao_insert(void)
                                (int) floor (ao_gps_angle() + 0.5),
                                (ao_gps_static.flags & 0xf) * 10);
 
+#endif
 #if 0
                        printf ("\t\tstate %-8.8s ground az: %4d el %4d mag az %4d el %4d rot az %4d el %4d el_diff %4d az_diff %4d angle %4d tilt %4d ground %8.5f %8.5f %8.5f cur %8.5f %8.5f %8.5f rot %8.5f %8.5f %8.5f\n",
                                ao_state_names[ao_flight_state],
@@ -581,9 +598,9 @@ ao_insert(void)
 #endif
 #endif
 
-#if 0
+#if 1
                        printf("%7.2f height %8.2f accel %8.3f "
-#if TELEMEGA
+#if TELEMEGA && 0
                               "angle %5d "
                               "accel_x %8.3f accel_y %8.3f accel_z %8.3f gyro_x %8.3f gyro_y %8.3f gyro_z %8.3f mag_x %8d mag_y %8d, mag_z %8d mag_angle %4d "
 #endif
@@ -591,7 +608,7 @@ ao_insert(void)
                               time,
                               height,
                               accel,
-#if TELEMEGA
+#if TELEMEGA && 0
                               ao_sample_orient,
 
                               ao_mpu6000_accel(ao_data_static.mpu6000.accel_x),
@@ -674,7 +691,8 @@ ao_sleep(void *wchan)
                        {
 #if TELEMEGA
                                ao_data_static.mpu6000 = ao_ground_mpu6000;
-#else
+#endif
+#if TELEMETRUM_V1
                                ao_data_static.adc.accel = ao_flight_ground_accel;
 #endif
                                ao_insert();
@@ -755,7 +773,10 @@ ao_sleep(void *wchan)
                                        ao_gps_static.tick = tick;
                                        ao_gps_static.latitude = int32(bytes, 0);
                                        ao_gps_static.longitude = int32(bytes, 4);
-                                       ao_gps_static.altitude = int32(bytes, 8);
+                                       {
+                                               int32_t altitude = int32(bytes, 8);
+                                               AO_TELEMETRY_LOCATION_SET_ALTITUDE(&ao_gps_static, altitude);
+                                       }
                                        ao_gps_static.flags = bytes[13];
                                        if (!ao_gps_count)
                                                ao_gps_first = ao_gps_static;
@@ -795,11 +816,64 @@ ao_sleep(void *wchan)
                                        pyro->flags |= ao_pyro_values[j].flag;
                                        if (ao_pyro_values[j].offset != NO_VALUE && i + 1 < nword) {
                                                int16_t val = strtoul(words[++i], NULL, 10);
+                                               printf("pyro %d condition %s value %d\n", p, words[i-1], val);
                                                *((int16_t *) ((char *) pyro + ao_pyro_values[j].offset)) = val;
                                        }
                                }
                        }
-#else
+#endif
+#if TELEMETRUM_V2
+                       if (log_format == AO_LOG_FORMAT_TELEMETRUM && nword == 14 && strlen(words[0]) == 1) {
+                               int     i;
+                               struct ao_ms5607_value  value;
+
+                               type = words[0][0];
+                               tick = strtoul(words[1], NULL, 16);
+//                             printf ("%c %04x", type, tick);
+                               for (i = 2; i < nword; i++) {
+                                       bytes[i - 2] = strtoul(words[i], NULL, 16);
+//                                     printf(" %02x", bytes[i-2]);
+                               }
+//                             printf ("\n");
+                               switch (type) {
+                               case 'F':
+                                       ao_flight_ground_accel = int16(bytes, 2);
+                                       ao_flight_started = 1;
+                                       ao_ground_pres = int32(bytes, 4);
+                                       ao_ground_height = ao_pa_to_altitude(ao_ground_pres);
+                                       break;
+                               case 'A':
+                                       ao_data_static.tick = tick;
+                                       ao_data_static.ms5607_raw.pres = int32(bytes, 0);
+                                       ao_data_static.ms5607_raw.temp = int32(bytes, 4);
+                                       ao_ms5607_convert(&ao_data_static.ms5607_raw, &value);
+                                       ao_data_static.mma655x = int16(bytes, 8);
+                                       ao_records_read++;
+                                       ao_insert();
+                                       return;
+                               }
+                               continue;
+                       } else if (nword == 3 && strcmp(words[0], "ms5607") == 0) {
+                               if (strcmp(words[1], "reserved:") == 0)
+                                       ao_ms5607_prom.reserved = strtoul(words[2], NULL, 10);
+                               else if (strcmp(words[1], "sens:") == 0)
+                                       ao_ms5607_prom.sens = strtoul(words[2], NULL, 10);
+                               else if (strcmp(words[1], "off:") == 0)
+                                       ao_ms5607_prom.off = strtoul(words[2], NULL, 10);
+                               else if (strcmp(words[1], "tcs:") == 0)
+                                       ao_ms5607_prom.tcs = strtoul(words[2], NULL, 10);
+                               else if (strcmp(words[1], "tco:") == 0)
+                                       ao_ms5607_prom.tco = strtoul(words[2], NULL, 10);
+                               else if (strcmp(words[1], "tref:") == 0)
+                                       ao_ms5607_prom.tref = strtoul(words[2], NULL, 10);
+                               else if (strcmp(words[1], "tempsens:") == 0)
+                                       ao_ms5607_prom.tempsens = strtoul(words[2], NULL, 10);
+                               else if (strcmp(words[1], "crc:") == 0)
+                                       ao_ms5607_prom.crc = strtoul(words[2], NULL, 10);
+                               continue;
+                       }
+#endif
+#if TELEMETRUM_V1
                        if (nword == 4 && log_format != AO_LOG_FORMAT_TELEMEGA) {
                                type = words[0][0];
                                tick = strtoul(words[1], NULL, 16);
@@ -924,7 +998,7 @@ ao_sleep(void *wchan)
                        if (type != 'F' && !ao_flight_started)
                                continue;
 
-#if TELEMEGA
+#if TELEMEGA || TELEMETRUM_V2
                        (void) a;
                        (void) b;
 #else
@@ -945,8 +1019,6 @@ ao_sleep(void *wchan)
                                ao_data_static.tick = tick;
                                ao_data_static.adc.accel = a;
                                ao_data_static.adc.pres_real = b;
-                               if (b < AO_MIN_BARO_VALUE)
-                                       b = AO_MIN_BARO_VALUE;
                                ao_data_static.adc.pres = b;
                                ao_records_read++;
                                ao_insert();
index e799ab0fc8f0a70e612c72bcbbe6c8c724842a31..543bbcc304b032ab69c6442dbf380ca62d596473 100644 (file)
@@ -53,6 +53,9 @@ struct ao_gps_orig {
        uint16_t                v_error;        /* m */
 };
 
+#define AO_TELEMETRY_LOCATION_ALTITUDE(l)      ((l)->altitude)
+#define AO_TELEMETRY_LOCATION_SET_ALTITUDE(l,a) ((l)->altitude = (a))
+
 #define SIRF_SAT_STATE_ACQUIRED                        (1 << 0)
 #define SIRF_SAT_STATE_CARRIER_PHASE_VALID     (1 << 1)
 #define SIRF_SAT_BIT_SYNC_COMPLETE             (1 << 2)
@@ -433,7 +436,7 @@ ao_dump_state(void *wchan)
 
        if (wchan != &ao_gps_new)
                return;
-       
+
        if (ao_gps_new & AO_GPS_NEW_DATA) {
                ao_gps_print(&ao_gps_data);
                putchar('\n');
index 1b590d5e972a5fff6bce45cf37f069c7f9a492ad..5eb7118d260bdf44e51488f55f23569c5f0d10d6 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #define AO_GPS_TEST
+#define HAS_GPS 1
 #include "ao_host.h"
 #include <termios.h>
 #include <errno.h>
@@ -53,6 +54,9 @@ struct ao_gps_orig {
        uint16_t                v_error;        /* m */
 };
 
+#define AO_TELEMETRY_LOCATION_ALTITUDE(l)      ((l)->altitude)
+#define AO_TELEMETRY_LOCATION_SET_ALTITUDE(l,a) ((l)->altitude = (a))
+
 #define SIRF_SAT_STATE_ACQUIRED                        (1 << 0)
 #define SIRF_SAT_STATE_CARRIER_PHASE_VALID     (1 << 1)
 #define SIRF_SAT_BIT_SYNC_COMPLETE             (1 << 2)
index 4eb4b837d6db7951b947041720f2cba742c62a7f..5ea205d66792fd1e6ce4391cb516a24e6d764859 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #define AO_GPS_TEST
+#define HAS_GPS        1
 #include "ao_host.h"
 #include <termios.h>
 #include <errno.h>
@@ -44,7 +45,7 @@ struct ao_telemetry_location {
        uint8_t                 flags;
        int32_t                 latitude;       /* degrees * 10⁷ */
        int32_t                 longitude;      /* degrees * 10⁷ */
-       int16_t                 altitude;       /* m */
+       int16_t                 altitude_low;   /* m */
        uint16_t                ground_speed;   /* cm/s */
        uint8_t                 course;         /* degrees / 2 */
        uint8_t                 pdop;           /* * 5 */
@@ -53,8 +54,14 @@ struct ao_telemetry_location {
        int16_t                 climb_rate;     /* cm/s */
        uint16_t                h_error;        /* m */
        uint16_t                v_error;        /* m */
+       int16_t                 altitude_high;  /* m */
 };
 
+typedef int32_t                gps_alt_t;
+#define AO_TELEMETRY_LOCATION_ALTITUDE(l)      (((gps_alt_t) (l)->altitude_high << 16) | ((l)->altitude_low))
+#define AO_TELEMETRY_LOCATION_SET_ALTITUDE(l,a) (((l)->altitude_high = (a) >> 16), \
+                                                ((l)->altitude_low = (a)))
+
 #define UBLOX_SAT_STATE_ACQUIRED               (1 << 0)
 #define UBLOX_SAT_STATE_CARRIER_PHASE_VALID    (1 << 1)
 #define UBLOX_SAT_BIT_SYNC_COMPLETE            (1 << 2)
index 5961bd9309ff700782dd639505d5d78acc32b7a6..f4af707e2bd54b68d873ad168915184001173728 100644 (file)
@@ -33,6 +33,7 @@ uint8_t ao_flight_debug;
 #define AO_FLIGHT_TEST
 
 typedef int32_t alt_t;
+typedef int32_t pres_t;
 
 #define AO_MS_TO_TICKS(ms)     ((ms) / 10)
 
index 76af5ee73f190fead49ca9b275382b7c8f44b5aa..7d253ff123ccedaa43b9580adf75544af9d70a87 100755 (executable)
@@ -10,7 +10,7 @@ plot "$1" using 1:3 with lines axes x1y1 title "raw height",\
 "$1" using 1:9 with lines axes x1y1 title "height",\
 "$1" using 1:11 with lines axes x1y2 title "speed",\
 "$1" using 1:13 with lines axes x1y2 title "accel",\
-"$1" using 1:15 with lines axes x1y1 title "drogue",\
-"$1" using 1:17 with lines axes x1y1 title "main",\
-"$1" using 1:19 with lines axes x1y1 title "error"
+"$1" using 1:17 with lines axes x1y1 title "drogue",\
+"$1" using 1:19 with lines axes x1y1 title "main",\
+"$1" using 1:21 with lines axes x1y1 title "error"
 EOF
index 22831d5091e8f3656dd1b7691455d8cacaf55b1a..d36f3f41de942c7726295e83ac12b39a8ca1ab7f 100644 (file)
@@ -185,105 +185,135 @@ line_t best_fit(real[] values, int first, int last) {
        return (line_t) { m = m, b = b };
 }
 
-real   min_Pa = 0;
-real   max_Pa = 120000;
+void print_table (int pa_sample_shift, int pa_part_shift)
+{
+       real    min_Pa = 0;
+       real    max_Pa = 120000;
 
-/* Target is an array of < 1000 entries */
-int pa_sample_shift = 2;
-int pa_part_shift = 6;
-int pa_part_mask = (1 << pa_part_shift) - 1;
+       int pa_part_mask = (1 << pa_part_shift) - 1;
 
-int num_part = ceil(max_Pa / (2 ** (pa_part_shift + pa_sample_shift)));
+       int num_part = ceil(max_Pa / (2 ** (pa_part_shift + pa_sample_shift)));
 
-int num_samples = num_part << pa_part_shift;
+       int num_samples = num_part << pa_part_shift;
 
-real sample_to_Pa(int sample) = sample << pa_sample_shift;
+       real sample_to_Pa(int sample) = sample << pa_sample_shift;
 
-real sample_to_altitude(int sample) = pressure_to_altitude(sample_to_Pa(sample));
+       real sample_to_altitude(int sample) = pressure_to_altitude(sample_to_Pa(sample));
 
-int part_to_sample(int part) = part << pa_part_shift;
+       int part_to_sample(int part) = part << pa_part_shift;
 
-int sample_to_part(int sample) = sample >> pa_part_shift;
+       int sample_to_part(int sample) = sample >> pa_part_shift;
 
-bool is_part(int sample) = (sample & pa_part_mask) == 0;
+       bool is_part(int sample) = (sample & pa_part_mask) == 0;
 
-real[num_samples] alt = { [n] = sample_to_altitude(n) };
+       real[num_samples] alt = { [n] = sample_to_altitude(n) };
 
-int seg_len = 1 << pa_part_shift;
+       int seg_len = 1 << pa_part_shift;
 
-line_t [num_part] fit = {
-       [n] = best_fit(alt, n * seg_len, n * seg_len + seg_len - 1)
-};
-
-real[num_samples/seg_len + 1]  alt_part;
-real[dim(alt_part)]            alt_error = {0...};
-
-alt_part[0] = fit[0].b;
-alt_part[dim(fit)] = fit[dim(fit)-1].m * dim(fit) * seg_len + fit[dim(fit)-1].b;
+       line_t [num_part] fit = {
+               [n] = best_fit(alt, n * seg_len, n * seg_len + seg_len - 1)
+       };
 
-for (int i = 0; i < dim(fit) - 1; i++) {
-       real    here, there;
-       here = fit[i].m * (i+1) * seg_len + fit[i].b;
-       there = fit[i+1].m * (i+1) * seg_len + fit[i+1].b;
-#      printf ("at %d mis-fit %8.2f\n", i, there - here);
-       alt_part[i+1] = (here + there) / 2;
-}
+       real[num_samples/seg_len + 1]   alt_part;
+       real[dim(alt_part)]             alt_error = {0...};
 
-real round(real x) = floor(x + 0.5);
+       alt_part[0] = fit[0].b;
+       alt_part[dim(fit)] = fit[dim(fit)-1].m * dim(fit) * seg_len + fit[dim(fit)-1].b;
 
-real sample_to_fit_altitude(int sample) {
-       int     sub = sample // seg_len;
-       int     off = sample % seg_len;
-       line_t  l = fit[sub];
-       real r_v;
-       real i_v;
+       for (int i = 0; i < dim(fit) - 1; i++) {
+               real    here, there;
+               here = fit[i].m * (i+1) * seg_len + fit[i].b;
+               there = fit[i+1].m * (i+1) * seg_len + fit[i+1].b;
+#              printf ("at %d mis-fit %8.2f\n", i, there - here);
+               alt_part[i+1] = (here + there) / 2;
+       }
 
-       r_v = sample * l.m + l.b;
-       i_v = (round(alt_part[sub]*10) * (seg_len - off) + round(alt_part[sub+1]*10) * off) / seg_len;
-       return i_v/10;
-}
+       real round(real x) = floor(x + 0.5);
 
-real max_error = 0;
-int max_error_sample = 0;
-real total_error = 0;
+       real sample_to_fit_altitude(int sample) {
+               int     sub = sample // seg_len;
+                       int     off = sample % seg_len;
+               line_t  l = fit[sub];
+               real r_v;
+               real i_v;
 
-for (int sample = 0; sample < num_samples; sample++) {
-       real    Pa = sample_to_Pa(sample);
-       real    meters = alt[sample];
+               r_v = sample * l.m + l.b;
+               i_v = (round(alt_part[sub]*10) * (seg_len - off) + round(alt_part[sub+1]*10) * off) / seg_len;
+               return i_v/10;
+       }
 
-       real    meters_approx = sample_to_fit_altitude(sample);
-       real    error = abs(meters - meters_approx);
+       real max_error = 0;
+       int max_error_sample = 0;
+       real total_error = 0;
+
+       for (int sample = 0; sample < num_samples; sample++) {
+               real    Pa = sample_to_Pa(sample);
+               real    meters = alt[sample];
+
+               real    meters_approx = sample_to_fit_altitude(sample);
+               real    error = abs(meters - meters_approx);
+
+               int     part = sample_to_part(sample);
+
+               if (error > alt_error[part])
+                       alt_error[part] = error;
+
+               total_error += error;
+               if (error > max_error) {
+                       max_error = error;
+                       max_error_sample = sample;
+               }
+               if (false) {
+                       printf ("       %8.1f %8.2f %8.2f %8.2f %s\n",
+                               Pa,
+                               meters,
+                               meters_approx,
+                               meters - meters_approx,
+                               is_part(sample) ? "*" : "");
+               }
+       }
 
-       int     part = sample_to_part(sample);
+       printf ("/*max error %f at %7.3f kPa. Average error %f*/\n",
+               max_error, sample_to_Pa(max_error_sample) / 1000, total_error / num_samples);
 
-       if (error > alt_error[part])
-               alt_error[part] = error;
+       printf ("#define NALT %d\n", dim(alt_part));
+       printf ("#define ALT_SHIFT %d\n", pa_part_shift + pa_sample_shift);
+       printf ("#ifndef AO_ALT_VALUE\n#define AO_ALT_VALUE(x) (alt_t) (x)\n#endif\n");
 
-       total_error += error;
-       if (error > max_error) {
-               max_error = error;
-               max_error_sample = sample;
-       }
-       if (false) {
-               printf ("       %8.1f %8.2f %8.2f %8.2f %s\n",
-                       Pa,
-                       meters,
-                       meters_approx,
-                       meters - meters_approx,
-                       is_part(sample) ? "*" : "");
+       for (int part = 0; part < dim(alt_part); part++) {
+               real kPa = sample_to_Pa(part_to_sample(part)) / 1000;
+               printf ("AO_ALT_VALUE(%10.1f), /* %6.2f kPa error %6.2fm */\n",
+                       round (alt_part[part]*10) / 10, kPa,
+                       alt_error[part]);
        }
 }
 
-printf ("/*max error %f at %7.3f kPa. Average error %f*/\n",
-       max_error, sample_to_Pa(max_error_sample) / 1000, total_error / num_samples);
-
-printf ("#define NALT %d\n", dim(alt_part));
-printf ("#define ALT_SHIFT %d\n", pa_part_shift + pa_sample_shift);
-printf ("#ifndef AO_ALT_VALUE\n#define AO_ALT_VALUE(x) (alt_t) (x)\n#endif\n");
-
-for (int part = 0; part < dim(alt_part); part++) {
-       real kPa = sample_to_Pa(part_to_sample(part)) / 1000;
-       printf ("AO_ALT_VALUE(%10.1f), /* %6.2f kPa error %6.2fm */\n",
-               round (alt_part[part]*10) / 10, kPa,
-               alt_error[part]);
+autoload ParseArgs;
+
+void main()
+{
+       /* Target is an array of < 1000 entries */
+       int pa_sample_shift = 2;
+       int pa_part_shift = 6;
+
+       ParseArgs::argdesc argd = {
+               .args = {
+                       { .var = { .arg_int = &pa_sample_shift },
+                         .abbr = 's',
+                         .name = "sample",
+                         .expr_name = "sample_shift",
+                         .desc = "sample shift value" },
+                       { .var = { .arg_int = &pa_part_shift },
+                         .abbr = 'p',
+                         .name = "part",
+                         .expr_name = "part_shift",
+                         .desc = "part shift value" },
+               }
+       };
+
+       ParseArgs::parseargs(&argd, &argv);
+
+       print_table(pa_sample_shift, pa_part_shift);
 }
+
+main();
index edb509f20418f39f6c96a7dc28fcd307a9f63dc3..1af9e0f1e2857f1968da417c7760dc27ced8de8d 100644 (file)
@@ -17,7 +17,7 @@ TeleGPS-Linux-*.tar.bz2
 TeleGPS-Linux-*.sh
 TeleGPS-Mac-*.zip
 TeleGPS-Windows-*.exe
-telegps.desktop
+*.desktop
 telegps-windows.log
 *.dll
 *.dylib
index df05bb6e27fe1c714f6d44674c2cdf2f7f67dfde..89870a8c65db1de604da262113d9a7668ed24610 100644 (file)
        <key>CFBundleInfoDictionaryVersion</key>
        <string>6.0</string>
        <key>CFBundleIconFile</key>
-       <string>TeleGPS.icns</string>
+       <string>altusmetrum-telegps.icns</string>
+       <key>CFBundleDocumentTypes</key>
+       <array>
+         <dict>
+           <key>CFBundleTypeName</key>
+           <string>Telemetry</string>
+           <key>CFBundleTypeIconFile</key>
+           <string>application-vnd.altusmetrum.telemetry.icns</string>
+           <key>CFBundleTypeExtensions</key>
+           <array>
+             <string>telem</string>
+           </array>
+           <key>CFBundleTypeRole</key>
+           <string>Editor</string>
+         </dict>
+         <dict>
+           <key>CFBundleTypeName</key>
+           <string>Eeprom</string>
+           <key>CFBundleTypeIconFile</key>
+           <string>application-vnd.altusmetrum.eeprom.icns</string>
+           <key>CFBundleTypeExtensions</key>
+           <array>
+             <string>eeprom</string>
+           </array>
+           <key>CFBundleTypeRole</key>
+           <string>Editor</string>
+         </dict>
+       </array>
        <key>Java</key>
        <dict>
                <key>MainClass</key>
index 7b550e9eccd00573c9b53be1d8d78045944c2080..3b33428ea6b2f2937fdebb703c081ecdb219c13b 100644 (file)
@@ -58,23 +58,42 @@ ALTOSUILIB_CLASS=\
 ICONDIR=$(top_srcdir)/icon
 
 JAVA_ICONS=\
-       $(ICONDIR)/telegps-16.png \
-       $(ICONDIR)/telegps-32.png \
-       $(ICONDIR)/telegps-48.png \
-       $(ICONDIR)/telegps-64.png \
-       $(ICONDIR)/telegps-128.png \
-       $(ICONDIR)/telegps-256.png
+       $(ICONDIR)/altusmetrum-telegps-16.png \
+       $(ICONDIR)/altusmetrum-telegps-32.png \
+       $(ICONDIR)/altusmetrum-telegps-48.png \
+       $(ICONDIR)/altusmetrum-telegps-64.png \
+       $(ICONDIR)/altusmetrum-telegps-128.png\
+       $(ICONDIR)/altusmetrum-telegps-256.png
 
 # icon base names for jar
-ICONJAR= -C $(ICONDIR) telegps-16.png \
-       -C $(ICONDIR) telegps-32.png \
-       -C $(ICONDIR) telegps-48.png \
-       -C $(ICONDIR) telegps-64.png \
-       -C $(ICONDIR) telegps-128.png \
-       -C $(ICONDIR) telegps-256.png
-
-WINDOWS_ICON=$(ICONDIR)/telegps.ico
-MACOSX_ICON=$(ICONDIR)/TeleGPS.icns
+ICONJAR= \
+       -C $(ICONDIR) altusmetrum-telegps-16.png \
+       -C $(ICONDIR) altusmetrum-telegps-32.png \
+       -C $(ICONDIR) altusmetrum-telegps-48.png \
+       -C $(ICONDIR) altusmetrum-telegps-64.png \
+       -C $(ICONDIR) altusmetrum-telegps-128.png\
+       -C $(ICONDIR) altusmetrum-telegps-256.png
+
+WINDOWS_ICONS  =\
+       ../icon/altusmetrum-telegps.ico \
+       ../icon/altusmetrum-telegps.exe
+       ../icon/application-vnd.altusmetrum.eeprom.ico \
+       ../icon/application-vnd.altusmetrum.eeprom.exe \
+       ../icon/application-vnd.altusmetrum.telemetry.ico \
+       ../icon/application-vnd.altusmetrum.telemetry.exe
+
+MACOSX_ICONS   =\
+       ../icon/altusmetrum-telegps.icns \
+       ../icon/application-vnd.altusmetrum.eeprom.icns \
+       ../icon/application-vnd.altusmetrum.telemetry.icns
+
+LINUX_ICONS    =\
+       $(ICONDIR)/altusmetrum-altosui.svg \
+       $(ICONDIR)/application-vnd.altusmetrum.eeprom.svg \
+       $(ICONDIR)/application-vnd.altusmetrum.telemetry.svg
+
+LINUX_MIMETYPE =\
+       $(ICONDIR)/org-altusmetrum-mimetypes.xml
 
 # Firmware
 FIRMWARE_TD_0_2=$(top_srcdir)/src/teledongle-v0.2/teledongle-v0.2-$(VERSION).ihx
@@ -89,7 +108,7 @@ FIRMWARE_TG=$(FIRMWARE_TG_1_0)
 FIRMWARE=$(FIRMWARE_TG) $(FIRMWARE_TD) $(FIRMWARE_TBT)
 
 desktopdir = $(datadir)/applications
-desktop_file = telegps.desktop
+desktop_file = altusmetrum-telegps.desktop
 desktop_SCRIPTS = $(desktop_file)
 
 all-local: telegps-test telegps-jdb $(JAR)
@@ -101,12 +120,12 @@ clean-local:
                $(ALTOSUILIB_CLASS) \
                $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) Manifest.txt Manifest-fat.txt \
                telegps telegps-test telegps-jdb macosx linux windows telegps-windows.log \
-               telegps-windows.nsi
+               telegps-windows.nsi *.desktop
 
 EXTRA_DIST = $(desktop_file).in
 
 $(desktop_file): $(desktop_file).in
-       sed -e 's#%bindir%#@bindir@#' -e 's#%icondir%#$(datadir)/icons/hicolor/scalable/apps#' ${srcdir}/telegps.desktop.in > $@
+       sed -e 's#%bindir%#@bindir@#' -e 's#%icondir%#$(datadir)/icons/hicolor/scalable/apps#' ${srcdir}/$(desktop_file).in > $@
        chmod +x $@
 
 LINUX_DIST=TeleGPS-Linux-$(VERSION).tar.bz2
@@ -120,15 +139,15 @@ DOC=$(TELEGPS_DOC)
 
 FAT_FILES=$(FATJAR) $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) $(FREETTS_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS)
 
-LINUX_FILES=$(FAT_FILES) libaltos.so $(FIRMWARE) $(DOC) telegps.desktop.in ../icon/telegps.svg
-LINUX_EXTRA=telegps-fat telegps.desktop.in
+LINUX_FILES=$(FAT_FILES) libaltos.so $(FIRMWARE) $(DOC) $(desktop_file).in $(LINUX_ICONS) $(LINUX_MIMETYPE)
+LINUX_EXTRA=telegps-fat $(desktop_file).in
 
 MACOSX_INFO_PLIST=Info.plist
 MACOSX_README=ReadMe-Mac.rtf
-MACOSX_FILES=$(FAT_FILES) libaltos.dylib $(MACOSX_INFO_PLIST) $(MACOSX_README) $(DOC) $(MACOSX_ICON)
+MACOSX_FILES=$(FAT_FILES) libaltos.dylib $(MACOSX_INFO_PLIST) $(MACOSX_README) $(DOC) $(MACOSX_ICONS)
 MACOSX_EXTRA=$(FIRMWARE)
 
-WINDOWS_FILES=$(FAT_FILES) altos.dll altos64.dll $(top_srcdir)/altusmetrum.inf $(top_srcdir)/altusmetrum.cat $(DOC) $(WINDOWS_ICON)
+WINDOWS_FILES=$(FAT_FILES) altos.dll altos64.dll $(top_srcdir)/altusmetrum.inf $(top_srcdir)/altusmetrum.cat $(DOC) $(WINDOWS_ICONS)
 
 if FATINSTALL
 
@@ -194,8 +213,6 @@ $(FATJAR): classtelegps.stamp Manifest-fat.txt $(ALTOSLIB_CLASS) $(ALTOSUILIB_CL
                -C classes org \
                -C ../libaltos libaltosJNI
 
-classaltosui.stamp: $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS)
-
 libaltos.so: build-libaltos
        -rm -f "$@"
        $(LN_S) ../libaltos/.libs/"$@" .
@@ -269,7 +286,7 @@ $(MACOSX_DIST): $(MACOSX_FILES) $(MACOSX_EXTRA) Makefile
        cp -a $(DOC) macosx/Doc
        cp -p Info.plist macosx/TeleGPS.app/Contents
        mkdir -p macosx/AltOS-$(VERSION) macosx/TeleGPS.app/Contents/Resources/Java
-       cp -p $(MACOSX_ICON) macosx/TeleGPS.app/Contents/Resources
+       cp -p $(MACOSX_ICONS) macosx/TeleGPS.app/Contents/Resources
        cp -p $(FATJAR) macosx/TeleGPS.app/Contents/Resources/Java/telegps.jar
        cp -p libaltos.dylib macosx/TeleGPS.app/Contents/Resources/Java
        cp -p $(ALTOSLIB_CLASS) macosx/TeleGPS.app/Contents/Resources/Java
index 6e68dd30e5087451d69702a656bddeb2e25bc955..a4b221e814b5444df1630fb46cd82fb15273b580 100644 (file)
@@ -23,8 +23,8 @@ import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
 import java.util.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class TeleGPS
        extends AltosUIFrame
@@ -32,12 +32,12 @@ public class TeleGPS
 {
 
        static String[] telegps_icon_names = {
-               "/telegps-16.png",
-               "/telegps-32.png",
-               "/telegps-48.png",
-               "/telegps-64.png",
-               "/telegps-128.png",
-               "/telegps-256.png"
+               "/altusmetrum-telegps-16.png",
+               "/altusmetrum-telegps-32.png",
+               "/altusmetrum-telegps-48.png",
+               "/altusmetrum-telegps-64.png",
+               "/altusmetrum-telegps-128.png",
+               "/altusmetrum-telegps-256.png"
        };
 
        static { set_icon_names(telegps_icon_names); }
@@ -58,8 +58,10 @@ public class TeleGPS
        JMenu                   file_menu;
        JMenu                   monitor_menu;
        JMenu                   device_menu;
-       AltosFreqList           frequencies;
+       AltosUIFreqList         frequencies;
        ActionListener          frequency_listener;
+       AltosUIRateList         rates;
+       ActionListener          rate_listener;
 
        Container               bag;
 
@@ -184,6 +186,7 @@ public class TeleGPS
 
                telegps_status.disable_receive();
                disable_frequency_menu();
+               disable_rate_menu();
        }
 
        void connect(AltosDevice device) {
@@ -364,6 +367,40 @@ public class TeleGPS
 
        }
 
+       void enable_rate_menu(int serial, final AltosFlightReader reader) {
+
+               if (rate_listener != null)
+                       disable_rate_menu();
+
+               rate_listener = new ActionListener() {
+                               public void actionPerformed(ActionEvent e) {
+                                       int rate = rates.rate();
+                                       try {
+                                               System.out.printf("set rate %d\n", rate);
+                                               reader.set_telemetry_rate(rate);
+                                       } catch (TimeoutException te) {
+                                       } catch (InterruptedException ie) {
+                                       }
+                                       reader.save_telemetry_rate();
+                               }
+                       };
+
+               rates.addActionListener(rate_listener);
+               rates.set_product("Monitor");
+               rates.set_serial(serial);
+               rates.set_rate(AltosUIPreferences.telemetry_rate(serial));
+               rates.setEnabled(reader.supports_telemetry_rate(AltosLib.ao_telemetry_rate_2400));
+       }
+
+       void disable_rate_menu() {
+               if (rate_listener != null) {
+                       rates.removeActionListener(rate_listener);
+                       rates.setEnabled(false);
+                       rate_listener = null;
+               }
+
+       }
+
        public void set_reader(AltosFlightReader reader, AltosDevice device) {
                status_update = new TeleGPSStatusUpdate(telegps_status);
 
@@ -374,8 +411,10 @@ public class TeleGPS
                thread = new TeleGPSDisplayThread(this, voice(), this, reader);
                thread.start();
 
-               if (device != null)
+               if (device != null) {
                        enable_frequency_menu(device.getSerial(), reader);
+                       enable_rate_menu(device.getSerial(), reader);
+               }
        }
 
        static int      number_of_windows;
@@ -409,16 +448,38 @@ public class TeleGPS
 
        private JMenu make_menu(String label, String[][] items) {
                JMenu   menu = new JMenu(label);
-               for (int i = 0; i < items.length; i++)
+               for (int i = 0; i < items.length; i++) {
+                       if (MAC_OS_X) {
+                               if (items[i][1].equals("exit"))
+                                       continue;
+                               if (items[i][1].equals("preferences"))
+                                       continue;
+                       }
                        add_menu(menu, items[i][0], items[i][1]);
+               }
                menu_bar.add(menu);
                return menu;
        }
 
+       /* OSXAdapter interfaces */
+       public void macosx_file_handler(String path) {
+               process_graph(new File(path));
+       }
+
+       public void macosx_quit_handler() {
+               System.exit(0);
+       }
+
+       public void macosx_preferences_handler() {
+               preferences();
+       }
+
        public TeleGPS() {
 
                AltosUIPreferences.set_component(this);
 
+               register_for_macosx_events();
+
                reader = null;
 
                bag = getContentPane();
@@ -434,9 +495,26 @@ public class TeleGPS
                file_menu = make_menu("File", file_menu_entries);
                monitor_menu = make_menu("Monitor", monitor_menu_entries);
                device_menu = make_menu("Device", device_menu_entries);
-               frequencies = new AltosFreqList();
+
+               frequencies = new AltosUIFreqList();
                frequencies.setEnabled(false);
-               menu_bar.add(frequencies);
+               c.gridx = 0;
+               c.gridy = 0;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.WEST;
+               c.weightx = 0;
+               c.gridwidth = 1;
+               bag.add(frequencies, c);
+
+               rates = new AltosUIRateList();
+               rates.setEnabled(false);
+               c.gridx = 1;
+               c.gridy = 0;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.WEST;
+               c.weightx = 0;
+               c.gridwidth = 1;
+               bag.add(rates, c);
 
                displays = new LinkedList<AltosFlightDisplay>();
 
index 3505b0bb643ba186cb51cdbdf9b568ccfa817970..e607a5a5510f0c52e173ca2fa9756c55d5fd7729 100644 (file)
@@ -22,8 +22,8 @@ import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
 import java.text.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class TeleGPSConfig implements ActionListener {
 
index 5f269fd30e2e126ea85a8c2677da0d67a3af6101..7a59bf48a6c8e05571de73286cdc0dc96eba3299 100644 (file)
@@ -21,8 +21,8 @@ import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
 import javax.swing.event.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class TeleGPSConfigUI
        extends AltosUIDialog
@@ -37,7 +37,9 @@ public class TeleGPSConfigUI
        JLabel                  radio_calibration_label;
        JLabel                  radio_frequency_label;
        JLabel                  radio_enable_label;
+       JLabel                  rate_label;
        JLabel                  aprs_interval_label;
+       JLabel                  aprs_ssid_label;
        JLabel                  flight_log_max_label;
        JLabel                  callsign_label;
        JLabel                  tracker_motion_label;
@@ -49,10 +51,12 @@ public class TeleGPSConfigUI
        JLabel                  product_value;
        JLabel                  version_value;
        JLabel                  serial_value;
-       AltosFreqList           radio_frequency_value;
+       AltosUIFreqList         radio_frequency_value;
        JTextField              radio_calibration_value;
        JRadioButton            radio_enable_value;
+       AltosUIRateList         rate_value;
        JComboBox<String>       aprs_interval_value;
+       JComboBox<Integer>      aprs_ssid_value;
        JComboBox<String>       flight_log_max_value;
        JTextField              callsign_value;
        JComboBox<String>       tracker_motion_value;
@@ -72,6 +76,10 @@ public class TeleGPSConfigUI
                "10"
        };
 
+       static Integer[]        aprs_ssid_values = {
+               0, 1, 2 ,3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+       };
+
        static String[]         tracker_motion_values_m = {
                "2",
                "5",
@@ -141,6 +149,13 @@ public class TeleGPSConfigUI
                        radio_enable_value.setToolTipText("Firmware version does not support disabling radio");
        }
 
+       void set_rate_tool_tip() {
+               if (rate_value.isEnabled())
+                       rate_value.setToolTipText("Select telemetry baud rate");
+               else
+                       rate_value.setToolTipText("Firmware version does not support variable telemetry rates");
+       }
+
        void set_aprs_interval_tool_tip() {
                if (aprs_interval_value.isEnabled())
                        aprs_interval_value.setToolTipText("Enable APRS and set the interval between APRS reports");
@@ -148,6 +163,15 @@ public class TeleGPSConfigUI
                        aprs_interval_value.setToolTipText("Hardware doesn't support APRS");
        }
 
+       void set_aprs_ssid_tool_tip() {
+               if (aprs_ssid_value.isEnabled())
+                       aprs_interval_value.setToolTipText("Set the APRS SSID (secondary station identifier)");
+               else if (aprs_interval_value.isEnabled())
+                       aprs_interval_value.setToolTipText("Software version doesn't support setting the APRS SSID");
+               else
+                       aprs_interval_value.setToolTipText("Hardware doesn't support APRS");
+       }
+
        void set_flight_log_max_tool_tip() {
                if (flight_log_max_value.isEnabled())
                        flight_log_max_value.setToolTipText("Size reserved for each flight log (in kB)");
@@ -255,7 +279,7 @@ public class TeleGPSConfigUI
                c.anchor = GridBagConstraints.LINE_START;
                c.insets = ir;
                c.ipady = 5;
-               radio_frequency_value = new AltosFreqList();
+               radio_frequency_value = new AltosUIFreqList();
                radio_frequency_value.addItemListener(this);
                pane.add(radio_frequency_value, c);
                radio_frequency_value.setToolTipText("Telemetry, RDF and packet frequency");
@@ -311,6 +335,31 @@ public class TeleGPSConfigUI
                set_radio_enable_tool_tip();
                row++;
 
+               /* Telemetry Rate */
+               c = new GridBagConstraints();
+               c.gridx = 0; c.gridy = row;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = il;
+               c.ipady = 5;
+               rate_label = new JLabel("Telemetry baud rate:");
+               pane.add(radio_enable_label, c);
+
+               c = new GridBagConstraints();
+               c.gridx = 4; c.gridy = row;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.weightx = 1;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = ir;
+               c.ipady = 5;
+               rate_value = new AltosUIRateList();
+               rate_value.addItemListener(this);
+               pane.add(rate_value, c);
+               set_rate_tool_tip();
+               row++;
+
                /* APRS interval */
                c = new GridBagConstraints();
                c.gridx = 0; c.gridy = row;
@@ -337,6 +386,33 @@ public class TeleGPSConfigUI
                set_aprs_interval_tool_tip();
                row++;
 
+               /* APRS SSID */
+               c = new GridBagConstraints();
+               c.gridx = 0; c.gridy = row;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = il;
+               c.ipady = 5;
+               aprs_ssid_label = new JLabel("APRS SSID:");
+               pane.add(aprs_ssid_label, c);
+
+               c = new GridBagConstraints();
+               c.gridx = 4; c.gridy = row;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.weightx = 1;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = ir;
+               c.ipady = 5;
+               aprs_ssid_value = new JComboBox<Integer>(aprs_ssid_values);
+               aprs_ssid_value.setEditable(false);
+               aprs_ssid_value.addItemListener(this);
+               aprs_ssid_value.setMaximumRowCount(aprs_ssid_values.length);
+               pane.add(aprs_ssid_value, c);
+               set_aprs_ssid_tool_tip();
+               row++;
+
                /* Callsign */
                c = new GridBagConstraints();
                c.gridx = 0; c.gridy = row;
@@ -566,12 +642,16 @@ public class TeleGPSConfigUI
        }
 
        public void units_changed(boolean imperial_units) {
+               boolean was_dirty = dirty;
+
                if (tracker_motion_value.isEnabled()) {
                        String motion = tracker_motion_value.getSelectedItem().toString();
                        tracker_motion_label.setText(get_tracker_motion_label());
                        set_tracker_motion_values();
                        set_tracker_motion((int) (AltosConvert.height.parse(motion, !imperial_units) + 0.5));
                }
+               if (!was_dirty)
+                       set_clean();
        }
 
        /* set and get all of the dialog values */
@@ -590,6 +670,9 @@ public class TeleGPSConfigUI
                serial_value.setText(String.format("%d", serial));
        }
 
+       public void set_altitude_32(int altitude_32) {
+       }
+
        public void set_main_deploy(int new_main_deploy) {
        }
 
@@ -657,6 +740,14 @@ public class TeleGPSConfigUI
                        return -1;
        }
 
+       public void set_telemetry_rate(int new_rate) {
+               rate_value.set_rate(new_rate);
+       }
+
+       public int telemetry_rate() {
+               return rate_value.rate();
+       }
+
        public void set_callsign(String new_callsign) {
                callsign_value.setVisible(new_callsign != null);
                callsign_value.setText(new_callsign);
@@ -748,7 +839,12 @@ public class TeleGPSConfigUI
        }
 
        public void set_tracker_motion(int tracker_motion) {
-               tracker_motion_value.setSelectedItem(AltosConvert.height.say(tracker_motion));
+               if (tracker_motion < 0) {
+                       tracker_motion_value.setEnabled(false);
+               } else {
+                       tracker_motion_value.setEnabled(true);
+                       tracker_motion_value.setSelectedItem(AltosConvert.height.say(tracker_motion));
+               }
        }
 
        public int tracker_motion() throws AltosConfigDataException {
@@ -756,7 +852,12 @@ public class TeleGPSConfigUI
        }
 
        public void set_tracker_interval(int tracker_interval) {
-               tracker_interval_value.setSelectedItem(String.format("%d", tracker_interval));
+               if (tracker_interval< 0) {
+                       tracker_interval_value.setEnabled(false);
+               } else {
+                       tracker_interval_value.setEnabled(true);
+                       tracker_interval_value.setSelectedItem(String.format("%d", tracker_interval));
+               }
        }
 
        public int tracker_interval() throws AltosConfigDataException {
@@ -782,4 +883,15 @@ public class TeleGPSConfigUI
                        return 0;
                return parse_int("aprs interval", s, false);
        }
+
+       public void set_aprs_ssid(int new_aprs_ssid) {
+               aprs_ssid_value.setSelectedItem(Math.max(0,new_aprs_ssid));
+               aprs_ssid_value.setVisible(new_aprs_ssid >= 0);
+               set_aprs_ssid_tool_tip();
+       }
+
+       public int aprs_ssid() throws AltosConfigDataException {
+               Integer i = (Integer) aprs_ssid_value.getSelectedItem();
+               return i;
+       }
 }
index a3d4ea079caedbbadcf8c0cc4c620533dcb3ec0e..18b8d9fcd7fe29d0bd086756da27b8277286b07c 100644 (file)
@@ -21,8 +21,8 @@ import java.awt.*;
 import javax.swing.*;
 import java.io.*;
 import java.text.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class TeleGPSDisplayThread extends Thread {
 
index 244eb7b9e11fee7112ffa78a030f7fac3cb17c79..b59b122cd4faa11d377e78c9cfec3787082c7247 100644 (file)
@@ -26,8 +26,8 @@ import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
 import java.util.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 import org.jfree.chart.ChartPanel;
 import org.jfree.chart.JFreeChart;
index e87fea90317a2f7a91f3568a66b65888feba2602..1b4751b924c35dba49ecb491471473ce0fecd1ba 100644 (file)
@@ -21,8 +21,8 @@ import java.util.*;
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class TeleGPSInfo extends AltosUIFlightTab {
 
index 8bd371f4b86eb589955ead56ce9180fb220375d5..2738ceea687084ebffb7d1337026866b94f3a609 100644 (file)
@@ -22,7 +22,7 @@ import java.awt.event.*;
 import java.beans.*;
 import javax.swing.*;
 import javax.swing.event.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class TeleGPSPreferences
        extends AltosUIConfigure
index a76182ed0e74c07bedcf9752822f11cf2c84b443..27321c73b3566ebe7428d040ac025baa24ae9f24 100644 (file)
@@ -21,8 +21,8 @@ import java.util.*;
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class TeleGPSState extends AltosUIFlightTab {
 
index f3951a37544dbc80d900024f3d78adb87adf49df..1d4415d6064d400444891ea769c3a0643a3ac0ea 100644 (file)
@@ -19,8 +19,8 @@ package org.altusmetrum.telegps;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
 
 public class TeleGPSStatus extends JComponent implements AltosFlightDisplay {
        GridBagLayout   layout;
index e7684d88f86c46eea427070014ee6e58a1576bca..3d2b7f348670f30cbdad7caff44432936d9b12f4 100644 (file)
@@ -18,7 +18,7 @@
 package org.altusmetrum.telegps;
 
 import java.awt.event.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
 
 public class TeleGPSStatusUpdate implements ActionListener {
 
diff --git a/telegps/altusmetrum-telegps.desktop.in b/telegps/altusmetrum-telegps.desktop.in
new file mode 100644 (file)
index 0000000..7a1b353
--- /dev/null
@@ -0,0 +1,10 @@
+[Desktop Entry]
+Type=Application
+Name=TeleGPS
+GenericName=TeleGPS monitor, download and analysis
+Comment=View and log data from TeleGPS tracking devices
+Icon=%icondir%/altusmetrum-telegps.svg
+Exec=%bindir%/telegps %f
+Terminal=false
+MimeType=application/vnd.altusmetrum.telemetry;application/vnd.altusmetrum.eeprom
+Categories=Education;Electronics;Science;
index b41455206532d5152840c88be662d70e5a598f9e..603d4971faf6ca5e93d2a01340790c665367092a 100644 (file)
@@ -2,14 +2,24 @@
 !addincludedir ../altosui/Instdrv/NSIS/Includes
 !include x64.nsh
 !include java.nsh
+!include refresh-sh.nsh
 
-Name "TeleGPS Installer"
+!define REG_NAME       "TeleGPS"
+!define PROG_ID_TELEM  "altusmetrum.telegps.telem.1"
+!define PROG_ID_EEPROM "altusmetrum.telegps.eeprom.1"
+!define FAT_NAME       "telegps-fat.jar"
+!define WIN_APP_ICON   "altusmetrum-telegps.ico"
+!define WIN_APP_EXE    "altusmetrum-telegps.exe"
+!define WIN_TELEM_EXE  "application-vnd.altusmetrum.telemetry.exe"
+!define WIN_EEPROM_EXE "application-vnd.altusmetrum.eeprom.exe"
+
+Name "${REG_NAME} Installer"
 
 ; Default install directory
 InstallDir "$PROGRAMFILES\AltusMetrum"
 
 ; Tell the installer where to re-install a new version
-InstallDirRegKey HKLM "Software\AltusMetrum" "Install_Dir"
+InstallDirRegKey HKLM "Software\${REG_NAME}" "Install_Dir"
 
 LicenseText "GNU General Public License Version 2"
 LicenseData "../COPYING"
@@ -19,7 +29,7 @@ RequestExecutionLevel admin
 
 ShowInstDetails Show
 
-ComponentText "TeleGPS Software Installer"
+ComponentText "${REG_NAME} Software and Driver Installer"
 
 Function .onInit
        DetailPrint "Checking host operating system"
@@ -31,6 +41,16 @@ Function .onInit
        ${EndIf}
 FunctionEnd
 
+Function un.onInit
+       DetailPrint "Checking host operating system"
+       ${If} ${RunningX64}
+               DetailPrint "Installer running on 64-bit host"
+               SetRegView 64
+               StrCpy $INSTDIR "$PROGRAMFILES64\AltusMetrum"
+               ${DisableX64FSRedirection}
+       ${EndIf}
+FunctionEnd
+
 ; Pages to present
 
 Page license
@@ -66,12 +86,12 @@ done:
 
 SectionEnd
 
-Section "TeleGPS Application"
+Section "${REG_NAME} Application"
        Call DetectJRE
 
        SetOutPath $INSTDIR
 
-       File "telegps-fat.jar"
+       File "${FAT_NAME}"
        File "altoslib_@ALTOSLIB_VERSION@.jar"
        File "altosuilib_@ALTOSUILIB_VERSION@.jar"
        File "cmudict04.jar"
@@ -86,13 +106,13 @@ Section "TeleGPS Application"
 
        File "*.dll"
 
-       File "../icon/*.ico"
+       File "../icon/${WIN_APP_ICON}"
 
-       CreateShortCut "$SMPROGRAMS\TeleGPS.lnk" "$SYSDIR\javaw.exe" "-jar telegps-fat.jar" "$INSTDIR\telegps.ico"
+       CreateShortCut "$SMPROGRAMS\${REG_NAME}.lnk" "$SYSDIR\javaw.exe" "-jar ${FAT_NAME}" "$INSTDIR\${WIN_APP_ICON}"
 SectionEnd
 
-Section "TeleGPS Desktop Shortcut"
-       CreateShortCut "$DESKTOP\TeleGPS.lnk" "$INSTDIR\telegps-fat.jar"  "" "$INSTDIR\telegps.ico"
+Section "${REG_NAME} Desktop Shortcut"
+       CreateShortCut "$DESKTOP\${REG_NAME}.lnk" "$INSTDIR\${FAT_NAME}"  "" "$INSTDIR\${WIN_APP_ICON}"
 SectionEnd
 
 Section "TeleGPS, TeleDongle and TeleBT Firmware"
@@ -114,38 +134,105 @@ Section "Documentation"
        File "../doc/telemetry.pdf"
 SectionEnd
 
+Section "File Associations"
+
+       ${DisableX64FSRedirection}
+
+       SetOutPath $INSTDIR
+
+       File "../icon/${WIN_APP_EXE}"
+       File "../icon/${WIN_TELEM_EXE}"
+       File "../icon/${WIN_EEPROM_EXE}"
+
+       DeleteRegKey HKCR "${PROG_ID_TELEM}"
+       DeleteRegKey HKCR "${PROG_ID_EEPROM}"
+
+       DeleteRegKey   HKCR ".eeprom\${PROG_ID_EEPROM}"
+       DeleteRegValue HKCR ".eeprom\OpenWithProgids" "${PROG_ID_EEPROM}"
+       DeleteRegKey   HKCR ".telem\${PROG_ID_EEPROM}"
+       DeleteRegValue HKCR ".telem\OpenWithProgids" "${PROG_ID_EEPROM}"
+
+       ; .eeprom elements
+
+       WriteRegStr HKCR "${PROG_ID_EEPROM}"            ""                              "Altus Metrum Log File"
+       WriteRegStr HKCR "${PROG_ID_EEPROM}"            "FriendlyTypeName"              "Altus Metrum Log File"
+       WriteRegStr HKCR "${PROG_ID_EEPROM}\CurVer"     ""                              "${PROG_ID_EEPROM}"
+       WriteRegStr HKCR "${PROG_ID_EEPROM}\DefaultIcon" ""                             '"$INSTDIR\${WIN_EEPROM_EXE}",-101'
+  WriteRegExpandStr HKCR "${PROG_ID_EEPROM}\shell\open\command" ""                     '"%SYSTEMROOT%\System32\javaw.exe" -Djava.library.path="$INSTDIR" -jar "$INSTDIR\${FAT_NAME}" "%1"'
+
+       WriteRegStr HKCR ".eeprom"                      ""                              "${PROG_ID_EEPROM}"
+       WriteRegStr HKCR ".eeprom"                      "PerceivedType"                 "Altus Metrum Log File"
+       WriteRegStr HKCR ".eeprom"                      "Content Type"                  "application/vnd.altusmetrum.eeprom"
+
+       WriteRegStr HKCR ".eeprom\OpenWithProgids"      "${PROG_ID_EEPROM}"             ""
+       WriteRegStr HKCR ".eeprom\${PROG_ID_EEPROM}"    ""                              "${REG_NAME}"
+       
+       ; .telem elements
+       
+       WriteRegStr HKCR "${PROG_ID_TELEM}"             ""                              "Altus Metrum Telemetry File"
+       WriteRegStr HKCR "${PROG_ID_TELEM}"             "FriendlyTypeName"              "Altus Metrum Telemetry File"
+       WriteRegStr HKCR "${PROG_ID_TELEM}\CurVer"      ""                              "${PROG_ID_TELEM}"
+       WriteRegStr HKCR "${PROG_ID_TELEM}\DefaultIcon" ""                              '"$INSTDIR\${WIN_TELEM_EXE}",-101'
+  WriteRegExpandStr HKCR "${PROG_ID_TELEM}\shell\open\command" ""                      '"%SYSTEMROOT%\System32\javaw.exe" -Djava.library.path="$INSTDIR" -jar "$INSTDIR\${FAT_NAME}" "%1"'
+
+       WriteRegStr HKCR ".telem"                       ""                              "${PROG_ID_TELEM}"
+       WriteRegStr HKCR ".telem"                       "PerceivedType"                 "Altus Metrum Telemetry File"
+       WriteRegStr HKCR ".telem"                       "Content Type"                  "application/vnd.altusmetrum.telemetry"
+
+       WriteRegStr HKCR ".telem\OpenWithProgids"       "${PROG_ID_TELEM}"              ""
+       WriteRegStr HKCR ".telem\${PROG_ID_TELEM}"      ""                              "${REG_NAME}"
+
+       Call RefreshShellIcons
+SectionEnd
+       
 Section "Uninstaller"
 
        ; Deal with the uninstaller
 
+       ${DisableX64FSRedirection}
        SetOutPath $INSTDIR
 
        ; Write the install path to the registry
-       WriteRegStr HKLM SOFTWARE\AltusMetrum "Install_Dir" "$INSTDIR"
+       WriteRegStr HKLM "SOFTWARE\${REG_NAME}" "Install_Dir" "$INSTDIR"
 
        ; Write the uninstall keys for windows
-       WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "DisplayName" "Altus Metrum"
-       WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "UninstallString" '"$INSTDIR\uninstall.exe"'
-       WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "NoModify" "1"
-       WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "NoRepair" "1"
+       WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "DisplayName" "${REG_NAME}"
+       WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "UninstallString" '"$INSTDIR\uninstall-${REG_NAME}.exe"'
+       WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "NoModify" "1"
+       WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "NoRepair" "1"
 
-       WriteUninstaller "uninstall.exe"
+       WriteUninstaller "uninstall-${REG_NAME}.exe"
 SectionEnd
 
 Section "Uninstall"
-       DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum"
-       DeleteRegKey HKLM "Software\AltusMetrum"
 
-       Delete "$INSTDIR\*.*"
-       RMDir "$INSTDIR"
+       ${DisableX64FSRedirection}
 
-       ; Remove devices
-       InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} AltusMetrumSerial
-       InstDrv::DeleteOemInfFiles /NOUNLOAD
-       InstDrv::RemoveAllDevices
+       DeleteRegKey   HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}"
+       DeleteRegKey   HKLM "SOFTWARE\${REG_NAME}"
+
+       DetailPrint "Delete uninstall reg entries"
+
+       DeleteRegKey   HKCR "${PROG_ID_EEPROM}"
+       DeleteRegKey   HKCR "${PROG_ID_TELEM}"
+
+       DeleteRegKey   HKCR ".eeprom\${PROG_ID_EEPROM}"
+       DeleteRegValue HKCR ".eeprom\OpenWithProgids" "${PROG_ID_EEPROM}"
+
+       DeleteRegKey   HKCR ".telem\${PROG_ID_TELEM}"
+       DeleteRegValue HKCR ".telem\OpenWithProgids" "${PROG_ID_TELEM}"
+
+       DetailPrint "Delete file association reg entries"
+
+       Delete "$INSTDIR\${FAT_NAME}"
+       Delete "$INSTDIR\uninstall-${REG_NAME}.exe"
+
+       Delete "$INSTDIR\${WIN_APP_ICON}"
+       Delete "$INSTDIR\${WIN_APP_EXE}"
 
        ; Remove shortcuts, if any
-       Delete "$SMPROGRAMS\TeleGPS.lnk"
-       Delete "$DESKTOP\TeleGPS.lnk"
+       Delete "$SMPROGRAMS\${REG_NAME}.lnk"
+       Delete "$DESKTOP\${REG_NAME}.lnk"
        
+       Call un.RefreshShellIcons
 SectionEnd
diff --git a/telegps/telegps.desktop.in b/telegps/telegps.desktop.in
deleted file mode 100644 (file)
index 3d249d8..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-[Desktop Entry]
-Type=Application
-Name=TeleGPS
-GenericName=TeleGPS monitor, download and analysis
-Comment=View and log data from TeleGPS tracking devices
-Icon=%icondir%/telegps.svg
-Exec=%bindir%/telegps %f
-Terminal=false
-MimeType=text/plain;
-Categories=Education;Electronics;Science;