summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog3167
-rw-r--r--Makefile.am5
-rw-r--r--Releasing19
-rw-r--r--altosdroid/Makefile.am2
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java2
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java2
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java2
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java2
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/AltosViewPager.java8
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java19
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/TabAscent.java2
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/TabDescent.java2
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/TabLanded.java2
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java2
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java6
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java2
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java2
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java2
-rw-r--r--altoslib/AltosAccel.java2
-rw-r--r--altoslib/AltosCRCException.java2
-rw-r--r--altoslib/AltosCSV.java (renamed from altosui/AltosCSV.java)7
-rw-r--r--altoslib/AltosCompanion.java2
-rw-r--r--altoslib/AltosConfigData.java121
-rw-r--r--altoslib/AltosConfigDataException.java26
-rw-r--r--altoslib/AltosConfigValues.java34
-rw-r--r--altoslib/AltosConvert.java71
-rw-r--r--altoslib/AltosDebug.java2
-rw-r--r--altoslib/AltosDistance.java2
-rw-r--r--altoslib/AltosEeprom.java6
-rw-r--r--altoslib/AltosEepromChunk.java7
-rw-r--r--altoslib/AltosEepromDownload.java4
-rw-r--r--altoslib/AltosEepromFile.java19
-rw-r--r--altoslib/AltosEepromGPS.java153
-rw-r--r--altoslib/AltosEepromHeader.java9
-rw-r--r--altoslib/AltosEepromIterable.java11
-rw-r--r--altoslib/AltosEepromList.java2
-rw-r--r--altoslib/AltosEepromLog.java2
-rw-r--r--altoslib/AltosEepromMega.java25
-rw-r--r--altoslib/AltosEepromMetrum2.java6
-rw-r--r--altoslib/AltosEepromMini.java4
-rw-r--r--altoslib/AltosEepromMonitor.java2
-rw-r--r--altoslib/AltosEepromTM.java2
-rw-r--r--altoslib/AltosEepromTm.java2
-rw-r--r--altoslib/AltosFile.java2
-rw-r--r--altoslib/AltosFlash.java2
-rw-r--r--altoslib/AltosFlashListener.java2
-rw-r--r--altoslib/AltosFlightReader.java2
-rw-r--r--altoslib/AltosFlightStats.java (renamed from altosui/AltosFlightStats.java)95
-rw-r--r--altoslib/AltosFrequency.java2
-rw-r--r--altoslib/AltosGPS.java2
-rw-r--r--altoslib/AltosGPSSat.java2
-rw-r--r--altoslib/AltosGreatCircle.java28
-rw-r--r--altoslib/AltosHeight.java2
-rw-r--r--altoslib/AltosHexfile.java2
-rw-r--r--altoslib/AltosHexsym.java2
-rw-r--r--altoslib/AltosIMU.java14
-rw-r--r--altoslib/AltosIdle.java2
-rw-r--r--altoslib/AltosIdleFetch.java4
-rw-r--r--altoslib/AltosIdleMonitor.java2
-rw-r--r--altoslib/AltosIdleMonitorListener.java2
-rw-r--r--altoslib/AltosIgnite.java2
-rw-r--r--altoslib/AltosKML.java (renamed from altosui/AltosKML.java)5
-rw-r--r--altoslib/AltosLatitude.java23
-rw-r--r--altoslib/AltosLib.java13
-rw-r--r--altoslib/AltosLine.java2
-rw-r--r--altoslib/AltosLink.java6
-rw-r--r--altoslib/AltosListenerState.java2
-rw-r--r--altoslib/AltosLocation.java66
-rw-r--r--altoslib/AltosLog.java3
-rw-r--r--altoslib/AltosLongitude.java23
-rw-r--r--altoslib/AltosMag.java3
-rw-r--r--altoslib/AltosMma655x.java2
-rw-r--r--altoslib/AltosMs5607.java6
-rw-r--r--altoslib/AltosNoSymbol.java2
-rw-r--r--altoslib/AltosOrient.java2
-rw-r--r--altoslib/AltosParse.java2
-rw-r--r--altoslib/AltosPreferences.java6
-rw-r--r--altoslib/AltosPreferencesBackend.java2
-rw-r--r--altoslib/AltosProgrammer.java2
-rw-r--r--altoslib/AltosPyro.java8
-rw-r--r--altoslib/AltosReplayReader.java4
-rw-r--r--altoslib/AltosRomconfig.java4
-rw-r--r--altoslib/AltosSelfFlash.java6
-rw-r--r--altoslib/AltosSensorEMini.java10
-rw-r--r--altoslib/AltosSensorMM.java2
-rw-r--r--altoslib/AltosSensorMega.java2
-rw-r--r--altoslib/AltosSensorMetrum.java2
-rw-r--r--altoslib/AltosSensorTM.java4
-rw-r--r--altoslib/AltosSensorTMini.java10
-rw-r--r--altoslib/AltosSpeed.java2
-rw-r--r--altoslib/AltosState.java151
-rw-r--r--altoslib/AltosStateIterable.java4
-rw-r--r--altoslib/AltosStateUpdate.java2
-rw-r--r--altoslib/AltosTelemetry.java6
-rw-r--r--altoslib/AltosTelemetryConfiguration.java10
-rw-r--r--altoslib/AltosTelemetryFile.java4
-rw-r--r--altoslib/AltosTelemetryIterable.java2
-rw-r--r--altoslib/AltosTelemetryLegacy.java4
-rw-r--r--altoslib/AltosTelemetryLocation.java2
-rw-r--r--altoslib/AltosTelemetryMap.java2
-rw-r--r--altoslib/AltosTelemetryMegaData.java8
-rw-r--r--altoslib/AltosTelemetryMegaSensor.java4
-rw-r--r--altoslib/AltosTelemetryMetrumData.java2
-rw-r--r--altoslib/AltosTelemetryMetrumSensor.java2
-rw-r--r--altoslib/AltosTelemetryMini.java2
-rw-r--r--altoslib/AltosTelemetryRaw.java2
-rw-r--r--altoslib/AltosTelemetryReader.java2
-rw-r--r--altoslib/AltosTelemetrySatellite.java4
-rw-r--r--altoslib/AltosTelemetrySensor.java2
-rw-r--r--altoslib/AltosTelemetryStandard.java2
-rw-r--r--altoslib/AltosTemperature.java2
-rw-r--r--altoslib/AltosUnits.java10
-rw-r--r--altoslib/AltosUnitsListener.java2
-rw-r--r--altoslib/AltosVoltage.java41
-rw-r--r--altoslib/AltosWriter.java (renamed from altosui/AltosWriter.java)5
-rw-r--r--altoslib/Makefile.am14
-rw-r--r--altosui/.gitignore2
-rw-r--r--altosui/Altos.java4
-rw-r--r--altosui/AltosAscent.java428
-rw-r--r--altosui/AltosChannelMenu.java2
-rw-r--r--altosui/AltosCompanionInfo.java20
-rw-r--r--altosui/AltosConfig.java38
-rw-r--r--altosui/AltosConfigPyroUI.java113
-rw-r--r--altosui/AltosConfigTD.java4
-rw-r--r--altosui/AltosConfigTDUI.java8
-rw-r--r--altosui/AltosConfigUI.java440
-rw-r--r--altosui/AltosConfigureUI.java10
-rw-r--r--altosui/AltosDescent.java460
-rw-r--r--altosui/AltosFlightStatus.java149
-rw-r--r--altosui/AltosFlightStatusTableModel.java2
-rw-r--r--altosui/AltosFlightStatusUpdate.java2
-rw-r--r--altosui/AltosFlightUI.java95
-rw-r--r--altosui/AltosGraphUI.java52
-rw-r--r--altosui/AltosIdleMonitorUI.java21
-rw-r--r--altosui/AltosIgniteUI.java6
-rw-r--r--altosui/AltosIgnitor.java91
-rw-r--r--altosui/AltosLanded.java257
-rw-r--r--altosui/AltosLaunch.java2
-rw-r--r--altosui/AltosLaunchUI.java2
-rw-r--r--altosui/AltosPad.java455
-rw-r--r--altosui/AltosSiteMap.java476
-rw-r--r--altosui/AltosSiteMapCache.java119
-rw-r--r--altosui/AltosSiteMapTile.java122
-rw-r--r--altosui/AltosUI.app/Contents/Resources/AltosUIIcon.icnsbin129010 -> 0 bytes
-rw-r--r--altosui/AltosUI.java22
-rw-r--r--altosui/AltosUIPreferencesBackend.java4
-rw-r--r--altosui/Makefile-standalone2
-rw-r--r--altosui/Makefile.am105
-rw-r--r--altosui/altos-windows.nsi.in63
-rw-r--r--altosui/altos.desktop.in (renamed from debian/altos.desktop)4
-rw-r--r--altosui/linux-install.sh239
-rw-r--r--altosuilib/AltosBTDevice.java (renamed from altosui/AltosBTDevice.java)19
-rw-r--r--altosuilib/AltosBTDeviceIterator.java (renamed from altosui/AltosBTDeviceIterator.java)4
-rw-r--r--altosuilib/AltosBTKnown.java (renamed from altosui/AltosBTKnown.java)6
-rw-r--r--altosuilib/AltosBTManage.java (renamed from altosui/AltosBTManage.java)18
-rw-r--r--altosuilib/AltosCSVUI.java (renamed from altosui/AltosCSVUI.java)13
-rw-r--r--altosuilib/AltosConfigFreqUI.java (renamed from altosui/AltosConfigFreqUI.java)21
-rw-r--r--altosuilib/AltosDataChooser.java (renamed from altosui/AltosDataChooser.java)13
-rw-r--r--altosuilib/AltosDevice.java2
-rw-r--r--altosuilib/AltosDeviceDialog.java20
-rw-r--r--altosuilib/AltosDeviceUIDialog.java (renamed from altosui/AltosDeviceUIDialog.java)5
-rw-r--r--altosuilib/AltosDisplayThread.java (renamed from altosui/AltosDisplayThread.java)44
-rw-r--r--altosuilib/AltosEepromDelete.java (renamed from altosui/AltosEepromDelete.java)6
-rw-r--r--altosuilib/AltosEepromManage.java (renamed from altosui/AltosEepromManage.java)11
-rw-r--r--altosuilib/AltosEepromMonitor.java (renamed from altosui/AltosEepromMonitor.java)3
-rw-r--r--altosuilib/AltosEepromMonitorUI.java (renamed from altosui/AltosEepromMonitorUI.java)5
-rw-r--r--altosuilib/AltosEepromSelect.java (renamed from altosui/AltosEepromSelect.java)5
-rw-r--r--altosuilib/AltosFlashUI.java (renamed from altosui/AltosFlashUI.java)32
-rw-r--r--altosuilib/AltosFlightDisplay.java (renamed from altosui/AltosFlightDisplay.java)8
-rw-r--r--altosuilib/AltosFlightInfoTableModel.java (renamed from altosui/AltosFlightInfoTableModel.java)2
-rw-r--r--altosuilib/AltosFlightStatsTable.java (renamed from altosui/AltosFlightStatsTable.java)105
-rw-r--r--altosuilib/AltosFontListener.java2
-rw-r--r--altosuilib/AltosFreqList.java (renamed from altosui/AltosFreqList.java)13
-rw-r--r--altosuilib/AltosGraph.java (renamed from altosui/AltosGraph.java)124
-rw-r--r--altosuilib/AltosGraphDataPoint.java (renamed from altosui/AltosGraphDataPoint.java)114
-rw-r--r--altosuilib/AltosGraphDataSet.java (renamed from altosui/AltosGraphDataSet.java)5
-rw-r--r--altosuilib/AltosInfoTable.java (renamed from altosui/AltosInfoTable.java)50
-rw-r--r--altosuilib/AltosLed.java (renamed from altosui/AltosLed.java)4
-rw-r--r--altosuilib/AltosLights.java (renamed from altosui/AltosLights.java)4
-rw-r--r--altosuilib/AltosPositionListener.java2
-rw-r--r--altosuilib/AltosRomconfigUI.java (renamed from altosui/AltosRomconfigUI.java)5
-rw-r--r--altosuilib/AltosScanUI.java (renamed from altosui/AltosScanUI.java)120
-rw-r--r--altosuilib/AltosSerial.java (renamed from altosui/AltosSerial.java)10
-rw-r--r--altosuilib/AltosSerialInUseException.java (renamed from altosui/AltosSerialInUseException.java)3
-rw-r--r--altosuilib/AltosUIAxis.java6
-rw-r--r--altosuilib/AltosUIConfigure.java31
-rw-r--r--altosuilib/AltosUIDataMissing.java2
-rw-r--r--altosuilib/AltosUIDataPoint.java2
-rw-r--r--altosuilib/AltosUIDataSet.java2
-rw-r--r--altosuilib/AltosUIDialog.java2
-rw-r--r--altosuilib/AltosUIEnable.java14
-rw-r--r--altosuilib/AltosUIFlightTab.java88
-rw-r--r--altosuilib/AltosUIFrame.java15
-rw-r--r--altosuilib/AltosUIGraph.java12
-rw-r--r--altosuilib/AltosUIGrapher.java6
-rw-r--r--altosuilib/AltosUIIndicator.java181
-rw-r--r--altosuilib/AltosUILatLon.java44
-rw-r--r--altosuilib/AltosUILib.java4
-rw-r--r--altosuilib/AltosUIListener.java2
-rw-r--r--altosuilib/AltosUIMap.java250
-rw-r--r--altosuilib/AltosUIMapCache.java114
-rw-r--r--altosuilib/AltosUIMapImage.java113
-rw-r--r--altosuilib/AltosUIMapLine.java116
-rw-r--r--altosuilib/AltosUIMapMark.java59
-rw-r--r--altosuilib/AltosUIMapPath.java96
-rw-r--r--altosuilib/AltosUIMapPreload.java (renamed from altosui/AltosSiteMapPreload.java)306
-rw-r--r--altosuilib/AltosUIMapRectangle.java45
-rw-r--r--altosuilib/AltosUIMapStore.java203
-rw-r--r--altosuilib/AltosUIMapStoreListener.java22
-rw-r--r--altosuilib/AltosUIMapTile.java192
-rw-r--r--altosuilib/AltosUIMapTileListener.java24
-rw-r--r--altosuilib/AltosUIMapTransform.java106
-rw-r--r--altosuilib/AltosUIMapView.java472
-rw-r--r--altosuilib/AltosUIMapZoomListener.java22
-rw-r--r--altosuilib/AltosUIMarker.java6
-rw-r--r--altosuilib/AltosUIPreferences.java4
-rw-r--r--altosuilib/AltosUIPreferencesBackend.java6
-rw-r--r--altosuilib/AltosUISeries.java9
-rw-r--r--altosuilib/AltosUIUnitsIndicator.java122
-rw-r--r--altosuilib/AltosUIVersion.java.in8
-rw-r--r--altosuilib/AltosUIVoltageIndicator.java42
-rw-r--r--altosuilib/AltosUSBDevice.java2
-rw-r--r--altosuilib/AltosVoice.java (renamed from altosui/AltosVoice.java)3
-rw-r--r--altosuilib/GrabNDrag.java (renamed from altosui/GrabNDrag.java)23
-rw-r--r--altosuilib/Makefile.am70
-rw-r--r--altusmetrum.catbin0 -> 6263 bytes
-rwxr-xr-xaltusmetrum.inf (renamed from telemetrum.inf)3
-rwxr-xr-xao-bringup/cal-freq2
-rwxr-xr-xao-bringup/test-baro99
-rwxr-xr-xao-bringup/test-easymini63
-rwxr-xr-xao-bringup/test-flash101
-rwxr-xr-xao-bringup/test-gps102
-rwxr-xr-xao-bringup/test-igniter136
-rwxr-xr-xao-bringup/test-telegps52
-rwxr-xr-xao-bringup/turnon_easymini72
-rwxr-xr-xao-bringup/turnon_telebt3
-rwxr-xr-xao-bringup/turnon_teledongle1
-rwxr-xr-xao-bringup/turnon_telegps81
-rwxr-xr-xao-bringup/turnon_telemega21
-rwxr-xr-xao-bringup/turnon_telemetrum2
-rwxr-xr-x[-rw-r--r--]ao-tools/ao-flash/ao-flash-lpc9
-rw-r--r--ao-tools/ao-load/ao-load.c2
-rw-r--r--ao-tools/ao-telem/ao-telem.c3
-rw-r--r--ao-tools/ao-usbload/ao-usbload.c28
-rw-r--r--ao-tools/lib/ao-editaltos.c26
-rw-r--r--ao-tools/lib/ao-hex.h1
-rw-r--r--ao-tools/lib/cc-telemetry.h2
-rw-r--r--ao-tools/lib/cc-usb.c60
-rw-r--r--ao-tools/lib/cc-usb.h3
-rw-r--r--configure.ac29
-rw-r--r--debian/altos.install1
-rw-r--r--debian/control2
-rw-r--r--doc/Makefile28
-rw-r--r--doc/altos.xsl10
-rw-r--r--doc/altusmetrum.xsl177
-rw-r--r--doc/ascent.pngbin64038 -> 55389 bytes
-rw-r--r--doc/configure-altimeter.pngbin47817 -> 44924 bytes
-rw-r--r--doc/configure-pyro.pngbin58478 -> 63276 bytes
-rw-r--r--doc/descent.pngbin63566 -> 55624 bytes
-rw-r--r--doc/easymini-outline.pdfbin4240 -> 0 bytes
-rw-r--r--doc/easymini-outline.svg219
-rw-r--r--doc/easymini-outline.xsl23
-rw-r--r--doc/easymini.svg33
-rw-r--r--doc/graph-configure.pngbin48907 -> 45370 bytes
-rw-r--r--doc/graph-map.pngbin991681 -> 443560 bytes
-rw-r--r--doc/ignitor.pngbin0 -> 51104 bytes
-rw-r--r--doc/landed.pngbin54003 -> 45642 bytes
-rw-r--r--doc/launch-pad.pngbin84008 -> 74702 bytes
-rw-r--r--doc/load-maps.pngbin390139 -> 520872 bytes
-rw-r--r--doc/micropeak.xsl2
-rw-r--r--doc/release-notes-1.4.xsl204
-rw-r--r--doc/site-map.pngbin619391 -> 615711 bytes
-rw-r--r--doc/telegps-configure.pngbin0 -> 32472 bytes
-rw-r--r--doc/telegps-graph-configure.pngbin0 -> 29487 bytes
-rw-r--r--doc/telegps-graph-graph.pngbin0 -> 103746 bytes
-rw-r--r--doc/telegps-graph-map.pngbin0 -> 604619 bytes
-rw-r--r--doc/telegps-graph-stats.pngbin0 -> 42796 bytes
-rw-r--r--doc/telegps-info.pngbin0 -> 47633 bytes
-rw-r--r--doc/telegps-location.pngbin0 -> 49996 bytes
-rw-r--r--doc/telegps-map.pngbin0 -> 490858 bytes
-rw-r--r--doc/telegps-preferences.pngbin0 -> 22445 bytes
-rw-r--r--doc/telegps-scan.pngbin0 -> 9852 bytes
-rw-r--r--doc/telegps-status.pngbin0 -> 49827 bytes
-rw-r--r--doc/telegps-table.pngbin0 -> 58663 bytes
-rw-r--r--doc/telegps-v1.0-top.jpgbin0 -> 370086 bytes
-rw-r--r--doc/telegps.xsl1300
-rw-r--r--doc/telemega-outline.pdfbin4349 -> 0 bytes
-rw-r--r--doc/telemega-outline.svg244
-rw-r--r--doc/telemega-outline.xsl23
-rw-r--r--doc/telemega.svg33
-rw-r--r--doc/telemetrum-outline.pdfbin2047 -> 0 bytes
-rw-r--r--doc/telemetrum-outline.svg207
-rw-r--r--doc/telemetrum-outline.xsl23
-rw-r--r--doc/telemetrum.svg10
-rw-r--r--doc/telemini.svg22
-rw-r--r--icon/.gitignore6
-rw-r--r--icon/Makefile.am73
-rw-r--r--icon/altus-metrum-128.pngbin8736 -> 0 bytes
-rw-r--r--icon/altus-metrum-16.pngbin507 -> 0 bytes
-rw-r--r--icon/altus-metrum-256.pngbin21589 -> 0 bytes
-rw-r--r--icon/altus-metrum-32.pngbin1475 -> 0 bytes
-rw-r--r--icon/altus-metrum-48.pngbin2507 -> 0 bytes
-rw-r--r--icon/altus-metrum-512.pngbin56581 -> 0 bytes
-rw-r--r--icon/altus-metrum-64.pngbin3678 -> 0 bytes
-rw-r--r--icon/altus-metrum.icobin285478 -> 0 bytes
-rw-r--r--icon/altusmetrum.svg250
-rw-r--r--icon/micro-peak.icobin285478 -> 0 bytes
-rw-r--r--icon/micropeak-128.pngbin4394 -> 0 bytes
-rw-r--r--icon/micropeak-16.pngbin534 -> 0 bytes
-rw-r--r--icon/micropeak-256.pngbin8055 -> 0 bytes
-rw-r--r--icon/micropeak-32.pngbin1072 -> 0 bytes
-rw-r--r--icon/micropeak-48.pngbin1662 -> 0 bytes
-rw-r--r--icon/micropeak-64.pngbin2240 -> 0 bytes
-rw-r--r--icon/micropeak.svg219
-rw-r--r--icon/telegps.svg324
-rwxr-xr-xjenkins.sh25
-rw-r--r--libaltos/Makefile.am2
-rw-r--r--libaltos/libaltos.c10
-rw-r--r--micropeak/.gitignore1
-rw-r--r--micropeak/Makefile.am34
-rw-r--r--micropeak/MicroData.java4
-rw-r--r--micropeak/MicroDataPoint.java2
-rw-r--r--micropeak/MicroDeviceDialog.java2
-rw-r--r--micropeak/MicroDownload.java4
-rw-r--r--micropeak/MicroExport.java4
-rw-r--r--micropeak/MicroFile.java4
-rw-r--r--micropeak/MicroFileChooser.java4
-rw-r--r--micropeak/MicroFrame.java2
-rw-r--r--micropeak/MicroGraph.java4
-rw-r--r--micropeak/MicroPeak.java4
-rw-r--r--micropeak/MicroRaw.java4
-rw-r--r--micropeak/MicroSave.java4
-rw-r--r--micropeak/MicroSerial.java2
-rw-r--r--micropeak/MicroSerialLog.java2
-rw-r--r--micropeak/MicroStats.java4
-rw-r--r--micropeak/MicroStatsTable.java7
-rw-r--r--micropeak/MicroUSB.java2
-rw-r--r--micropeak/micropeak-windows.nsi.in39
-rw-r--r--micropeak/micropeak.desktop.in10
-rw-r--r--signing-driver20
-rw-r--r--src/Makefile9
-rw-r--r--src/attiny/ao_async.c89
-rw-r--r--src/avr-demo/Makefile4
-rw-r--r--src/avr/ao_usb_avr.c2
-rw-r--r--src/cc1111/Makefile.cc11112
-rw-r--r--src/cc1111/ao_arch.h2
-rw-r--r--src/cc1111/ao_pins.h49
-rw-r--r--src/cc1111/ao_timer.c40
-rw-r--r--src/cc1111/ao_usb.c14
-rw-r--r--src/core/ao_config.h53
-rw-r--r--src/drivers/ao_aprs.c175
-rw-r--r--src/drivers/ao_cc115l.c37
-rw-r--r--src/drivers/ao_gps_ublox.c13
-rw-r--r--src/drivers/ao_lco_func.c2
-rw-r--r--src/drivers/ao_ms5607.c22
-rw-r--r--src/drivers/ao_ms5607.h4
-rw-r--r--src/drivers/ao_ms5607_convert.c12
-rw-r--r--src/drivers/ao_ms5607_convert_8051.c20
-rw-r--r--src/drivers/ao_pad.c6
-rw-r--r--src/drivers/ao_pca9922.c21
-rw-r--r--src/drivers/ao_quadrature.c103
-rw-r--r--src/easymega-v0.1/.gitignore2
-rw-r--r--src/easymega-v0.1/Makefile144
-rw-r--r--src/easymega-v0.1/ao_easymega.c95
-rw-r--r--src/easymega-v0.1/ao_pins.h352
-rw-r--r--src/easymega-v0.1/flash-loader/Makefile8
-rw-r--r--src/easymega-v0.1/flash-loader/ao_pins.h34
-rw-r--r--src/easymini-v1.0/Makefile1
-rw-r--r--src/easymini-v1.0/ao_pins.h21
-rw-r--r--src/kernel/altitude.h (renamed from src/core/altitude.h)0
-rw-r--r--src/kernel/ao.h (renamed from src/core/ao.h)79
-rw-r--r--src/kernel/ao_adc.h (renamed from src/core/ao_adc.h)0
-rw-r--r--src/kernel/ao_aes.h (renamed from src/core/ao_aes.h)0
-rw-r--r--src/kernel/ao_balloon.c (renamed from src/teleballoon-v1.1/ao_balloon.c)13
-rw-r--r--src/kernel/ao_beep.h (renamed from src/core/ao_beep.h)19
-rw-r--r--src/kernel/ao_boot.h (renamed from src/stm/ao_boot.h)4
-rw-r--r--src/kernel/ao_btm.h (renamed from src/core/ao_btm.h)0
-rw-r--r--src/kernel/ao_cmd.c (renamed from src/core/ao_cmd.c)20
-rw-r--r--src/kernel/ao_companion.h (renamed from src/core/ao_companion.h)0
-rw-r--r--src/kernel/ao_config.c (renamed from src/core/ao_config.c)111
-rw-r--r--src/kernel/ao_config.h146
-rw-r--r--src/kernel/ao_convert.c (renamed from src/core/ao_convert.c)0
-rw-r--r--src/kernel/ao_convert_pa.c (renamed from src/core/ao_convert_pa.c)0
-rw-r--r--src/kernel/ao_convert_pa_test.c (renamed from src/core/ao_convert_pa_test.c)0
-rw-r--r--src/kernel/ao_convert_test.c (renamed from src/core/ao_convert_test.c)0
-rw-r--r--src/kernel/ao_convert_volt.c (renamed from src/core/ao_convert_volt.c)10
-rw-r--r--src/kernel/ao_data.c (renamed from src/core/ao_data.c)0
-rw-r--r--src/kernel/ao_data.h (renamed from src/core/ao_data.h)0
-rw-r--r--src/kernel/ao_dbg.h (renamed from src/core/ao_dbg.h)0
-rw-r--r--src/kernel/ao_debounce.c (renamed from src/core/ao_debounce.c)0
-rw-r--r--src/kernel/ao_debounce.h (renamed from src/core/ao_debounce.h)0
-rw-r--r--src/kernel/ao_distance.c123
-rw-r--r--src/kernel/ao_distance.h25
-rw-r--r--src/kernel/ao_ee_fake.c (renamed from src/core/ao_ee_fake.c)0
-rw-r--r--src/kernel/ao_eeprom.h (renamed from src/core/ao_eeprom.h)0
-rw-r--r--src/kernel/ao_fake_flight.c219
-rw-r--r--src/kernel/ao_fake_flight.h53
-rw-r--r--src/kernel/ao_fec.h (renamed from src/core/ao_fec.h)0
-rw-r--r--src/kernel/ao_fec_rx.c (renamed from src/core/ao_fec_rx.c)0
-rw-r--r--src/kernel/ao_fec_tx.c (renamed from src/core/ao_fec_tx.c)0
-rw-r--r--src/kernel/ao_flight.c (renamed from src/core/ao_flight.c)14
-rw-r--r--src/kernel/ao_flight.h (renamed from src/core/ao_flight.h)0
-rw-r--r--src/kernel/ao_flight_nano.c (renamed from src/core/ao_flight_nano.c)0
-rw-r--r--src/kernel/ao_freq.c (renamed from src/core/ao_freq.c)0
-rw-r--r--src/kernel/ao_gps_print.c (renamed from src/core/ao_gps_print.c)0
-rw-r--r--src/kernel/ao_gps_report.c (renamed from src/core/ao_gps_report.c)0
-rw-r--r--src/kernel/ao_gps_report_mega.c (renamed from src/core/ao_gps_report_mega.c)44
-rw-r--r--src/kernel/ao_gps_report_metrum.c (renamed from src/core/ao_gps_report_metrum.c)0
-rw-r--r--src/kernel/ao_gps_show.c (renamed from src/core/ao_gps_show.c)0
-rw-r--r--src/kernel/ao_host.h (renamed from src/core/ao_host.h)0
-rw-r--r--src/kernel/ao_ignite.c (renamed from src/core/ao_ignite.c)0
-rw-r--r--src/kernel/ao_int64.c (renamed from src/core/ao_int64.c)6
-rw-r--r--src/kernel/ao_int64.h (renamed from src/core/ao_int64.h)0
-rw-r--r--src/kernel/ao_kalman.c (renamed from src/core/ao_kalman.c)0
-rw-r--r--src/kernel/ao_lcd.h (renamed from src/core/ao_lcd.h)0
-rw-r--r--src/kernel/ao_led.h (renamed from src/core/ao_led.h)0
-rw-r--r--src/kernel/ao_list.h (renamed from src/core/ao_list.h)0
-rw-r--r--src/kernel/ao_log.c (renamed from src/core/ao_log.c)62
-rw-r--r--src/kernel/ao_log.h (renamed from src/core/ao_log.h)56
-rw-r--r--src/kernel/ao_log_big.c (renamed from src/core/ao_log_big.c)1
-rw-r--r--src/kernel/ao_log_gps.c137
-rw-r--r--src/kernel/ao_log_gps.h33
-rw-r--r--src/kernel/ao_log_mega.c (renamed from src/core/ao_log_mega.c)7
-rw-r--r--src/kernel/ao_log_metrum.c (renamed from src/core/ao_log_metrum.c)3
-rw-r--r--src/kernel/ao_log_micro.c (renamed from src/core/ao_log_micro.c)0
-rw-r--r--src/kernel/ao_log_micro.h (renamed from src/core/ao_log_micro.h)0
-rw-r--r--src/kernel/ao_log_mini.c (renamed from src/core/ao_log_mini.c)1
-rw-r--r--src/kernel/ao_log_single.c (renamed from src/core/ao_log_single.c)0
-rw-r--r--src/kernel/ao_log_telem.c (renamed from src/core/ao_log_telem.c)0
-rw-r--r--src/kernel/ao_log_telescience.c (renamed from src/core/ao_log_telescience.c)0
-rw-r--r--src/kernel/ao_log_tiny.c (renamed from src/core/ao_log_tiny.c)0
-rw-r--r--src/kernel/ao_microflight.c (renamed from src/core/ao_microflight.c)0
-rw-r--r--src/kernel/ao_microkalman.c (renamed from src/core/ao_microkalman.c)0
-rw-r--r--src/kernel/ao_monitor.c (renamed from src/core/ao_monitor.c)0
-rw-r--r--src/kernel/ao_mutex.c (renamed from src/core/ao_mutex.c)0
-rw-r--r--src/kernel/ao_notask.c (renamed from src/core/ao_notask.c)0
-rw-r--r--src/kernel/ao_notask.h (renamed from src/core/ao_notask.h)0
-rw-r--r--src/kernel/ao_packet.h (renamed from src/core/ao_packet.h)0
-rw-r--r--src/kernel/ao_panic.c (renamed from src/core/ao_panic.c)0
-rw-r--r--src/kernel/ao_product.c (renamed from src/core/ao_product.c)0
-rw-r--r--src/kernel/ao_pyro.c (renamed from src/core/ao_pyro.c)14
-rw-r--r--src/kernel/ao_pyro.h (renamed from src/core/ao_pyro.h)8
-rw-r--r--src/kernel/ao_quaternion.h (renamed from src/core/ao_quaternion.h)0
-rw-r--r--src/kernel/ao_radio_cmac.c (renamed from src/core/ao_radio_cmac.c)0
-rw-r--r--src/kernel/ao_radio_cmac.h (renamed from src/core/ao_radio_cmac.h)0
-rw-r--r--src/kernel/ao_radio_cmac_cmd.c (renamed from src/core/ao_radio_cmac_cmd.c)0
-rw-r--r--src/kernel/ao_radio_cmac_cmd.h (renamed from src/core/ao_radio_cmac_cmd.h)0
-rw-r--r--src/kernel/ao_report.c (renamed from src/core/ao_report.c)103
-rw-r--r--src/kernel/ao_report_micro.c (renamed from src/core/ao_report_micro.c)0
-rw-r--r--src/kernel/ao_rssi.c (renamed from src/core/ao_rssi.c)0
-rw-r--r--src/kernel/ao_sample.c (renamed from src/core/ao_sample.c)0
-rw-r--r--src/kernel/ao_sample.h (renamed from src/core/ao_sample.h)0
-rw-r--r--src/kernel/ao_sample_profile.c (renamed from src/core/ao_sample_profile.c)0
-rw-r--r--src/kernel/ao_sample_profile.h (renamed from src/core/ao_sample_profile.h)0
-rw-r--r--src/kernel/ao_send_packet.c (renamed from src/core/ao_send_packet.c)0
-rw-r--r--src/kernel/ao_send_packet.h (renamed from src/core/ao_send_packet.h)0
-rw-r--r--src/kernel/ao_serial.h (renamed from src/core/ao_serial.h)0
-rw-r--r--src/kernel/ao_sqrt.c (renamed from src/core/ao_sqrt.c)0
-rw-r--r--src/kernel/ao_state.c (renamed from src/core/ao_state.c)0
-rw-r--r--src/kernel/ao_stdio.c (renamed from src/core/ao_stdio.c)3
-rw-r--r--src/kernel/ao_storage.c (renamed from src/core/ao_storage.c)0
-rw-r--r--src/kernel/ao_storage.h (renamed from src/core/ao_storage.h)0
-rw-r--r--src/kernel/ao_task.c (renamed from src/core/ao_task.c)0
-rw-r--r--src/kernel/ao_task.h (renamed from src/core/ao_task.h)0
-rw-r--r--src/kernel/ao_telem.h (renamed from src/core/ao_telem.h)0
-rw-r--r--src/kernel/ao_telemetry.c (renamed from src/core/ao_telemetry.c)14
-rw-r--r--src/kernel/ao_telemetry.h (renamed from src/core/ao_telemetry.h)8
-rw-r--r--src/kernel/ao_tracker.c226
-rw-r--r--src/kernel/ao_tracker.h37
-rw-r--r--src/kernel/ao_usb.h (renamed from src/core/ao_usb.h)2
-rw-r--r--src/lpc/Makefile-lpc.defs4
-rw-r--r--src/lpc/ao_adc_lpc.c2
-rw-r--r--src/lpc/ao_arch.h9
-rw-r--r--src/lpc/ao_boot_chain.c4
-rw-r--r--src/lpc/ao_exti_lpc.c4
-rw-r--r--src/lpc/ao_interrupt.c2
-rw-r--r--src/lpc/ao_led_lpc.c20
-rw-r--r--src/lpc/ao_serial_lpc.c4
-rw-r--r--src/lpc/ao_usb_lpc.c4
-rw-r--r--src/lpcxpresso/ao_pins.h1
-rw-r--r--src/megadongle-v0.1/Makefile1
-rw-r--r--src/micropeak/Makefile17
-rw-r--r--src/microwater/.gitignore2
-rw-r--r--src/microwater/Makefile121
-rw-r--r--src/microwater/ao_pins.h70
-rw-r--r--src/nanopeak-v0.1/Makefile4
-rw-r--r--src/product/Makefile.teledongle4
-rw-r--r--src/product/Makefile.telelaunch4
-rw-r--r--src/product/Makefile.telemetrum4
-rw-r--r--src/product/Makefile.telemini4
-rw-r--r--src/product/Makefile.telenano4
-rw-r--r--src/product/ao_flash_task.c39
-rw-r--r--src/product/ao_micropeak.h2
-rw-r--r--src/spiradio-v0.1/.sdcdbrc2
-rw-r--r--src/spiradio-v0.1/Makefile4
-rw-r--r--src/stm-bringup/Makefile2
-rw-r--r--src/stm-demo/Makefile2
-rw-r--r--src/stm-demo/ao_demo.c41
-rw-r--r--src/stm-demo/ao_pins.h11
-rw-r--r--src/stm-demo/flash-loader/Makefile8
-rw-r--r--src/stm-demo/flash-loader/ao_pins.h35
-rw-r--r--src/stm-flash/Makefile1
-rw-r--r--src/stm/Makefile-flash.defs4
-rw-r--r--src/stm/Makefile.defs4
-rw-r--r--src/stm/ao_arch.h3
-rw-r--r--src/stm/ao_boot_chain.c2
-rw-r--r--src/stm/ao_boot_pin.c2
-rw-r--r--src/stm/ao_fast_timer.c8
-rw-r--r--src/stm/ao_interrupt.c32
-rw-r--r--src/stm/ao_timer.c10
-rw-r--r--src/stm/ao_usb_stm.c5
-rw-r--r--src/stm/registers.ld5
-rw-r--r--src/stm/stm32l.h57
-rw-r--r--src/teleballoon-v1.1/Makefile4
-rw-r--r--src/teleballoon-v1.1/ao_pins.h1
-rw-r--r--src/teleballoon-v2.0/.gitignore3
-rw-r--r--src/teleballoon-v2.0/Makefile130
-rw-r--r--src/teleballoon-v2.0/ao_pins.h328
-rw-r--r--src/teleballoon-v2.0/ao_teleballoon.c92
-rw-r--r--src/telebt-v1.0/.sdcdbrc2
-rw-r--r--src/telebt-v1.0/Makefile4
-rw-r--r--src/telefire-v0.1/.sdcdbrc2
-rw-r--r--src/telefire-v0.1/Makefile4
-rw-r--r--src/telefire-v0.2/.sdcdbrc2
-rw-r--r--src/telefire-v0.2/Makefile4
-rw-r--r--src/telegps-v0.1/Makefile1
-rw-r--r--src/telegps-v0.3/Makefile14
-rw-r--r--src/telegps-v0.3/ao_pins.h10
-rw-r--r--src/telegps-v0.3/ao_telegps.c12
-rw-r--r--src/telegps-v1.0/.gitignore3
-rw-r--r--src/telegps-v1.0/Makefile91
-rw-r--r--src/telegps-v1.0/ao_pins.h149
-rw-r--r--src/telegps-v1.0/ao_telegps.c66
-rw-r--r--src/telegps-v1.0/flash-loader/Makefile8
-rw-r--r--src/telegps-v1.0/flash-loader/ao_pins.h (renamed from src/lpc/ao_boot.h)30
-rw-r--r--src/telelco-v0.1/Makefile1
-rw-r--r--src/telelco-v0.2/Makefile1
-rw-r--r--src/telelco-v0.2/ao_lco.c16
-rw-r--r--src/telelco-v0.2/ao_pins.h2
-rw-r--r--src/telemega-v0.1/ao_pins.h5
-rw-r--r--src/telemega-v1.0/Makefile1
-rw-r--r--src/telemega-v1.0/ao_pins.h5
-rw-r--r--src/telemetrum-v1.0/.sdcdbrc2
-rw-r--r--src/telemetrum-v1.1/.sdcdbrc2
-rw-r--r--src/telemetrum-v1.1/Makefile1
-rw-r--r--src/telemetrum-v1.2/Makefile1
-rw-r--r--src/telemetrum-v2.0/Makefile1
-rw-r--r--src/telemetrum-v2.0/ao_pins.h5
-rw-r--r--src/telemini-v1.0/.sdcdbrc2
-rw-r--r--src/telemini-v2.0/.sdcdbrc2
-rw-r--r--src/telemini-v2.0/Makefile6
-rw-r--r--src/telemini-v2.0/ao_pins.h28
-rw-r--r--src/telepyro-v0.1/Makefile4
-rw-r--r--src/telescience-pwm/Makefile4
-rw-r--r--src/telescience-v0.1/Makefile4
-rw-r--r--src/teleshield-v0.1/Makefile4
-rw-r--r--src/teleterra-v0.2/.sdcdbrc2
-rw-r--r--src/teleterra-v0.2/Makefile4
-rw-r--r--src/test/Makefile8
-rw-r--r--src/test/ao_aprs_test.c39
-rw-r--r--src/test/ao_flight_test.c54
-rw-r--r--src/test/ao_ms5607_convert_test.c2
-rw-r--r--src/tidongle/Makefile4
-rw-r--r--src/usbrelay-v0.1/ao_pins.h79
-rw-r--r--src/usbrelay-v0.1/ao_serial_lpc.h33
-rw-r--r--src/usbrelay-v0.1/ao_usbrelay.c90
-rw-r--r--src/usbrelay-v0.1/flash-loader/ao_pins.h33
-rw-r--r--src/usbtrng/Makefile70
-rw-r--r--src/usbtrng/ao_pins.h73
-rw-r--r--src/usbtrng/ao_usbtrng.c63
-rw-r--r--src/usbtrng/flash-loader/Makefile8
-rw-r--r--src/usbtrng/flash-loader/ao_pins.h33
-rw-r--r--telegps/.gitignore27
-rw-r--r--telegps/Info.plist.in46
-rw-r--r--telegps/Makefile.am294
-rw-r--r--telegps/ReadMe-Mac.rtf58
-rwxr-xr-xtelegps/TeleGPS.app/Contents/MacOS/JavaApplicationStubbin0 -> 61296 bytes
-rw-r--r--telegps/TeleGPS.app/Contents/PkgInfo1
-rw-r--r--telegps/TeleGPS.app/Contents/Resources/TeleGPSIcon.icnsbin0 -> 127249 bytes
-rw-r--r--telegps/TeleGPS.java668
-rw-r--r--telegps/TeleGPSConfig.java297
-rw-r--r--telegps/TeleGPSConfigUI.java785
-rw-r--r--telegps/TeleGPSDisplayThread.java207
-rw-r--r--telegps/TeleGPSGraphUI.java101
-rw-r--r--telegps/TeleGPSInfo.java214
-rw-r--r--telegps/TeleGPSPreferences.java120
-rw-r--r--telegps/TeleGPSState.java207
-rw-r--r--telegps/TeleGPSStatus.java253
-rw-r--r--telegps/TeleGPSStatusUpdate.java41
-rwxr-xr-xtelegps/telegps-fat4
-rw-r--r--telegps/telegps-windows.nsi.in194
-rw-r--r--telegps/telegps.146
-rw-r--r--telegps/telegps.desktop.in10
593 files changed, 20806 insertions, 4376 deletions
diff --git a/ChangeLog b/ChangeLog
index 51afdad1..e8d53477 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,3170 @@
+commit 97a7cbaee806965ca7c696fb02f6e1d24b026b9b
+Author: Bdale Garbee <bdale@gag.com>
+Date: Sun Jun 15 17:43:06 2014 -0600
+
+ add release to revision history
+
+commit 79c3dc334d79eacd63bbbbec046fc2c31266560c
+Author: Bdale Garbee <bdale@gag.com>
+Date: Sun Jun 15 17:40:27 2014 -0600
+
+ tweaks
+
+commit a6c61fb993d3fd15183f8755d9058f05c606c9c0
+Merge: 0634119 4384899
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Jun 15 16:31:01 2014 -0700
+
+ Merge remote-tracking branch 'origin/master'
+
+commit 0634119df45bf8d8a040b47bdfc6d9801b5e069a
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Jun 15 16:24:28 2014 -0700
+
+ micropeak: Deal with 64-bit windows
+
+ Install 64-bit version of java. Install our bits in the 64-bit app directory
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b6eb1ac1b777b6c11e8f24c5ab5915b224101d40
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Jun 15 16:16:59 2014 -0700
+
+ Add notes about windows driver signing in the 'signing-driver' file
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6277827520df4df5ecda58898e5f99035f90282c
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Jun 15 16:11:49 2014 -0700
+
+ altosui: Ship telegps firmware
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3b5651d311d4268a130996e71afc11b508e59637
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Jun 15 16:10:15 2014 -0700
+
+ windows: Sign altusmetrum.inf with altusmetrum.cat
+
+ This .cat file will need to be updated when we get our 'real'
+ signature.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ef6998c2d052bf639f257b71baefacf3a652506f
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Jun 15 16:06:42 2014 -0700
+
+ icon: Add drop-shadows to the SVG files; stop generating in the png versions
+
+ Now everyone gets drop shadows.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 43848991defaeb7fae994101675b0056f9d9a2ed
+Author: Bdale Garbee <bdale@gag.com>
+Date: Sun Jun 15 17:29:49 2014 -0600
+
+ update Releasing document to include TeleGPS firmware files in those copied
+
+commit 90e03dfc8534fc4fc25f6a5ee9ec109b98baa238
+Author: Bdale Garbee <bdale@gag.com>
+Date: Sun Jun 15 17:28:02 2014 -0600
+
+ document mounting hole size for TeleGPS
+
+commit 44fc36b3f74386f0055eac4d9b9d201e6fff0847
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Jun 15 16:08:27 2014 -0700
+
+ altosui: Deal with 64-bit windows
+
+ Get a 64-bit java version installed
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1a563026409ccff5dea6f89e567accb09bc4b5f6
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Jun 15 14:09:09 2014 -0700
+
+ telegps: Deal with 64-bit windows differently on install
+
+ Download a 64-bit version of java as needed, install in 64-bit paths
+ instead of 32-bit paths.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit abf731b3d79b66d9da62496cebf157f2888a4c93
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Jun 15 12:39:49 2014 -0700
+
+ windows: Rename telemetrum.inf to altusmetrum.inf
+
+ Use the corporate name for this file
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8073007292875169a6304824ae52039ce6564813
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 14 22:29:01 2014 -0700
+
+ telegps: Include telegps firmware in windows package
+
+ This was disabled when the firmware wasn't ready yet
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6cad0b783f654864f0d6d8726c74605f108db3e0
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 14 22:23:10 2014 -0700
+
+ altosuilib: Remove some debugging printfs
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 823ef386f9dc5c5df197936f4254921f2e0282b0
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 14 20:08:40 2014 -0700
+
+ altoslib: AltosFlightStatsTable: another editable text field that shouldn't be
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5392ee3c5328f8384ed30a2d147e4be96075e064
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 14 18:51:25 2014 -0700
+
+ altosuilib: Serialize access to async tile notify function in preload
+
+ This ensures that we see each tile getting downloaded and don't
+ mis-count, which would result in wedging the process
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 23708b4760250f55e8e3b1a0141df9a9ee17a936
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 14 18:34:09 2014 -0700
+
+ icon: Make the icon shadows a bit less harsh
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4e3318645d08dda483aced97450b344629902c4d
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 14 18:11:28 2014 -0700
+
+ debian: Build requires /usr/bin/convert now
+
+ This is provided by either graphicsmagick or imagemagick
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 382e27de3472489f8f26c8c0868732d67754ecf5
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 14 18:09:31 2014 -0700
+
+ telegps/micropeak: Ship built Mac OSX icons
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 33da986161c38936cff82fe43046f0bcd5e24d8e
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 14 18:07:39 2014 -0700
+
+ icon: Build resolutions needed for Java bits too
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 66c4a091bb6a294f9d406e75f3634492c886d139
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 14 18:06:36 2014 -0700
+
+ altosui: Build MacOSX icon from svg
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b825ea71ebcc4a8da3e339ab3e21b0ad47f2e48f
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 14 18:02:51 2014 -0700
+
+ icon: Build windows ico files, clean built files
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4ec960b705b87b15d015abb2a9a3e23eee414f1d
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 14 17:51:46 2014 -0700
+
+ icon: Create all icons from .svg files
+
+ Remove images from repository, leaving only the svg files and build
+ instructions
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 951fda701ed31f4d8390c130215597e8f63e837e
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 14 16:26:22 2014 -0700
+
+ altosuilib: Make graph enable buttons be CheckBoxes instead of RadioButtons
+
+ aj noticed.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8e00f59be582de86cef28b33ce5523f39d3dc933
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 14 16:05:51 2014 -0700
+
+ telegps: Fix Mac icon file name
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 92943bf4536d4167edd097e61de5e6b4f29130f8
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 14 15:44:20 2014 -0700
+
+ micropeak: Make statistics entries un-editable
+
+ Otherwise you can actually type in the various fields.x
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1fc3032d688cbb7c09c1dffde30cc815f3594e29
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 14 15:20:07 2014 -0700
+
+ alotsuilib: Remove old "mega" and "mini" file extensions from data chooser
+
+ We never shipped AltosUI which stored mega/mini files in different extensions
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c11b2f5caa3fbe2bc977e716ec1c3ccee9e75884
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 14 14:41:13 2014 -0700
+
+ altosui/telegps: Switch to AltosUIIndicator and AltosUIFlightTab
+
+ Removes replicated code across all flight tabs
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f5887a3e7cf993e23dbb1e0f6b9ebece78c34413
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 14 14:40:24 2014 -0700
+
+ altosuilib: Add AltosUIFlightTab class
+
+ This covers most of the common functions for all flight status display tabs.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8250777e6e869bcee9781691caa1f2a7cfb33b43
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 14 14:39:26 2014 -0700
+
+ altosuilib: Add more options to AltosUIIndicator to suit AltosUI
+
+ This makes AltosUIIndicator capable of displaying most stuff in AltosUI
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 19273a4a341342ca6b5d65cfc490d92cbf23356f
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 14 14:38:00 2014 -0700
+
+ altosuilib: Make sure only one thread is closing serial device
+
+ Multiple closers can cause a crash by freeing the libaltos device twice
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2903f0911e79e381c6125022bb84096321c258eb
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 14 14:37:35 2014 -0700
+
+ altosuilib: provide getName() for AltosInfoTable
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 242e968a6982f2ceaa79780cbeec8c4e21321b44
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 14 14:36:49 2014 -0700
+
+ altosuilib: In graph, show zero sats in view as 0 instead of MISSING
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c7553c54765dcc9ac532fe52aae9594b2ad5e560
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 14 14:36:11 2014 -0700
+
+ altosuilib: Require all flight display classes to provide a name
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 14f0faae48849ff6f1e326a294b54c504c730bb9
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 14 14:34:59 2014 -0700
+
+ altoslib: When GPS disappears, set range and elevation to MISSING
+
+ Use MISSING instead of bogus values so that displayers can tell what
+ to do.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 451950bba9ee3b25b5d0c6e5f0b55f08a5b29f73
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 14 14:33:58 2014 -0700
+
+ altoslib: Add units converters for latitude and longitude
+
+ Makes display of these values consistent across all instances
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ae7084f5199318dc6582e212492a50cfda1cebb8
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Jun 13 22:36:00 2014 -0700
+
+ doc: TeleGPS docs are complete
+
+ All TeleGPS features should now be documented to some degree
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit bfbabfa60f3cedd994f693867bce56aad05be02a
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Jun 13 22:04:57 2014 -0700
+
+ telegps: Allow TeleGPS preferences to have a custom title and label
+
+ Don't just inherit the AltosUI ones
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 536db8d03aedb45698c42418c50a46d609fc98ad
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Jun 13 22:04:35 2014 -0700
+
+ doc: Add a bunch more stuff to the telegps docs
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9a6a3c34293eac6442f766e13ce148f595e891eb
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Jun 13 21:26:33 2014 -0700
+
+ altosuilib: Make map-cache per-window instead of global
+
+ This consumes more memory, but avoids cache conflicts between windows
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 92895c87bc3d97bf4990f1feda0bd8b07da4c405
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Jun 13 21:25:41 2014 -0700
+
+ telegps: Shuffle menu entries around
+
+ I think this makes them a bit more logical
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit fb2d0c1ef98d9df3f64fb756d78392ce63a73435
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Jun 13 15:54:08 2014 -0700
+
+ altosdroid: Improve voice for TeleGPS
+
+ This avoids making lots of useless voice announcements for TeleGPS
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 191ea4a7bbcb22d70c648a9ba746f1061e6f74cb
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Jun 13 15:53:30 2014 -0700
+
+ altosdroid: Don't crash when the map is touched
+
+ The map 'canScroll' method was crashing when dereferencing a null
+ value somewhere. Just check all of them and bail instead of crashing.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3f7e885055f8a97f334e0cd3163b760b174114b6
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Jun 13 15:23:30 2014 -0700
+
+ telegps: Add status tab
+
+ This includes pad-relative information, battery voltage and version information
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 876acbdc22ff93c22836f789e0b6394eb19e0da3
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Jun 13 15:22:25 2014 -0700
+
+ altoslib: Correctly save firmware version in AltosState
+
+ It wasn't getting cloned
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3bfba8f9dbc1627a317804713f83b9d06566d008
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Jun 13 15:21:28 2014 -0700
+
+ altoslib: Add conversion class for voltages
+
+ Provide a common presentation for voltage values
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7ed63b6c3d5878a59f52f4114b5b01942735805f
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Jun 13 15:20:20 2014 -0700
+
+ altosuilib: Build some common classes for displaying values in flight window
+
+ Right now, all of the flight displays have piles of custom code for
+ displaying values. These new widgets should be able to replace most of
+ that.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a21dbb05fad2625d17bc2302faa96dc295e6ed7c
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Jun 13 00:28:38 2014 -0700
+
+ telegps: Show flight number in monitor window
+
+ This lets the user find the flight by number
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8cb41ce9a64029b611b3595c86a4a8e74b952ff4
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Jun 13 00:28:09 2014 -0700
+
+ telegps: Disconnect telemetry device when closing monitor window
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit fd9ae83492648c5d39f60bdcff15481efb365701
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Jun 13 00:27:19 2014 -0700
+
+ altoslib: Remove telem monitoring when closing log file
+
+ If we don't remove the telemetry monitor, the telemetry device will
+ still be sending telemetry, which isn't good.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 07baa7596b36cf808cd1ee26ff158b1cf8585294
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Jun 13 00:01:46 2014 -0700
+
+ altoslib: Call state.set_serial first for telemetry parsing
+
+ If we ever get around to supporting multiple simultaneous remote
+ devices, we'll need to notice that the serial changed right away
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f49540acd48292bd9f68ded647561d0e800c619d
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 12 23:59:37 2014 -0700
+
+ altos/telegps: Create new flight if current flight is erased
+
+ telegps is unique in that USB may be connected while a flight is
+ active and sensible things should happen. If a flight is being
+ recorded and gets erased, then a new flight should be started.
+
+ This is done by hooking in the flight erase code and calling out to
+ the tracker code to figure out whether to switch to a new flight or not.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8117ba3553789a2bae9beb92fbe9e14e3cc79389
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 12 23:56:07 2014 -0700
+
+ altos: Define ao_log_mutex in ao_log.c rather than every log product
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit dcaaf51245b44a440ee8590512f71195c30c16ae
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 12 21:54:13 2014 -0700
+
+ altos/telegps: Keep ring of recent GPS positions to detect motion quickly
+
+ Instead of comparing only against the last logged value, keep a ring
+ and start logging as soon as we move away from the furthest one in the ring.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 740d964ab82da8695c04650926afee4a0905011c
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 12 21:53:07 2014 -0700
+
+ altos/telegps: Set default log to 496kB for 4 logs
+
+ This leaves space for four flight logs.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 77b5c0cc7f085aa3c0fada5d4a943eeaf16cf6e0
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 12 21:52:13 2014 -0700
+
+ altos: Show current flight number for TeleGPS
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit bfdaa95cb72c833896076d4e1a4bfe61d9549fed
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 12 15:59:20 2014 -0700
+
+ debian: Fix build depends icotool -> icoutils
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7e911c2afff78db2e385c6346c90bfcd72a8f3fb
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 12 14:34:02 2014 -0700
+
+ altos/telegps: Don't log data when plugged in to USB
+
+ We don't want to accidentally log stuff when you're just trying to
+ charge the battery.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7d77d83685cbfce5323767bbfae3bd18be175ffc
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 12 14:32:15 2014 -0700
+
+ telegps: Don't re-add frequency menu when already present.
+
+ If the receiver disappears, we'll stop tracking, but won't pull the
+ frequency menu down. Doing that would take a bit of work, and it
+ doesn't seem worth the effort. As a kludge-around, avoid re-creating
+ the frequency menu if it's already displayed when we connect to
+ another device.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8044eb8e23366e91c741060939baff5137f841c7
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 12 14:12:08 2014 -0700
+
+ altosui/telegps: Reduce CPU time needed for flight displays
+
+ Don't update displays which aren't shown; track hierarchy changes to
+ trigger display from most recent state data.
+
+ Don't update values which haven't changed; remember previous values
+ and compare with new before updating widget contents.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e00ffe6ab6197ab48ba8ce3cf71a197f7215649f
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jun 11 23:28:55 2014 -0700
+
+ doc: Add TeleGPS screenshots
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c7774114f7bc62e2100c7575b1dcf3536ed56343
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jun 11 23:28:36 2014 -0700
+
+ doc: Update altusmetrum docs and screen shots for 1.4
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1ed591c7bdf19fe54bbde1827d0717f0ae51e003
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jun 11 23:27:16 2014 -0700
+
+ telegps: Remove 'Flight' from titles
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0495f1b5282d8f7449cbbc1dbf99d63818d7c03c
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jun 11 23:26:36 2014 -0700
+
+ altos/telegps: Build .ihx versions for TeleGPS
+
+ Needed to load with java
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6f306b267f63d0f59fb77b1ce41c678042dd6802
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jun 11 23:04:46 2014 -0700
+
+ altosuilib: Repaint map when starting line draw
+
+ Starting line draw will remove any existing line, so repaint to get
+ rid of it
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit efb6a3d5ed12f8061a48a66efcfe066e68eaf792
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jun 11 23:04:11 2014 -0700
+
+ altoslib: Report GPS height when baro height is not available
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 57272609b0d2890029fdeceeca14da93cebdb471
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jun 11 21:37:23 2014 -0700
+
+ altosui: Don't list tracker parameters when configuring altimeter
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit bfc0c65c9f9ec9547d71016fc897ba35bdb414f8
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jun 11 20:36:49 2014 -0700
+
+ altosuilib: Handle font and units changes in maps and stats table
+
+ Add AltosFontListener and AltosUnitsListener bits as needed
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2182c49298e0862a60dea104450d5f74dbeaeeb2
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jun 11 19:57:24 2014 -0700
+
+ doc: Update 1.4 release notes to include a few more changes
+
+ pyro firing time.
+ flight erase on TeleMega/TeleMetrum v2
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d744e588b7504f314e39b1407152d11c031673c9
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jun 11 19:51:37 2014 -0700
+
+ altosui: Add pyro firing time configuration
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit fcbfb3aea20e564045fc6a86f978cacabfc73226
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jun 11 18:58:09 2014 -0700
+
+ altosdroid: Altosdroid build doesn't work in parallel, so stop trying
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c661d5de7d9c8e430211e0f97ab0bf3f09a1a543
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jun 11 18:53:42 2014 -0700
+
+ altos: Re-enable telemini v2.0 builds
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 18b0f0966dfc4d1a716d4faea6f661bd3594bd94
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jun 11 18:53:10 2014 -0700
+
+ altos/telemini-v2.0: Disable beep frequency config on TeleMini v2.0
+
+ Not enough flash otherwise.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ac5b15692874ea3f7b3814250ab49c68786aa982
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jun 11 18:51:19 2014 -0700
+
+ altosuilib: Remove old widget-based map UI
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7a70e6fe3a11382d7f6653d19afac9ceb563db3b
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jun 11 18:50:07 2014 -0700
+
+ altos: Disable TeleMini v2.0 build for now
+
+commit a8325483adb8d9ffda62d3f4900cf52bde70ff62
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jun 11 18:48:11 2014 -0700
+
+ altoslib: Use GPS seconds as an additional sort key for TeleGPS eeprom
+
+ Long idle periods with TeleGPS can easily overflow 16 bits of tick
+ count. Using the GPS seconds provides an additional sort which will
+ span the tick wrap-around.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit db2443fdbf65b65703217174303027c439124a83
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jun 11 18:46:47 2014 -0700
+
+ altosuilib: Rewrite map GUI bits
+
+ Use a single large Canvas and draw images on top by hand.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ac33ca137551e32235cd2a0304da4b5e7af51a44
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jun 10 11:36:03 2014 -0700
+
+ telegps: Add statistics tab to graph UI
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 73249dbf16382c91c2a220ff852a4f099fe0de3d
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jun 10 11:35:30 2014 -0700
+
+ altosuilib: Move AltosFlightStatsTable to altosuilib
+
+ So that TeleGPS can share it
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9ef32b103c5c312aaa90b6546e504f2edeb1f99a
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jun 10 11:34:21 2014 -0700
+
+ altosuilib: Skip voice announcements for invalid values
+
+ When height and speed values aren't available, don't say anything
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 90686853e46b7f0df9bdaf671f859819eef926e0
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jun 10 11:32:57 2014 -0700
+
+ altosui: Show "Missing" instead of huge numbers in descent/landed tabs
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7bdd0deabaae38ddfecd1ea2ea8deaf9af40b2ac
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jun 10 11:31:53 2014 -0700
+
+ altoslib: Use GPS speed/height values when other sensors are missing
+
+ This lets TeleGPS report height/speed values without needing to
+ customize every AltosState user to pull out GPS values when the other
+ sensors aren't present.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6fc58142d2a108c91d257eb0175098bf082834f9
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jun 10 11:30:36 2014 -0700
+
+ altosuilib: Split battery graph enable out from other adc enables
+
+ This lets TeleGPS just show the battery voltage values without also
+ adding enable lines for the other flight computer ADC values like
+ ignitor voltages.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9d39bbd22e6cde1bbb39e7b5450f297d47365769
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jun 10 10:19:43 2014 -0700
+
+ altoslib: Check for time going backwards when replaying from file
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ff13cf1359e1f4ae33b16a5867fd364993566b65
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jun 10 10:18:44 2014 -0700
+
+ altoslib: Add new 'stateless' flight state for TeleGPS
+
+ TeleGPS has no flight state, so add a new 'stateless' state for code
+ to handle this case differently than any of the existing states
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 871fb4753a3b54cc2e22309e80e24dfe9cc54511
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jun 10 10:15:47 2014 -0700
+
+ altoslib: TeleGPS no longer logs satellite information
+
+ This doubles the amount of space available to log position information
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5f2029bd4e31289fb03e6af39abdbc16f8b8fa78
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jun 10 10:14:07 2014 -0700
+
+ altoslib/altosui/telegps: Switch TeleGPS config to motion/interval
+
+ TeleGPS had configurable boost-detect values; those have been replaced
+ with a configurable stop-tracking motion limit and logging/telemetry
+ interval value.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ae1174317fc476e39077f7dc257ec08709c6b301
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jun 10 10:11:03 2014 -0700
+
+ altoslib/altosui/telegps: Change log size configuration
+
+ * Use new log-space value provided by firmware when available.
+
+ * Divide that up into 1-8 flights and offer those sizes as options to
+ the user instead of a fixed set of sizes.
+
+ * Show how many flights each selection will store
+
+ * This also checks values provided by the user
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 44ca50a2c9404c92cc887a23dfa25b335ebe6198
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jun 10 09:55:04 2014 -0700
+
+ altos: Set TeleGPS default log size to half of avaiable memory
+
+ LPC11U14 doesn't have on-chip config space, so we're consuming a block
+ of external flash. As a result, only 1984kB are available for
+ logging. Set the default log size to half of that to store two flights.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9d7f4fb6af0fee843191766858e39a481aeda347
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jun 10 09:52:15 2014 -0700
+
+ altos: Simplify tracker logic, removing boost detect
+
+ This removes the ao_flight_state value from the tracker code and makes
+ it simply log position information when the device has moved within
+ the last 10 log intervals. This also changes the configuration
+ parameters to define what 'motionless' means, and what interval to
+ configure the GPS receiver for, log data and send telemetry.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c5a7889a8da3da64deb0f118656784e0ee3fd511
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jun 10 09:47:04 2014 -0700
+
+ Revert adding state to GPS location packets
+
+ TeleGPS no longer has ao_flight_state
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f6d633d73a8f826cf2a3128e3e234bd11af49718
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jun 10 09:44:57 2014 -0700
+
+ Revert "ao-tools: Parse TeleGPS state value from gps location packet"
+
+ This reverts commit 428d09294ba0395fedd71346ad00fd90a4cdde97.
+
+commit da9575fce5ff4dfe83522e290973a01c43e4661f
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jun 10 09:42:43 2014 -0700
+
+ altos: Make extra pyro channel firing time configurable
+
+ This adds a 'I' parameter to set the extra pyro channel firing time
+ (in ticks). This has no effect on the main/drogue channels.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 75df97b5f6ade3310618a477b685d39b7fd4666e
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jun 10 09:37:43 2014 -0700
+
+ altos: Report total available log space in version command
+
+ This provides a more accurate means of determining available log space
+ than guessing whether some portion of the flash chip holds
+ configuration data.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 998eae61ecf56dd6ead4ec6ad82c952ae84170df
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jun 10 09:36:59 2014 -0700
+
+ Revert "altos: Write current flight state to GPS data from GPS drivers"
+
+ This reverts commit db6003d34595fbd103d5b131912b6a797254f1c5.
+
+commit d696b34b4823647e2e91093ba9d5a351d3a52f8a
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Jun 8 16:08:30 2014 -0700
+
+ Revert "altoslib: Parse TeleGPS state value from GPS telemetry packet"
+
+ This reverts commit d69547796caf74405f8304d23d4ae318315bbd7b.
+
+commit 5c117621444bc13aebbc7dc618b4a56f620931ac
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 7 22:37:30 2014 -0700
+
+ Bump to version 1.3.2.4
+
+commit b33de8ba1e48d8ad0cb78f1c5692bb81da916080
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 7 22:25:17 2014 -0700
+
+ altoslib: Recover battery voltage from TeleGPS configuration packet
+
+ TeleGPS stuffs battery voltage in the apogee_delay slot of the
+ configuration packet. Pull it out from there and stick it into the
+ current state.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6950506beacb1bcd5b8e54c3935174cf800e9aed
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 7 22:24:08 2014 -0700
+
+ altoslib: TeleMega uses 5.6k/10k divider for v_batt
+
+ I suspect the 15 and 27 values are a 'close approximation' for integer
+ work on the cc1111 devices
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ee2216af17f23781ea912caba29fbd7e4d9ff480
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 7 22:23:19 2014 -0700
+
+ altos: Enable ADC for TeleGPS v1.0 battery voltage measuring
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ef85b3bc5300904ebfb878b1c7313a82b5b7aebf
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 7 21:57:43 2014 -0700
+
+ altos: Encode TeleGPS battery voltage in configuration packet
+
+ TeleGPS doesn't need apogee delay, so re-purpose it for the battery voltage
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d69547796caf74405f8304d23d4ae318315bbd7b
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 7 21:13:40 2014 -0700
+
+ altoslib: Parse TeleGPS state value from GPS telemetry packet
+
+ TeleGPS adds 0x80 to the state value to signify that this otherwise
+ unused byte contains the current state value
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 428d09294ba0395fedd71346ad00fd90a4cdde97
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 7 21:12:44 2014 -0700
+
+ ao-tools: Parse TeleGPS state value from gps location packet
+
+ TeleGPS encodes state in a spare gps location packet byte, masking in
+ 0x80 to signify that the state value is valid
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 23d9d37fd2a8f4b867f34e71a2b0f7cb090717c1
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 7 21:12:09 2014 -0700
+
+ altos: Make telegps builds depend on ao_tracker.h
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d165079b9275c69e727a1dac996ad1788c58ed40
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 7 21:11:33 2014 -0700
+
+ altos: Reduce tracker GPS buffer to 4 samples
+
+ We just don't have enough RAM for 8 samples.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit bd9e4f30b2a491b030246943767960ab053ac94c
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 7 21:05:01 2014 -0700
+
+ altos: Define lat/lon sum variables as 64-bit instead of 16
+
+ Oops. 16 bits won't hold position information...
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 08550425fca3da73d8f16de567a2c956b85d676e
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 7 21:02:26 2014 -0700
+
+ altos: Use 0x80 to indicate valid state value in the GPS location packet
+
+ And only set this for tracker products; other products place state in
+ separate state packets
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d8b271502bfd1301b2244e3be5e8c9917a9c624a
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 7 12:17:46 2014 -0700
+
+ Set version to 1.3.2.3
+
+ Mayhem 2014 Saturday 2014-6-7
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d550c3b3eccbb0283c588b5df69edb2e9b44b4cc
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 7 11:52:28 2014 -0700
+
+ telegps: Track graph windows as one of the TeleGPS windows
+
+ TeleGPS exits when the number of windows goes to zero; track graphing
+ windows in addition to the usual flight monitoring windows.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9f2189e0b99aa32b788ecb4576dcb9bcc926f4e2
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 7 11:50:42 2014 -0700
+
+ altosuilib: Fix crash when initializing site map cache
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 611dc26ab4a3ee303c0253698b1e12931aa3644f
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 7 11:50:04 2014 -0700
+
+ altosuilib: Add GPS altitude as a possible graph value
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5617919091d4c4a1e627470ddab0b45cf649f7a1
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 7 11:49:14 2014 -0700
+
+ altosuilib: Show GPS instead of (missing) flight data for TeleGPS graphs
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e0dfa934ba76d6f913af37999e05c20e614bd3e9
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 7 11:47:11 2014 -0700
+
+ altoslib: Record whether flight data includes sensor values in AltosFlightStats
+
+ Provide a way to elide the usual flight data from a graph for TeleGPS
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit fcea12ac416b1eab11e9e8aae801358574308f73
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 7 11:46:32 2014 -0700
+
+ altoslib: Add TeleGPS log parsing code
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 537db628c0223f0c1f797705a353857c696f8051
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 7 11:44:55 2014 -0700
+
+ altoslib: All products with logging have the 'l' command
+
+ Instead of listing products with the 'l' command, just exclude
+ products that don't have logging from using the 'l' command to collect
+ the number of stored flights.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d562a5d3a6dfea334a66ee74893b400bdca09315
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 7 11:44:07 2014 -0700
+
+ altos: Switch TeleGPS to GPS logging format
+
+ It's customized for TeleGPS uses
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d71e6a5fc68d5b9bc1d12bbfc3fd5a4d86fb12f2
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 7 11:41:59 2014 -0700
+
+ altos: Update other CONFIG_EEPROM users to set LOG_ERASE_MARK
+
+ All products placing config and erase marks in on-CPU EEPROM needs to
+ configure the erase code correctly.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 394ab536257ab58de0190b3828dd3bb897ad4474
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 7 11:40:41 2014 -0700
+
+ altos: Write tracker logging from tracker thread directly
+
+ Also, logs 8 pre-launch GPS packets so we can get the ground position.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit db6003d34595fbd103d5b131912b6a797254f1c5
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 7 11:39:10 2014 -0700
+
+ altos: Write current flight state to GPS data from GPS drivers
+
+ This will be useful with TeleGPS which has no other packet containing
+ flight state.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 302842ccda46a0a3d58b60d5c7fc82e05f614b0b
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 7 11:34:29 2014 -0700
+
+ altos: Add TeleGPS logging format
+
+ This is mostly like the mega format, but places the flight state in a
+ spare byte of the GPS data and writes the gps starting location to the
+ flight packet.
+
+ Log data is written by the main tracker thread; there's no reason for
+ a separate thread given the GPS update rate and the lack of flight
+ controls. This means ao_log_gps has an API to be called from there,
+ rather than a thread to run.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 62aa51f0b785bea146d1e9331e6253de2d547c94
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 7 11:01:14 2014 -0700
+
+ altos/telemega-v1.0: Adjust config params to make flight erase work
+
+ Flight erase records are supposed to be written after the ao_config to
+ eeprom in telemega. They were getting written in the middle of one of
+ the pyro channel config blocks. Put a bunch of space between the two
+ by making the config max 1024 bytes instead of 128 bytes.
+
+ Set the log erase marker to 0x55 -- eeprom comes from the factory as
+ 0x00, so we use any value other than 0x55 to indicate 'unused' erase
+ slots.
+
+ Save space for more flight erase blocks; we've got plenty.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5d973570ef2324b21a64477eecb0a292652ff467
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 7 10:54:14 2014 -0700
+
+ altos: Clear out eeprom erase records when writing entry 0
+
+ When writing config/erase to eeprom, there's no 'erase' operation as
+ on-chip eeprom is writable at a byte level. As such, we can't tell
+ when the erase blocks get reset when the config gets written. When
+ this happens, erase block 0 gets written explicitly, so just use that
+ call to trigger explicit erasing of the data.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1d6ca536c688d35b3cba0a829b04b93c5124b328
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 7 10:09:51 2014 -0700
+
+ altos: Allow value other than 0 for marking erased flights
+
+ on-chip eeprom doesn't erase to 0xff, so let TeleMega use a different
+ value.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b8a29d65ec605a995de1d1ec8b110d620d2f7a87
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 7 10:05:21 2014 -0700
+
+ altos: Allow AO_CONFIG_MAX_SIZE to be configured. Validate it.
+
+ TeleMega config is 200 bytes. AO_CONFIG_MAX_SIZE was 128. That didn't
+ work out well when logging erased flight information. Allow TeleMega
+ to use a larger value (1k), and then do a compiler hack to make sure
+ the defined value is at least as large as the ao_config structure.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1873d539a8f1a0e1e8ad539af5d49a77a129b928
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 7 07:41:11 2014 -0700
+
+ altos: Move ao_tracker.c to kernel
+
+ Doesn't make sense to be in product
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6a79fe8144dcab10294caa4b0eac967eeb0d8e7e
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 5 21:42:10 2014 -0700
+
+ altos: Add telegps-v1.0 code and loader
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0e867c67c8e2c40058ae36723e06b2ce00bd0419
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 5 21:40:39 2014 -0700
+
+ altos/telegps-v0.3: Remove ao_flight_number from main program
+
+ We've got logging enabled now
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f830d4e9202d2a138fc9aaacb2388f94390399db
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 5 21:39:50 2014 -0700
+
+ altos/telegps-v0.3: Disable APRS by default. Set log max to 1M
+
+ And adjust default radio cal to be a bit closer
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit cab6d80f11e07dd26b865727eb7ce4fd45be5c7c
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 5 21:37:38 2014 -0700
+
+ altos: Force telemetry on by default for v0.3 TeleGPS boards
+
+ These don't have a USB connect indicator, so just turn on telemetry by
+ default
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 102b1977c138b30c2d2592ab310f7be072130a3b
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 5 21:36:16 2014 -0700
+
+ altos/lpc: HAS_USB_CONNECT has been changed to mean a custom pin
+
+ The LPC stuff isn't actually very useful and TeleGPS uses a custom pin
+ instead, and was using HAS_USB_CONNECT to mean the same thing. That
+ wasn't good.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ec3de3ac461f2380d23c5c5d948333a9a210c400
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 5 21:35:41 2014 -0700
+
+ altos: Fix config to set default log size for all devices with log
+
+ Not just devices with flight
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d8f84ba82bab653c041eb85f93b9dcb1083bd849
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 5 18:55:26 2014 -0700
+
+ altos: Add AO_LOG_FLIGHT packet to TeleGPS logs
+
+ This encodes the flight number for tracking of data files.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit fe0aaf4413035f9de2c805c612c71188ec8c6f4d
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 5 18:49:59 2014 -0700
+
+ altos/telegps-v0.3: Add tracker task
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6160ddadeae324b4a68db800c98c339156b63076
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 5 18:49:01 2014 -0700
+
+ altos: Add debug to tracker to force launch
+
+ This lets us test the move from pad to drogue state
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4a29df3f9f6c4969eb01598f6917ce78c9ce37a6
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 5 18:47:27 2014 -0700
+
+ altos: tracker distance computation flipped arguments around
+
+ ao_distance takes (lat, lon, lat, lon) not (lat, lat, lon, lon)
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b619199345256cdc456f8a0b99c0ad9335e877c7
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 5 18:45:18 2014 -0700
+
+ altos: Fix tracker start state
+
+ Make sure log can start by scanning existing logs
+ Enable RDF by default
+ Turn off telemetry until we decide whether to turn it on in the loop
+ Allow TeleGPS v0.3 to run without ADC
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 97dac0f66bc938940e6b49409d950a1736c92655
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 5 18:44:26 2014 -0700
+
+ altos: Stick flight state in GPS location packets
+
+ Useful for TeleGPS
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit eebcf07950e909e4516b08c32e289a870f772793
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 5 18:35:45 2014 -0700
+
+ altos: Have tracker average 5 GPS samples before moving to pad mode
+
+ Avoids early GPS noise right after lock
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e063701310c1ab5b766c27f24088699aad142fbd
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 5 18:33:33 2014 -0700
+
+ altos: Change tracker not-moving speed to 2m/s and document
+
+ Just adjust to avoid sensing motion from GPS noise
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d7df6e8c47df35c0d27f1a2559ecc305ef28d271
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 5 18:31:06 2014 -0700
+
+ altos: ao_distance was overflowing when checking for longitude wrap
+
+ Need to shift everyone right one bit to fit in 32 bits
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2db2b75f8847ca0066bb19771653a65c9098ae52
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 5 17:24:57 2014 -0700
+
+ altos: Allow cc115l driver to be built without radio power control
+
+ TeleGPS just wants full power, so remove the configuration option
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b8201bc9ba4a5f5f0522b68493cd5e7f013fd4bb
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 5 17:14:28 2014 -0700
+
+ altos: Include sensor logging task only on flight boards
+
+ This lets TeleGPS use the logging infrastructure without wasting a
+ task to log sensor data
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3e28d8a242955d65d8cd50dbba4cad4609e2e1ae
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 5 17:12:06 2014 -0700
+
+ altos: Add tracker task for TeleGPS
+
+ This replaces the flight code to monitor GPS state and switch flight
+ states between startup/pad/drogue
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6e152dd5c0786a650aed8f0c09babdc93895bff1
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 5 17:10:28 2014 -0700
+
+ altos: Add ao_distance.c to compute cartesian distances on the globe
+
+ This is not a great circle distance, but should be good enough for
+ points reasonably close together
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8e7b8b0533e03e89425296d464b7a1a26fb63686
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 5 16:52:36 2014 -0700
+
+ telegps: Update icon and icon building
+
+ Switch to satellite icon, build the osx and windows icons.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1bcafc452f50e518c4d86cbd6b9057c4bf7e676f
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 5 16:50:29 2014 -0700
+
+ altosuilib: Let the user hand-edit the preload map radius
+
+ In case they want more than 5
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f59d69064763cfad2b4b15fd9660fd5fa21dba5e
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Jun 2 23:43:54 2014 -0700
+
+ doc: Create release notes for version 1.4
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit cd2179cb0d71749f3637cc3ee03ccc6adfd74aae
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Jun 2 22:59:23 2014 -0700
+
+ telegps: Trap AltosConfigDataException in telegps config
+
+ This was added for pyro configuration errors in AltosUI
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5e4087cd2fbb3ac67f90cd82edaa73c1eedbf67c
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Jun 2 22:23:31 2014 -0700
+
+ altoslib: Add missing AltosConfigDataException file
+
+commit ace5f42b5567cff07a61b622171ac364ea8c165d
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Jun 2 22:07:39 2014 -0700
+
+ altosui: Display error message when parsing pyro channel values fails
+
+ Build an exception handling chain to get numeric parse errors
+ propagated all the way back to the original 'save' command and up into
+ a dialog window, including the pyro channel, field and value that were
+ in error.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 206fbb99d28961ce159e3affdd5c96f5e379a603
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Jun 2 22:06:22 2014 -0700
+
+ altosui: Fix pyro channel value formatting
+
+ Was using %6.1f for 1 and 2 fraction digit values as the
+ conditional structure for figuring out which format to use was
+ broken.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d20c608ce833fb8949dce527f92887775d216823
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Jun 2 22:05:11 2014 -0700
+
+ altos: Fetch/store only 8 bits for pyro state values
+
+ These fields are uint8_t, not int16_t. Fetching and storing 16 bits is
+ a bad idea.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b7abc063fb27da29cd7a717bbea15f92882bd205
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Jun 2 22:04:11 2014 -0700
+
+ altos: Maximum pyro configuration parameter has 4 bytes in the name
+
+ "f>=" needs four bytes, not just three to store the whole string. If
+ we only store three, then we never manage to compare correctly as the
+ null terminating byte is missing.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7385c76af46ff400b9e79a8540199be289cb57c0
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Jun 2 22:03:26 2014 -0700
+
+ altos: Configuring pyro channels can use more than 48 characters
+
+ Increase the command buffer from 48 to 128 bytes to hold the longest
+ pyro configuration commands
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 177d3c0333fd4218f01e05c78cbc5f186c8e32c0
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri May 30 17:27:10 2014 -0700
+
+ altos: Allow sparse GPS data logging for TeleGPS
+
+ When the device hasn't moved for a while, stop logging data. Start as
+ soon as it moves again.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 12c408c5aa1d234fe9c946078d8a343b4fda7ebb
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri May 30 17:30:08 2014 -0700
+
+ altos: Test APRS altitude encoding
+
+ Verify fixed point version against naïve implementation
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a7b0a5613c8e59b4c672b21f8d0890fd5cffd4dc
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri May 30 17:24:51 2014 -0700
+
+ altos: Switch APRS altitude encoding computation to fixed point
+
+ APRS altitude is logarithmically encoded, so this implementation
+ includes a fixed point log-base-2 function along with a bit of other
+ fixed point stuff. This eliminates all floating point from TeleGPS,
+ saving around 4kB of code space.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2d9842ee011139f5783a102ceb2b7f4c88b1a10f
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri May 30 17:17:42 2014 -0700
+
+ telegps: Add config for tracker starting distances
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 29d325f418b401f61580288b5947b0df8ac5b717
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu May 29 22:03:48 2014 -0700
+
+ telegps: Fixup windows fat build harder
+
+commit b74dfc9c2cbe14593738eb994e9163d466155326
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu May 29 21:48:11 2014 -0700
+
+ TeleGPS firmware isn't quite ready, don't include in windows fat build yet
+
+commit e60d0456f59c76ad786bc8f8065fbe84e6cae922
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu May 29 21:37:53 2014 -0700
+
+ Capture windows build error messages
+
+commit 48074131ad05b4646e5d2dcf30ba4a1d17e249f8
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu May 29 16:39:26 2014 -0700
+
+ telegps: Add missing TeleGPSGraphUI.java file
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ca7e64a09823977e1af028e9482424e643beee68
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu May 29 14:40:39 2014 -0700
+
+ Build telegps distribution bits with 'make fat'
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit bf684a4c290573a3aa627fd8ddf6f6ebbe5fa057
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu May 29 14:36:14 2014 -0700
+
+ telegps: Add graph display
+
+ Moved the altosui graph files to altosuilib and fixed things up.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f80075be4ebb9c5fe00c24b8c7638fad23267424
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu May 29 14:03:58 2014 -0700
+
+ java: Refactor AltosFlightDisplay units and font update handling
+
+ Make AltosFlightDisplay explicitly implement AltosFontListener and
+ AltosUnitsListener interfaces to make everyone use the same API. Then,
+ actually go implement units listeners so that changing units updates
+ all of the active displays immediately
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 71715337eb532a1fbe1a753240e7417d5223489f
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu May 29 10:16:15 2014 -0700
+
+ telegps: Add info table
+
+ Move a couple of files from altosui to altosuilib, hook up the info
+ table after changing it to implement the AltosFlightDisplay interface
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 13f84be8d1568a3fc2ed5eef5dcc2093c149285e
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 28 22:53:06 2014 -0700
+
+ telegps: Add flash device functionality
+
+ Move bits from altosui to altosuilib and use those.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8ba523cd793f2263bb1acd7a5a10f8964075bdc5
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 28 22:45:23 2014 -0700
+
+ telegps: Auto-connect to any base stations plugged in at startup
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c30130d0bdc18ee351eb3d02e51f70f8a05905b1
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 28 22:06:43 2014 -0700
+
+ telegps: Don't try to ship TeleGPS firmware yet
+
+ It's not quite ready. Instead, ship TBT and TD firmware.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3871b9ac036e3adfa1da089245fc7973b268c921
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 28 21:56:52 2014 -0700
+
+ telegps: Add 'Info' tab
+
+ This contains a summary of the tracking info, including position,
+ speed and course.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4cec35564324f909dcddeb7c0d83a2daa8223042
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 28 20:58:01 2014 -0700
+
+ telegps: Hook up data download dialog
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9a4c2c7fc6af922d052e23a1b99bf847fbf9b0e9
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 28 20:48:59 2014 -0700
+
+ telegps: Add scan UI
+
+ Move scan UI bits into altosuilib, allow telegps to not show telemetry
+ format options.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 82a69777c67128192b50bbf77ace0a6525f49cac
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 28 20:24:04 2014 -0700
+
+ telegps: Add preferences dialog
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a7fd31842a602a8ac803d0e09efb4ffabf7a289b
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 28 20:19:44 2014 -0700
+
+ telegps: Add device configuration dialogs
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d6c5904e2a05c8ae023a8cd954cf16c19c477d7d
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 28 20:00:10 2014 -0700
+
+ telegps: Use altosui's Instdrv NSIS plugin for telegps
+
+ Instead of copying it, just point at it
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit fe14315d4cfccf8b53d9c4b7fa79302fd36b2c9a
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 28 19:50:52 2014 -0700
+
+ telegps: Working towards building fat versions of telegps application
+
+ Lots more of the bits necessary for windows/macosx
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 47ff6f7528e3984012e874f91ea4f5c1d68cb465
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 28 19:45:01 2014 -0700
+
+ doc: Add outline of TeleGPS doc
+
+ No actual content, mostly a place holder to make the build work
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e19121d5e7368ef723d4642d26c24252a386a790
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 28 19:44:21 2014 -0700
+
+ Mark version 1.3.2.2
+
+ Preliminary 1.3.3 version (1.4?)
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2fa7785f9efdefaf0fc2fa8e0b03c85047613b84
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 28 16:08:30 2014 -0700
+
+ telegps: Add first version of telegps
+
+ Not much implemented yet, but a shell of the UI and the map
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9b3516419981967a1c6ab956269139977ac368ca
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 28 16:06:14 2014 -0700
+
+ altosui/altosuilib: Shuffle lots more code from altosui into
+ altosuilib
+
+ All of the bluetooth management stuff, and AltosSerial.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 02e657e45e217dc483a81f28020cfe65a826e9be
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 28 10:43:09 2014 -0700
+
+ Document the need for ~/altusmetrumllc/google-maps-api-key
+
+ Stick this in Releasing
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9b9e4bf1b51c45553879141811748e65debfc251
+Author: Tom Marble <tmarble@info9.net>
+Date: Wed May 28 14:08:02 2014 -0500
+
+ jenkins.sh: make -j 4 can fail, fix for altosui-test
+
+commit 96ffe5bbd2a1b44ddda6cb25d37d2b0a672045f5
+Author: Tom Marble <tmarble@info9.net>
+Date: Wed May 28 12:50:42 2014 -0500
+
+ fix for jenkins.sh
+
+commit 5eaef0c98488fa3fbd3a6494dc15e1b793eb6f94
+Author: Tom Marble <tmarble@info9.net>
+Date: Wed May 28 12:38:36 2014 -0500
+
+ add jenkins.sh
+
+commit 324380dcf86be338c6d556b901d6889ddde97f7e
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 28 10:31:47 2014 -0700
+
+ altosuilib: Don't try to draw to destroyed map windows
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1e5807ef428c9a0eb88ed8a3aef40098ab347d80
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 28 10:27:52 2014 -0700
+
+ altosuilib: Publish AltosSiteMap.centre. Add prefetchMaps with old API
+
+ This gets altosui working again.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 52ce41952c5a3c31532fa4f0d1b3155a162b76f4
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 28 10:16:38 2014 -0700
+
+ altosuilib: Update map preloading UI to include zoom and maptypes
+
+ This lets you specify precisely which maps to load.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5c3991768d3cb17fc99ad32b2d6d8d11f0e37dfa
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 28 02:18:41 2014 -0700
+
+ altosuilib: Remove debug printf in AltosSiteMapCache
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4a5ef9eaa8b809c56813625133120e7e91fc8e65
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 28 02:06:18 2014 -0700
+
+ altoslib: When log-format is missing, use product
+
+ log-format was added for 1.0; earlier log files don't include that,
+ but do say which product they're from.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3773e89c47d356c4df58edc5725c33bca89b9605
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 28 00:42:24 2014 -0700
+
+ altosuilib: Add google maps API key, configured with -with-google-key
+
+ This places the actual key outside of the repository, allowing the
+ user to configure the name of the file containing the key. By default,
+ this pulls the key from $HOME/altusmetrumllc/google-maps-api-key.
+
+ With the key present, there are no longer any rate limits to loading
+ map data.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e6cfa25702b3dc1d492c5f1a4d0b4ba4831d30bd
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue May 27 20:34:29 2014 -0700
+
+ altosuilib: Decompress map images asynchronously and in parallel
+
+ This speeds up loading map images from disk quite a bit, and keeps the
+ UI responsive while that happens as well.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8e44580cbe978f1570d4d2ac13d3dd7cd470ecf7
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue May 27 15:39:13 2014 -0700
+
+ altosuilib: Add distance measuring line to site map.
+
+ Use any modifier or button other than the left one to draw a line on
+ the map. The length of the line is shown at the start of the line.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c674a20432c2cb97e5bc2a3de891f78b9e172fe9
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue May 27 11:05:02 2014 -0700
+
+ altos: Fake flight code changes in kernel and stm
+
+ Redirects data input from local sensors to USB sourced data, leaving
+ USB enabled when the computer goes into pad mode.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit db08e99361d82de63058d3388823f486e5fc9839
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue May 27 10:58:53 2014 -0700
+
+ altosuilib: Add multiple zoom levels and content types to map
+
+ Also changes the file format for hybrid, satellite and terrain maps to
+ jpg to save disk space.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 535271f7312f1a88af11d4f1dbf3d405b660f26c
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun May 25 21:14:42 2014 -0700
+
+ altos/test: Fix ADC structure for mega, use ao_config.h
+
+ This switches from hand-coding the ao_config structure to using
+ ao_config.h and also updates the ADC structure for ao_flight_test_mega
+ to using the same one as telemega does natively
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1894b51daceaf9fb6b49a0625e09a366985d15b6
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun May 25 21:12:29 2014 -0700
+
+ altos: Move ao_config declarations to ao_config.h
+
+ No sense leaving these in ao.h, and it's nice to make that file smaller
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3d5db24708b37d86eac187169e2553a408dfeb83
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun May 25 21:11:23 2014 -0700
+
+ altos: Make MS5607 PROM a public variable
+
+ This will let the fake flight code update it as necessary, without
+ creating a new interface in ao_ms5607.c
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4df84dd5d007120f54cbda380789306608f2fc46
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun May 25 21:08:44 2014 -0700
+
+ micropeak: Add -Xlint:unchecked to javac line
+
+ This shows missing parametric type errors
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f0216d721ed13f4d3dc608bb6ad8f83732b27c0a
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun May 25 21:01:38 2014 -0700
+
+ altoslib/altosuilib: Change versions to altoslib:4, altosuilib:2
+
+ API has changed for these libraries, time to bump the file versions
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d63319f6f29ef714bb1d5c359c2448f63e7a4534
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun May 25 20:58:24 2014 -0700
+
+ ao-tools: Add cc_usb_write function
+
+ This writes raw bytes to the USB port; useful for sending binary data
+ for flashing or the upcoming flight test stuff.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0a6c76fc0525d6588a1d88127f0085f13a02f1af
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun May 25 20:55:11 2014 -0700
+
+ altosui/altosuilib/altoslib: Move more stuff out of autosui. Reduce site map memory
+
+ Prepare to share with TeleGPS application.
+
+ This also has the changes to the site map tile which cache only a few
+ images and regenerate the flight path on the fly, saving piles of memory
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4ac7797d3efb9cc2d9fae88519f55e40b1050224
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun May 25 20:47:49 2014 -0700
+
+ altosui/altosuilib: Cleanup -Xlint:unchecked warnings
+
+ Add parametric types to avoid unchecked warnings.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b60a3689910731d9bdb8a431a3dcc9e99f961b35
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu May 22 18:46:58 2014 -0700
+
+ altoslib: Move CSV/KML output code to altoslib
+
+ It's sharable, so share it
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2625a464417c8475c66101757ca2c30cd6c74e0c
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 21 14:02:35 2014 -0700
+
+ altos: Add config values for tracker start motion limits
+
+ TeleGPS switches from 'pad' to 'drogue' states after the device moves
+ a specified distance from the initial starting point. These values can
+ be configured, and this is the configuration for them.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 161ae96f9ec11e2586df07c0f6d724ddc4dad76c
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 21 14:00:05 2014 -0700
+
+ altos/test: Parse mega ground data. Fix pyro parsing
+
+ This gets ao_flight_test_mega working with eeprom files
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 43be26603827b5930bf3e8082610cfa19b45534d
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 21 13:58:54 2014 -0700
+
+ altos/test: Get APRS generation test working again
+
+ APRS now includes sat info, so we have to fake that up to generate an
+ APRS test file
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2a3846df381a5eeac8ec3327c770af502aaf4e76
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 21 01:37:57 2014 -0700
+
+ altos: Don't define ao_ignite_decivolt without igniters
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit af782e92c6a0c0a6b0fc2fa52519749a88ca8fb8
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 21 01:36:40 2014 -0700
+
+ altos: Expose ao_gps_set_rate from u-blox driver
+
+ This lets applications set the desired GPS update rate to reduce power usage
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8b488bdd0f5c91be7e5aae1c8f0193e713734b14
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 21 01:35:33 2014 -0700
+
+ altos: Fix cc115l debug build
+
+ New compiler warning flags and moving to the nxp require a few minor
+ changes in the code to make it work.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit cb228304d8df3063914ab505a530d4ea79ca027d
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 21 01:34:27 2014 -0700
+
+ altos: Allow APRS to send just battery voltage
+
+ Don't require apogee and main voltages as well
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ca338a897ba3237652a3ae092e660f26c9e35074
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 21 01:39:46 2014 -0700
+
+ altos/lpc: whitespace
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0a3312e725d914bbba6355e07d2f1d2833d2d6c2
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 21 01:39:01 2014 -0700
+
+ altos/lpc: adc code computes number of active ADC channels
+
+ Don't require the application to provide AO_NUM_ADC when AO_ADC_NUM is
+ computed automatically.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b278a73cb54ba2f107bf91089f87c11528f017ab
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 21 01:41:38 2014 -0700
+
+ altos/stm: Make stm applications depend on ao_boot.h
+
+ This should make sure they get recompiled when boot stuff changes.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f3544daf08f38aa8e28ca214a19ab7fd47c0c802
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri May 16 00:00:12 2014 -0600
+
+ altosui: Remove another beep config debug printf
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit eeacc001ba089b4bf5552b8ef36e61a0a96efabe
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu May 15 23:57:50 2014 -0600
+
+ altosui: Remove debug printf about beep config
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6833e466d7d77765199bf4d21437c34a4eceb044
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu May 15 23:46:41 2014 -0600
+
+ altos: stm and lpc ao_boot.h were identical. move to kernel.
+
+ These two files were absolutely identical, so share them by moving
+ under kernel instead.x
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 211d9af507daf9a8611ed1813415bee27e3839eb
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu May 15 23:34:17 2014 -0600
+
+ altos: Use explicit boot loader signal in ao_boot_reboot
+
+ Instead of just "knowing" that ao_boot_loader will be passed zero when
+ the application wants to get back to the boot loader, explicitly
+ define the values so that both sides always agree.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0bf1c74e83fe49a11916b52596363f4dd56c522c
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu May 15 23:10:54 2014 -0600
+
+ doc: Document the Apogee Lockout setting
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit dbb0fcf6d161a9d49fe699c37a18e4c33c409b59
+Author: Bdale Garbee <bdale@gag.com>
+Date: Thu May 15 17:20:39 2014 -0600
+
+ include EasyMega Makefiles
+
+commit 0948f5d96456b2e7f57ad75dfc9ef455ba197163
+Author: Bdale Garbee <bdale@gag.com>
+Date: Thu May 15 17:19:08 2014 -0600
+
+ working?
+
+commit 0fd608868aa03f81b2d902e1da13ee0b1ab20b78
+Author: Bdale Garbee <bdale@gag.com>
+Date: Thu May 15 16:23:17 2014 -0600
+
+ lose the (old) easymega-v1.0 directory in favor of my fresher 0.1
+
+commit 819f73698f57e76dca50fe4fadccebd23ffb776d
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu May 15 09:31:24 2014 -0600
+
+ altos: Make quadrature debounce per-pin rather than per-device
+
+ Debouncing per-pin means we don't lose transitions, which makes
+ counting a lot more precise.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit da13064382e9673e69cdfae6abbac253c9fc42fc
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu May 15 09:30:32 2014 -0600
+
+ altos/telemini-v2.0: Enable beep frequency configuration
+
+ Now that there's space for this, add it in.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 36002fc724702d34302f3cc0df593019ca8db4e0
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu May 15 09:29:52 2014 -0600
+
+ altos/telemini-v2.0: Remove old baro->alt conversion table
+
+ TeleMini doesn't have two baro sensors...
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d0d29cc233b0d444782530fea15d957b2b4c45d7
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu May 15 09:28:30 2014 -0600
+
+ altos/cc1111: Switch P1_0 from a green LED to USB pullup
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3225fb54ec1beaf6dc8553ab4f5b86bea6bdf1f3
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu May 15 09:27:34 2014 -0600
+
+ altos/cc1111: Add support for CPU-driven USB pullup
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 940ec6a2d5b054f68da39945a00f4d1b36d1b318
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue May 13 22:46:19 2014 -0700
+
+ altos/cc1111: Errata fix isn't needed for discontinued products
+
+ And, doesn't fit in memory for some of them, so don't compile it.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit feb0b5f8b28767197f87e5818812d6640c1f40e6
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue May 13 17:30:47 2014 -0700
+
+ altos/cc1111: Wait for xtal to be stable
+
+ Errata http://www.ti.com/lit/er/swrz022c/swrz022c.pdf says that the
+ xtal is stable bit is bogus and that you need to just delay for a while.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8124af8c27b2b9e446aa3a4f1da83d4db7c1ea87
+Merge: 6dd7eae 3bcf4bd
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon May 12 23:21:55 2014 -0700
+
+ Merge remote-tracking branch 'origin/master'
+
+commit 6dd7eae5e4752d2098797e96953db8923e26835b
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon May 12 23:20:08 2014 -0700
+
+ ao-tools/ao-usbload: Check image flash usage against device flash availability
+
+ For devices which report the range of valid flash addresses from their
+ boot loader, check the loaded image to make sure it fits within that range.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8a114bac1145359f3953ce70f049a6be71df5300
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon May 12 23:18:41 2014 -0700
+
+ altos/flash-loader: Check memory addresses against flash space
+
+ This validates memory read/write requests to make sure they are within
+ the available flash memory space.
+
+ This also reports the flash base and bounds addresses in the 'version'
+ command so that the loader can validate the image before attempting to
+ write it.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a25c34ef0a92beaa0695e0d0020eda5e26b309e2
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon May 12 22:56:38 2014 -0700
+
+ altos/stm: Use #define'd constants for GPIO register addresses
+
+ This lets the compiler short-circuit the tests in ao_enable_gpio and
+ ao_disable_gpio to save a bit of code space and time.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 530894f508874f4cb3db644ca9ca679ed704f964
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon May 12 22:55:38 2014 -0700
+
+ altos/stm: Figure out available flash space based on chip id registers
+
+ Look at the flash size and the device id registers to figure out how
+ much flash is available.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2c543be5548ccda6bd29a2a7659fcc287f7a9f07
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon May 12 22:54:35 2014 -0700
+
+ altos/stm: White space fix in ao_boot_pin.c
+
+commit 2f196323a2829f9537f3b339f19478127ffde623
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon May 12 22:53:07 2014 -0700
+
+ altos/stm: Use flash address of boot loader instead of 0x0
+
+ Flash is at 0x08000000, but when the chip boots, it can be at 0x0 as
+ well. Use the 0x08000000 address when rebooting to flash
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6a6053dfed6fc1a7f50be0c62782d0050758cd0b
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon May 12 22:51:50 2014 -0700
+
+ altos: Assume all LPC products will have 32KB of flash
+
+ If we ever use something smaller than this, we'll need to figure out
+ how to tell how much memory the device has.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d1908101241b1002fbc582b0a2c27045065a6615
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon May 12 22:51:16 2014 -0700
+
+ altos: Report amount of program space available in the version command
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3af4e824938fe07fe75c6d24d9906aebfbe578f3
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon May 12 22:50:41 2014 -0700
+
+ altos: Add LED test command to pca9922 driver
+
+ This lets you control the LEDs from the command line to test things.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 47750e236c45ab03f28fc3393996edb2bd4312e3
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon May 12 22:49:39 2014 -0700
+
+ ao-bringup: Use official binaries for EasyMini turnon
+
+ Don't use locally built ones, use the official ones found in
+ ~/altusmetrumllc/Binaries to ensure that all devices are shipped with
+ known firmware.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5f4a1b3e553276a4d6727c111fe290fa3690fa1e
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon May 12 22:48:45 2014 -0700
+
+ ao-bringup: test-baro should accept altitudes a bit below sea level
+
+ Testing baro sensors on a particularly high pressure day at Keith's
+ house yields altitudes down to -20m or so.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 238ddde1ffdb8521d06519306cfb76271ae552b9
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon May 12 22:47:55 2014 -0700
+
+ atosui: Hide Callsign and RSSI tabs for devices without a radio
+
+ When doing Monitor Idle with EasyMini, it's nice to not put fields on
+ the screen which won't ever have useful data in them.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3bcf4bdd3e3f3751ad9d517696b5573dd4593846
+Author: Bdale Garbee <bdale@gag.com>
+Date: Mon May 12 17:31:14 2014 -0600
+
+ update TeleMega turn-on script and Releasing for new stable firmware home
+
+commit cbb6f7a3abbde39163f2905badba0ae88744b104
+Author: Bdale Garbee <bdale@gag.com>
+Date: Fri May 9 12:30:25 2014 -0600
+
+ fix copyright year
+
+commit 8d9c79f5c162e07d57d42c6ba5825a3327a911d5
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri May 9 00:05:39 2014 -0700
+
+ altos: Simplify quadrature tracking
+
+ Set the timer to 200Hz for a 5ms debounce interval. Then, simply look
+ for transitions ending in both bits in the encoder being off, which
+ indicates the the encoder is resting in a detent. If bit '2' is
+ turning off, the encoder was rotated clockwise, otherwise the encoder
+ was rotated counter clockwise.
+
+ This is a lot more reliable, although still not perfect.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ef48e1bb73c791d731b0d2c0e5beef1539103049
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon May 5 23:46:34 2014 -0700
+
+ altos: Clean up trailing whitespace in ao_pad.c
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c8ad50495e2d81209a4882dd4f82c19d9ae2ac34
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon May 5 23:45:30 2014 -0700
+
+ altos: Fix byte offsets in the mega AO_LOG_FLIGHT packets
+
+ Just comments, but even those should be correct
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b22dff94778b1f15a6ad1989d526b936f0fa09ea
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon May 5 23:43:44 2014 -0700
+
+ altos: ublox driver always offers course data when it has a fix
+
+ Set the AO_GPS_COURSE_VALID bit to signal that this part of the GPS
+ data is valid.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c9d6a1fbb3148f03864df6d1ed5f6b6dccd7b383
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon May 5 23:41:43 2014 -0700
+
+ altosui: Add GPS course, ground speed and climb rate to graphs
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 39fbc4cb1d4c92522c90aa5e36fd62a4827d8306
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon May 5 23:38:44 2014 -0700
+
+ altoslib: Parse remaining mega AO_LOG_FLIGNT and AO_LOG_GPS_TIME fields
+
+ GPS fields past 'day' were not getting parsed. Ground values for the
+ IMU were not getting parsed, but a false 'temperature' value was being read.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d2e6efa810b7fccc5af937386a40ae5af064bf26
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon May 5 23:38:05 2014 -0700
+
+ altoslib: Add a comment to remind us to fix the IMU code to deal with calibration
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d59d6787bfe26c3b18491ece602ad6cc5cf26c42
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat May 3 10:58:31 2014 -0700
+
+ altos: 8051 64 * 16 multiply function was broken for negative 64-bit
+
+ It was jumping around the actual multiply when the 64-bit argument was negative.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c49e13a7807a74bb66c83cd4a2e10eb601f59e62
+Author: Bdale Garbee <bdale@gag.com>
+Date: Thu May 8 16:24:26 2014 -0600
+
+ relay control implemented, this project is now complete
+
+commit acaad70e3db8f0b6ae45ca8309833db57bdf5ca2
+Author: Bdale Garbee <bdale@gag.com>
+Date: Thu May 8 16:09:11 2014 -0600
+
+ first cut of usbrelay-v0.1 support .. LEDs wiggle, not switching relay yet
+
+commit 2dfc4bc92b11252f17103f28198a702a3fdc2b2d
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri May 2 13:53:08 2014 -0700
+
+ altosui: Add configuration UI for beeper tone
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 027b1470c7a2d007eaab5c8d49f772b0c7559b80
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri May 2 12:26:07 2014 -0700
+
+ altos: Add configurable beep tone
+
+ This lets you directly set the mid-range beep tone; the high and low
+ tones remain set off of that in the same ratio as before.
+
+ Note that none of the cc1111 products get this feature as they don't
+ have enough flash space anymore...
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8e3842660274ac4bcd7b5a78f5db215222b1c4de
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Apr 30 22:14:37 2014 -0700
+
+ altos: For telelco discovery packets, retry 5 times with shorter timeout
+
+ A timeout of 10ms is more than enough to receive a query packet, but
+ if we miss it during device discovery, it's a pain, so retry 5 times
+ to make sure we find everyone.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0223fced2c6d2b9f63ede6258afae46c3f55c200
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Apr 30 22:13:44 2014 -0700
+
+ ao-tools: Clean up ao-sym structure an initializers
+
+ Remove unused 'default_addr' field. Use named initializers when
+ setting up the struct.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 35efd4e51ece706234f80c076eb7f4f70c66098d
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Apr 30 22:12:30 2014 -0700
+
+ ao-load: Make ao_sym static to avoid collision with ao-editaltos
+
+ ao-load doesn't use ao-editaltos at this point, but does share the
+ same name for the symbol table. To make the linker happier, make the
+ ao-load version static.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit fd406000659a11862e05c22dbb20cdb738f56b01
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Apr 30 22:11:39 2014 -0700
+
+ ao-telem: Dump orientation field from TeleMega sensor telemetry packet
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2cf65d60e1c73dbff0badbe1ee6cb43d75bf803c
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Apr 30 22:10:29 2014 -0700
+
+ altosui: Mark TeleMega additional pyro ignitor fired points in graphs
+
+ Add markers to indicate when each additional pyro channel fires
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ecebb3902868d1d7485d2bc99ba4140c6b90567e
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Apr 30 21:30:46 2014 -0700
+
+ altoslib: Track pyro firing state when reading mega eeprom files
+
+ TeleMega records whether each pyro has been fired in the eeprom file;
+ track that in the AltosState record.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5fb246fb50e262aa81ef7eb430be9782cfcf8848
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Apr 29 19:04:30 2014 -0700
+
+ altosui: Add extra ignitors to graphable objects
+
+ List all of the available extra ignitors as possible things to graph.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f8429152e438eb72618edaf5983ae1cd5d3d4dab
+Author: Bdale Garbee <bdale@gag.com>
+Date: Sun Apr 13 08:58:36 2014 -0600
+
+ ugly hack (just make sleep longer) to work around ttyACM* discovery issue
+
+commit 3b5c4d88671e6c511fbfb1ce6b046f558dd6c2bf
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 12 17:46:34 2014 -0700
+
+ altos: Switch beeping to farnsworth spacing
+
+ Use 17wpm/12wpm farnsworth spacing for the state reports. Leave the
+ numeric reports running slowly as those require counting.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8628f7e02834a476d5cb3afa4cbf8d46a4b3c513
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 12 17:45:38 2014 -0700
+
+ altosuilib: Make lines in graphs 2 units wide
+
+ This makes the graphs a lot easier to read.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9e18c524fa2d1f648f265b3c3105f5ceacf06c10
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Apr 11 16:40:06 2014 -0700
+
+ altoslib/altosui/altosuilib/libaltos: Remove trailing whitespace
+
+ Just cleaning up the source code.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7b275ddfe20f54857d7d1abb98607c406b678090
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Apr 11 16:31:32 2014 -0700
+
+ altos: Add 'microwater' product
+
+ This is a custom firmware spin for micropeak designed for use with
+ water rockets that sets the boost detect altitude to 10m instead of 30m.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 99c729495a8cc589718607ee35d22454c6af2994
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Apr 6 23:46:48 2014 -0700
+
+ altosui: Disable flight log configuration while flights are stored
+
+ The log code won't let you resize the maximum flight log while there
+ is still data on the flight computer; the code to figure that out in
+ the UI was busted, leaving users confused about why it wasn't working.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4211c59e585545817b3cac02b41bb73106d6403e
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Apr 6 22:27:37 2014 -0700
+
+ altos: Fix nanopeak compile
+
+ Nanopeak uses port B bit 3 for the LED instead of bit 4. Fix the async
+ code to support arbitrary bits for the serial LED.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 350d941a825d0271933de0bfdea82d3af5744c21
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Apr 6 20:14:49 2014 -0700
+
+ altos: Provide stable binaries for MicroPeak
+
+ Publish MicroPeak .hex file to LLC repo and install it from there,
+ rather than rebuilding it locally. This ensures that the installed
+ bits don't depend on local configuration of any kind.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2427eae5f3b429d302fbe14f708dcbc68c851954
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Apr 6 19:48:07 2014 -0700
+
+ altos: Replace C code attiny async output with inline asm
+
+ Using inline asm instead of C ensures that compiler changes will not
+ affect the timing of the serial data.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1d943d4cade0a40723143626abf6e67f8eca9dcb
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 5 18:17:17 2014 -0700
+
+ altos: Build TeleBalloon v2.0 by default
+
+ We're supporting this now, we might as well build it.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c14cfb1436c988eb0a0d26d7c4d83aeccecbc8a3
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 5 18:16:21 2014 -0700
+
+ ao-bringup: Split out easymini test into separate script
+
+ This lets you run the easy mini testing code without also flashing the device.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9cb10d73fee0e3f36c778fd2a9c9992b87669fe2
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 5 18:14:35 2014 -0700
+
+ altosui: Add ignitor tab for TeleMega extra ignitors
+
+ Show the current state of the additional ignitors in another tab;
+ there's not really room in the 'Pad' tab.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ca66a035edecd7feffcd22257d3413ce0e189c07
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 5 00:28:13 2014 -0700
+
+ doc: Document new voltage beeping at startup time
+
+commit 18148c33540cda8cb6658724a048ffd426c1a6bb
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 5 00:20:22 2014 -0700
+
+ Bump version to 1.3.3
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0d367fc24bfd0377db6f3b00a888a18245616767
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 5 00:18:57 2014 -0700
+
+ altos: Report battery voltage instead of S at startup
+
+ This works on everything with a beeper except TeleMetrum v1.0 which
+ just doesn't have enough flash space for the code.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8bd732ac9cb816630f46dd269448ff8422620df8
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Apr 4 23:40:22 2014 -0700
+
+ doc: Outline files are now generated, so don't put them in git
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ca4b20f9781b1dc6974d26952973dfe0d607478c
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Apr 4 23:38:40 2014 -0700
+
+ ao-tools: Wait for device to become ready instead of failing
+
+ For some reason, USB devices take 'a while' to become usable; instead
+ of bailing immediately, sit around waiting to see if the device
+ becomes usable if we get an EBUSY or EACCES error.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2424c0e6fe53789dc83d1e96439dcdc13e847b07
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Apr 4 23:37:15 2014 -0700
+
+ ao-tools: Use 'program' command in ao-flash-lpc instead of 'flash'
+
+ The program meta-command is supposed to do the whole thing, and seems
+ more reliable in actually getting what we want flashed to the board.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4800497fa1fc449807ef0097cc3fed367641ae29
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Apr 4 23:36:34 2014 -0700
+
+ ao-bringup: Get turnon_telemini working
+
+ This script now does complete testing of the board
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 24167015705ae831692b95735968b04a876f935e
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Apr 4 23:34:48 2014 -0700
+
+ altos: Rename 'core' to 'kernel'
+
+ core remains a bad name to use -- dirvish skips files (and
+ directories, it seems) with that name.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit bb9fdef607728cc326a82aa632e59724f272e53b
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Apr 3 00:10:19 2014 -0700
+
+ altoslib: Missed a couple of easy mini voltage API changes
+
+ Oh, and Tm was using Em conversions (which is almost right, except Tm
+ doesn't have the history)
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 834cd051af1b80a98678de221d3c45cb30f8bb0d
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Apr 2 23:35:36 2014 -0700
+
+ Add easymini turnon script and helpers
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 21d584b9bf93b96a05ab374105493c0e17df320f
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Apr 2 22:04:18 2014 -0700
+
+ altoslib: Fix EasyMini voltage computations
+
+ Early Em prototypes had a 3.0V regulator.
+ Early v1.0 boards measured power past the blocking diode.
+
+ Deal with both conditions to try and report more accurate voltages for
+ EasyMini data.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit adddad0dd45f67d01487c8dd75b040ca3ab50fe2
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Apr 2 20:36:26 2014 -0700
+
+ altoslib: Ignore speed/accel after boost when finding maxima
+
+ Large spikes in acceleration often occur with ejection charges, which
+ can cause bogus acceleration and speed data to be seen. Ignore those
+ for the purpose of computing the maximum values of each.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ff4deb417a460d96645fb6934890c2c195142be3
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Mar 28 23:33:25 2014 -0700
+
+ altos: HAS_LED is useless; remove it
+
+ ao_flight was trying to decide whether to turn off the red LED by
+ checking whether HAS_LED was defined. And yet, none of the flight
+ firmware defines that anymore, except for easymini which defines it to
+ zero.
+
+ Remove all uses and defines of this value, substituting AO_LED_RED in
+ ao_flight.c, which has to be defined for the ao_led_off call to work.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ca0bf9fb2d6323d7a454e5ce04b48d11366eee67
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Mar 16 18:12:33 2014 -0700
+
+ Add easymega firmware
+
+ A trimmed down TeleMega build with no radio or GPS, along with pin
+ changes necessary for the device.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7e0b549b9b30d0a1290d28b2b94025a98af6a4de
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Mar 10 22:55:45 2014 -0700
+
+ altosui: Hide Tilt Angle values when not available
+
+ In the Ascent table, make sure the tilt angle fields are hidden when
+ they are set to MISSING.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3b50e50fb814a572f7b4ea9e268a1ae150fe678c
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Mar 9 21:10:10 2014 -0700
+
+ altos: Another missing usbtrng file
+
+commit b5ac64bc0a6fd0fc23f39283e469c9820bdc88fe
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Mar 9 21:08:25 2014 -0700
+
+ altos: Missing ao_pins files for usbtrng
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 469bd376d84bf8d76faa3b726d96061d4d98b998
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Mar 9 20:59:43 2014 -0700
+
+ altos: Fix LPC LED driver
+
+ Was using wrong types
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6a4a074d690fb34af49704ac3cc4826eaf06dd9d
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Mar 9 20:58:36 2014 -0700
+
+ altos: fix building LPC serial support for STDIO
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9671ca6c42544463fd551f81113c221265a2296e
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Mar 9 20:57:31 2014 -0700
+
+ altos: Don't require projects to define PACKET_HAS_SLAVE
+
+ Really, most don't need it, and whinging about not having it defined
+ isn't useful.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e1e00a4b67fbdbae339219b35aefd44a1bcf9486
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Mar 8 21:39:33 2014 -0800
+
+ Add USB True Random Number Generator product
+
+ Just basic device support
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6dad9ca543fbed3f849b01300224b1b21ef2eb08
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Mar 8 16:25:33 2014 -0800
+
+ Re-add LCD bits to stm-demo
+
+commit 32f0f39a953dabe19ec92611570e4a82da8f8dce
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Mar 8 16:25:10 2014 -0800
+
+ Add flash loader for stm-demo board
+
+commit 4c7da6d0ad568448c37761cd0c0108b9161a9345
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Mar 7 21:27:26 2014 -0800
+
+ doc: Add separate outline pdf generation
+
+ This generates one-page pdf files that contain just the outline of
+ each product.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8f2a85027b496451c5934eb36fcdffbd5e5da177
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Feb 28 23:04:54 2014 -0800
+
+ Install .desktopfile as _SCRIPTS so they are left executable
+
+ .desktop files should be marked executable so that the desktop
+ environment knows they are correct.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a072cbb137126e677d3ebbf0245ec4ea5aa481ad
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Feb 28 21:16:57 2014 -0800
+
+ altosui: Retry device enumeration after rebooting for self flash
+
+ Windows takes 'a while' to include the rebooted device in the list of
+ available devices, so try a few times with a 100ms delay so that we
+ can avoid asking the user to select from an empty list.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ac2cfb03158b4902466a72edad5dc471ee6bdb91
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Feb 28 21:16:36 2014 -0800
+
+ Mark development sequence to 1.3.3 by bumping version to 1.3.2.1
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 57e5d13c0577e1b0a6e8117e2d04eeda6cf0b045
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Feb 23 17:42:08 2014 -0800
+
+ libaltos: Link so with -znoexecstack flag
+
+ This marks the library as not requiring an executable stack, which
+ openjdk prefers
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 104b8bfc9b37fda175f2cb2a1e33601fbf6f48f6
+Merge: 403b95e 1edf7ef
+Author: Bdale Garbee <bdale@gag.com>
+Date: Thu Feb 20 13:23:52 2014 -0700
+
+ Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos
+
+commit 403b95ee27782309b564855b85285c9f5f5c7068
+Author: Bdale Garbee <bdale@gag.com>
+Date: Thu Feb 20 13:23:32 2014 -0700
+
+ update turnon scripts to store cal values
+
+commit 3ef0cc28758c68e6076afa809e157a84ce3661fb
+Author: Bdale Garbee <bdale@gag.com>
+Date: Thu Feb 20 13:23:20 2014 -0700
+
+ typo fixes from Matt Kraai
+
+commit 1edf7ef8026ac4ab698a7f99671e9348d18ffd0a
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Feb 18 09:47:51 2014 -0800
+
+ altos: Create balloon-specific load for TMv2 hardware
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ff4ae350c24b3d6ef71e29191bb719b07ab9c5bb
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Feb 18 09:46:17 2014 -0800
+
+ altos: Make balloon code run again
+
+ This fixes the balloon code so that it works with recent altos bits
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8b6f051663dd17492bece9efb9e898ef113ab414
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Feb 18 09:45:41 2014 -0800
+
+ altos: Set reasonable accel values when !HAS_ACCEL
+
+ This lets us use telemetrum log and telemetry formats for balloons
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9f6983e3d61fa5231f3d0ce33dbc5aadf946b597
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Feb 18 09:44:52 2014 -0800
+
+ altos: Expose ao_usb_running globally
+
+ This lets other bits of the code know when USB has been connected.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9b9d5b273a410e315739c5c6eaa4105523056b9a
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Feb 18 09:43:43 2014 -0800
+
+ altos: Move balloon flight code to core
+
+ This lets us create more than one balloon product
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 43b1797189095c402e1c35bdc317c4196e180e66
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Feb 17 21:30:28 2014 -0800
+
+ doc: Need to publish .svg files as well
+
+ The drill templates are all .svg files that are referenced by the
+ generated html.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 874d0065ecb066ee746a016876edebc7cc6e3d96
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Feb 17 21:27:57 2014 -0800
+
+ Re-create drill templates
+
+ Using inkscape, the drill templates weren't getting printed
+ correctly. Switching to hand-generated svg fixes that.
+
+ The .xsl file is also fixed to really encourage the images to be
+ printed at exactly 100%.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6e713f0a53d608a8855884b7a48e4e3423d8a3d2
+Author: Bdale Garbee <bdale@gag.com>
+Date: Mon Feb 17 00:15:58 2014 -0700
+
+ deliver images used in MicroPeak manual to web server, too
+
+commit 1d421a43494cf2003ac23fb8cd21d6ae05edfac8
+Author: Bdale Garbee <bdale@gag.com>
+Date: Mon Feb 17 00:10:05 2014 -0700
+
+ update copyright year assertion in MicroPeak manual, remember during releases
+
+commit a3ddb5906167e445f937b16fafb7f5c537852f0a
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Feb 16 18:01:10 2014 -0800
+
+ Mark .desktop files as executable
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c860d837a0c97a091c5f47fce91bdb8beb4602d3
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Feb 16 15:53:50 2014 -0800
+
+ micropeak: Construct linux install script
+
+ Uses the same script as altosui, just edits the final path name
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 948a614a62754fd4fffd9b84ad83fd444e4f0437
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Feb 16 15:17:40 2014 -0800
+
+ Move .desktop and icon management out of debian dir
+
+ This constructs a .desktop file from a template and installs it, along
+ with suitable .svg icons, during the normal build process
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 066a01ad0b4e73fdb47b43a42c1d0b7fae81a180
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Feb 16 14:57:38 2014 -0800
+
+ Put altusmetrum.svg and micropeak.svg in icon directory
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 95f5a6ef52947088993d395874cf6aa502fd2503
+Merge: 135b6d4 de2a619
+Author: Bdale Garbee <bdale@gag.com>
+Date: Sun Feb 16 15:53:35 2014 -0700
+
+ Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos
+
+commit 135b6d4019f584c050b3d70c11fb5bcf2c7396c4
+Author: Bdale Garbee <bdale@gag.com>
+Date: Sun Feb 16 15:53:22 2014 -0700
+
+ use svg in the .desktop file
+
+commit 13dccd1869cdf00d4aa0df55a3ece33936cd520a
+Author: Bdale Garbee <bdale@gag.com>
+Date: Sun Feb 16 15:51:32 2014 -0700
+
+ have the cal-freq script save cal values to a file
+
+commit de2a619900ee23911c866d5aaff63a0f9388bfc7
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Feb 16 13:01:29 2014 -0800
+
+ Add linux installer script
+
+ Create a linux installer shell script that unpacks the archive in a
+ sensible place and adds a .desktop file to the environment
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit bf268354535a3a7b2e093235e5347ed2a6d809ff
+Author: Bdale Garbee <bdale@gag.com>
+Date: Thu Feb 13 21:53:13 2014 -0700
+
+ updating changelog for release
+
commit e53be56179f4cd93227b6bdc28c2ae60b81db57d
Author: Keith Packard <keithp@keithp.com>
Date: Sun Feb 9 23:47:47 2014 -0800
diff --git a/Makefile.am b/Makefile.am
index fa4da1fe..15d2c82d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS=ao-tools src doc altoslib libaltos altosuilib altosui micropeak ao-utils altosdroid
+SUBDIRS=ao-tools src doc icon altoslib libaltos altosuilib altosui micropeak ao-utils altosdroid telegps
EXTRA_DIST = ChangeLog
@@ -20,6 +20,7 @@ fat:
cd altosuilib && $(MAKE) all
cd altosui && $(MAKE) fat
cd micropeak && $(MAKE) fat
+ cd telegps && $(MAKE) fat
set-java-versions:
- $(top_srcdir)/fix-java-versions org.altusmetrum.altoslib=$(ALTOSLIB_VERSION) org.altusmetrum.altosuilib=$(ALTOSUILIB_VERSION) \ No newline at end of file
+ $(top_srcdir)/fix-java-versions org.altusmetrum.altoslib=$(ALTOSLIB_VERSION) org.altusmetrum.altosuilib=$(ALTOSUILIB_VERSION)
diff --git a/Releasing b/Releasing
index 1c8bd2a1..1822efbe 100644
--- a/Releasing
+++ b/Releasing
@@ -7,6 +7,12 @@ These are Bdale's notes on how to do a release.
and add release to the revision history at the front (release notes
will be pulled in automatically)
+ - get a Google Maps API key and install it in
+ ~/altusmetrumllc/google-maps-api-key. If you don't have a
+ key, the app will still work, but downloading map tiles will
+ be slow, and you will only be able to download a limited
+ number per day.
+
- update the version in configure.ac
git log > ChangeLog
git commit -a
@@ -56,6 +62,19 @@ These are Bdale's notes on how to do a release.
this pushes packages for each platform to web site
+ # store a stable copy of ARM binaries for production use
+ cp src/easymini-v1.0/*.elf \
+ src/telegps-v1.0/*.elf \
+ src/telemega-v1.0/*.elf \
+ src/telemetrum-v2.0/*.elf \
+ ~/altusmetrumllc/Binaries/
+ cp src/easymini-v1.0/flash-loader/*.elf \
+ src/telegps-v1.0/flash-loader/*.elf \
+ src/telemega-v1.0/flash-loader/*.elf \
+ src/telemetrum-v2.0/flash-loader/*.elf \
+ ~/altusmetrumllc/Binaries/loaders/
+ (cd ~/altusmetrumllc ; git commit -a)
+
- copy the relevant release notes file from doc/ to
/home/bdale/web/altusmetrum/AltOS/releases/<rev>
diff --git a/altosdroid/Makefile.am b/altosdroid/Makefile.am
index 1590e0c9..d5784483 100644
--- a/altosdroid/Makefile.am
+++ b/altosdroid/Makefile.am
@@ -40,6 +40,8 @@ SRC=$(JAVA_SRC) $(DRAWABLES)
all: $(all_target)
+.NOTPARALLEL:
+
$(EXT_LIBDIR):
mkdir -p $(EXT_LIBDIR)
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java
index 634769cc..1b4d45ed 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java
@@ -31,7 +31,7 @@ import android.os.Handler;
//import android.os.Message;
import android.util.Log;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
public class AltosBluetooth extends AltosLink {
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java
index 9125d56b..f61baf1e 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java
@@ -49,7 +49,7 @@ import android.widget.Toast;
import android.app.AlertDialog;
import android.location.Location;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
public class AltosDroid extends FragmentActivity {
// Debugging
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java
index 067cb620..f6e6881d 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java
@@ -23,7 +23,7 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.os.Environment;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
public class AltosDroidPreferences implements AltosPreferencesBackend {
public final static String NAME = "org.altusmetrum.AltosDroid";
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java
index 9d155385..fac4b8d4 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java
@@ -17,7 +17,7 @@
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
import android.location.Location;
public interface AltosDroidTab {
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosViewPager.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosViewPager.java
index ebddc266..223ae75a 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosViewPager.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosViewPager.java
@@ -34,10 +34,14 @@ public class AltosViewPager extends ViewPager {
@Override
protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
- if(v.getClass().getPackage().getName().startsWith("maps.")){
+ if(v.getClass() != null &&
+ v.getClass().getPackage() != null &&
+ v.getClass().getPackage().getName() != null &&
+ v.getClass().getPackage().getName().startsWith("maps."))
+ {
return true;
}
return super.canScroll(v, checkV, dx, x, y);
}
-} \ No newline at end of file
+}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java
index b50cab22..5e8515cb 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java
@@ -21,7 +21,7 @@ package org.altusmetrum.AltosDroid;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
public class AltosVoice {
@@ -63,14 +63,17 @@ public class AltosVoice {
boolean spoke = false;
if (old_state == null || old_state.state != state.state) {
- speak(state.state_name());
+ if (state.state != AltosLib.ao_flight_stateless)
+ speak(state.state_name());
if ((old_state == null || old_state.state <= AltosLib.ao_flight_boost) &&
state.state > AltosLib.ao_flight_boost) {
- speak(String.format("max speed: %d meters per second.", (int) (state.max_speed() + 0.5)));
+ if (state.max_speed() != AltosLib.MISSING)
+ speak(String.format("max speed: %d meters per second.", (int) (state.max_speed() + 0.5)));
spoke = true;
} else if ((old_state == null || old_state.state < AltosLib.ao_flight_drogue) &&
state.state >= AltosLib.ao_flight_drogue) {
- speak(String.format("max height: %d meters.", (int) (state.max_height() + 0.5)));
+ if (state.max_height() != AltosLib.MISSING)
+ speak(String.format("max height: %d meters.", (int) (state.max_height() + 0.5)));
spoke = true;
}
}
@@ -109,8 +112,9 @@ public class AltosVoice {
}
/* If the rocket isn't on the pad, then report height */
- if (AltosLib.ao_flight_drogue <= state.state &&
- state.state < AltosLib.ao_flight_landed &&
+ if (((AltosLib.ao_flight_drogue <= state.state &&
+ state.state < AltosLib.ao_flight_landed) ||
+ state.state == AltosLib.ao_flight_stateless) &&
state.range >= 0)
{
speak(String.format("Height %d, bearing %s %d, elevation %d, range %d.\n",
@@ -121,7 +125,8 @@ public class AltosVoice {
(int) (state.elevation + 0.5),
(int) (state.range + 0.5)));
} else if (state.state > AltosLib.ao_flight_pad) {
- speak(String.format("%d meters", (int) (state.height() + 0.5)));
+ if (state.height() != AltosLib.MISSING)
+ speak(String.format("%d meters", (int) (state.height() + 0.5)));
} else {
reported_landing = 0;
}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabAscent.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabAscent.java
index edfd8245..e4a815eb 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/TabAscent.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabAscent.java
@@ -17,7 +17,7 @@
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
import android.app.Activity;
import android.os.Bundle;
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabDescent.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabDescent.java
index cc070b0d..cbbe4d44 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/TabDescent.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabDescent.java
@@ -17,7 +17,7 @@
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
import android.app.Activity;
import android.os.Bundle;
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabLanded.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabLanded.java
index 5a703978..b2e6fd20 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/TabLanded.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabLanded.java
@@ -17,7 +17,7 @@
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
import android.app.Activity;
import android.os.Bundle;
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java
index 5fe88f51..38922771 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java
@@ -19,7 +19,7 @@ package org.altusmetrum.AltosDroid;
import java.util.Arrays;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java
index 3f0a1887..2d88974d 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java
@@ -17,7 +17,7 @@
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
import android.app.Activity;
import android.os.Bundle;
@@ -125,7 +125,9 @@ public class TabPad extends Fragment implements AltosDroidTab {
mDataLoggingLights.set(state.flight != 0, state.flight == AltosLib.MISSING);
if (state.gps != null) {
- mGPSLockedView.setText(AltosDroid.integer("%4d sats", state.gps.nsat));
+ int soln = state.gps.nsat;
+ int nsat = state.gps.cc_gps_sat != null ? state.gps.cc_gps_sat.length : 0;
+ mGPSLockedView.setText(String.format("%4d in soln, %4d in view", soln, nsat));
mGPSLockedLights.set(state.gps.locked && state.gps.nsat >= 4, false);
if (state.gps_ready)
mGPSReadyView.setText("Ready");
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java
index c8c61838..4215a330 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java
@@ -1,6 +1,6 @@
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
import android.content.BroadcastReceiver;
import android.content.Context;
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java
index 2a2cc404..5bc4b90d 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java
@@ -25,7 +25,7 @@ import java.util.concurrent.*;
import android.util.Log;
import android.os.Handler;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
public class TelemetryReader extends Thread {
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java
index 96cedad8..da5e044f 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java
@@ -44,7 +44,7 @@ import android.location.LocationManager;
import android.location.LocationListener;
import android.location.Criteria;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
public class TelemetryService extends Service implements LocationListener {
diff --git a/altoslib/AltosAccel.java b/altoslib/AltosAccel.java
index 43dc20bd..3d340e5d 100644
--- a/altoslib/AltosAccel.java
+++ b/altoslib/AltosAccel.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public class AltosAccel extends AltosUnits {
diff --git a/altoslib/AltosCRCException.java b/altoslib/AltosCRCException.java
index 94962731..253ca435 100644
--- a/altoslib/AltosCRCException.java
+++ b/altoslib/AltosCRCException.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public class AltosCRCException extends Exception {
public int rssi;
diff --git a/altosui/AltosCSV.java b/altoslib/AltosCSV.java
index 13f29f07..27e1fade 100644
--- a/altosui/AltosCSV.java
+++ b/altoslib/AltosCSV.java
@@ -15,11 +15,10 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altoslib_4;
import java.io.*;
import java.util.*;
-import org.altusmetrum.altoslib_3.*;
public class AltosCSV implements AltosWriter {
File name;
@@ -281,7 +280,7 @@ public class AltosCSV implements AltosWriter {
}
public void write(AltosState state) {
- if (state.state == Altos.ao_flight_startup)
+ if (state.state == AltosLib.ao_flight_startup)
return;
if (!header_written) {
write_header(state.imu != null || state.mag != null,
@@ -289,7 +288,7 @@ public class AltosCSV implements AltosWriter {
header_written = true;
}
if (!seen_boost) {
- if (state.state >= Altos.ao_flight_boost) {
+ if (state.state >= AltosLib.ao_flight_boost) {
seen_boost = true;
boost_tick = state.tick;
flush_pad();
diff --git a/altoslib/AltosCompanion.java b/altoslib/AltosCompanion.java
index 47ca328e..09bfe9f3 100644
--- a/altoslib/AltosCompanion.java
+++ b/altoslib/AltosCompanion.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public class AltosCompanion {
public final static int board_id_telescience = 0x0a;
diff --git a/altoslib/AltosConfigData.java b/altoslib/AltosConfigData.java
index c4e108f8..e1043958 100644
--- a/altoslib/AltosConfigData.java
+++ b/altoslib/AltosConfigData.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.util.*;
import java.text.*;
@@ -29,6 +29,7 @@ public class AltosConfigData implements Iterable<String> {
public int serial;
public int flight;
public int log_format;
+ public int log_space;
public String version;
/* Strings returned */
@@ -66,10 +67,14 @@ public class AltosConfigData implements Iterable<String> {
public AltosPyro[] pyros;
public int npyro;
public int pyro;
+ public double pyro_firing_time;
/* HAS_APRS */
public int aprs_interval;
+ /* HAS_BEEP */
+ public int beep;
+
/* Storage info replies */
public int storage_size;
public int storage_erase_unit;
@@ -77,6 +82,10 @@ public class AltosConfigData implements Iterable<String> {
/* Log listing replies */
public int stored_flight;
+ /* HAS_TRACKER */
+ public int tracker_motion;
+ public int tracker_interval;
+
public static String get_string(String line, String label) throws ParseException {
if (line.startsWith(label)) {
String quoted = line.substring(label.length()).trim();
@@ -100,10 +109,40 @@ public class AltosConfigData implements Iterable<String> {
throw new ParseException("mismatch", 0);
}
+ public static int[] get_values(String line, String label) throws NumberFormatException, ParseException {
+ if (line.startsWith(label)) {
+ String tail = line.substring(label.length()).trim();
+ String[] tokens = tail.split("\\s+");
+ if (tokens.length > 1) {
+ int[] values = new int[2];
+ values[0] = Integer.parseInt(tokens[0]);
+ values[1] = Integer.parseInt(tokens[1]);
+ return values;
+ }
+ }
+ throw new ParseException("mismatch", 0);
+ }
+
public Iterator<String> iterator() {
return lines.iterator();
}
+ public int log_space() {
+ if (log_space > 0)
+ return log_space;
+
+ if (storage_size > 0) {
+ int space = storage_size;
+
+ if (storage_erase_unit > 0 && use_flash_for_config())
+ space -= storage_erase_unit;
+
+ if (space > 0)
+ return space;
+ }
+ return 0;
+ }
+
public int log_available() {
switch (log_format) {
case AltosLib.AO_LOG_FORMAT_TINY:
@@ -117,7 +156,7 @@ public class AltosConfigData implements Iterable<String> {
if (flight_log_max <= 0)
return 1;
int log_max = flight_log_max * 1024;
- int log_space = storage_size - storage_erase_unit;
+ int log_space = log_space();
int log_used;
if (stored_flight <= 0)
@@ -182,6 +221,7 @@ public class AltosConfigData implements Iterable<String> {
serial = 0;
flight = 0;
log_format = AltosLib.AO_LOG_FORMAT_UNKNOWN;
+ log_space = -1;
version = "unknown";
main_deploy = -1;
@@ -207,9 +247,15 @@ public class AltosConfigData implements Iterable<String> {
pyro = 0;
npyro = 0;
pyros = null;
+ pyro_firing_time = -1;
aprs_interval = -1;
+ beep = -1;
+
+ tracker_motion = -1;
+ tracker_interval = -1;
+
storage_size = -1;
storage_erase_unit = -1;
stored_flight = 0;
@@ -223,6 +269,7 @@ public class AltosConfigData implements Iterable<String> {
try { serial = get_int(line, "serial-number"); } catch (Exception e) {}
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 { version = get_string(line, "software-version"); } catch (Exception e) {}
/* Version also contains MS5607 info, which we ignore here */
@@ -282,10 +329,21 @@ public class AltosConfigData implements Iterable<String> {
pyros[pyro++] = p;
} catch (Exception e) {}
}
+ try { pyro_firing_time = get_int(line, "Pyro time:") / 100.0; } catch (Exception e) {}
/* HAS_APRS */
try { aprs_interval = get_int(line, "APRS interval:"); } catch (Exception e) {}
+ /* HAS_BEEP */
+ try { beep = get_int(line, "Beeper setting:"); } catch (Exception e) {}
+
+ /* HAS_TRACKER */
+ try {
+ int[] values = get_values(line, "Tracker setting:");
+ tracker_motion = values[0];
+ tracker_interval = values[1];
+ } catch (Exception e) {}
+
/* Storage info replies */
try { storage_size = get_int(line, "Storage size:"); } catch (Exception e) {}
try { storage_erase_unit = get_int(line, "Storage erase unit:"); } catch (Exception e) {}
@@ -351,16 +409,16 @@ public class AltosConfigData implements Iterable<String> {
channel);
}
- public int log_limit() {
- if (storage_size > 0 && storage_erase_unit > 0) {
- int log_limit = storage_size - storage_erase_unit;
- if (log_limit > 0)
- return log_limit / 1024;
- }
- return 1024;
+ boolean use_flash_for_config() {
+ if (product.startsWith("TeleMega"))
+ return false;
+ if (product.startsWith("TeleMetrum-v2"))
+ return false;
+ return true;
}
- public void get_values(AltosConfigValues source) {
+
+ public void get_values(AltosConfigValues source) throws AltosConfigDataException {
/* HAS_FLIGHT */
if (main_deploy >= 0)
@@ -395,9 +453,21 @@ public class AltosConfigData implements Iterable<String> {
/* AO_PYRO_NUM */
if (npyro > 0)
pyros = source.pyros();
+ if (pyro_firing_time >= 0)
+ pyro_firing_time = source.pyro_firing_time();
+ /* HAS_APRS */
if (aprs_interval >= 0)
aprs_interval = source.aprs_interval();
+
+ /* HAS_BEEP */
+ if (beep >= 0)
+ beep = source.beep();
+ /* HAS_TRACKER */
+ if (tracker_motion >= 0)
+ tracker_motion = source.tracker_motion();
+ if (tracker_interval >= 0)
+ tracker_interval = source.tracker_interval();
}
public void set_values(AltosConfigValues dest) {
@@ -410,18 +480,23 @@ public class AltosConfigData implements Iterable<String> {
dest.set_radio_calibration(radio_calibration);
dest.set_radio_frequency(frequency());
boolean max_enabled = true;
+
+ if (log_space() == 0)
+ max_enabled = false;
+
switch (log_format) {
case AltosLib.AO_LOG_FORMAT_TINY:
max_enabled = false;
break;
default:
- if (stored_flight >= 0)
+ if (stored_flight > 0)
max_enabled = false;
break;
}
+
dest.set_flight_log_max_enabled(max_enabled);
dest.set_radio_enable(radio_enable);
- dest.set_flight_log_max_limit(log_limit());
+ dest.set_flight_log_max_limit(log_space() / 1024);
dest.set_flight_log_max(flight_log_max);
dest.set_ignite_mode(ignite_mode);
dest.set_pad_orientation(pad_orientation);
@@ -430,7 +505,11 @@ public class AltosConfigData implements Iterable<String> {
dest.set_pyros(pyros);
else
dest.set_pyros(null);
+ dest.set_pyro_firing_time(pyro_firing_time);
dest.set_aprs_interval(aprs_interval);
+ dest.set_beep(beep);
+ dest.set_tracker_motion(tracker_motion);
+ dest.set_tracker_interval(tracker_interval);
}
public void save(AltosLink link, boolean remote) throws InterruptedException, TimeoutException {
@@ -492,11 +571,21 @@ public class AltosConfigData implements Iterable<String> {
pyros[p].toString());
}
}
+ if (pyro_firing_time >= 0)
+ link.printf("c I %d\n", (int) (pyro_firing_time * 100.0 + 0.5));
/* HAS_APRS */
if (aprs_interval >= 0)
link.printf("c A %d\n", aprs_interval);
+ /* HAS_BEEP */
+ if (beep >= 0)
+ link.printf("c b %d\n", beep);
+
+ /* HAS_TRACKER */
+ if (tracker_motion >= 0 && tracker_interval >= 0)
+ link.printf("c t %d %d\n", tracker_motion, tracker_interval);
+
link.printf("c w\n");
link.flush_output();
}
@@ -506,12 +595,12 @@ public class AltosConfigData implements Iterable<String> {
link.printf("c s\nf\nv\n");
read_link(link, "software-version");
switch (log_format) {
- case AltosLib.AO_LOG_FORMAT_FULL:
- case AltosLib.AO_LOG_FORMAT_TINY:
- case AltosLib.AO_LOG_FORMAT_TELEMEGA:
+ case AltosLib.AO_LOG_FORMAT_UNKNOWN:
+ case AltosLib.AO_LOG_FORMAT_NONE:
+ break;
+ default:
link.printf("l\n");
read_link(link, "done");
- default:
break;
}
}
diff --git a/altoslib/AltosConfigDataException.java b/altoslib/AltosConfigDataException.java
new file mode 100644
index 00000000..ae5621cc
--- /dev/null
+++ b/altoslib/AltosConfigDataException.java
@@ -0,0 +1,26 @@
+/*
+ * 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.altoslib_4;
+
+public class AltosConfigDataException extends Exception {
+
+ public AltosConfigDataException(String format, Object... args) {
+ super(String.format(format, args));
+ }
+
+}
diff --git a/altoslib/AltosConfigValues.java b/altoslib/AltosConfigValues.java
index 4aa55d6a..724ba7dc 100644
--- a/altoslib/AltosConfigValues.java
+++ b/altoslib/AltosConfigValues.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public interface AltosConfigValues {
/* set and get all of the dialog values */
@@ -27,23 +27,23 @@ public interface AltosConfigValues {
public abstract void set_main_deploy(int new_main_deploy);
- public abstract int main_deploy();
+ public abstract int main_deploy() throws AltosConfigDataException;
public abstract void set_apogee_delay(int new_apogee_delay);
- public abstract int apogee_delay();
+ public abstract int apogee_delay() throws AltosConfigDataException;
public abstract void set_apogee_lockout(int new_apogee_lockout);
- public abstract int apogee_lockout();
+ public abstract int apogee_lockout() throws AltosConfigDataException;
public abstract void set_radio_frequency(double new_radio_frequency);
- public abstract double radio_frequency();
+ public abstract double radio_frequency() throws AltosConfigDataException;
public abstract void set_radio_calibration(int new_radio_calibration);
- public abstract int radio_calibration();
+ public abstract int radio_calibration() throws AltosConfigDataException;
public abstract void set_radio_enable(int new_radio_enable);
@@ -57,7 +57,7 @@ public interface AltosConfigValues {
public abstract void set_flight_log_max_enabled(boolean enable);
- public abstract int flight_log_max();
+ public abstract int flight_log_max() throws AltosConfigDataException;
public abstract void set_flight_log_max_limit(int flight_log_max_limit);
@@ -71,9 +71,25 @@ public interface AltosConfigValues {
public abstract void set_pyros(AltosPyro[] new_pyros);
- public abstract AltosPyro[] pyros();
+ public abstract AltosPyro[] pyros() throws AltosConfigDataException;
- public abstract int aprs_interval();
+ public abstract void set_pyro_firing_time(double new_pyro_firing_time);
+
+ public abstract double pyro_firing_time() throws AltosConfigDataException;
+
+ public abstract int aprs_interval() throws AltosConfigDataException;
public abstract void set_aprs_interval(int new_aprs_interval);
+
+ public abstract int beep() throws AltosConfigDataException;
+
+ public abstract void set_beep(int new_beep);
+
+ public abstract int tracker_motion() throws AltosConfigDataException;
+
+ public abstract void set_tracker_motion(int tracker_motion);
+
+ public abstract int tracker_interval() throws AltosConfigDataException;
+
+ public abstract void set_tracker_interval(int tracker_motion);
}
diff --git a/altoslib/AltosConvert.java b/altoslib/AltosConvert.java
index 8f214c8b..dc0fbb62 100644
--- a/altoslib/AltosConvert.java
+++ b/altoslib/AltosConvert.java
@@ -18,7 +18,7 @@
/*
* Sensor data conversion functions
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public class AltosConvert {
/*
@@ -208,7 +208,7 @@ public class AltosConvert {
static public double mega_battery_voltage(int v_batt) {
if (v_batt != AltosLib.MISSING)
- return 3.3 * mega_adc(v_batt) * (15.0 + 27.0) / 27.0;
+ return 3.3 * mega_adc(v_batt) * (5.6 + 10.0) / 10.0;
return AltosLib.MISSING;
}
@@ -224,10 +224,27 @@ public class AltosConvert {
return sensor / 32767.0 * supply * 127/27;
}
- static double easy_mini_voltage(int sensor) {
- double supply = 3.0;
+ static double tele_gps_voltage(int sensor) {
+ double supply = 3.3;
- return sensor / 32767.0 * supply * 127/27;
+ return sensor / 32767.0 * supply * (5.6 + 10.0) / 10.0;
+ }
+
+ static double easy_mini_voltage(int sensor, int serial) {
+ double supply = 3.3;
+ double diode_offset = 0.0;
+
+ /* early prototypes had a 3.0V regulator */
+ if (serial < 1000)
+ supply = 3.0;
+
+ /* Purple v1.0 boards had the sensor after the
+ * blocking diode, which drops about 150mV
+ */
+ if (serial < 1665)
+ diode_offset = 0.150;
+
+ return sensor / 32767.0 * supply * 127/27 + diode_offset;
}
public static double radio_to_frequency(int freq, int setting, int cal, int channel) {
@@ -332,6 +349,12 @@ public class AltosConvert {
public static AltosOrient orient = new AltosOrient();
+ public static AltosVoltage voltage = new AltosVoltage();
+
+ public static AltosLatitude latitude = new AltosLatitude();
+
+ public static AltosLongitude longitude = new AltosLongitude();
+
public static String show_gs(String format, double a) {
a = meters_to_g(a);
format = format.concat(" g");
@@ -348,4 +371,42 @@ public class AltosConvert {
csum += data[i + start];
return csum & 0xff;
}
+
+ public static double beep_value_to_freq(int value) {
+ if (value == 0)
+ return 4000;
+ return 1.0/2.0 * (24.0e6/32.0) / (double) value;
+ }
+
+ public static int beep_freq_to_value(double freq) {
+ if (freq == 0)
+ return 94;
+ return (int) Math.floor (1.0/2.0 * (24.0e6/32.0) / freq + 0.5);
+ }
+
+ public static final int BEARING_LONG = 0;
+ public static final int BEARING_SHORT = 1;
+ public static final int BEARING_VOICE = 2;
+
+ public static String bearing_to_words(int length, double bearing) {
+ String [][] bearing_string = {
+ {
+ "North", "North North East", "North East", "East North East",
+ "East", "East South East", "South East", "South South East",
+ "South", "South South West", "South West", "West South West",
+ "West", "West North West", "North West", "North North West"
+ }, {
+ "N", "NNE", "NE", "ENE",
+ "E", "ESE", "SE", "SSE",
+ "S", "SSW", "SW", "WSW",
+ "W", "WNW", "NW", "NNW"
+ }, {
+ "north", "nor nor east", "north east", "east nor east",
+ "east", "east sow east", "south east", "sow sow east",
+ "south", "sow sow west", "south west", "west sow west",
+ "west", "west nor west", "north west", "nor nor west "
+ }
+ };
+ return bearing_string[length][(int)((bearing / 90 * 8 + 1) / 2)%16];
+ }
}
diff --git a/altoslib/AltosDebug.java b/altoslib/AltosDebug.java
index 4dfb31e5..b0e52fc1 100644
--- a/altoslib/AltosDebug.java
+++ b/altoslib/AltosDebug.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.io.*;
diff --git a/altoslib/AltosDistance.java b/altoslib/AltosDistance.java
index 71ee81d7..76ca20c0 100644
--- a/altoslib/AltosDistance.java
+++ b/altoslib/AltosDistance.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public class AltosDistance extends AltosUnits {
diff --git a/altoslib/AltosEeprom.java b/altoslib/AltosEeprom.java
index 57ee73ad..020590eb 100644
--- a/altoslib/AltosEeprom.java
+++ b/altoslib/AltosEeprom.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.io.*;
import java.util.*;
@@ -43,6 +43,10 @@ public abstract class AltosEeprom implements AltosStateUpdate {
return data8[i] | (data8[i+1] << 8) | (data8[i+2] << 16) | (data8[i+3] << 24);
}
+ public boolean has_seconds() { return false; }
+
+ public int seconds() { return 0; }
+
public final static int header_length = 4;
public abstract int record_length();
diff --git a/altoslib/AltosEepromChunk.java b/altoslib/AltosEepromChunk.java
index c884b659..91eebc5a 100644
--- a/altoslib/AltosEepromChunk.java
+++ b/altoslib/AltosEepromChunk.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.text.*;
import java.util.concurrent.*;
@@ -84,6 +84,9 @@ public class AltosEepromChunk {
case AltosLib.AO_LOG_FORMAT_EASYMINI:
eeprom = new AltosEepromMini(this, offset);
break;
+ case AltosLib.AO_LOG_FORMAT_TELEGPS:
+ eeprom = new AltosEepromGPS(this, offset);
+ break;
default:
throw new ParseException("unknown eeprom format " + log_format, 0);
}
@@ -125,4 +128,4 @@ public class AltosEepromChunk {
}
}
}
-} \ No newline at end of file
+}
diff --git a/altoslib/AltosEepromDownload.java b/altoslib/AltosEepromDownload.java
index 04101079..a2dfc438 100644
--- a/altoslib/AltosEepromDownload.java
+++ b/altoslib/AltosEepromDownload.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.io.*;
import java.util.*;
@@ -132,7 +132,7 @@ public class AltosEepromDownload implements Runnable {
CheckFile(false);
}
-
+
void CaptureLog(AltosEepromLog log) throws IOException, InterruptedException, TimeoutException, ParseException {
int block, state_block = 0;
int log_format = flights.config_data.log_format;
diff --git a/altoslib/AltosEepromFile.java b/altoslib/AltosEepromFile.java
index 91ffc223..b7e446ce 100644
--- a/altoslib/AltosEepromFile.java
+++ b/altoslib/AltosEepromFile.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.io.*;
import java.util.*;
@@ -72,7 +72,17 @@ public class AltosEepromFile extends AltosStateIterable {
headers = new AltosEepromIterable(AltosEepromHeader.read(input));
start = headers.state();
- start.set_state(AltosLib.ao_flight_pad);
+ if (start.state != AltosLib.ao_flight_stateless)
+ start.set_state(AltosLib.ao_flight_pad);
+
+ if (start.log_format == AltosLib.MISSING) {
+ if (start.product != null) {
+ if (start.product.startsWith("TeleMetrum"))
+ start.log_format = AltosLib.AO_LOG_FORMAT_FULL;
+ else if (start.product.startsWith("TeleMini"))
+ start.log_format = AltosLib.AO_LOG_FORMAT_TINY;
+ }
+ }
switch (start.log_format) {
case AltosLib.AO_LOG_FORMAT_FULL:
@@ -93,6 +103,9 @@ public class AltosEepromFile extends AltosStateIterable {
case AltosLib.AO_LOG_FORMAT_EASYMINI:
body = new AltosEepromIterable(AltosEepromMini.read(input));
break;
+ case AltosLib.AO_LOG_FORMAT_TELEGPS:
+ body = new AltosEepromIterable(AltosEepromGPS.read(input));
+ break;
default:
body = new AltosEepromIterable(new LinkedList<AltosEeprom>());
break;
@@ -120,4 +133,4 @@ public class AltosEepromFile extends AltosStateIterable {
}
return new AltosEepromIterator(state, i);
}
-} \ No newline at end of file
+}
diff --git a/altoslib/AltosEepromGPS.java b/altoslib/AltosEepromGPS.java
new file mode 100644
index 00000000..3c1852c0
--- /dev/null
+++ b/altoslib/AltosEepromGPS.java
@@ -0,0 +1,153 @@
+/*
+ * 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.altoslib_4;
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
+public class AltosEepromGPS extends AltosEeprom {
+ public static final int record_length = 32;
+
+ public static final int max_sat = 12;
+
+ public int record_length() { return record_length; }
+
+ /* AO_LOG_FLIGHT elements */
+ public int flight() { return data16(0); }
+ public int start_altitude() { return data16(2); }
+ public int start_latitude() { return data32(4); }
+ public int start_longitude() { return data32(8); }
+
+ /* 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 hour() { return data8(10); }
+ public int minute() { return data8(11); }
+ public int second() { return data8(12); }
+ public int flags() { return data8(13); }
+ public int year() { return data8(14); }
+ public int month() { return data8(15); }
+ public int day() { return data8(16); }
+ public int course() { return data8(17); }
+ public int ground_speed() { return data16(18); }
+ public int climb_rate() { return data16(20); }
+ public int pdop() { return data8(22); }
+ public int hdop() { return data8(23); }
+ public int vdop() { return data8(24); }
+ public int mode() { return data8(25); }
+
+ public boolean has_seconds() { return cmd == AltosLib.AO_LOG_GPS_TIME; }
+
+ public int seconds() {
+ switch (cmd) {
+ case AltosLib.AO_LOG_GPS_TIME:
+ return second() + 60 * (minute() + 60 * (hour() + 24 * (day() + 31 * month())));
+ default:
+ return 0;
+ }
+ }
+
+ public AltosEepromGPS (AltosEepromChunk chunk, int start) throws ParseException {
+ parse_chunk(chunk, start);
+ }
+
+ public void update_state(AltosState state) {
+ super.update_state(state);
+
+ AltosGPS gps;
+
+ /* Flush any pending GPS changes */
+ if (state.gps_pending) {
+ switch (cmd) {
+ case AltosLib.AO_LOG_GPS_LAT:
+ case AltosLib.AO_LOG_GPS_LON:
+ case AltosLib.AO_LOG_GPS_ALT:
+ case AltosLib.AO_LOG_GPS_SAT:
+ case AltosLib.AO_LOG_GPS_DATE:
+ break;
+ default:
+ state.set_temp_gps();
+ break;
+ }
+ }
+
+ switch (cmd) {
+ case AltosLib.AO_LOG_FLIGHT:
+ state.set_boost_tick(tick);
+ state.set_flight(flight());
+ /* no place to log start lat/lon yet */
+ break;
+ case AltosLib.AO_LOG_GPS_TIME:
+ state.set_tick(tick);
+ gps = state.make_temp_gps(false);
+ gps.lat = latitude() / 1e7;
+ gps.lon = longitude() / 1e7;
+ gps.alt = altitude();
+
+ gps.hour = hour();
+ gps.minute = minute();
+ gps.second = second();
+
+ int flags = flags();
+
+ gps.connected = (flags & AltosLib.AO_GPS_RUNNING) != 0;
+ gps.locked = (flags & AltosLib.AO_GPS_VALID) != 0;
+ gps.nsat = (flags & AltosLib.AO_GPS_NUM_SAT_MASK) >>
+ AltosLib.AO_GPS_NUM_SAT_SHIFT;
+
+ gps.year = 2000 + year();
+ gps.month = month();
+ gps.day = day();
+ 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();
+ break;
+ }
+ }
+
+ public AltosEepromGPS (String line) {
+ parse_string(line);
+ }
+
+ static public LinkedList<AltosEeprom> read(FileInputStream input) {
+ LinkedList<AltosEeprom> tgpss = new LinkedList<AltosEeprom>();
+
+ for (;;) {
+ try {
+ String line = AltosLib.gets(input);
+ if (line == null)
+ break;
+ try {
+ AltosEepromGPS tgps = new AltosEepromGPS(line);
+ if (tgps.cmd != AltosLib.AO_LOG_INVALID)
+ tgpss.add(tgps);
+ } catch (Exception e) {
+ System.out.printf ("exception\n");
+ }
+ } catch (IOException ie) {
+ break;
+ }
+ }
+
+ return tgpss;
+ }
+}
diff --git a/altoslib/AltosEepromHeader.java b/altoslib/AltosEepromHeader.java
index 6ce7ddd3..839aa06e 100644
--- a/altoslib/AltosEepromHeader.java
+++ b/altoslib/AltosEepromHeader.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.io.*;
import java.util.*;
@@ -53,9 +53,10 @@ public class AltosEepromHeader extends AltosEeprom {
case AltosLib.AO_LOG_MANUFACTURER:
break;
case AltosLib.AO_LOG_PRODUCT:
+ state.product = data;
break;
case AltosLib.AO_LOG_LOG_FORMAT:
- state.log_format = config_a;
+ state.set_log_format(config_a);
break;
case AltosLib.AO_LOG_SERIAL_NUMBER:
state.set_serial(config_a);
@@ -162,7 +163,7 @@ public class AltosEepromHeader extends AltosEeprom {
break;
}
}
-
+
public AltosEepromHeader (String[] tokens) {
last = false;
valid = true;
@@ -269,7 +270,7 @@ public class AltosEepromHeader extends AltosEeprom {
for (AltosEepromHeader header : headers) {
header.write(out);
}
-
+
}
public AltosEepromHeader (String line) {
diff --git a/altoslib/AltosEepromIterable.java b/altoslib/AltosEepromIterable.java
index 081721b3..d6832c1b 100644
--- a/altoslib/AltosEepromIterable.java
+++ b/altoslib/AltosEepromIterable.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.io.*;
import java.util.*;
@@ -38,6 +38,13 @@ class AltosEepromOrdered implements Comparable<AltosEepromOrdered> {
if (cmd_diff != 0)
return cmd_diff;
+ if (eeprom.has_seconds() && o.eeprom.has_seconds()) {
+ int seconds_diff = eeprom.seconds() - o.eeprom.seconds();
+
+ if (seconds_diff != 0)
+ return seconds_diff;
+ }
+
int tick_diff = tick - o.tick;
if (tick_diff != 0)
@@ -116,4 +123,4 @@ public class AltosEepromIterable implements Iterable<AltosEeprom> {
eeproms = new LinkedList<AltosEeprom>();
return new AltosEepromOrderedIterator(eeproms);
}
-} \ No newline at end of file
+}
diff --git a/altoslib/AltosEepromList.java b/altoslib/AltosEepromList.java
index a9dac13a..ab853a88 100644
--- a/altoslib/AltosEepromList.java
+++ b/altoslib/AltosEepromList.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.io.*;
import java.util.*;
diff --git a/altoslib/AltosEepromLog.java b/altoslib/AltosEepromLog.java
index cc298207..1a430c03 100644
--- a/altoslib/AltosEepromLog.java
+++ b/altoslib/AltosEepromLog.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.text.*;
import java.util.concurrent.*;
diff --git a/altoslib/AltosEepromMega.java b/altoslib/AltosEepromMega.java
index b8a1b9e8..71719a26 100644
--- a/altoslib/AltosEepromMega.java
+++ b/altoslib/AltosEepromMega.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.io.*;
import java.util.*;
@@ -32,7 +32,12 @@ public class AltosEepromMega extends AltosEeprom {
public int flight() { return data16(0); }
public int ground_accel() { return data16(2); }
public int ground_pres() { return data32(4); }
- public int ground_temp() { return data32(8); }
+ public int ground_accel_along() { return data16(8); }
+ public int ground_accel_across() { return data16(10); }
+ public int ground_accel_through() { return data16(12); }
+ public int ground_roll() { return data16(14); }
+ public int ground_pitch() { return data16(16); }
+ public int ground_yaw() { return data16(18); }
/* AO_LOG_STATE elements */
public int state() { return data16(0); }
@@ -70,7 +75,14 @@ public class AltosEepromMega extends AltosEeprom {
public int year() { return data8(14); }
public int month() { return data8(15); }
public int day() { return data8(16); }
-
+ public int course() { return data8(17); }
+ public int ground_speed() { return data16(18); }
+ public int climb_rate() { return data16(20); }
+ public int pdop() { return data8(22); }
+ public int hdop() { return data8(23); }
+ public int vdop() { return data8(24); }
+ public int mode() { return data8(25); }
+
/* AO_LOG_GPS_SAT elements */
public int nsat() { return data16(0); }
public int svid(int n) { return data8(2 + n * 2); }
@@ -106,7 +118,6 @@ public class AltosEepromMega extends AltosEeprom {
state.set_flight(flight());
state.set_ground_accel(ground_accel());
state.set_ground_pressure(ground_pres());
- state.set_temperature(ground_temp() / 100.0);
break;
case AltosLib.AO_LOG_STATE:
state.set_tick(tick);
@@ -150,6 +161,7 @@ public class AltosEepromMega extends AltosEeprom {
voltages[i] = AltosConvert.mega_pyro_voltage(sense(i));
state.set_ignitor_voltage(voltages);
+ state.set_pyro_fired(pyro());
break;
case AltosLib.AO_LOG_GPS_TIME:
state.set_tick(tick);
@@ -172,6 +184,11 @@ public class AltosEepromMega extends AltosEeprom {
gps.year = 2000 + year();
gps.month = month();
gps.day = day();
+ 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();
break;
case AltosLib.AO_LOG_GPS_SAT:
state.set_tick(tick);
diff --git a/altoslib/AltosEepromMetrum2.java b/altoslib/AltosEepromMetrum2.java
index f1bca6dc..d137614a 100644
--- a/altoslib/AltosEepromMetrum2.java
+++ b/altoslib/AltosEepromMetrum2.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.io.*;
import java.util.*;
@@ -59,7 +59,7 @@ public class AltosEepromMetrum2 extends AltosEeprom {
public int year() { return data8(4); }
public int month() { return data8(5); }
public int day() { return data8(6); }
-
+
/* AO_LOG_GPS_SAT elements */
public int nsat() { return data8(0); }
public int more() { return data8(1); }
@@ -161,7 +161,7 @@ public class AltosEepromMetrum2 extends AltosEeprom {
break;
try {
AltosEepromMetrum2 metrum = new AltosEepromMetrum2(line);
-
+
if (metrum.cmd != AltosLib.AO_LOG_INVALID)
metrums.add(metrum);
} catch (Exception e) {
diff --git a/altoslib/AltosEepromMini.java b/altoslib/AltosEepromMini.java
index fb3b4d23..32985639 100644
--- a/altoslib/AltosEepromMini.java
+++ b/altoslib/AltosEepromMini.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.io.*;
import java.util.*;
@@ -43,7 +43,7 @@ public class AltosEepromMini extends AltosEeprom {
double voltage(AltosState state, int sensor) {
if (state.log_format == AltosLib.AO_LOG_FORMAT_EASYMINI)
- return AltosConvert.easy_mini_voltage(sensor);
+ return AltosConvert.easy_mini_voltage(sensor, state.serial);
else
return AltosConvert.tele_mini_voltage(sensor);
}
diff --git a/altoslib/AltosEepromMonitor.java b/altoslib/AltosEepromMonitor.java
index 9ab1a5ab..b97287c3 100644
--- a/altoslib/AltosEepromMonitor.java
+++ b/altoslib/AltosEepromMonitor.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public interface AltosEepromMonitor {
diff --git a/altoslib/AltosEepromTM.java b/altoslib/AltosEepromTM.java
index c8b1e60c..77fe20c5 100644
--- a/altoslib/AltosEepromTM.java
+++ b/altoslib/AltosEepromTM.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.io.*;
import java.util.*;
diff --git a/altoslib/AltosEepromTm.java b/altoslib/AltosEepromTm.java
index 049dd340..6cbb7253 100644
--- a/altoslib/AltosEepromTm.java
+++ b/altoslib/AltosEepromTm.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.io.*;
import java.util.*;
diff --git a/altoslib/AltosFile.java b/altoslib/AltosFile.java
index 37bf7075..2a738996 100644
--- a/altoslib/AltosFile.java
+++ b/altoslib/AltosFile.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.io.File;
import java.util.*;
diff --git a/altoslib/AltosFlash.java b/altoslib/AltosFlash.java
index 25c76863..8e8722c2 100644
--- a/altoslib/AltosFlash.java
+++ b/altoslib/AltosFlash.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.io.*;
diff --git a/altoslib/AltosFlashListener.java b/altoslib/AltosFlashListener.java
index b7fcd73b..8bb86bba 100644
--- a/altoslib/AltosFlashListener.java
+++ b/altoslib/AltosFlashListener.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public interface AltosFlashListener {
public void position(String label, int percent);
diff --git a/altoslib/AltosFlightReader.java b/altoslib/AltosFlightReader.java
index 86757e82..2fcd556e 100644
--- a/altoslib/AltosFlightReader.java
+++ b/altoslib/AltosFlightReader.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.text.*;
import java.io.*;
diff --git a/altosui/AltosFlightStats.java b/altoslib/AltosFlightStats.java
index 0be49c2f..56feb848 100644
--- a/altosui/AltosFlightStats.java
+++ b/altoslib/AltosFlightStats.java
@@ -15,40 +15,42 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altoslib_4;
import java.io.*;
-import org.altusmetrum.altoslib_3.*;
public class AltosFlightStats {
- double max_height;
- double max_gps_height;
- double max_speed;
- double max_acceleration;
- double[] state_speed = new double[Altos.ao_flight_invalid + 1];
- double[] state_accel = new double[Altos.ao_flight_invalid + 1];
- int[] state_count = new int[Altos.ao_flight_invalid + 1];
- double[] state_start = new double[Altos.ao_flight_invalid + 1];
- double[] state_end = new double[Altos.ao_flight_invalid + 1];
- int serial;
- int flight;
- int year, month, day;
- int hour, minute, second;
- double lat, lon;
- double pad_lat, pad_lon;
- boolean has_gps;
- boolean has_other_adc;
- boolean has_rssi;
- boolean has_imu;
- boolean has_mag;
- boolean has_orient;
+ public double max_height;
+ public double max_gps_height;
+ public double max_speed;
+ public double max_acceleration;
+ public double[] state_speed = new double[AltosLib.ao_flight_invalid + 1];
+ public double[] state_accel = new double[AltosLib.ao_flight_invalid + 1];
+ public int[] state_count = new int[AltosLib.ao_flight_invalid + 1];
+ public double[] state_start = new double[AltosLib.ao_flight_invalid + 1];
+ public double[] state_end = new double[AltosLib.ao_flight_invalid + 1];
+ public int serial;
+ public int flight;
+ public int year, month, day;
+ public int hour, minute, second;
+ public double lat, lon;
+ public double pad_lat, pad_lon;
+ public boolean has_flight_data;
+ public boolean has_gps;
+ public boolean has_flight_adc;
+ public boolean has_battery;
+ public boolean has_rssi;
+ public boolean has_imu;
+ public boolean has_mag;
+ public boolean has_orient;
+ public int num_ignitor;
double landed_time(AltosStateIterable states) {
AltosState state = null;
for (AltosState s : states) {
state = s;
- if (state.state == Altos.ao_flight_landed)
+ if (state.state == AltosLib.ao_flight_landed)
break;
}
@@ -109,8 +111,10 @@ public class AltosFlightStats {
hour = minute = second = AltosLib.MISSING;
serial = flight = AltosLib.MISSING;
lat = lon = AltosLib.MISSING;
+ has_flight_data = false;
has_gps = false;
- has_other_adc = false;
+ has_flight_adc = false;
+ has_battery = false;
has_rssi = false;
has_imu = false;
has_mag = false;
@@ -121,16 +125,21 @@ public class AltosFlightStats {
if (flight == AltosLib.MISSING && state.flight != AltosLib.MISSING)
flight = state.flight;
if (state.battery_voltage != AltosLib.MISSING)
- has_other_adc = true;
+ has_battery = true;
+ if (state.main_voltage != AltosLib.MISSING)
+ has_flight_adc = true;
if (state.rssi != AltosLib.MISSING)
has_rssi = true;
end_time = state.time;
+ if (state.pressure() != AltosLib.MISSING)
+ has_flight_data = true;
+
int state_id = state.state;
- if (state.time >= boost_time && state_id < Altos.ao_flight_boost)
- state_id = Altos.ao_flight_boost;
- if (state.time >= landed_time && state_id < Altos.ao_flight_landed)
- state_id = Altos.ao_flight_landed;
+ if (state.time >= boost_time && state_id < AltosLib.ao_flight_boost)
+ state_id = AltosLib.ao_flight_boost;
+ if (state.time >= landed_time && state_id < AltosLib.ao_flight_landed)
+ state_id = AltosLib.ao_flight_landed;
if (state.gps != null && state.gps.locked) {
year = state.gps.year;
month = state.gps.month;
@@ -139,7 +148,12 @@ public class AltosFlightStats {
minute = state.gps.minute;
second = state.gps.second;
}
- if (0 <= state_id && state_id < Altos.ao_flight_invalid) {
+ max_height = state.max_height();
+ max_speed = state.max_speed();
+ max_acceleration = state.max_acceleration();
+ max_gps_height = state.max_gps_height();
+
+ if (0 <= state_id && state_id < AltosLib.ao_flight_invalid) {
double acceleration = state.acceleration();
double speed = state.speed();
if (acceleration != AltosLib.MISSING && speed != AltosLib.MISSING) {
@@ -151,16 +165,12 @@ public class AltosFlightStats {
state_start[state_id] = state.time;
if (state_end[state_id] < state.time)
state_end[state_id] = state.time;
- max_height = state.max_height();
- max_speed = state.max_speed();
- max_acceleration = state.max_acceleration();
- max_gps_height = state.max_gps_height();
+ }
+ if (state.pad_lat != AltosLib.MISSING) {
+ pad_lat = state.pad_lat;
+ pad_lon = state.pad_lon;
}
if (state.gps != null && state.gps.locked && state.gps.nsat >= 4) {
- if (state_id <= Altos.ao_flight_pad) {
- pad_lat = state.gps.lat;
- pad_lon = state.gps.lon;
- }
lat = state.gps.lat;
lon = state.gps.lon;
has_gps = true;
@@ -171,11 +181,16 @@ public class AltosFlightStats {
has_mag = true;
if (state.orient() != AltosLib.MISSING)
has_orient = true;
+ if (state.ignitor_voltage != null && state.ignitor_voltage.length > num_ignitor)
+ num_ignitor = state.ignitor_voltage.length;
}
- for (int s = Altos.ao_flight_startup; s <= Altos.ao_flight_landed; s++) {
+ for (int s = AltosLib.ao_flight_startup; s <= AltosLib.ao_flight_landed; s++) {
if (state_count[s] > 0) {
state_speed[s] /= state_count[s];
state_accel[s] /= state_count[s];
+ } else {
+ state_speed[s] = AltosLib.MISSING;
+ state_accel[s] = AltosLib.MISSING;
}
if (state_start[s] == 0)
state_start[s] = end_time;
diff --git a/altoslib/AltosFrequency.java b/altoslib/AltosFrequency.java
index 5770b646..7c291ea9 100644
--- a/altoslib/AltosFrequency.java
+++ b/altoslib/AltosFrequency.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public class AltosFrequency {
public double frequency;
diff --git a/altoslib/AltosGPS.java b/altoslib/AltosGPS.java
index 01e6fdbc..2708d026 100644
--- a/altoslib/AltosGPS.java
+++ b/altoslib/AltosGPS.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.text.*;
import java.util.concurrent.*;
diff --git a/altoslib/AltosGPSSat.java b/altoslib/AltosGPSSat.java
index 76fa3a56..ef24d497 100644
--- a/altoslib/AltosGPSSat.java
+++ b/altoslib/AltosGPSSat.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public class AltosGPSSat {
public int svid;
diff --git a/altoslib/AltosGreatCircle.java b/altoslib/AltosGreatCircle.java
index b884a3bc..4782c34d 100644
--- a/altoslib/AltosGreatCircle.java
+++ b/altoslib/AltosGreatCircle.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.lang.Math;
@@ -30,30 +30,12 @@ public class AltosGreatCircle implements Cloneable {
static final double rad = Math.PI / 180;
static final double earth_radius = 6371.2 * 1000; /* in meters */
- public static final int BEARING_LONG = 0;
- public static final int BEARING_SHORT = 1;
- public static final int BEARING_VOICE = 2;
+ public static final int BEARING_LONG = AltosConvert.BEARING_LONG;
+ public static final int BEARING_SHORT = AltosConvert.BEARING_SHORT;
+ public static final int BEARING_VOICE = AltosConvert.BEARING_VOICE;
public String bearing_words(int length) {
- String [][] bearing_string = {
- {
- "North", "North North East", "North East", "East North East",
- "East", "East South East", "South East", "South South East",
- "South", "South South West", "South West", "West South West",
- "West", "West North West", "North West", "North North West"
- }, {
- "N", "NNE", "NE", "ENE",
- "E", "ESE", "SE", "SSE",
- "S", "SSW", "SW", "WSW",
- "W", "WNW", "NW", "NNW"
- }, {
- "north", "nor nor east", "north east", "east nor east",
- "east", "east sow east", "south east", "sow sow east",
- "south", "sow sow west", "south west", "west sow west",
- "west", "west nor west", "north west", "nor nor west "
- }
- };
- return bearing_string[length][(int)((bearing / 90 * 8 + 1) / 2)%16];
+ return AltosConvert.bearing_to_words(length, bearing);
}
public AltosGreatCircle (double start_lat, double start_lon, double start_alt,
diff --git a/altoslib/AltosHeight.java b/altoslib/AltosHeight.java
index a81897e7..84981032 100644
--- a/altoslib/AltosHeight.java
+++ b/altoslib/AltosHeight.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public class AltosHeight extends AltosUnits {
diff --git a/altoslib/AltosHexfile.java b/altoslib/AltosHexfile.java
index 60f4ecdc..d5fa8f5f 100644
--- a/altoslib/AltosHexfile.java
+++ b/altoslib/AltosHexfile.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.io.*;
import java.util.LinkedList;
diff --git a/altoslib/AltosHexsym.java b/altoslib/AltosHexsym.java
index a98ef0fc..403b5644 100644
--- a/altoslib/AltosHexsym.java
+++ b/altoslib/AltosHexsym.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public class AltosHexsym {
String name;
diff --git a/altoslib/AltosIMU.java b/altoslib/AltosIMU.java
index 260f3587..a22b3fed 100644
--- a/altoslib/AltosIMU.java
+++ b/altoslib/AltosIMU.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.util.concurrent.*;
@@ -28,6 +28,18 @@ public class AltosIMU implements Cloneable {
public double gyro_y;
public double gyro_z;
+/*
+ * XXX use ground measurements to adjust values
+
+ public double ground_accel_x;
+ public double ground_accel_y;
+ public double ground_accel_z;
+
+ public double ground_gyro_x;
+ public double ground_gyro_y;
+ public double ground_gyro_z;
+*/
+
public static int counts_per_g = 2048;
public static double convert_accel(int counts) {
diff --git a/altoslib/AltosIdle.java b/altoslib/AltosIdle.java
index c7b546b6..55f6f5c9 100644
--- a/altoslib/AltosIdle.java
+++ b/altoslib/AltosIdle.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.io.*;
import java.util.*;
diff --git a/altoslib/AltosIdleFetch.java b/altoslib/AltosIdleFetch.java
index 02cb7a94..5cd8bf36 100644
--- a/altoslib/AltosIdleFetch.java
+++ b/altoslib/AltosIdleFetch.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.io.*;
import java.util.*;
@@ -142,7 +142,7 @@ public class AltosIdleFetch implements AltosStateUpdate {
state.set_received_time(System.currentTimeMillis());
} catch (TimeoutException te) {
}
-
+
}
public AltosIdleFetch(AltosLink link) {
diff --git a/altoslib/AltosIdleMonitor.java b/altoslib/AltosIdleMonitor.java
index 8342f8a5..f81abdff 100644
--- a/altoslib/AltosIdleMonitor.java
+++ b/altoslib/AltosIdleMonitor.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.io.*;
import java.util.concurrent.*;
diff --git a/altoslib/AltosIdleMonitorListener.java b/altoslib/AltosIdleMonitorListener.java
index dcaa77a6..6a9abea2 100644
--- a/altoslib/AltosIdleMonitorListener.java
+++ b/altoslib/AltosIdleMonitorListener.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public interface AltosIdleMonitorListener {
public void update(AltosState state, AltosListenerState listener_state);
diff --git a/altoslib/AltosIgnite.java b/altoslib/AltosIgnite.java
index 8ab47d1d..c21f17ac 100644
--- a/altoslib/AltosIgnite.java
+++ b/altoslib/AltosIgnite.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.util.*;
import java.io.*;
diff --git a/altosui/AltosKML.java b/altoslib/AltosKML.java
index ae1f8259..d55da9ef 100644
--- a/altosui/AltosKML.java
+++ b/altoslib/AltosKML.java
@@ -15,10 +15,9 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altoslib_4;
import java.io.*;
-import org.altusmetrum.altoslib_3.*;
public class AltosKML implements AltosWriter {
@@ -95,7 +94,7 @@ public class AltosKML implements AltosWriter {
boolean started = false;
void state_start(AltosState state) {
- String state_name = Altos.state_name(state.state);
+ String state_name = AltosLib.state_name(state.state);
out.printf(kml_style_start, state_name, kml_state_colors[state.state]);
out.printf("\tState: %s\n", state_name);
out.printf("%s", kml_style_end);
diff --git a/altoslib/AltosLatitude.java b/altoslib/AltosLatitude.java
new file mode 100644
index 00000000..6156d6dc
--- /dev/null
+++ b/altoslib/AltosLatitude.java
@@ -0,0 +1,23 @@
+/*
+ * 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.altoslib_4;
+
+public class AltosLatitude extends AltosLocation {
+ public String pos() { return "N"; }
+ public String neg() { return "S"; }
+}
diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java
index 05f0af8d..69c6d604 100644
--- a/altoslib/AltosLib.java
+++ b/altoslib/AltosLib.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.util.*;
import java.io.*;
@@ -79,6 +79,7 @@ public class AltosLib {
public static final int ao_flight_main = 7;
public static final int ao_flight_landed = 8;
public static final int ao_flight_invalid = 9;
+ public static final int ao_flight_stateless = 10;
/* USB product IDs */
public final static int vendor_altusmetrum = 0xfffe;
@@ -187,6 +188,7 @@ public class AltosLib {
string_to_state.put("main", ao_flight_main);
string_to_state.put("landed", ao_flight_landed);
string_to_state.put("invalid", ao_flight_invalid);
+ string_to_state.put("stateless", ao_flight_stateless);
map_initialized = true;
}
@@ -203,7 +205,7 @@ public class AltosLib {
throw new IllegalArgumentException(String.format("Invalid telemetry %d",
telemetry));
}
-
+
private static String[] state_to_string = {
"startup",
"idle",
@@ -215,6 +217,7 @@ public class AltosLib {
"main",
"landed",
"invalid",
+ "stateless",
};
private static String[] state_to_string_capital = {
@@ -228,6 +231,7 @@ public class AltosLib {
"Main",
"Landed",
"Invalid",
+ "Stateless",
};
public static int state(String state) {
@@ -265,6 +269,7 @@ public class AltosLib {
public static final int AO_LOG_FORMAT_EASYMINI = 6;
public static final int AO_LOG_FORMAT_TELEMETRUM = 7;
public static final int AO_LOG_FORMAT_TELEMINI = 8;
+ public static final int AO_LOG_FORMAT_TELEGPS = 9;
public static final int AO_LOG_FORMAT_NONE = 127;
public static boolean isspace(int c) {
@@ -479,4 +484,8 @@ public class AltosLib {
default: return "unknown";
}
}
+
+ public static String ignitor_name(int i) {
+ return String.format("Ignitor %c", 'A' + i);
+ }
}
diff --git a/altoslib/AltosLine.java b/altoslib/AltosLine.java
index 9d796a89..f9c712a3 100644
--- a/altoslib/AltosLine.java
+++ b/altoslib/AltosLine.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public class AltosLine {
public String line;
diff --git a/altoslib/AltosLink.java b/altoslib/AltosLink.java
index 97fa7062..7f434a06 100644
--- a/altoslib/AltosLink.java
+++ b/altoslib/AltosLink.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.io.*;
import java.util.concurrent.*;
@@ -76,7 +76,7 @@ public abstract class AltosLink implements Runnable {
return get_reply(5000);
}
-
+
public abstract boolean can_cancel_reply();
public abstract boolean show_reply_timeout();
public abstract void hide_reply_timeout();
@@ -215,7 +215,7 @@ public abstract class AltosLink implements Runnable {
break;
}
}
-
+
} finally {
--in_reply;
}
diff --git a/altoslib/AltosListenerState.java b/altoslib/AltosListenerState.java
index 53ed33f9..5bf761b0 100644
--- a/altoslib/AltosListenerState.java
+++ b/altoslib/AltosListenerState.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public class AltosListenerState {
public int crc_errors;
diff --git a/altoslib/AltosLocation.java b/altoslib/AltosLocation.java
new file mode 100644
index 00000000..725a02ba
--- /dev/null
+++ b/altoslib/AltosLocation.java
@@ -0,0 +1,66 @@
+/*
+ * 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.altoslib_4;
+
+public abstract class AltosLocation extends AltosUnits {
+
+ public abstract String pos();
+ public abstract String neg();
+
+ public double value(double v, boolean imperial_units) {
+ return v;
+ }
+
+ public double inverse(double v, boolean imperial_units) {
+ return v;
+ }
+
+ public String show_units(boolean imperial_units) {
+ return "°";
+ }
+
+ public String say_units(boolean imperial_units) {
+ return "degrees";
+ }
+
+ public int show_fraction(int width, boolean imperial_units) {
+ return 2;
+ }
+
+ public String show(int width, double v, boolean imperial_units) {
+ String h = pos();
+ if (v < 0) {
+ h = neg();
+ v = -v;
+ }
+ int deg = (int) Math.floor(v);
+ double min = (v - Math.floor(v)) * 60.0;
+ return String.format("%s %4d° %9.6f", h, deg, min);
+ }
+
+ public String say(double v, boolean imperial_units) {
+ String h = pos();
+ if (v < 0) {
+ h = neg();
+ v = -v;
+ }
+ int deg = (int) Math.floor(v);
+ double min = (v - Math.floor(v)) * 60.0;
+ return String.format("%s %d degrees %d", h, deg, (int) Math.floor(min + 0.5));
+ }
+}
diff --git a/altoslib/AltosLog.java b/altoslib/AltosLog.java
index 70c017b7..c4e9e425 100644
--- a/altoslib/AltosLog.java
+++ b/altoslib/AltosLog.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.io.*;
import java.text.*;
@@ -48,6 +48,7 @@ public class AltosLog implements Runnable {
}
public void close() {
+ link.remove_monitor(input_queue);
close_log_file();
if (log_thread != null) {
log_thread.interrupt();
diff --git a/altoslib/AltosLongitude.java b/altoslib/AltosLongitude.java
new file mode 100644
index 00000000..29a5dcd4
--- /dev/null
+++ b/altoslib/AltosLongitude.java
@@ -0,0 +1,23 @@
+/*
+ * 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.altoslib_4;
+
+public class AltosLongitude extends AltosLocation {
+ public String pos() { return "E"; }
+ public String neg() { return "W"; }
+}
diff --git a/altoslib/AltosMag.java b/altoslib/AltosMag.java
index d2bb9da6..9262de2d 100644
--- a/altoslib/AltosMag.java
+++ b/altoslib/AltosMag.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.util.concurrent.*;
@@ -87,4 +87,3 @@ public class AltosMag implements Cloneable {
}
}
}
- \ No newline at end of file
diff --git a/altoslib/AltosMma655x.java b/altoslib/AltosMma655x.java
index 0d90c351..cb2e63d4 100644
--- a/altoslib/AltosMma655x.java
+++ b/altoslib/AltosMma655x.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.util.concurrent.*;
diff --git a/altoslib/AltosMs5607.java b/altoslib/AltosMs5607.java
index 97d08c3e..5aa3a7ec 100644
--- a/altoslib/AltosMs5607.java
+++ b/altoslib/AltosMs5607.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.util.concurrent.*;
@@ -44,7 +44,7 @@ public class AltosMs5607 {
//int P;
dT = raw_temp - ((int) tref << 8);
-
+
TEMP = (int) (2000 + (((long) dT * (long) tempsens) >> 23));
if (ms5611) {
@@ -55,7 +55,7 @@ public class AltosMs5607 {
OFF = ((long) off << 17) + (((long) tco * (long) dT) >> 6);
SENS = ((long) sens << 16) + (((long) tcs * (long) dT) >> 7);
- }
+ }
if (TEMP < 2000) {
int T2 = (int) (((long) dT * (long) dT) >> 31);
diff --git a/altoslib/AltosNoSymbol.java b/altoslib/AltosNoSymbol.java
index 791899c0..f5e53b8c 100644
--- a/altoslib/AltosNoSymbol.java
+++ b/altoslib/AltosNoSymbol.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public class AltosNoSymbol extends Exception {
public AltosNoSymbol(String name) {
diff --git a/altoslib/AltosOrient.java b/altoslib/AltosOrient.java
index d916a0fb..5fcbe28d 100644
--- a/altoslib/AltosOrient.java
+++ b/altoslib/AltosOrient.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public class AltosOrient extends AltosUnits {
diff --git a/altoslib/AltosParse.java b/altoslib/AltosParse.java
index 5137fef8..1bff7682 100644
--- a/altoslib/AltosParse.java
+++ b/altoslib/AltosParse.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.text.*;
diff --git a/altoslib/AltosPreferences.java b/altoslib/AltosPreferences.java
index b8920d26..d299f27b 100644
--- a/altoslib/AltosPreferences.java
+++ b/altoslib/AltosPreferences.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.io.*;
import java.util.*;
@@ -55,7 +55,7 @@ public class AltosPreferences {
/* Launcher channel preference name */
public final static String launcherChannelPreference = "LAUNCHER-CHANNEL";
-
+
/* Default logdir is ~/TeleMetrum */
public final static String logdirName = "TeleMetrum";
@@ -349,7 +349,7 @@ public class AltosPreferences {
return launcher_channel;
}
}
-
+
public static AltosPreferencesBackend bt_devices() {
synchronized (backend) {
return backend.node("bt_devices");
diff --git a/altoslib/AltosPreferencesBackend.java b/altoslib/AltosPreferencesBackend.java
index 2eb29702..461b5c80 100644
--- a/altoslib/AltosPreferencesBackend.java
+++ b/altoslib/AltosPreferencesBackend.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.io.File;
diff --git a/altoslib/AltosProgrammer.java b/altoslib/AltosProgrammer.java
index 750e1f02..c96f04ca 100644
--- a/altoslib/AltosProgrammer.java
+++ b/altoslib/AltosProgrammer.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.io.*;
diff --git a/altoslib/AltosPyro.java b/altoslib/AltosPyro.java
index aefc6fbd..9e47bc80 100644
--- a/altoslib/AltosPyro.java
+++ b/altoslib/AltosPyro.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.util.*;
import java.text.*;
@@ -105,7 +105,7 @@ public class AltosPyro {
private static HashMap<Integer,AltosUnits> pyro_to_units = new HashMap<Integer,AltosUnits>();
private static HashMap<Integer,Double> pyro_to_scale = new HashMap<Integer,Double>();
-
+
private static void insert_map(int flag, String string, String name, AltosUnits units, double scale) {
string_to_pyro.put(string, flag);
pyro_to_string.put(flag, string);
@@ -114,7 +114,7 @@ public class AltosPyro {
pyro_to_units.put(flag, units);
pyro_to_scale.put(flag, scale);
}
-
+
public static int string_to_pyro(String name) {
if (string_to_pyro.containsKey(name))
return string_to_pyro.get(name);
@@ -174,7 +174,7 @@ public class AltosPyro {
insert_map(pyro_after_motor, pyro_after_motor_string, pyro_after_motor_name, null, 1.0);
insert_map(pyro_delay, pyro_delay_string, pyro_delay_name, null, pyro_delay_scale);
-
+
insert_map(pyro_state_less, pyro_state_less_string, pyro_state_less_name, null, 1.0);
insert_map(pyro_state_greater_or_equal, pyro_state_greater_or_equal_string, pyro_state_greater_or_equal_name, null, 1.0);
}
diff --git a/altoslib/AltosReplayReader.java b/altoslib/AltosReplayReader.java
index 4cf642ca..bf7e0e5b 100644
--- a/altoslib/AltosReplayReader.java
+++ b/altoslib/AltosReplayReader.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.io.*;
import java.util.*;
@@ -39,7 +39,7 @@ 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)
+ if (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());
}
diff --git a/altoslib/AltosRomconfig.java b/altoslib/AltosRomconfig.java
index 1273fbc6..10df11af 100644
--- a/altoslib/AltosRomconfig.java
+++ b/altoslib/AltosRomconfig.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.io.*;
@@ -144,7 +144,7 @@ public class AltosRomconfig {
ao_romconfig_check,
ao_serial_number
};
-
+
private static boolean name_required(String name) {
for (String required : required_names)
if (name.equals(required))
diff --git a/altoslib/AltosSelfFlash.java b/altoslib/AltosSelfFlash.java
index aae993eb..502c6d65 100644
--- a/altoslib/AltosSelfFlash.java
+++ b/altoslib/AltosSelfFlash.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.io.*;
@@ -47,7 +47,7 @@ public class AltosSelfFlash extends AltosProgrammer {
for (int offset = 0; offset < len; offset += 0x100) {
link.printf("R %x\n", addr + offset);
byte[] reply = link.get_binary_reply(5000, 0x100);
-
+
if (reply == null)
throw new IOException("Read device memory timeout");
for (b = 0; b < len; b++)
@@ -55,7 +55,7 @@ public class AltosSelfFlash extends AltosProgrammer {
}
return data;
}
-
+
void write_memory(long addr, byte[] data, int start, int len) {
int b;
link.printf("W %x\n", addr);
diff --git a/altoslib/AltosSensorEMini.java b/altoslib/AltosSensorEMini.java
index f888754c..ee0238f9 100644
--- a/altoslib/AltosSensorEMini.java
+++ b/altoslib/AltosSensorEMini.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.util.concurrent.TimeoutException;
@@ -31,10 +31,10 @@ public class AltosSensorEMini {
if (sensor_emini == null)
return;
- state.set_battery_voltage(AltosConvert.easy_mini_voltage(sensor_emini.batt));
- state.set_apogee_voltage(AltosConvert.easy_mini_voltage(sensor_emini.apogee));
- state.set_main_voltage(AltosConvert.easy_mini_voltage(sensor_emini.main));
-
+ state.set_battery_voltage(AltosConvert.easy_mini_voltage(sensor_emini.batt, config_data.serial));
+ state.set_apogee_voltage(AltosConvert.easy_mini_voltage(sensor_emini.apogee, config_data.serial));
+ state.set_main_voltage(AltosConvert.easy_mini_voltage(sensor_emini.main, config_data.serial));
+
} catch (TimeoutException te) {
}
}
diff --git a/altoslib/AltosSensorMM.java b/altoslib/AltosSensorMM.java
index 0c23d671..e34e71b7 100644
--- a/altoslib/AltosSensorMM.java
+++ b/altoslib/AltosSensorMM.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.util.concurrent.TimeoutException;
diff --git a/altoslib/AltosSensorMega.java b/altoslib/AltosSensorMega.java
index c52f688d..02f3a256 100644
--- a/altoslib/AltosSensorMega.java
+++ b/altoslib/AltosSensorMega.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.util.concurrent.TimeoutException;
diff --git a/altoslib/AltosSensorMetrum.java b/altoslib/AltosSensorMetrum.java
index bb794a1e..e5421ef5 100644
--- a/altoslib/AltosSensorMetrum.java
+++ b/altoslib/AltosSensorMetrum.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.util.concurrent.TimeoutException;
diff --git a/altoslib/AltosSensorTM.java b/altoslib/AltosSensorTM.java
index b8f54bcb..2d60d8cf 100644
--- a/altoslib/AltosSensorTM.java
+++ b/altoslib/AltosSensorTM.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.util.concurrent.TimeoutException;
@@ -40,7 +40,7 @@ public class AltosSensorTM {
state.set_battery_voltage(AltosConvert.cc_battery_to_voltage(sensor_tm.batt));
state.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(sensor_tm.drogue));
state.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(sensor_tm.main));
-
+
} catch (TimeoutException te) {
}
}
diff --git a/altoslib/AltosSensorTMini.java b/altoslib/AltosSensorTMini.java
index 35857e35..b9eeca0c 100644
--- a/altoslib/AltosSensorTMini.java
+++ b/altoslib/AltosSensorTMini.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.util.concurrent.TimeoutException;
@@ -31,10 +31,10 @@ public class AltosSensorTMini {
if (sensor_tmini == null)
return;
- state.set_battery_voltage(AltosConvert.easy_mini_voltage(sensor_tmini.batt));
- state.set_apogee_voltage(AltosConvert.easy_mini_voltage(sensor_tmini.apogee));
- state.set_main_voltage(AltosConvert.easy_mini_voltage(sensor_tmini.main));
-
+ state.set_battery_voltage(AltosConvert.tele_mini_voltage(sensor_tmini.batt));
+ state.set_apogee_voltage(AltosConvert.tele_mini_voltage(sensor_tmini.apogee));
+ state.set_main_voltage(AltosConvert.tele_mini_voltage(sensor_tmini.main));
+
} catch (TimeoutException te) {
}
}
diff --git a/altoslib/AltosSpeed.java b/altoslib/AltosSpeed.java
index d93229dd..9134f5f4 100644
--- a/altoslib/AltosSpeed.java
+++ b/altoslib/AltosSpeed.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public class AltosSpeed extends AltosUnits {
diff --git a/altoslib/AltosState.java b/altoslib/AltosState.java
index 758fd636..b05cd358 100644
--- a/altoslib/AltosState.java
+++ b/altoslib/AltosState.java
@@ -19,7 +19,7 @@
* Track flight state from telemetry or eeprom data stream
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public class AltosState implements Cloneable {
@@ -50,12 +50,13 @@ public class AltosState implements Cloneable {
private double set_time;
private double prev_set_time;
+ boolean can_max() { return true; }
+
void set(double new_value, double time) {
if (new_value != AltosLib.MISSING) {
value = new_value;
- if (max_value == AltosLib.MISSING || value > max_value) {
+ if (can_max() && (max_value == AltosLib.MISSING || value > max_value))
max_value = value;
- }
set_time = time;
}
}
@@ -108,7 +109,7 @@ public class AltosState implements Cloneable {
void set_derivative(AltosValue in) {
double n = in.rate();
-
+
if (n == AltosLib.MISSING)
return;
@@ -123,7 +124,7 @@ public class AltosState implements Cloneable {
/* Clip changes to reduce noise */
double ddt = in.time() - pt;
double ddv = (n - p) / ddt;
-
+
final double max = 100000;
/* 100gs */
@@ -246,11 +247,11 @@ public class AltosState implements Cloneable {
void set_integral(AltosValue in) {
computed.set_integral(in);
}
-
+
void set_integral(AltosCValue in) {
set_integral(in.altos_value());
}
-
+
void copy(AltosCValue old) {
measured.copy(old.measured);
computed.copy(old.computed);
@@ -337,7 +338,7 @@ public class AltosState implements Cloneable {
}
private AltosGroundPressure ground_pressure;
-
+
public double ground_pressure() {
return ground_pressure.value();
}
@@ -388,6 +389,11 @@ public class AltosState implements Cloneable {
private AltosGpsAltitude gps_altitude;
+ private AltosValue gps_ground_speed;
+ private AltosValue gps_ascent_rate;
+ private AltosValue gps_course;
+ private AltosValue gps_speed;
+
public double altitude() {
double a = altitude.value();
if (a != AltosLib.MISSING)
@@ -418,6 +424,34 @@ public class AltosState implements Cloneable {
gps_altitude.set(new_gps_altitude, time);
}
+ public double gps_ground_speed() {
+ return gps_ground_speed.value();
+ }
+
+ public double max_gps_ground_speed() {
+ return gps_ground_speed.max();
+ }
+
+ public double gps_ascent_rate() {
+ return gps_ascent_rate.value();
+ }
+
+ public double max_gps_ascent_rate() {
+ return gps_ascent_rate.max();
+ }
+
+ public double gps_course() {
+ return gps_course.value();
+ }
+
+ public double gps_speed() {
+ return gps_speed.value();
+ }
+
+ public double max_gps_speed() {
+ return gps_speed.max();
+ }
+
class AltosPressure extends AltosValue {
void set(double p, double time) {
super.set(p, time);
@@ -447,7 +481,7 @@ public class AltosState implements Cloneable {
double g = ground_altitude();
if (a != AltosLib.MISSING && g != AltosLib.MISSING)
return a - g;
- return AltosLib.MISSING;
+ return gps_height();
}
public double max_height() {
@@ -459,7 +493,7 @@ public class AltosState implements Cloneable {
double g = ground_altitude();
if (a != AltosLib.MISSING && g != AltosLib.MISSING)
return a - g;
- return AltosLib.MISSING;
+ return max_gps_height();
}
public double gps_height() {
@@ -481,7 +515,11 @@ public class AltosState implements Cloneable {
}
class AltosSpeed extends AltosCValue {
-
+
+ boolean can_max() {
+ return state < AltosLib.ao_flight_fast || state == AltosLib.ao_flight_stateless;
+ }
+
void set_accel() {
acceleration.set_derivative(this);
}
@@ -508,17 +546,34 @@ public class AltosState implements Cloneable {
double v = kalman_speed.value();
if (v != AltosLib.MISSING)
return v;
- return speed.value();
+ v = speed.value();
+ if (v != AltosLib.MISSING)
+ return v;
+ v = gps_speed();
+ if (v != AltosLib.MISSING)
+ return v;
+ return AltosLib.MISSING;
}
public double max_speed() {
double v = kalman_speed.max();
if (v != AltosLib.MISSING)
return v;
- return speed.max();
+ v = speed.max();
+ if (v != AltosLib.MISSING)
+ return v;
+ v = max_gps_speed();
+ if (v != AltosLib.MISSING)
+ return v;
+ return AltosLib.MISSING;
}
class AltosAccel extends AltosCValue {
+
+ boolean can_max() {
+ return state < AltosLib.ao_flight_fast || state == AltosLib.ao_flight_stateless;
+ }
+
void set_measured(double a, double time) {
super.set_measured(a, time);
if (ascent)
@@ -604,11 +659,14 @@ public class AltosState implements Cloneable {
public double ground_accel_avg;
public int log_format;
+ public String product;
public AltosMs5607 baro;
public AltosCompanion companion;
+ public int pyro_fired;
+
public void set_npad(int npad) {
this.npad = npad;
gps_waiting = MIN_PAD_SAMPLES - npad;
@@ -682,11 +740,16 @@ public class AltosState implements Cloneable {
gps_altitude = new AltosGpsAltitude();
gps_ground_altitude = new AltosGpsGroundAltitude();
+ gps_ground_speed = new AltosValue();
+ gps_speed = new AltosValue();
+ gps_ascent_rate = new AltosValue();
+ gps_course = new AltosValue();
speak_tick = AltosLib.MISSING;
speak_altitude = AltosLib.MISSING;
callsign = null;
+ firmware_version = null;
accel_plus_g = AltosLib.MISSING;
accel_minus_g = AltosLib.MISSING;
@@ -696,11 +759,14 @@ public class AltosState implements Cloneable {
ground_accel_avg = AltosLib.MISSING;
log_format = AltosLib.MISSING;
+ product = null;
serial = AltosLib.MISSING;
receiver_serial = AltosLib.MISSING;
baro = null;
companion = null;
+
+ pyro_fired = 0;
}
void finish_update() {
@@ -729,7 +795,7 @@ public class AltosState implements Cloneable {
time = old.time;
time_change = old.time_change;
prev_time = old.time;
-
+
tick = old.tick;
prev_tick = old.tick;
boost_tick = old.boost_tick;
@@ -747,7 +813,7 @@ public class AltosState implements Cloneable {
apogee_delay = old.apogee_delay;
main_deploy = old.main_deploy;
flight_log_max = old.flight_log_max;
-
+
set = 0;
ground_pressure.copy(old.ground_pressure);
@@ -808,6 +874,10 @@ public class AltosState implements Cloneable {
gps_altitude.copy(old.gps_altitude);
gps_ground_altitude.copy(old.gps_ground_altitude);
+ gps_ground_speed.copy(old.gps_ground_speed);
+ gps_ascent_rate.copy(old.gps_ascent_rate);
+ gps_course.copy(old.gps_course);
+ gps_speed.copy(old.gps_speed);
pad_lat = old.pad_lat;
pad_lon = old.pad_lon;
@@ -817,6 +887,7 @@ public class AltosState implements Cloneable {
speak_altitude = old.speak_altitude;
callsign = old.callsign;
+ firmware_version = old.firmware_version;
accel_plus_g = old.accel_plus_g;
accel_minus_g = old.accel_minus_g;
@@ -825,28 +896,31 @@ public class AltosState implements Cloneable {
ground_accel_avg = old.ground_accel_avg;
log_format = old.log_format;
+ product = old.product;
serial = old.serial;
receiver_serial = old.receiver_serial;
baro = old.baro;
companion = old.companion;
+
+ pyro_fired = old.pyro_fired;
}
-
+
void update_time() {
}
void update_gps() {
- elevation = 0;
- range = -1;
+ elevation = AltosLib.MISSING;
+ range = AltosLib.MISSING;
if (gps == null)
return;
if (gps.locked && gps.nsat >= 4) {
/* Track consecutive 'good' gps reports, waiting for 10 of them */
- if (state == AltosLib.ao_flight_pad) {
+ if (state == AltosLib.ao_flight_pad || state == AltosLib.ao_flight_stateless) {
set_npad(npad+1);
- if (pad_lat != AltosLib.MISSING) {
+ if (pad_lat != AltosLib.MISSING && (npad < 10 || state == AltosLib.ao_flight_pad)) {
pad_lat = (pad_lat * 31 + gps.lat) / 32;
pad_lon = (pad_lon * 31 + gps.lon) / 32;
gps_ground_altitude.set_filtered(gps.alt, time);
@@ -858,6 +932,15 @@ public class AltosState implements Cloneable {
gps_ground_altitude.set(gps.alt, time);
}
gps_altitude.set(gps.alt, time);
+ if (gps.climb_rate != AltosLib.MISSING)
+ gps_ascent_rate.set(gps.climb_rate, time);
+ if (gps.ground_speed != AltosLib.MISSING)
+ gps_ground_speed.set(gps.ground_speed, time);
+ if (gps.climb_rate != AltosLib.MISSING && gps.ground_speed != AltosLib.MISSING)
+ gps_speed.set(Math.sqrt(gps.ground_speed * gps.ground_speed +
+ gps.climb_rate * gps.climb_rate), time);
+ if (gps.course != AltosLib.MISSING)
+ gps_course.set(gps.course, time);
}
if (gps.lat != 0 && gps.lon != 0 &&
pad_lat != AltosLib.MISSING &&
@@ -902,18 +985,34 @@ public class AltosState implements Cloneable {
state <= AltosLib.ao_flight_coast);
boost = (AltosLib.ao_flight_boost == state);
}
-
}
public void set_device_type(int device_type) {
this.device_type = device_type;
+ switch (device_type) {
+ case AltosLib.product_telegps:
+ this.state = AltosLib.ao_flight_stateless;
+ break;
+ }
}
- public void set_config(int major, int minor, int apogee_delay, int main_deploy, int flight_log_max) {
- config_major = major;
- config_minor = minor;
+ public void set_log_format(int log_format) {
+ this.log_format = log_format;
+ switch (log_format) {
+ case AltosLib.AO_LOG_FORMAT_TELEGPS:
+ this.state = AltosLib.ao_flight_stateless;
+ break;
+ }
+ }
+
+ public void set_flight_params(int apogee_delay, int main_deploy) {
this.apogee_delay = apogee_delay;
this.main_deploy = main_deploy;
+ }
+
+ public void set_config(int major, int minor, int flight_log_max) {
+ config_major = major;
+ config_minor = minor;
this.flight_log_max = flight_log_max;
}
@@ -1104,6 +1203,10 @@ public class AltosState implements Cloneable {
this.ignitor_voltage = voltage;
}
+ public void set_pyro_fired(int fired) {
+ this.pyro_fired = fired;
+ }
+
public double time_since_boost() {
if (tick == AltosLib.MISSING)
return 0.0;
diff --git a/altoslib/AltosStateIterable.java b/altoslib/AltosStateIterable.java
index 5a919b66..be812095 100644
--- a/altoslib/AltosStateIterable.java
+++ b/altoslib/AltosStateIterable.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.io.*;
import java.util.*;
@@ -24,6 +24,6 @@ public abstract class AltosStateIterable implements Iterable<AltosState> {
public void write_comments (PrintStream out) {
}
-
+
public abstract void write(PrintStream out);
}
diff --git a/altoslib/AltosStateUpdate.java b/altoslib/AltosStateUpdate.java
index 4614c67a..ac4e963e 100644
--- a/altoslib/AltosStateUpdate.java
+++ b/altoslib/AltosStateUpdate.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public interface AltosStateUpdate {
public void update_state(AltosState state) throws InterruptedException;
diff --git a/altoslib/AltosTelemetry.java b/altoslib/AltosTelemetry.java
index 01bedd5e..8182ec6b 100644
--- a/altoslib/AltosTelemetry.java
+++ b/altoslib/AltosTelemetry.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.text.*;
@@ -43,9 +43,9 @@ public abstract class AltosTelemetry implements AltosStateUpdate {
}
public void update_state(AltosState state) {
+ state.set_serial(serial);
if (state.state == AltosLib.ao_flight_invalid)
state.set_state(AltosLib.ao_flight_startup);
- state.set_serial(serial);
state.set_tick(tick);
state.set_rssi(rssi, status);
state.set_received_time(received_time);
@@ -67,7 +67,7 @@ public abstract class AltosTelemetry implements AltosStateUpdate {
final static int packet_type_metrum_sensor = 0x0a;
final static int packet_type_metrum_data = 0x0b;
final static int packet_type_mini = 0x10;
-
+
static AltosTelemetry parse_hex(String hex) throws ParseException, AltosCRCException {
AltosTelemetry telem = null;
diff --git a/altoslib/AltosTelemetryConfiguration.java b/altoslib/AltosTelemetryConfiguration.java
index 67a43748..e3884051 100644
--- a/altoslib/AltosTelemetryConfiguration.java
+++ b/altoslib/AltosTelemetryConfiguration.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public class AltosTelemetryConfiguration extends AltosTelemetryStandard {
@@ -25,6 +25,7 @@ public class AltosTelemetryConfiguration extends AltosTelemetryStandard {
int config_minor;
int apogee_delay;
int main_deploy;
+ int v_batt;
int flight_log_max;
String callsign;
String version;
@@ -36,6 +37,7 @@ public class AltosTelemetryConfiguration extends AltosTelemetryStandard {
flight = uint16(6);
config_major = uint8(8);
config_minor = uint8(9);
+ v_batt = uint16(10);
apogee_delay = uint16(10);
main_deploy = uint16(12);
flight_log_max = uint16(14);
@@ -47,7 +49,11 @@ public class AltosTelemetryConfiguration extends AltosTelemetryStandard {
super.update_state(state);
state.set_device_type(device_type);
state.set_flight(flight);
- state.set_config(config_major, config_minor, apogee_delay, main_deploy, flight_log_max);
+ state.set_config(config_major, config_minor, flight_log_max);
+ if (device_type == AltosLib.product_telegps)
+ state.set_battery_voltage(AltosConvert.tele_gps_voltage(v_batt));
+ else
+ state.set_flight_params(apogee_delay, main_deploy);
state.set_callsign(callsign);
state.set_firmware_version(version);
diff --git a/altoslib/AltosTelemetryFile.java b/altoslib/AltosTelemetryFile.java
index 09d7d3f8..3d3fa407 100644
--- a/altoslib/AltosTelemetryFile.java
+++ b/altoslib/AltosTelemetryFile.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.io.*;
import java.util.*;
@@ -62,7 +62,7 @@ public class AltosTelemetryFile extends AltosStateIterable {
}
public void write(PrintStream out) {
-
+
}
public AltosTelemetryFile(FileInputStream input) {
diff --git a/altoslib/AltosTelemetryIterable.java b/altoslib/AltosTelemetryIterable.java
index 002f53b4..cba97ddc 100644
--- a/altoslib/AltosTelemetryIterable.java
+++ b/altoslib/AltosTelemetryIterable.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.io.*;
import java.util.*;
diff --git a/altoslib/AltosTelemetryLegacy.java b/altoslib/AltosTelemetryLegacy.java
index d302addd..3367ece7 100644
--- a/altoslib/AltosTelemetryLegacy.java
+++ b/altoslib/AltosTelemetryLegacy.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.text.*;
@@ -470,7 +470,7 @@ public class AltosTelemetryLegacy extends AltosTelemetry {
batt = int16(29);
apogee = int16(31);
main = int16(33);
-
+
ground_accel = int16(7);
ground_pres = int16(15);
accel_plus_g = int16(17);
diff --git a/altoslib/AltosTelemetryLocation.java b/altoslib/AltosTelemetryLocation.java
index 8dcda9e1..8368188f 100644
--- a/altoslib/AltosTelemetryLocation.java
+++ b/altoslib/AltosTelemetryLocation.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public class AltosTelemetryLocation extends AltosTelemetryStandard {
diff --git a/altoslib/AltosTelemetryMap.java b/altoslib/AltosTelemetryMap.java
index 37b2527b..8d0de355 100644
--- a/altoslib/AltosTelemetryMap.java
+++ b/altoslib/AltosTelemetryMap.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.text.*;
import java.util.HashMap;
diff --git a/altoslib/AltosTelemetryMegaData.java b/altoslib/AltosTelemetryMegaData.java
index a4df70be..fac5695f 100644
--- a/altoslib/AltosTelemetryMegaData.java
+++ b/altoslib/AltosTelemetryMegaData.java
@@ -15,11 +15,11 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public class AltosTelemetryMegaData extends AltosTelemetryStandard {
int state;
-
+
int v_batt;
int v_pyro;
int sense[];
@@ -41,7 +41,7 @@ public class AltosTelemetryMegaData extends AltosTelemetryStandard {
v_batt = int16(6);
v_pyro = int16(8);
- sense = new int[6];
+ sense = new int[6];
for (int i = 0; i < 6; i++) {
sense[i] = int8(10 + i) << 4;
@@ -62,7 +62,7 @@ public class AltosTelemetryMegaData extends AltosTelemetryStandard {
super.update_state(state);
state.set_state(this.state);
-
+
state.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt));
state.set_pyro_voltage(AltosConvert.mega_pyro_voltage(v_pyro));
diff --git a/altoslib/AltosTelemetryMegaSensor.java b/altoslib/AltosTelemetryMegaSensor.java
index d1a463c0..9e73bc4e 100644
--- a/altoslib/AltosTelemetryMegaSensor.java
+++ b/altoslib/AltosTelemetryMegaSensor.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public class AltosTelemetryMegaSensor extends AltosTelemetryStandard {
int accel;
@@ -67,7 +67,7 @@ public class AltosTelemetryMegaSensor extends AltosTelemetryStandard {
state.set_orient(orient);
AltosIMU imu = new AltosIMU();
-
+
imu.accel_x = AltosIMU.convert_accel(accel_x);
imu.accel_y = AltosIMU.convert_accel(accel_y);
imu.accel_z = AltosIMU.convert_accel(accel_z);
diff --git a/altoslib/AltosTelemetryMetrumData.java b/altoslib/AltosTelemetryMetrumData.java
index b8f7e9ea..96617306 100644
--- a/altoslib/AltosTelemetryMetrumData.java
+++ b/altoslib/AltosTelemetryMetrumData.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public class AltosTelemetryMetrumData extends AltosTelemetryStandard {
diff --git a/altoslib/AltosTelemetryMetrumSensor.java b/altoslib/AltosTelemetryMetrumSensor.java
index 232468bb..e7055404 100644
--- a/altoslib/AltosTelemetryMetrumSensor.java
+++ b/altoslib/AltosTelemetryMetrumSensor.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public class AltosTelemetryMetrumSensor extends AltosTelemetryStandard {
diff --git a/altoslib/AltosTelemetryMini.java b/altoslib/AltosTelemetryMini.java
index e0a493dc..fbfaff8e 100644
--- a/altoslib/AltosTelemetryMini.java
+++ b/altoslib/AltosTelemetryMini.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public class AltosTelemetryMini extends AltosTelemetryStandard {
diff --git a/altoslib/AltosTelemetryRaw.java b/altoslib/AltosTelemetryRaw.java
index 91cfbb18..0dca62aa 100644
--- a/altoslib/AltosTelemetryRaw.java
+++ b/altoslib/AltosTelemetryRaw.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public class AltosTelemetryRaw extends AltosTelemetryStandard {
public AltosTelemetryRaw(int[] bytes) {
diff --git a/altoslib/AltosTelemetryReader.java b/altoslib/AltosTelemetryReader.java
index 5e283587..3dff661a 100644
--- a/altoslib/AltosTelemetryReader.java
+++ b/altoslib/AltosTelemetryReader.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
import java.text.*;
import java.io.*;
diff --git a/altoslib/AltosTelemetrySatellite.java b/altoslib/AltosTelemetrySatellite.java
index 01252bde..d611e88c 100644
--- a/altoslib/AltosTelemetrySatellite.java
+++ b/altoslib/AltosTelemetrySatellite.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public class AltosTelemetrySatellite extends AltosTelemetryStandard {
int channels;
@@ -43,7 +43,7 @@ public class AltosTelemetrySatellite extends AltosTelemetryStandard {
super.update_state(state);
AltosGPS gps = state.make_temp_gps(true);
-
+
gps.cc_gps_sat = sats;
state.set_temp_gps();
}
diff --git a/altoslib/AltosTelemetrySensor.java b/altoslib/AltosTelemetrySensor.java
index d6389865..ad4d9283 100644
--- a/altoslib/AltosTelemetrySensor.java
+++ b/altoslib/AltosTelemetrySensor.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public class AltosTelemetrySensor extends AltosTelemetryStandard {
diff --git a/altoslib/AltosTelemetryStandard.java b/altoslib/AltosTelemetryStandard.java
index c9531fcb..23ae9d21 100644
--- a/altoslib/AltosTelemetryStandard.java
+++ b/altoslib/AltosTelemetryStandard.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public abstract class AltosTelemetryStandard extends AltosTelemetry {
int[] bytes;
diff --git a/altoslib/AltosTemperature.java b/altoslib/AltosTemperature.java
index 36e26564..5fa71b86 100644
--- a/altoslib/AltosTemperature.java
+++ b/altoslib/AltosTemperature.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public class AltosTemperature extends AltosUnits {
diff --git a/altoslib/AltosUnits.java b/altoslib/AltosUnits.java
index e573a43b..d29cfae7 100644
--- a/altoslib/AltosUnits.java
+++ b/altoslib/AltosUnits.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public abstract class AltosUnits {
@@ -41,7 +41,7 @@ public abstract class AltosUnits {
public double value(double v) {
return value(v, AltosConvert.imperial_units);
}
-
+
public double inverse(double v) {
return inverse(v, AltosConvert.imperial_units);
}
@@ -49,15 +49,15 @@ public abstract class AltosUnits {
public String show_units() {
return show_units(AltosConvert.imperial_units);
}
-
+
public String say_units() {
return say_units(AltosConvert.imperial_units);
}
-
+
public int show_fraction(int width) {
return show_fraction(width, AltosConvert.imperial_units);
}
-
+
int say_fraction(boolean imperial_units) {
return 0;
}
diff --git a/altoslib/AltosUnitsListener.java b/altoslib/AltosUnitsListener.java
index e9b29f9a..ca6faafd 100644
--- a/altoslib/AltosUnitsListener.java
+++ b/altoslib/AltosUnitsListener.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_4;
public interface AltosUnitsListener {
public void units_changed(boolean imperial_units);
diff --git a/altoslib/AltosVoltage.java b/altoslib/AltosVoltage.java
new file mode 100644
index 00000000..351bf115
--- /dev/null
+++ b/altoslib/AltosVoltage.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altoslib_4;
+
+public class AltosVoltage extends AltosUnits {
+
+ public double value(double v, boolean imperial_units) {
+ return v;
+ }
+
+ public double inverse(double v, boolean imperial_units) {
+ return v;
+ }
+
+ public String show_units(boolean imperial_units) {
+ return "V";
+ }
+
+ public String say_units(boolean imperial_units) {
+ return "volts";
+ }
+
+ public int show_fraction(int width, boolean imperial_units) {
+ return 2;
+ }
+}
diff --git a/altosui/AltosWriter.java b/altoslib/AltosWriter.java
index 5ff44584..c3479a93 100644
--- a/altosui/AltosWriter.java
+++ b/altoslib/AltosWriter.java
@@ -15,10 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
-
-import org.altusmetrum.altoslib_3.*;
-
+package org.altusmetrum.altoslib_4;
public interface AltosWriter {
diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am
index 2ee4d89f..e81418bb 100644
--- a/altoslib/Makefile.am
+++ b/altoslib/Makefile.am
@@ -1,4 +1,4 @@
-AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -source 6
+AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked -source 6
JAVAROOT=bin
@@ -28,9 +28,11 @@ altoslib_JAVA = \
AltosLib.java \
AltosCompanion.java \
AltosConfigData.java \
+ AltosConfigDataException.java \
AltosConfigValues.java \
AltosConvert.java \
AltosCRCException.java \
+ AltosCSV.java \
AltosDebug.java \
AltosEeprom.java \
AltosEepromChunk.java \
@@ -45,11 +47,13 @@ altoslib_JAVA = \
AltosEepromMega.java \
AltosEepromMetrum2.java \
AltosEepromMini.java \
+ AltosEepromGPS.java \
AltosEepromMonitor.java \
AltosFile.java \
AltosFlash.java \
AltosFlashListener.java \
AltosFlightReader.java \
+ AltosFlightStats.java \
AltosFrequency.java \
AltosGPS.java \
AltosGPSSat.java \
@@ -62,6 +66,7 @@ altoslib_JAVA = \
AltosIdleMonitorListener.java \
AltosIgnite.java \
AltosIMU.java \
+ AltosKML.java \
AltosLine.java \
AltosLink.java \
AltosListenerState.java \
@@ -114,7 +119,12 @@ altoslib_JAVA = \
AltosSpeed.java \
AltosTemperature.java \
AltosAccel.java \
- AltosPyro.java
+ AltosVoltage.java \
+ AltosLocation.java \
+ AltosLatitude.java \
+ AltosLongitude.java \
+ AltosPyro.java \
+ AltosWriter.java
JAR=altoslib_$(ALTOSLIB_VERSION).jar
diff --git a/altosui/.gitignore b/altosui/.gitignore
index 4ee3f4ad..10b600e4 100644
--- a/altosui/.gitignore
+++ b/altosui/.gitignore
@@ -14,8 +14,10 @@ altosui-jdb
classaltosui.stamp
altos-windows.nsi
Altos-Linux-*.tar.bz2
+Altos-Linux-*.sh
Altos-Mac-*.zip
Altos-Windows-*.exe
+altos.desktop
*.dll
*.dylib
*.so
diff --git a/altosui/Altos.java b/altosui/Altos.java
index 4b171fa7..28038ad6 100644
--- a/altosui/Altos.java
+++ b/altosui/Altos.java
@@ -20,8 +20,8 @@ package altosui;
import java.awt.*;
import libaltosJNI.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
public class Altos extends AltosUILib {
diff --git a/altosui/AltosAscent.java b/altosui/AltosAscent.java
index 3f74fdd1..3bc80406 100644
--- a/altosui/AltosAscent.java
+++ b/altosui/AltosAscent.java
@@ -17,385 +17,151 @@
package altosui;
+import java.util.*;
import java.awt.*;
+import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
-public class AltosAscent extends JComponent implements AltosFlightDisplay {
- GridBagLayout layout;
- JLabel cur, max;
+public class AltosAscent extends AltosUIFlightTab {
+ JLabel cur, max;
- public class AscentStatus {
- JLabel label;
- JTextField value;
- AltosLights lights;
+ class Height extends AltosUIUnitsIndicator {
- void show() {
- value.setVisible(true);
- lights.setVisible(true);
- label.setVisible(true);
- }
-
- void hide() {
- value.setVisible(false);
- lights.setVisible(false);
- label.setVisible(false);
- }
-
- void show(AltosState state, AltosListenerState listener_state) {}
-
- void show(String s) {
- show();
- value.setText(s);
- }
-
- void show(AltosUnits units, double v) {
- show(units.show(8, v));
- }
-
- void show(String format, double v) {
- show(String.format(format, v));
- }
-
- void reset() {
- value.setText("");
- lights.set(false);
- }
-
- void set_font() {
- label.setFont(Altos.label_font);
- value.setFont(Altos.value_font);
+ public double value(AltosState state, int i) {
+ if (i == 0)
+ return state.height();
+ else
+ return state.max_height();
}
- public AscentStatus (GridBagLayout layout, int y, String text) {
- GridBagConstraints c = new GridBagConstraints();
- c.weighty = 1;
-
- lights = new AltosLights();
- c.gridx = 0; c.gridy = y;
- c.anchor = GridBagConstraints.CENTER;
- c.fill = GridBagConstraints.VERTICAL;
- c.weightx = 0;
- layout.setConstraints(lights, c);
- add(lights);
-
- label = new JLabel(text);
- label.setFont(Altos.label_font);
- label.setHorizontalAlignment(SwingConstants.LEFT);
- c.gridx = 1; c.gridy = y;
- c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
- c.anchor = GridBagConstraints.WEST;
- c.fill = GridBagConstraints.VERTICAL;
- c.weightx = 0;
- layout.setConstraints(label, c);
- add(label);
-
- value = new JTextField(Altos.text_width);
- value.setFont(Altos.value_font);
- value.setHorizontalAlignment(SwingConstants.RIGHT);
- c.gridx = 2; c.gridy = y;
- c.gridwidth = 2;
- c.anchor = GridBagConstraints.WEST;
- c.fill = GridBagConstraints.BOTH;
- c.weightx = 1;
- layout.setConstraints(value, c);
- add(value);
-
+ public Height(Container container, int y) {
+ super(container, y, AltosConvert.height, "Height", 2, false, 1);
}
}
- public class AscentValue {
- JLabel label;
- JTextField value;
- void show(AltosState state, AltosListenerState listener_state) {}
-
- void reset() {
- value.setText("");
+ class Speed extends AltosUIUnitsIndicator {
+ public double value(AltosState state, int i) {
+ if (i == 0)
+ return state.speed();
+ else
+ return state.max_speed();
}
- void show() {
- label.setVisible(true);
- value.setVisible(true);
+ public Speed(Container container, int y) {
+ super(container, y, AltosConvert.speed, "Speed", 2, false, 1);
}
+ }
- void show(String s) {
- show();
- value.setText(s);
- }
-
- void show(AltosUnits units, double v) {
- show(units.show(8, v));
- }
+ class Accel extends AltosUIUnitsIndicator {
+ public boolean hide(double v) { return v == AltosLib.MISSING; }
- void show(String format, double v) {
- show(String.format(format, v));
- }
-
- void hide() {
- label.setVisible(false);
- value.setVisible(false);
- }
- void set_font() {
- label.setFont(Altos.label_font);
- value.setFont(Altos.value_font);
+ public double value(AltosState state, int i) {
+ if (i == 0)
+ return state.acceleration();
+ else
+ return state.max_acceleration();
}
- public AscentValue (GridBagLayout layout, int y, String text) {
- GridBagConstraints c = new GridBagConstraints();
- c.weighty = 1;
-
- label = new JLabel(text);
- label.setFont(Altos.label_font);
- label.setHorizontalAlignment(SwingConstants.LEFT);
- c.gridx = 1; c.gridy = y;
- c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
- c.anchor = GridBagConstraints.WEST;
- c.fill = GridBagConstraints.VERTICAL;
- c.weightx = 0;
- layout.setConstraints(label, c);
- add(label);
-
- value = new JTextField(Altos.text_width);
- value.setFont(Altos.value_font);
- value.setHorizontalAlignment(SwingConstants.RIGHT);
- c.gridx = 2; c.gridy = y;
- c.anchor = GridBagConstraints.WEST;
- c.fill = GridBagConstraints.BOTH;
- c.gridwidth = 2;
- c.weightx = 1;
- layout.setConstraints(value, c);
- add(value);
+ public Accel(Container container, int y) {
+ super(container, y, AltosConvert.accel, "Acceleration", 2, false, 1);
}
}
- public class AscentValueHold {
- JLabel label;
- JTextField value;
- JTextField max_value;
- double max;
+ class Orient extends AltosUIUnitsIndicator {
- void show(AltosState state, AltosListenerState listener_state) {}
+ public boolean hide(double v) { return v == AltosLib.MISSING; }
- void reset() {
- value.setText("");
- max_value.setText("");
- max = AltosLib.MISSING;
+ public double value(AltosState state, int i) {
+ if (i == 0)
+ return state.orient();
+ else
+ return state.max_orient();
}
- void set_font() {
- label.setFont(Altos.label_font);
- value.setFont(Altos.value_font);
- max_value.setFont(Altos.value_font);
+ public Orient(Container container, int y) {
+ super(container, y, AltosConvert.orient, "Tilt Angle", 2, false, 1);
}
- void show(AltosUnits units, double v) {
- if (v == AltosLib.MISSING) {
- value.setText("Missing");
- max_value.setText("Missing");
- } else {
- value.setText(units.show(8, v));
- if (v > max || max == AltosLib.MISSING) {
- max_value.setText(units.show(8, v));
- max = v;
- }
- }
- }
- public AscentValueHold (GridBagLayout layout, int y, String text) {
- GridBagConstraints c = new GridBagConstraints();
- c.weighty = 1;
-
- label = new JLabel(text);
- label.setFont(Altos.label_font);
- label.setHorizontalAlignment(SwingConstants.LEFT);
- c.gridx = 1; c.gridy = y;
- c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
- c.anchor = GridBagConstraints.WEST;
- c.fill = GridBagConstraints.VERTICAL;
- c.weightx = 0;
- layout.setConstraints(label, c);
- add(label);
-
- value = new JTextField(Altos.text_width);
- value.setFont(Altos.value_font);
- value.setHorizontalAlignment(SwingConstants.RIGHT);
- c.gridx = 2; c.gridy = y;
- c.anchor = GridBagConstraints.EAST;
- c.fill = GridBagConstraints.BOTH;
- c.weightx = 1;
- layout.setConstraints(value, c);
- add(value);
-
- max_value = new JTextField(Altos.text_width);
- max_value.setFont(Altos.value_font);
- max_value.setHorizontalAlignment(SwingConstants.RIGHT);
- c.gridx = 3; c.gridy = y;
- c.anchor = GridBagConstraints.EAST;
- c.fill = GridBagConstraints.BOTH;
- c.weightx = 1;
- layout.setConstraints(max_value, c);
- add(max_value);
- }
}
+ class Apogee extends AltosUIUnitsIndicator {
- class Height extends AscentValueHold {
- void show (AltosState state, AltosListenerState listener_state) {
- show(AltosConvert.height, state.height());
+ public double value(AltosState state, int i) {
+ return state.apogee_voltage;
}
- public Height (GridBagLayout layout, int y) {
- super (layout, y, "Height");
- }
- }
- Height height;
+ public boolean good(double v) { return v >= AltosLib.ao_igniter_good; }
+ public boolean hide(double v) { return v == AltosLib.MISSING; }
- class Speed extends AscentValueHold {
- void show (AltosState state, AltosListenerState listener_state) {
- show(AltosConvert.speed, state.speed());
- }
- public Speed (GridBagLayout layout, int y) {
- super (layout, y, "Speed");
+ public Apogee (Container container, int y) {
+ super(container, y, AltosConvert.voltage, "Apogee Igniter Voltage", 1, true, 2);
}
}
- Speed speed;
-
- class Accel extends AscentValueHold {
- void show (AltosState state, AltosListenerState listener_state) {
- show(AltosConvert.accel, state.acceleration());
+ class Main extends AltosUIUnitsIndicator {
+ public double value(AltosState state, int i) {
+ return state.main_voltage;
}
- public Accel (GridBagLayout layout, int y) {
- super (layout, y, "Acceleration");
- }
- }
- Accel accel;
+ public boolean good(double v) { return v >= AltosLib.ao_igniter_good; }
+ public boolean hide(double v) { return v == AltosLib.MISSING; }
- class Orient extends AscentValueHold {
- void show (AltosState state, AltosListenerState listener_state) {
- show(AltosConvert.orient, state.orient());
- }
- public Orient (GridBagLayout layout, int y) {
- super (layout, y, "Tilt Angle");
+ public Main (Container container, int y) {
+ super(container, y, AltosConvert.voltage, "Main Igniter Voltage", 1, true, 2);
}
}
- Orient orient;
+ class Lat extends AltosUIUnitsIndicator {
- String pos(double p, String pos, String neg) {
- String h = pos;
- if (p < 0) {
- h = neg;
- p = -p;
+ public boolean hide(AltosState state, int i) {
+ return state.gps == null || !state.gps.connected;
}
- int deg = (int) Math.floor(p);
- double min = (p - Math.floor(p)) * 60.0;
- return String.format("%s %4d° %9.6f", h, deg, min);
- }
- class Apogee extends AscentStatus {
- void show (AltosState state, AltosListenerState listener_state) {
- show("%4.2f V", state.apogee_voltage);
- lights.set(state.apogee_voltage >= AltosLib.ao_igniter_good);
- }
- public Apogee (GridBagLayout layout, int y) {
- super(layout, y, "Apogee Igniter Voltage");
+ public double value(AltosState state, int i) {
+ if (state.gps == null)
+ return AltosLib.MISSING;
+ if (!state.gps.connected)
+ return AltosLib.MISSING;
+ return state.gps.lat;
}
- }
- Apogee apogee;
-
- class Main extends AscentStatus {
- void show (AltosState state, AltosListenerState listener_state) {
- show("%4.2f V", state.main_voltage);
- lights.set(state.main_voltage >= AltosLib.ao_igniter_good);
- }
- public Main (GridBagLayout layout, int y) {
- super(layout, y, "Main Igniter Voltage");
+ Lat (Container container, int y) {
+ super (container, y, AltosConvert.latitude, "Latitude", 1, false, 2);
}
}
- Main main;
+ class Lon extends AltosUIUnitsIndicator {
- class Lat extends AscentValue {
- void show (AltosState state, AltosListenerState listener_state) {
- if (state.gps != null && state.gps.connected && state.gps.lat != AltosLib.MISSING)
- show(pos(state.gps.lat,"N", "S"));
- else
- show("???");
+ public boolean hide(AltosState state, int i) {
+ return state.gps == null || !state.gps.connected;
}
- public Lat (GridBagLayout layout, int y) {
- super (layout, y, "Latitude");
- }
- }
-
- Lat lat;
- class Lon extends AscentValue {
- void show (AltosState state, AltosListenerState listener_state) {
- if (state.gps != null && state.gps.connected && state.gps.lon != AltosLib.MISSING)
- show(pos(state.gps.lon,"E", "W"));
- else
- show("???");
- }
- public Lon (GridBagLayout layout, int y) {
- super (layout, y, "Longitude");
+ public double value(AltosState state, int i) {
+ if (state.gps == null)
+ return AltosLib.MISSING;
+ if (!state.gps.connected)
+ return AltosLib.MISSING;
+ return state.gps.lon;
}
- }
- Lon lon;
-
- public void reset() {
- lat.reset();
- lon.reset();
- main.reset();
- apogee.reset();
- height.reset();
- speed.reset();
- accel.reset();
- orient.reset();
- }
-
- public void set_font() {
- cur.setFont(Altos.label_font);
- max.setFont(Altos.label_font);
- lat.set_font();
- lon.set_font();
- main.set_font();
- apogee.set_font();
- height.set_font();
- speed.set_font();
- accel.set_font();
- orient.set_font();
+ Lon (Container container, int y) {
+ super (container, y, AltosConvert.longitude, "Longitude", 1, false, 2);
+ }
}
- public void show(AltosState state, AltosListenerState listener_state) {
- if (state.gps != null && state.gps.connected) {
- lat.show(state, listener_state);
- lon.show(state, listener_state);
- } else {
- lat.hide();
- lon.hide();
- }
- height.show(state, listener_state);
- if (state.main_voltage != AltosLib.MISSING)
- main.show(state, listener_state);
- else
- main.hide();
- if (state.apogee_voltage != AltosLib.MISSING)
- apogee.show(state, listener_state);
- else
- apogee.hide();
- speed.show(state, listener_state);
- accel.show(state, listener_state);
- orient.show(state, listener_state);
+ public void font_size_changed(int font_size) {
+ super.font_size_changed(font_size);
+ cur.setFont(AltosUILib.label_font);
+ max.setFont(AltosUILib.label_font);
}
public void labels(GridBagLayout layout, int y) {
GridBagConstraints c;
cur = new JLabel("Current");
- cur.setFont(Altos.label_font);
+ cur.setFont(AltosUILib.label_font);
c = new GridBagConstraints();
c.gridx = 2; c.gridy = y;
c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
@@ -403,7 +169,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay {
add(cur);
max = new JLabel("Maximum");
- max.setFont(Altos.label_font);
+ max.setFont(AltosUILib.label_font);
c.gridx = 3; c.gridy = y;
layout.setConstraints(max, c);
add(max);
@@ -414,25 +180,15 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay {
}
public AltosAscent() {
- layout = new GridBagLayout();
-
- setLayout(layout);
-
- /* Elements in ascent display:
- *
- * lat
- * lon
- * height
- */
int y = 0;
labels(layout, y++);
- height = new Height(layout, y++);
- speed = new Speed(layout, y++);
- accel = new Accel(layout, y++);
- orient = new Orient(layout, y++);
- lat = new Lat(layout, y++);
- lon = new Lon(layout, y++);
- apogee = new Apogee(layout, y++);
- main = new Main(layout, y++);
+ add(new Height(this, y++));
+ add(new Speed(this, y++));
+ add(new Accel(this, y++));
+ add(new Orient(this, y++));
+ add(new Lat(this, y++));
+ add(new Lon(this, y++));
+ add(new Apogee(this, y++));
+ add(new Main(this, y++));
}
}
diff --git a/altosui/AltosChannelMenu.java b/altosui/AltosChannelMenu.java
index f90a11c0..382b6ae4 100644
--- a/altosui/AltosChannelMenu.java
+++ b/altosui/AltosChannelMenu.java
@@ -20,7 +20,7 @@ package altosui;
import java.awt.event.*;
import javax.swing.*;
-public class AltosChannelMenu extends JComboBox implements ActionListener {
+public class AltosChannelMenu extends JComboBox<String> implements ActionListener {
int channel;
public AltosChannelMenu(int current_channel) {
diff --git a/altosui/AltosCompanionInfo.java b/altosui/AltosCompanionInfo.java
index 4cc6c462..e7b335ac 100644
--- a/altosui/AltosCompanionInfo.java
+++ b/altosui/AltosCompanionInfo.java
@@ -19,9 +19,10 @@ package altosui;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
-public class AltosCompanionInfo extends JTable {
+public class AltosCompanionInfo extends JTable implements AltosFlightDisplay {
private AltosFlightInfoTableModel model;
static final int info_columns = 2;
@@ -32,25 +33,28 @@ public class AltosCompanionInfo extends JTable {
return (infoValueMetrics.getHeight() + infoValueMetrics.getLeading()) * 18 / 10;
}
- public void set_font() {
+ public void font_size_changed(int font_size) {
setFont(Altos.table_value_font);
setRowHeight(desired_row_height());
doLayout();
}
+ public void units_changed(boolean imperial_units) {
+ }
+
public AltosCompanionInfo() {
super(new AltosFlightInfoTableModel(info_rows, info_columns));
model = (AltosFlightInfoTableModel) getModel();
setAutoResizeMode(AUTO_RESIZE_ALL_COLUMNS);
setShowGrid(true);
- set_font();
+ font_size_changed(AltosUIPreferences.font_size());
}
public Dimension getPreferredScrollableViewportSize() {
return getPreferredSize();
}
- void info_reset() {
+ public void reset() {
model.reset();
}
@@ -82,13 +86,15 @@ public class AltosCompanionInfo extends JTable {
return String.format("%02x\n", companion.board_id);
}
}
-
+
+ public String getName() { return "Companion"; }
+
public void show(AltosState state, AltosListenerState listener_state) {
if (state == null)
return;
if (state.companion != null)
companion = state.companion;
- info_reset();
+ reset();
info_add_row(0, "Companion board", "%s", board_name());
if (companion != null) {
info_add_row(0, "Last Data", "%5d", companion.tick);
diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java
index e1805fc1..6eb7d40c 100644
--- a/altosui/AltosConfig.java
+++ b/altosui/AltosConfig.java
@@ -22,8 +22,8 @@ import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
import java.text.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
public class AltosConfig implements ActionListener {
@@ -229,22 +229,28 @@ public class AltosConfig implements ActionListener {
void save_data() {
- /* bounds check stuff */
- if (config_ui.flight_log_max() > data.log_limit()) {
+ try {
+ /* bounds check stuff */
+ if (config_ui.flight_log_max() > data.log_space() / 1024) {
+ JOptionPane.showMessageDialog(owner,
+ String.format("Requested flight log, %dk, is larger than the available space, %dk.\n",
+ config_ui.flight_log_max(),
+ data.log_space() / 1024),
+ "Maximum Flight Log Too Large",
+ JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+
+ /* Pull data out of the UI and stuff back into our local data record */
+
+ data.get_values(config_ui);
+ run_serial_thread(serial_mode_save);
+ } catch (AltosConfigDataException ae) {
JOptionPane.showMessageDialog(owner,
- String.format("Requested flight log, %dk, is larger than the available space, %dk.\n",
- config_ui.flight_log_max(),
- data.log_limit()),
- "Maximum Flight Log Too Large",
+ ae.getMessage(),
+ "Configuration Data Error",
JOptionPane.ERROR_MESSAGE);
- return;
}
-
- /* Pull data out of the UI and stuff back into our local data record */
-
- data.get_values(config_ui);
-
- run_serial_thread(serial_mode_save);
}
public void actionPerformed(ActionEvent e) {
@@ -298,4 +304,4 @@ public class AltosConfig implements ActionListener {
}
}
}
-} \ No newline at end of file
+}
diff --git a/altosui/AltosConfigPyroUI.java b/altosui/AltosConfigPyroUI.java
index b14c39ab..f0b4f0f9 100644
--- a/altosui/AltosConfigPyroUI.java
+++ b/altosui/AltosConfigPyroUI.java
@@ -21,8 +21,8 @@ import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
public class AltosConfigPyroUI
extends AltosUIDialog
@@ -50,7 +50,7 @@ public class AltosConfigPyroUI
public int flag;
public JCheckBox enable;
public JTextField value;
- public JComboBox combo;
+ public JComboBox<String> combo;
AltosConfigPyroUI ui;
boolean setting;
@@ -63,22 +63,22 @@ public class AltosConfigPyroUI
public void itemStateChanged(ItemEvent e) {
set_enable(enable.isSelected());
- if (!setting)
+ if (!setting)
ui.set_dirty();
}
public void changedUpdate(DocumentEvent e) {
- if (!setting)
+ if (!setting)
ui.set_dirty();
}
public void insertUpdate(DocumentEvent e) {
- if (!setting)
+ if (!setting)
ui.set_dirty();
}
public void removeUpdate(DocumentEvent e) {
- if (!setting)
+ if (!setting)
ui.set_dirty();
}
@@ -105,11 +105,13 @@ public class AltosConfigPyroUI
AltosUnits units = AltosPyro.pyro_to_units(flag);
if (units != null)
unit_value = units.value(new_value);
- String format = "%6.0f";
- if (scale >= 10)
- format = "%6.1f";
- else if (scale >= 100)
+ String format;
+ if (scale >= 100)
format = "%6.2f";
+ else if (scale >= 10)
+ format = "%6.1f";
+ else
+ format = "%6.0f";
value.setText(String.format(format, unit_value));
}
if (combo != null)
@@ -122,12 +124,16 @@ public class AltosConfigPyroUI
return enable.isSelected();
}
- public double value() {
+ public double value() throws AltosConfigDataException {
if (value != null) {
AltosUnits units = AltosPyro.pyro_to_units(flag);
- if (units != null)
- return units.parse(value.getText());
- return Double.parseDouble(value.getText());
+ try {
+ if (units != null)
+ return units.parse(value.getText());
+ return Double.parseDouble(value.getText());
+ } catch (NumberFormatException e) {
+ throw new AltosConfigDataException("\"%s\": %s\n", value.getText(), e.getMessage());
+ }
}
if (combo != null)
return combo.getSelectedIndex() + AltosLib.ao_flight_boost;
@@ -149,7 +155,7 @@ public class AltosConfigPyroUI
enable = new JCheckBox();
enable.addItemListener(this);
pane.add(enable, c);
-
+
if ((flag & AltosPyro.pyro_no_value) == 0) {
c = new GridBagConstraints();
c.gridx = x+1; c.gridy = y;
@@ -159,7 +165,7 @@ public class AltosConfigPyroUI
c.insets = il;
if ((flag & AltosPyro.pyro_state_value) != 0) {
make_state_names();
- combo = new JComboBox(state_names);
+ combo = new JComboBox<String>(state_names);
combo.addItemListener(this);
pane.add(combo, c);
} else {
@@ -187,15 +193,21 @@ public class AltosConfigPyroUI
}
}
- public AltosPyro get() {
+ public AltosPyro get() throws AltosConfigDataException {
AltosPyro p = new AltosPyro(channel);
int row = 0;
for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1) {
if ((AltosPyro.pyro_all & flag) != 0) {
if (items[row].enabled()) {
+ try {
p.flags |= flag;
p.set_value(flag, items[row].value());
+ } catch (AltosConfigDataException ae) {
+ throw new AltosConfigDataException("%s, %s",
+ AltosPyro.pyro_to_name(flag),
+ ae.getMessage());
+ }
}
row++;
}
@@ -224,7 +236,7 @@ public class AltosConfigPyroUI
items = new PyroItem[nrow];
int row = 0;
-
+
GridBagConstraints c;
c = new GridBagConstraints();
c.gridx = x; c.gridy = y;
@@ -254,13 +266,40 @@ public class AltosConfigPyroUI
}
}
- public AltosPyro[] get_pyros() {
+ public AltosPyro[] get_pyros() throws AltosConfigDataException {
AltosPyro[] pyros = new AltosPyro[columns.length];
- for (int c = 0; c < columns.length; c++)
- pyros[c] = columns[c].get();
+ for (int c = 0; c < columns.length; c++) {
+ try {
+ pyros[c] = columns[c].get();
+ } catch (AltosConfigDataException ae) {
+ throw new AltosConfigDataException ("Channel %c, %s", c + 'A', ae.getMessage());
+ }
+ }
return pyros;
}
+ JLabel pyro_firing_time_label;
+ JComboBox<String> pyro_firing_time_value;
+
+ static String[] pyro_firing_time_values = {
+ "0.050", "0.100", "0.250", "0.500", "1.0", "2.0"
+ };
+
+ public void set_pyro_firing_time(double new_pyro_firing_time) {
+ pyro_firing_time_value.setSelectedItem(Double.toString(new_pyro_firing_time));
+ pyro_firing_time_value.setEnabled(new_pyro_firing_time >= 0);
+ }
+
+ public double get_pyro_firing_time() throws AltosConfigDataException {
+ String v = pyro_firing_time_value.getSelectedItem().toString();
+
+ try {
+ return Double.parseDouble(v);
+ } catch (NumberFormatException e) {
+ throw new AltosConfigDataException("Invalid pyro firing time \"%s\"", v);
+ }
+ }
+
public void set_dirty() {
owner.set_dirty();
}
@@ -317,7 +356,7 @@ public class AltosConfigPyroUI
setVisible(false);
}
- public AltosConfigPyroUI(AltosConfigUI in_owner, AltosPyro[] pyros) {
+ public AltosConfigPyroUI(AltosConfigUI in_owner, AltosPyro[] pyros, double pyro_firing_time) {
super(in_owner, "Configure Pyro Channels", false);
@@ -362,6 +401,32 @@ public class AltosConfigPyroUI
columns[i].set(pyros[i]);
}
+ /* Pyro firing time */
+ c = new GridBagConstraints();
+ c.gridx = 0; c.gridy = row;
+ c.gridwidth = 2;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = il;
+ c.ipady = 5;
+ pyro_firing_time_label = new JLabel("Pyro Firing Time(s):");
+ pane.add(pyro_firing_time_label, c);
+
+ c = new GridBagConstraints();
+ c.gridx = 2; c.gridy = row;
+ c.gridwidth = 7;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.weightx = 1;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = ir;
+ c.ipady = 5;
+ pyro_firing_time_value = new JComboBox<String>(pyro_firing_time_values);
+ pyro_firing_time_value.setEditable(true);
+ pyro_firing_time_value.addItemListener(this);
+ set_pyro_firing_time(pyro_firing_time);
+ pane.add(pyro_firing_time_value, c);
+ pyro_firing_time_value.setToolTipText("Length of extra pyro channel firing pulse");
+
c = new GridBagConstraints();
c.gridx = pyros.length*2-1;
c.fill = GridBagConstraints.HORIZONTAL;
@@ -371,7 +436,7 @@ public class AltosConfigPyroUI
pane.add(close, c);
close.addActionListener(this);
close.setActionCommand("Close");
-
+
addWindowListener(new ConfigListener(this, owner));
AltosPreferences.register_units_listener(this);
}
diff --git a/altosui/AltosConfigTD.java b/altosui/AltosConfigTD.java
index ad9ebbfa..bfbd2c77 100644
--- a/altosui/AltosConfigTD.java
+++ b/altosui/AltosConfigTD.java
@@ -21,8 +21,8 @@ import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
public class AltosConfigTD implements ActionListener {
diff --git a/altosui/AltosConfigTDUI.java b/altosui/AltosConfigTDUI.java
index 3ce0d98c..22b3384d 100644
--- a/altosui/AltosConfigTDUI.java
+++ b/altosui/AltosConfigTDUI.java
@@ -21,8 +21,8 @@ import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
public class AltosConfigTDUI
extends AltosUIDialog
@@ -311,7 +311,7 @@ public class AltosConfigTDUI
int i;
for (i = 0; i < radio_frequency_value.getItemCount(); i++) {
AltosFrequency f = (AltosFrequency) radio_frequency_value.getItemAt(i);
-
+
if (f.close(new_radio_frequency)) {
radio_frequency_value.setSelectedIndex(i);
return;
@@ -319,7 +319,7 @@ public class AltosConfigTDUI
}
for (i = 0; i < radio_frequency_value.getItemCount(); i++) {
AltosFrequency f = (AltosFrequency) radio_frequency_value.getItemAt(i);
-
+
if (new_radio_frequency < f.frequency)
break;
}
diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigUI.java
index 21ea50e6..1b5ff988 100644
--- a/altosui/AltosConfigUI.java
+++ b/altosui/AltosConfigUI.java
@@ -21,102 +21,130 @@ import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
public class AltosConfigUI
extends AltosUIDialog
implements ActionListener, ItemListener, DocumentListener, AltosConfigValues, AltosUnitsListener
{
- Container pane;
- JLabel product_label;
- JLabel version_label;
- JLabel serial_label;
- JLabel main_deploy_label;
- JLabel apogee_delay_label;
- JLabel apogee_lockout_label;
- JLabel frequency_label;
- JLabel radio_calibration_label;
- JLabel radio_frequency_label;
- JLabel radio_enable_label;
- JLabel aprs_interval_label;
- JLabel flight_log_max_label;
- JLabel ignite_mode_label;
- JLabel pad_orientation_label;
- JLabel callsign_label;
+ Container pane;
+ JLabel product_label;
+ JLabel version_label;
+ JLabel serial_label;
+ JLabel main_deploy_label;
+ JLabel apogee_delay_label;
+ JLabel apogee_lockout_label;
+ JLabel frequency_label;
+ JLabel radio_calibration_label;
+ JLabel radio_frequency_label;
+ JLabel radio_enable_label;
+ JLabel aprs_interval_label;
+ JLabel flight_log_max_label;
+ JLabel ignite_mode_label;
+ JLabel pad_orientation_label;
+ JLabel callsign_label;
+ JLabel beep_label;
+ JLabel tracker_motion_label;
+ JLabel tracker_interval_label;
public boolean dirty;
- JFrame owner;
- JLabel product_value;
- JLabel version_value;
- JLabel serial_value;
- JComboBox main_deploy_value;
- JComboBox apogee_delay_value;
- JComboBox apogee_lockout_value;
- AltosFreqList radio_frequency_value;
- JTextField radio_calibration_value;
- JRadioButton radio_enable_value;
- JComboBox aprs_interval_value;
- JComboBox flight_log_max_value;
- JComboBox ignite_mode_value;
- JComboBox pad_orientation_value;
- JTextField callsign_value;
-
- JButton pyro;
-
- JButton save;
- JButton reset;
- JButton reboot;
- JButton close;
-
- AltosPyro[] pyros;
-
- ActionListener listener;
-
- static String[] main_deploy_values_m = {
+ JFrame owner;
+ JLabel product_value;
+ JLabel version_value;
+ JLabel serial_value;
+ JComboBox<String> main_deploy_value;
+ JComboBox<String> apogee_delay_value;
+ JComboBox<String> apogee_lockout_value;
+ AltosFreqList radio_frequency_value;
+ JTextField radio_calibration_value;
+ JRadioButton radio_enable_value;
+ JComboBox<String> aprs_interval_value;
+ JComboBox<String> flight_log_max_value;
+ JComboBox<String> ignite_mode_value;
+ JComboBox<String> pad_orientation_value;
+ JTextField callsign_value;
+ JComboBox<String> beep_value;
+ JComboBox<String> tracker_motion_value;
+ JComboBox<String> tracker_interval_value;
+
+ JButton pyro;
+
+ JButton save;
+ JButton reset;
+ JButton reboot;
+ JButton close;
+
+ AltosPyro[] pyros;
+ double pyro_firing_time;
+
+ ActionListener listener;
+
+ static String[] main_deploy_values_m = {
"100", "150", "200", "250", "300", "350",
"400", "450", "500"
};
- static String[] main_deploy_values_ft = {
+ static String[] main_deploy_values_ft = {
"250", "500", "750", "1000", "1250", "1500",
"1750", "2000"
};
- static String[] apogee_delay_values = {
+ static String[] apogee_delay_values = {
"0", "1", "2", "3", "4", "5"
};
- static String[] apogee_lockout_values = {
+ static String[] apogee_lockout_values = {
"0", "5", "10", "15", "20"
};
- static String[] flight_log_max_values = {
- "64", "128", "192", "256", "320",
- "384", "448", "512", "576", "640",
- "704", "768", "832", "896", "960",
- };
-
- static String[] ignite_mode_values = {
+ static String[] ignite_mode_values = {
"Dual Deploy",
"Redundant Apogee",
"Redundant Main",
};
- static String[] aprs_interval_values = {
+ static String[] aprs_interval_values = {
"Disabled",
"2",
"5",
"10"
};
- static String[] pad_orientation_values = {
+ static String[] beep_values = {
+ "3750",
+ "4000",
+ "4250",
+ };
+
+ static String[] pad_orientation_values = {
"Antenna Up",
"Antenna Down",
};
+ static String[] tracker_motion_values_m = {
+ "2",
+ "5",
+ "10",
+ "25",
+ };
+
+ static String[] tracker_motion_values_ft = {
+ "5",
+ "20",
+ "50",
+ "100"
+ };
+
+ static String[] tracker_interval_values = {
+ "1",
+ "2",
+ "5",
+ "10"
+ };
+
/* A window listener to catch closing events and tell the config code */
class ConfigListener extends WindowAdapter {
AltosConfigUI ui;
@@ -132,11 +160,21 @@ public class AltosConfigUI
}
}
+ boolean is_telemini_v1() {
+ String product = product_value.getText();
+ return product != null && product.startsWith("TeleMini-v1");
+ }
+
boolean is_telemini() {
String product = product_value.getText();
return product != null && product.startsWith("TeleMini");
}
+ boolean is_easymini() {
+ String product = product_value.getText();
+ return product != null && product.startsWith("EasyMini");
+ }
+
boolean is_telemetrum() {
String product = product_value.getText();
return product != null && product.startsWith("TeleMetrum");
@@ -167,12 +205,10 @@ public class AltosConfigUI
if (flight_log_max_value.isEnabled())
flight_log_max_value.setToolTipText("Size reserved for each flight log (in kB)");
else {
- if (is_telemetrum())
- flight_log_max_value.setToolTipText("Cannot set max value with flight logs in memory");
- else if (is_telemini())
- flight_log_max_value.setToolTipText("TeleMini stores only one flight");
+ if (is_telemini_v1())
+ flight_log_max_value.setToolTipText("TeleMini-v1 stores only one flight");
else
- flight_log_max_value.setToolTipText("Cannot set max flight log value");
+ flight_log_max_value.setToolTipText("Cannot set max value with flight logs in memory");
}
}
@@ -189,13 +225,20 @@ public class AltosConfigUI
else {
if (is_telemetrum())
pad_orientation_value.setToolTipText("Older TeleMetrum firmware must fly antenna forward");
- else if (is_telemini())
- pad_orientation_value.setToolTipText("TeleMini doesn't care how it is mounted");
+ else if (is_telemini() || is_easymini())
+ pad_orientation_value.setToolTipText("TeleMini and EasyMini don't care how they are mounted");
else
pad_orientation_value.setToolTipText("Can't select orientation");
}
}
+ void set_beep_tool_tip() {
+ if (beep_value.isEnabled())
+ beep_value.setToolTipText("What frequency the beeper will sound at");
+ else
+ beep_value.setToolTipText("Older firmware could not select beeper frequency");
+ }
+
/* Build the UI using a grid bag */
public AltosConfigUI(JFrame in_owner, boolean remote) {
super (in_owner, "Configure Flight Computer", false);
@@ -296,7 +339,7 @@ public class AltosConfigUI
c.anchor = GridBagConstraints.LINE_START;
c.insets = ir;
c.ipady = 5;
- main_deploy_value = new JComboBox(main_deploy_values());
+ main_deploy_value = new JComboBox<String>(main_deploy_values());
main_deploy_value.setEditable(true);
main_deploy_value.addItemListener(this);
pane.add(main_deploy_value, c);
@@ -322,7 +365,7 @@ public class AltosConfigUI
c.anchor = GridBagConstraints.LINE_START;
c.insets = ir;
c.ipady = 5;
- apogee_delay_value = new JComboBox(apogee_delay_values);
+ apogee_delay_value = new JComboBox<String>(apogee_delay_values);
apogee_delay_value.setEditable(true);
apogee_delay_value.addItemListener(this);
pane.add(apogee_delay_value, c);
@@ -348,7 +391,7 @@ public class AltosConfigUI
c.anchor = GridBagConstraints.LINE_START;
c.insets = ir;
c.ipady = 5;
- apogee_lockout_value = new JComboBox(apogee_lockout_values);
+ apogee_lockout_value = new JComboBox<String>(apogee_lockout_values);
apogee_lockout_value.setEditable(true);
apogee_lockout_value.addItemListener(this);
pane.add(apogee_lockout_value, c);
@@ -451,7 +494,7 @@ public class AltosConfigUI
c.anchor = GridBagConstraints.LINE_START;
c.insets = ir;
c.ipady = 5;
- aprs_interval_value = new JComboBox(aprs_interval_values);
+ aprs_interval_value = new JComboBox<String>(aprs_interval_values);
aprs_interval_value.setEditable(true);
aprs_interval_value.addItemListener(this);
pane.add(aprs_interval_value, c);
@@ -491,7 +534,7 @@ public class AltosConfigUI
c.anchor = GridBagConstraints.LINE_START;
c.insets = il;
c.ipady = 5;
- flight_log_max_label = new JLabel("Maximum Flight Log Size:");
+ flight_log_max_label = new JLabel("Maximum Flight Log Size (kB):");
pane.add(flight_log_max_label, c);
c = new GridBagConstraints();
@@ -502,7 +545,7 @@ public class AltosConfigUI
c.anchor = GridBagConstraints.LINE_START;
c.insets = ir;
c.ipady = 5;
- flight_log_max_value = new JComboBox(flight_log_max_values);
+ flight_log_max_value = new JComboBox<String>();
flight_log_max_value.setEditable(true);
flight_log_max_value.addItemListener(this);
pane.add(flight_log_max_value, c);
@@ -528,7 +571,7 @@ public class AltosConfigUI
c.anchor = GridBagConstraints.LINE_START;
c.insets = ir;
c.ipady = 5;
- ignite_mode_value = new JComboBox(ignite_mode_values);
+ ignite_mode_value = new JComboBox<String>(ignite_mode_values);
ignite_mode_value.setEditable(false);
ignite_mode_value.addItemListener(this);
pane.add(ignite_mode_value, c);
@@ -554,13 +597,90 @@ public class AltosConfigUI
c.anchor = GridBagConstraints.LINE_START;
c.insets = ir;
c.ipady = 5;
- pad_orientation_value = new JComboBox(pad_orientation_values);
+ pad_orientation_value = new JComboBox<String>(pad_orientation_values);
pad_orientation_value.setEditable(false);
pad_orientation_value.addItemListener(this);
pane.add(pad_orientation_value, c);
set_pad_orientation_tool_tip();
row++;
+ /* Beeper */
+ 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;
+ beep_label = new JLabel("Beeper Frequency:");
+ pane.add(beep_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;
+ beep_value = new JComboBox<String>(beep_values);
+ beep_value.setEditable(true);
+ beep_value.addItemListener(this);
+ pane.add(beep_value, c);
+ set_beep_tool_tip();
+ row++;
+
+ /* Tracker triger horiz distances */
+ 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;
+ tracker_motion_label = new JLabel(get_tracker_motion_label());
+ pane.add(tracker_motion_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;
+ tracker_motion_value = new JComboBox<String>(tracker_motion_values());
+ tracker_motion_value.setEditable(true);
+ tracker_motion_value.addItemListener(this);
+ pane.add(tracker_motion_value, c);
+ row++;
+
+ /* Tracker triger vert distances */
+ 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;
+ tracker_interval_label = new JLabel("Position Reporting Interval(s):");
+ pane.add(tracker_interval_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;
+ tracker_interval_value = new JComboBox<String>(tracker_interval_values);
+ tracker_interval_value.setEditable(true);
+ tracker_interval_value.addItemListener(this);
+ pane.add(tracker_interval_value, c);
+ set_tracker_tool_tip();
+ row++;
+
/* Pyro channels */
c = new GridBagConstraints();
c.gridx = 4; c.gridy = row;
@@ -673,7 +793,7 @@ public class AltosConfigUI
if (cmd.equals("Pyro")) {
if (pyro_ui == null && pyros != null)
- pyro_ui = new AltosConfigPyroUI(this, pyros);
+ pyro_ui = new AltosConfigPyroUI(this, pyros, pyro_firing_time);
if (pyro_ui != null)
pyro_ui.make_visible();
return;
@@ -742,14 +862,14 @@ public class AltosConfigUI
String get_main_deploy_label() {
return String.format("Main Deploy Altitude(%s):", AltosConvert.height.show_units());
}
-
+
String[] main_deploy_values() {
if (AltosConvert.imperial_units)
return main_deploy_values_ft;
else
return main_deploy_values_m;
}
-
+
void set_main_deploy_values() {
String[] v = main_deploy_values();
while (main_deploy_value.getItemCount() > 0)
@@ -758,13 +878,20 @@ public class AltosConfigUI
main_deploy_value.addItem(v[i]);
main_deploy_value.setMaximumRowCount(v.length);
}
-
+
public void units_changed(boolean imperial_units) {
String v = main_deploy_value.getSelectedItem().toString();
main_deploy_label.setText(get_main_deploy_label());
set_main_deploy_values();
int m = (int) (AltosConvert.height.parse(v, !imperial_units) + 0.5);
set_main_deploy(m);
+
+ 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));
+ }
}
public void set_apogee_delay(int new_apogee_delay) {
@@ -772,8 +899,19 @@ public class AltosConfigUI
apogee_delay_value.setEnabled(new_apogee_delay >= 0);
}
- public int apogee_delay() {
- return Integer.parseInt(apogee_delay_value.getSelectedItem().toString());
+ private int parse_int(String name, String s, boolean split) throws AltosConfigDataException {
+ String v = s;
+ if (split)
+ v = s.split("\\s+")[0];
+ try {
+ return Integer.parseInt(v);
+ } catch (NumberFormatException ne) {
+ throw new AltosConfigDataException("Invalid %s \"%s\"", name, s);
+ }
+ }
+
+ public int apogee_delay() throws AltosConfigDataException {
+ return parse_int("apogee delay", apogee_delay_value.getSelectedItem().toString(), false);
}
public void set_apogee_lockout(int new_apogee_lockout) {
@@ -781,8 +919,8 @@ public class AltosConfigUI
apogee_lockout_value.setEnabled(new_apogee_lockout >= 0);
}
- public int apogee_lockout() {
- return Integer.parseInt(apogee_lockout_value.getSelectedItem().toString());
+ public int apogee_lockout() throws AltosConfigDataException {
+ return parse_int("apogee lockout", apogee_lockout_value.getSelectedItem().toString(), false);
}
public void set_radio_frequency(double new_radio_frequency) {
@@ -801,8 +939,8 @@ public class AltosConfigUI
radio_calibration_value.setText(String.format("%d", new_radio_calibration));
}
- public int radio_calibration() {
- return Integer.parseInt(radio_calibration_value.getText());
+ public int radio_calibration() throws AltosConfigDataException {
+ return parse_int("radio calibration", radio_calibration_value.getText(), false);
}
public void set_radio_enable(int new_radio_enable) {
@@ -833,9 +971,22 @@ public class AltosConfigUI
return callsign_value.getText();
}
+ int flight_log_max_limit;
+ int flight_log_max;
+
+ public String flight_log_max_label(int flight_log_max) {
+ if (flight_log_max_limit != 0) {
+ int nflight = flight_log_max_limit / flight_log_max;
+ String plural = nflight > 1 ? "s" : "";
+
+ return String.format("%d (%d flight%s)", flight_log_max, nflight, plural);
+ }
+ return String.format("%d", flight_log_max);
+ }
+
public void set_flight_log_max(int new_flight_log_max) {
- flight_log_max_value.setEnabled(new_flight_log_max > 0);
- flight_log_max_value.setSelectedItem(Integer.toString(new_flight_log_max));
+ 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();
}
@@ -844,20 +995,19 @@ public class AltosConfigUI
set_flight_log_max_tool_tip();
}
- public int flight_log_max() {
- return Integer.parseInt(flight_log_max_value.getSelectedItem().toString());
+ public int flight_log_max() throws AltosConfigDataException {
+ return parse_int("flight log max", flight_log_max_value.getSelectedItem().toString(), true);
}
- public void set_flight_log_max_limit(int flight_log_max_limit) {
- //boolean any_added = false;
+ public void set_flight_log_max_limit(int new_flight_log_max_limit) {
+ flight_log_max_limit = new_flight_log_max_limit;
flight_log_max_value.removeAllItems();
- for (int i = 0; i < flight_log_max_values.length; i++) {
- if (Integer.parseInt(flight_log_max_values[i]) < flight_log_max_limit){
- flight_log_max_value.addItem(flight_log_max_values[i]);
- //any_added = true;
- }
+ for (int i = 8; i >= 1; i--) {
+ int size = flight_log_max_limit / i;
+ flight_log_max_value.addItem(String.format("%d (%d flights)", size, i));
}
- flight_log_max_value.addItem(String.format("%d", flight_log_max_limit));
+ if (flight_log_max != 0)
+ set_flight_log_max(flight_log_max);
}
public void set_ignite_mode(int new_ignite_mode) {
@@ -901,6 +1051,87 @@ public class AltosConfigUI
return -1;
}
+ public void set_beep(int new_beep) {
+ 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]))) {
+ beep_value.setSelectedIndex(i);
+ set_beep_tool_tip();
+ return;
+ }
+ beep_value.setSelectedItem(String.format("%d", new_freq));
+ beep_value.setEnabled(new_beep >= 0);
+ set_beep_tool_tip();
+ }
+
+ public int beep() {
+ if (beep_value.isEnabled())
+ return AltosConvert.beep_freq_to_value(Integer.parseInt(beep_value.getSelectedItem().toString()));
+ else
+ return -1;
+ }
+
+ String[] tracker_motion_values() {
+ if (AltosConvert.imperial_units)
+ return tracker_motion_values_ft;
+ else
+ return tracker_motion_values_m;
+ }
+
+ void set_tracker_motion_values() {
+ String[] v = tracker_motion_values();
+ while (tracker_motion_value.getItemCount() > 0)
+ tracker_motion_value.removeItemAt(0);
+ for (int i = 0; i < v.length; i++)
+ tracker_motion_value.addItem(v[i]);
+ tracker_motion_value.setMaximumRowCount(v.length);
+ }
+
+ String get_tracker_motion_label() {
+ return String.format("Logging Trigger Motion (%s):", AltosConvert.height.show_units());
+ }
+
+ void set_tracker_tool_tip() {
+ if (tracker_motion_value.isEnabled())
+ tracker_motion_value.setToolTipText("How far the device must move before logging");
+ else
+ tracker_motion_value.setToolTipText("This device doesn't disable logging when stationary");
+ if (tracker_interval_value.isEnabled())
+ tracker_interval_value.setToolTipText("How often to report GPS position");
+ else
+ tracker_interval_value.setToolTipText("This device can't configure interval");
+ }
+
+ public void set_tracker_motion(int tracker_motion) {
+ if (tracker_motion < 0) {
+ tracker_motion_label.setVisible(false);
+ tracker_motion_value.setVisible(false);
+ } else {
+ tracker_motion_label.setVisible(true);
+ tracker_motion_value.setVisible(true);
+ tracker_motion_value.setSelectedItem(AltosConvert.height.say(tracker_motion));
+ }
+ }
+
+ public int tracker_motion() throws AltosConfigDataException {
+ return (int) AltosConvert.height.parse(tracker_motion_value.getSelectedItem().toString());
+ }
+
+ public void set_tracker_interval(int tracker_interval) {
+ if (tracker_interval< 0) {
+ tracker_interval_label.setVisible(false);
+ tracker_interval_value.setVisible(false);
+ } else {
+ tracker_interval_label.setVisible(true);
+ tracker_interval_value.setVisible(true);
+ tracker_interval_value.setSelectedItem(String.format("%d", tracker_interval));
+ }
+ }
+
+ public int tracker_interval() throws AltosConfigDataException {
+ return parse_int ("tracker interval", tracker_interval_value.getSelectedItem().toString(), false);
+ }
+
public void set_pyros(AltosPyro[] new_pyros) {
pyros = new_pyros;
pyro.setVisible(pyros != null);
@@ -908,12 +1139,25 @@ public class AltosConfigUI
pyro_ui.set_pyros(pyros);
}
- public AltosPyro[] pyros() {
+ public AltosPyro[] pyros() throws AltosConfigDataException {
if (pyro_ui != null)
pyros = pyro_ui.get_pyros();
return pyros;
}
+ public void set_pyro_firing_time(double new_pyro_firing_time) {
+ pyro_firing_time = new_pyro_firing_time;
+ pyro.setVisible(pyro_firing_time >= 0);
+ if (pyro_firing_time >= 0 && pyro_ui != null)
+ pyro_ui.set_pyro_firing_time(pyro_firing_time);
+ }
+
+ public double pyro_firing_time() throws AltosConfigDataException {
+ if (pyro_ui != null)
+ pyro_firing_time = pyro_ui.get_pyro_firing_time();
+ return pyro_firing_time;
+ }
+
public void set_aprs_interval(int new_aprs_interval) {
String s;
@@ -926,11 +1170,11 @@ public class AltosConfigUI
set_aprs_interval_tool_tip();
}
- public int aprs_interval() {
+ public int aprs_interval() throws AltosConfigDataException {
String s = aprs_interval_value.getSelectedItem().toString();
if (s.equals("Disabled"))
return 0;
- return Integer.parseInt(s);
+ return parse_int("aprs interval", s, false);
}
}
diff --git a/altosui/AltosConfigureUI.java b/altosui/AltosConfigureUI.java
index 5e42f430..e61a4a5b 100644
--- a/altosui/AltosConfigureUI.java
+++ b/altosui/AltosConfigureUI.java
@@ -22,7 +22,7 @@ import java.awt.event.*;
import java.beans.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altosuilib_2.*;
public class AltosConfigureUI
extends AltosUIConfigure
@@ -31,7 +31,7 @@ public class AltosConfigureUI
AltosVoice voice;
public JTextField callsign_value;
- public JComboBox position_value;
+ public JComboBox<String> position_value;
/* DocumentListener interface methods */
public void insertUpdate(DocumentEvent e) {
@@ -123,11 +123,11 @@ public class AltosConfigureUI
"Bottom",
"Bottom right",
};
-
+
public void add_position() {
pane.add(new JLabel ("Menu position"), constraints(0, 1));
-
- position_value = new JComboBox (position_names);
+
+ position_value = new JComboBox<String>(position_names);
position_value.setMaximumRowCount(position_names.length);
int position = AltosUIPreferences.position();
position_value.setSelectedIndex(position);
diff --git a/altosui/AltosDescent.java b/altosui/AltosDescent.java
index d1379083..36fc1613 100644
--- a/altosui/AltosDescent.java
+++ b/altosui/AltosDescent.java
@@ -17,446 +17,148 @@
package altosui;
+import java.util.*;
import java.awt.*;
+import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
-public class AltosDescent extends JComponent implements AltosFlightDisplay {
- GridBagLayout layout;
+public class AltosDescent extends AltosUIFlightTab {
- public abstract class DescentStatus {
- JLabel label;
- JTextField value;
- AltosLights lights;
-
- abstract void show(AltosState state, AltosListenerState listener_state);
-
- void show() {
- label.setVisible(true);
- value.setVisible(true);
- lights.setVisible(true);
- }
-
- void show(String s) {
- show();
- value.setText(s);
- }
-
- void show(String format, double value) {
- show(String.format(format, value));
- }
-
- void hide() {
- label.setVisible(false);
- value.setVisible(false);
- lights.setVisible(false);
- }
-
- void reset() {
- value.setText("");
- lights.set(false);
- }
-
- void set_font() {
- label.setFont(Altos.label_font);
- value.setFont(Altos.value_font);
- }
-
- public DescentStatus (GridBagLayout layout, int y, String text) {
- GridBagConstraints c = new GridBagConstraints();
- c.weighty = 1;
-
- lights = new AltosLights();
- c.gridx = 0; c.gridy = y;
- c.anchor = GridBagConstraints.CENTER;
- c.fill = GridBagConstraints.VERTICAL;
- c.weightx = 0;
- layout.setConstraints(lights, c);
- add(lights);
-
- label = new JLabel(text);
- label.setFont(Altos.label_font);
- label.setHorizontalAlignment(SwingConstants.LEFT);
- c.gridx = 1; c.gridy = y;
- c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
- c.anchor = GridBagConstraints.WEST;
- c.fill = GridBagConstraints.VERTICAL;
- c.gridwidth = 3;
- c.weightx = 0;
- layout.setConstraints(label, c);
- add(label);
-
- value = new JTextField(Altos.text_width);
- value.setFont(Altos.value_font);
- value.setHorizontalAlignment(SwingConstants.RIGHT);
- c.gridx = 4; c.gridy = y;
- c.gridwidth = 1;
- c.anchor = GridBagConstraints.WEST;
- c.fill = GridBagConstraints.BOTH;
- c.weightx = 1;
- layout.setConstraints(value, c);
- add(value);
+ class Height extends AltosUIUnitsIndicator {
+ public double value(AltosState state, int i) { return state.height(); }
+ public Height (Container container, int x, int y) {
+ super (container, x, y, AltosConvert.height, "Height");
}
}
- public abstract class DescentValue {
- JLabel label;
- JTextField value;
-
- void reset() {
- value.setText("");
- }
-
- abstract void show(AltosState state, AltosListenerState listener_state);
-
- void show() {
- label.setVisible(true);
- value.setVisible(true);
- }
-
- void hide() {
- label.setVisible(false);
- value.setVisible(false);
- }
+ class Speed extends AltosUIUnitsIndicator {
+ public double value(AltosState state, int i) { return state.speed(); }
- void show(String v) {
- show();
- value.setText(v);
- }
-
- void show(AltosUnits units, double v) {
- show(units.show(8, v));
- }
-
- void show(String format, double v) {
- show(String.format(format, v));
- }
-
- void set_font() {
- label.setFont(Altos.label_font);
- value.setFont(Altos.value_font);
- }
-
- public DescentValue (GridBagLayout layout, int x, int y, String text) {
- GridBagConstraints c = new GridBagConstraints();
- c.weighty = 1;
-
- label = new JLabel(text);
- label.setFont(Altos.label_font);
- label.setHorizontalAlignment(SwingConstants.LEFT);
- c.gridx = x + 1; c.gridy = y;
- c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
- c.anchor = GridBagConstraints.WEST;
- c.fill = GridBagConstraints.VERTICAL;
- c.weightx = 0;
- add(label, c);
-
- value = new JTextField(Altos.text_width);
- value.setFont(Altos.value_font);
- value.setHorizontalAlignment(SwingConstants.RIGHT);
- c.gridx = x + 2; c.gridy = y;
- c.gridwidth = 1;
- c.anchor = GridBagConstraints.WEST;
- c.fill = GridBagConstraints.BOTH;
- c.weightx = 1;
- add(value, c);
+ public Speed (Container container, int x, int y) {
+ super (container, x, y, AltosConvert.speed, "Speed");
}
}
- public abstract class DescentDualValue {
- JLabel label;
- JTextField value1;
- JTextField value2;
-
- void reset() {
- value1.setText("");
- value2.setText("");
- }
-
- void show() {
- label.setVisible(true);
- value1.setVisible(true);
- value2.setVisible(true);
- }
-
- void hide() {
- label.setVisible(false);
- value1.setVisible(false);
- value2.setVisible(false);
- }
-
- void set_font() {
- label.setFont(Altos.label_font);
- value1.setFont(Altos.value_font);
- value2.setFont(Altos.value_font);
- }
-
- abstract void show(AltosState state, AltosListenerState listener_state);
-
- void show(String v1, String v2) {
- show();
- value1.setText(v1);
- value2.setText(v2);
- }
- void show(String f1, double v1, String f2, double v2) {
- show();
- value1.setText(String.format(f1, v1));
- value2.setText(String.format(f2, v2));
- }
-
- public DescentDualValue (GridBagLayout layout, int x, int y, String text) {
- GridBagConstraints c = new GridBagConstraints();
- c.weighty = 1;
-
- label = new JLabel(text);
- label.setFont(Altos.label_font);
- label.setHorizontalAlignment(SwingConstants.LEFT);
- c.gridx = x + 1; c.gridy = y;
- c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
- c.anchor = GridBagConstraints.WEST;
- c.fill = GridBagConstraints.VERTICAL;
- c.weightx = 0;
- layout.setConstraints(label, c);
- add(label);
+ class Lat extends AltosUIUnitsIndicator {
- value1 = new JTextField(Altos.text_width);
- value1.setFont(Altos.value_font);
- value1.setHorizontalAlignment(SwingConstants.RIGHT);
- c.gridx = x + 2; c.gridy = y;
- c.anchor = GridBagConstraints.WEST;
- c.fill = GridBagConstraints.BOTH;
- c.weightx = 1;
- layout.setConstraints(value1, c);
- add(value1);
+ public boolean hide (AltosState state, int i) { return state.gps == null || !state.gps.connected; }
- value2 = new JTextField(Altos.text_width);
- value2.setFont(Altos.value_font);
- value2.setHorizontalAlignment(SwingConstants.RIGHT);
- c.gridx = x + 4; c.gridy = y;
- c.anchor = GridBagConstraints.WEST;
- c.fill = GridBagConstraints.BOTH;
- c.weightx = 1;
- c.gridwidth = 1;
- layout.setConstraints(value2, c);
- add(value2);
+ public double value(AltosState state, int i) {
+ if (state.gps == null)
+ return AltosLib.MISSING;
+ if (!state.gps.connected)
+ return AltosLib.MISSING;
+ return state.gps.lat;
}
- }
- class Height extends DescentValue {
- void show (AltosState state, AltosListenerState listener_state) {
- show(AltosConvert.height, state.height());
- }
- public Height (GridBagLayout layout, int x, int y) {
- super (layout, x, y, "Height");
+ public Lat (Container container, int x, int y) {
+ super (container, x, y, AltosConvert.latitude, "Latitude");
}
}
- Height height;
+ class Lon extends AltosUIUnitsIndicator {
+ public boolean hide (AltosState state, int i) { return state.gps == null || !state.gps.connected; }
- class Speed extends DescentValue {
- void show (AltosState state, AltosListenerState listener_state) {
- show(AltosConvert.speed, state.speed());
- }
- public Speed (GridBagLayout layout, int x, int y) {
- super (layout, x, y, "Speed");
+ public double value(AltosState state, int i) {
+ if (state.gps == null)
+ return AltosLib.MISSING;
+ if (!state.gps.connected)
+ return AltosLib.MISSING;
+ return state.gps.lon;
}
- }
-
- Speed speed;
- String pos(double p, String pos, String neg) {
- String h = pos;
- if (p < 0) {
- h = neg;
- p = -p;
+ public Lon (Container container, int x, int y) {
+ super (container, x, y, AltosConvert.longitude, "Longitude");
}
- int deg = (int) Math.floor(p);
- double min = (p - Math.floor(p)) * 60.0;
- return String.format("%s %d° %9.6f", h, deg, min);
}
- class Lat extends DescentValue {
- void show (AltosState state, AltosListenerState listener_state) {
- if (state.gps != null && state.gps.connected && state.gps.lat != AltosLib.MISSING)
- show(pos(state.gps.lat,"N", "S"));
- else
- show("???");
- }
- public Lat (GridBagLayout layout, int x, int y) {
- super (layout, x, y, "Latitude");
+ class Apogee extends AltosUIUnitsIndicator {
+ public boolean hide(double v) { return v == AltosLib.MISSING; }
+ public double value(AltosState state, int i) { return state.apogee_voltage; }
+ public double good() { return AltosLib.ao_igniter_good; }
+
+ public Apogee (Container container, int y) {
+ super(container, 0, y, 3, AltosConvert.voltage, "Apogee Igniter Voltage", 1, true, 3);
}
}
- Lat lat;
+ class Main extends AltosUIUnitsIndicator {
+ public boolean hide(double v) { return v == AltosLib.MISSING; }
+ public double value(AltosState state, int i) { return state.main_voltage; }
+ public double good() { return AltosLib.ao_igniter_good; }
- class Lon extends DescentValue {
- void show (AltosState state, AltosListenerState listener_state) {
- if (state.gps != null && state.gps.connected && state.gps.lon != AltosLib.MISSING)
- show(pos(state.gps.lon,"W", "E"));
- else
- show("???");
- }
- public Lon (GridBagLayout layout, int x, int y) {
- super (layout, x, y, "Longitude");
+ public Main (Container container, int y) {
+ super(container, 0, y, 3, AltosConvert.voltage, "Main Igniter Voltage", 1, true, 3);
}
}
- Lon lon;
-
- class Distance extends DescentValue {
- void show(AltosState state, AltosListenerState listener_state) {
+ class Distance extends AltosUIUnitsIndicator {
+ public double value(AltosState state, int i) {
if (state.from_pad != null)
- show(AltosConvert.distance, state.from_pad.distance);
+ return state.from_pad.distance;
else
- show("???");
- }
-
- public Distance (GridBagLayout layout, int x, int y) {
- super(layout, x, y, "Ground Distance");
+ return AltosLib.MISSING;
}
- }
-
- Distance distance;
-
- class Apogee extends DescentStatus {
- void show (AltosState state, AltosListenerState listener_state) {
- show("%4.2f V", state.apogee_voltage);
- lights.set(state.apogee_voltage >= AltosLib.ao_igniter_good);
- }
- public Apogee (GridBagLayout layout, int y) {
- super(layout, y, "Apogee Igniter Voltage");
+ public Distance(Container container, int x, int y) {
+ super(container, x, y, AltosConvert.distance, "Ground Distance");
}
}
- Apogee apogee;
-
- class Main extends DescentStatus {
- void show (AltosState state, AltosListenerState listener_state) {
- show("%4.2f V", state.main_voltage);
- lights.set(state.main_voltage >= AltosLib.ao_igniter_good);
+ class Range extends AltosUIUnitsIndicator {
+ public double value(AltosState state, int i) {
+ return state.range;
}
- public Main (GridBagLayout layout, int y) {
- super(layout, y, "Main Igniter Voltage");
+ public Range (Container container, int x, int y) {
+ super (container, x, y, AltosConvert.distance, "Range");
}
}
- Main main;
-
- class Bearing extends DescentDualValue {
- void show (AltosState state, AltosListenerState listener_state) {
- if (state.from_pad != null) {
+ class Bearing extends AltosUIIndicator {
+ public void show (AltosState state, AltosListenerState listener_state) {
+ if (state.from_pad != null && state.from_pad.bearing != AltosLib.MISSING) {
show( String.format("%3.0f°", state.from_pad.bearing),
state.from_pad.bearing_words(
AltosGreatCircle.BEARING_LONG));
} else {
- show("???", "???");
+ show("Missing", "Missing");
}
}
- public Bearing (GridBagLayout layout, int x, int y) {
- super (layout, x, y, "Bearing");
+ public Bearing (Container container, int x, int y) {
+ super (container, x, y, 1, "Bearing", 2, false, 1, 2);
}
}
- Bearing bearing;
-
- class Range extends DescentValue {
- void show (AltosState state, AltosListenerState listener_state) {
- show(AltosConvert.distance, state.range);
- }
- public Range (GridBagLayout layout, int x, int y) {
- super (layout, x, y, "Range");
- }
- }
-
- Range range;
-
- class Elevation extends DescentValue {
- void show (AltosState state, AltosListenerState listener_state) {
- show("%3.0f°", state.elevation);
+ class Elevation extends AltosUIIndicator {
+ public void show (AltosState state, AltosListenerState listener_state) {
+ if (state.elevation == AltosLib.MISSING)
+ show("Missing");
+ else
+ show("%3.0f°", state.elevation);
}
- public Elevation (GridBagLayout layout, int x, int y) {
- super (layout, x, y, "Elevation");
+ public Elevation (Container container, int x, int y) {
+ super (container, x, y, "Elevation", 1, false, 1);
}
}
- Elevation elevation;
-
- public void reset() {
- lat.reset();
- lon.reset();
- height.reset();
- speed.reset();
- bearing.reset();
- range.reset();
- distance.reset();
- elevation.reset();
- main.reset();
- apogee.reset();
- }
-
- public void set_font() {
- lat.set_font();
- lon.set_font();
- height.set_font();
- speed.set_font();
- bearing.set_font();
- range.set_font();
- distance.set_font();
- elevation.set_font();
- main.set_font();
- apogee.set_font();
- }
-
- public void show(AltosState state, AltosListenerState listener_state) {
- height.show(state, listener_state);
- speed.show(state, listener_state);
- if (state.gps != null && state.gps.connected) {
- bearing.show(state, listener_state);
- range.show(state, listener_state);
- distance.show(state, listener_state);
- elevation.show(state, listener_state);
- lat.show(state, listener_state);
- lon.show(state, listener_state);
- } else {
- bearing.hide();
- range.hide();
- distance.hide();
- elevation.hide();
- lat.hide();
- lon.hide();
- }
- if (state.main_voltage != AltosLib.MISSING)
- main.show(state, listener_state);
- else
- main.hide();
- if (state.apogee_voltage != AltosLib.MISSING)
- apogee.show(state, listener_state);
- else
- apogee.hide();
- }
-
public String getName() {
return "Descent";
}
public AltosDescent() {
- layout = new GridBagLayout();
-
- setLayout(layout);
-
/* Elements in descent display */
- speed = new Speed(layout, 0, 0);
- height = new Height(layout, 2, 0);
- elevation = new Elevation(layout, 0, 1);
- range = new Range(layout, 2, 1);
- bearing = new Bearing(layout, 0, 2);
- distance = new Distance(layout, 0, 3);
- lat = new Lat(layout, 0, 4);
- lon = new Lon(layout, 2, 4);
-
- apogee = new Apogee(layout, 5);
- main = new Main(layout, 6);
+ add(new Speed(this, 0, 0));
+ add(new Height(this, 2, 0));
+ add(new Elevation(this, 0, 1));
+ add(new Range(this, 2, 1));
+ add(new Bearing(this, 0, 2));
+ add(new Distance(this, 0, 3));
+ add(new Lat(this, 0, 4));
+ add(new Lon(this, 2, 4));
+ add(new Apogee(this, 5));
+ add(new Main(this, 6));
}
}
diff --git a/altosui/AltosFlightStatus.java b/altosui/AltosFlightStatus.java
index c6d75420..46c0b387 100644
--- a/altosui/AltosFlightStatus.java
+++ b/altosui/AltosFlightStatus.java
@@ -19,16 +19,27 @@ package altosui;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
public class AltosFlightStatus extends JComponent implements AltosFlightDisplay {
GridBagLayout layout;
- public class FlightValue {
+ public abstract class FlightValue {
JLabel label;
JTextField value;
- void show(AltosState state, AltosListenerState listener_state) {}
+ void show() {
+ label.setVisible(true);
+ value.setVisible(true);
+ }
+
+ void hide() {
+ label.setVisible(false);
+ value.setVisible(false);
+ }
+
+ abstract void show(AltosState state, AltosListenerState listener_state);
void reset() {
value.setText("");
@@ -39,6 +50,11 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay
value.setFont(Altos.status_font);
}
+ void setVisible(boolean visible) {
+ label.setVisible(visible);
+ value.setVisible(visible);
+ }
+
public FlightValue (GridBagLayout layout, int x, String text) {
GridBagConstraints c = new GridBagConstraints();
c.insets = new Insets(5, 5, 5, 5);
@@ -55,6 +71,7 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay
add(label);
value = new JTextField("");
+ value.setEditable(false);
value.setFont(Altos.status_font);
value.setHorizontalAlignment(SwingConstants.CENTER);
c.gridx = x; c.gridy = 1;
@@ -64,9 +81,33 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay
}
class Call extends FlightValue {
+
+ String last_call = "";
+
+ boolean same_call(String call) {
+ if (last_call == null)
+ return call == null;
+ else
+ return last_call.equals(call);
+ }
+
void show(AltosState state, AltosListenerState listener_state) {
- value.setText(state.callsign);
+ if (!same_call(state.callsign)) {
+ show();
+ value.setText(state.callsign);
+ if (state.callsign == null)
+ setVisible(false);
+ else
+ setVisible(true);
+ last_call = state.callsign;
+ }
}
+
+ public void reset() {
+ super.reset();
+ last_call = "";
+ }
+
public Call (GridBagLayout layout, int x) {
super (layout, x, "Callsign");
}
@@ -75,12 +116,24 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay
Call call;
class Serial extends FlightValue {
+
+ int last_serial = -1;
void show(AltosState state, AltosListenerState listener_state) {
- if (state.serial == AltosLib.MISSING)
- value.setText("none");
- else
- value.setText(String.format("%d", state.serial));
+ if (state.serial != last_serial) {
+ show();
+ if (state.serial == AltosLib.MISSING)
+ value.setText("none");
+ else
+ value.setText(String.format("%d", state.serial));
+ last_serial = state.serial;
+ }
}
+
+ public void reset() {
+ super.reset();
+ last_serial = -1;
+ }
+
public Serial (GridBagLayout layout, int x) {
super (layout, x, "Serial");
}
@@ -89,12 +142,25 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay
Serial serial;
class Flight extends FlightValue {
+
+ int last_flight = -1;
+
void show(AltosState state, AltosListenerState listener_state) {
- if (state.flight == AltosLib.MISSING)
- value.setText("none");
- else
- value.setText(String.format("%d", state.flight));
+ if (state.flight != last_flight) {
+ show();
+ if (state.flight == AltosLib.MISSING)
+ value.setText("none");
+ else
+ value.setText(String.format("%d", state.flight));
+ last_flight = state.flight;
+ }
}
+
+ public void reset() {
+ super.reset();
+ last_flight = -1;
+ }
+
public Flight (GridBagLayout layout, int x) {
super (layout, x, "Flight");
}
@@ -103,9 +169,26 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay
Flight flight;
class FlightState extends FlightValue {
+
+ int last_state = -1;
+
void show(AltosState state, AltosListenerState listener_state) {
- value.setText(state.state_name());
+ if (state.state != last_state) {
+ if (state.state == AltosLib.ao_flight_stateless)
+ hide();
+ else {
+ show();
+ value.setText(state.state_name());
+ }
+ last_state = state.state;
+ }
}
+
+ public void reset() {
+ super.reset();
+ last_state = -1;
+ }
+
public FlightState (GridBagLayout layout, int x) {
super (layout, x, "State");
}
@@ -114,9 +197,26 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay
FlightState flight_state;
class RSSI extends FlightValue {
+
+ int last_rssi = 10000;
+
void show(AltosState state, AltosListenerState listener_state) {
- value.setText(String.format("%d", state.rssi()));
+ if (state.rssi() != last_rssi) {
+ show();
+ value.setText(String.format("%d", state.rssi()));
+ if (state.rssi == AltosLib.MISSING)
+ setVisible(false);
+ else
+ setVisible(true);
+ last_rssi = state.rssi();
+ }
}
+
+ public void reset() {
+ super.reset();
+ last_rssi = 10000;
+ }
+
public RSSI (GridBagLayout layout, int x) {
super (layout, x, "RSSI");
}
@@ -125,10 +225,22 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay
RSSI rssi;
class LastPacket extends FlightValue {
+
+ long last_secs = -1;
+
void show(AltosState state, AltosListenerState listener_state) {
long secs = (System.currentTimeMillis() - state.received_time + 500) / 1000;
- value.setText(String.format("%d", secs));
+ if (secs != last_secs) {
+ value.setText(String.format("%d", secs));
+ last_secs = secs;
+ }
+ }
+
+ public void reset() {
+ super.reset();
+ last_secs = -1;
}
+
public LastPacket(GridBagLayout layout, int x) {
super (layout, x, "Age");
}
@@ -145,7 +257,7 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay
last_packet.reset();
}
- public void set_font () {
+ public void font_size_changed(int font_size) {
call.set_font();
serial.set_font();
flight.set_font();
@@ -154,6 +266,9 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay
last_packet.set_font();
}
+ public void units_changed(boolean imperial_units) {
+ }
+
public void show (AltosState state, AltosListenerState listener_state) {
call.show(state, listener_state);
serial.show(state, listener_state);
@@ -168,6 +283,8 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay
return d.height;
}
+ public String getName() { return "Flight Status"; }
+
public AltosFlightStatus() {
layout = new GridBagLayout();
diff --git a/altosui/AltosFlightStatusTableModel.java b/altosui/AltosFlightStatusTableModel.java
index e372d401..b33f40a4 100644
--- a/altosui/AltosFlightStatusTableModel.java
+++ b/altosui/AltosFlightStatusTableModel.java
@@ -27,7 +27,7 @@ import java.util.*;
import java.text.*;
import java.util.prefs.*;
import java.util.concurrent.LinkedBlockingQueue;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
public class AltosFlightStatusTableModel extends AbstractTableModel {
private String[] columnNames = {
diff --git a/altosui/AltosFlightStatusUpdate.java b/altosui/AltosFlightStatusUpdate.java
index 93399a13..0daec04e 100644
--- a/altosui/AltosFlightStatusUpdate.java
+++ b/altosui/AltosFlightStatusUpdate.java
@@ -18,7 +18,7 @@
package altosui;
import java.awt.event.*;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
public class AltosFlightStatusUpdate implements ActionListener {
diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java
index e8cf7f08..43deb631 100644
--- a/altosui/AltosFlightUI.java
+++ b/altosui/AltosFlightUI.java
@@ -20,26 +20,31 @@ package altosui;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
+import java.util.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
-public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay, AltosFontListener {
+public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay {
AltosVoice voice;
AltosFlightReader reader;
AltosDisplayThread thread;
+ LinkedList<AltosFlightDisplay> displays;
+
JTabbedPane pane;
AltosPad pad;
+ AltosIgnitor ignitor;
AltosAscent ascent;
AltosDescent descent;
AltosLanded landed;
AltosCompanionInfo companion;
- AltosSiteMap sitemap;
+ AltosUIMap sitemap;
boolean has_map;
boolean has_companion;
boolean has_state;
+ boolean has_ignitor;
private AltosFlightStatus flightStatus;
private AltosInfoTable flightInfo;
@@ -54,6 +59,8 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay, A
return ascent;
if (state.state <= Altos.ao_flight_main)
return descent;
+ if (state.state == AltosLib.ao_flight_stateless)
+ return descent;
return landed;
}
@@ -72,29 +79,19 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay, A
}
public void reset() {
- pad.reset();
- ascent.reset();
- descent.reset();
- landed.reset();
- flightInfo.clear();
- sitemap.reset();
- }
-
- public void set_font() {
- pad.set_font();
- ascent.set_font();
- descent.set_font();
- landed.set_font();
- flightStatus.set_font();
- flightInfo.set_font();
- sitemap.set_font();
- companion.set_font();
+ for (AltosFlightDisplay d : displays)
+ d.reset();
}
public void font_size_changed(int font_size) {
- set_font();
+ for (AltosFlightDisplay d : displays)
+ d.font_size_changed(font_size);
}
+ public void units_changed(boolean imperial_units) {
+ for (AltosFlightDisplay d : displays)
+ d.units_changed(imperial_units);
+ }
AltosFlightStatusUpdate status_update;
@@ -104,8 +101,6 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay, A
if (state == null)
state = new AltosState();
- pad.show(state, listener_state);
-
if (state.state != Altos.ao_flight_startup) {
if (!has_state) {
pane.setTitleAt(0, "Launch Pad");
@@ -116,10 +111,6 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay, A
}
}
- ascent.show(state, listener_state);
- descent.show(state, listener_state);
- landed.show(state, listener_state);
-
JComponent tab = which_tab(state);
if (tab != cur_tab) {
if (cur_tab == pane.getSelectedComponent()) {
@@ -127,33 +118,51 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay, A
}
cur_tab = tab;
}
- flightStatus.show(state, listener_state);
- flightInfo.show(state, listener_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;
+ }
+ }
if (state.companion != null) {
if (!has_companion) {
pane.add("Companion", companion);
has_companion= true;
}
- companion.show(state, listener_state);
} else {
if (has_companion) {
pane.remove(companion);
has_companion = false;
}
}
+
if (state.gps != null && state.gps.connected) {
if (!has_map) {
pane.add("Site Map", sitemap);
has_map = true;
}
- sitemap.show(state, listener_state);
} else {
if (has_map) {
pane.remove(sitemap);
has_map = false;
}
}
+
+ for (AltosFlightDisplay d : displays) {
+ try {
+ d.show(state, listener_state);
+ } catch (Exception e) {
+ System.out.printf("Exception showing %s\n", d.getName());
+ e.printStackTrace();
+ }
+ }
}
public void set_exit_on_close() {
@@ -162,7 +171,7 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay, A
Container bag;
AltosFreqList frequencies;
- JComboBox telemetries;
+ JComboBox<String> telemetries;
JLabel telemetry;
ActionListener show_timer;
@@ -170,6 +179,8 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay, A
public AltosFlightUI(AltosVoice in_voice, AltosFlightReader in_reader, final int serial) {
AltosUIPreferences.set_component(this);
+ displays = new LinkedList<AltosFlightDisplay>();
+
voice = in_voice;
reader = in_reader;
@@ -208,8 +219,8 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay, A
// Telemetry format menu
if (reader.supports_telemetry(Altos.ao_telemetry_standard)) {
- telemetries = new JComboBox();
- for (int i = 1; i <= Altos.ao_telemetry_max; i++)
+ 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 ||
@@ -258,6 +269,7 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay, A
/* Flight status is always visible */
flightStatus = new AltosFlightStatus();
+ displays.add(flightStatus);
c.gridx = 0;
c.gridy = 1;
c.fill = GridBagConstraints.HORIZONTAL;
@@ -272,20 +284,29 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay, A
pane = new JTabbedPane();
pad = new AltosPad();
+ displays.add(pad);
pane.add("Status", pad);
+ ignitor = new AltosIgnitor();
+ displays.add(ignitor);
ascent = new AltosAscent();
+ displays.add(ascent);
descent = new AltosDescent();
+ displays.add(descent);
landed = new AltosLanded(reader);
+ displays.add(landed);
flightInfo = new AltosInfoTable();
+ displays.add(flightInfo);
pane.add("Table", new JScrollPane(flightInfo));
companion = new AltosCompanionInfo();
+ displays.add(companion);
has_companion = false;
has_state = false;
- sitemap = new AltosSiteMap();
+ sitemap = new AltosUIMap();
+ displays.add(sitemap);
has_map = false;
/* Make the tabbed pane use the rest of the window space */
@@ -300,6 +321,7 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay, A
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
AltosUIPreferences.register_font_listener(this);
+ AltosPreferences.register_units_listener(this);
addWindowListener(new WindowAdapter() {
@Override
@@ -308,6 +330,7 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay, A
setVisible(false);
dispose();
AltosUIPreferences.unregister_font_listener(AltosFlightUI.this);
+ AltosPreferences.unregister_units_listener(AltosFlightUI.this);
if (exit_on_close)
System.exit(0);
}
diff --git a/altosui/AltosGraphUI.java b/altosui/AltosGraphUI.java
index 40d2f7f4..07fe9317 100644
--- a/altosui/AltosGraphUI.java
+++ b/altosui/AltosGraphUI.java
@@ -1,6 +1,19 @@
-
-// Copyright (c) 2010 Anthony Towns
-// GPL v2 or later
+/*
+ * Copyright © 2010 Anthony Towns
+ *
+ * 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 or any later version 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 altosui;
@@ -8,20 +21,21 @@ import java.io.*;
import java.util.ArrayList;
import java.awt.*;
+import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.ui.RefineryUtilities;
-public class AltosGraphUI extends AltosUIFrame
+public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, AltosUnitsListener
{
JTabbedPane pane;
AltosGraph graph;
AltosUIEnable enable;
- AltosSiteMap map;
+ AltosUIMap map;
AltosState state;
AltosGraphDataSet graphDataSet;
AltosFlightStats stats;
@@ -33,13 +47,22 @@ public class AltosGraphUI extends AltosUIFrame
for (AltosState state : states) {
if (state.gps != null && state.gps.locked && state.gps.nsat >= 4) {
if (map == null)
- map = new AltosSiteMap();
+ map = new AltosUIMap();
map.show(state, null);
has_gps = true;
}
}
}
+ public void font_size_changed(int font_size) {
+ map.font_size_changed(font_size);
+ statsTable.font_size_changed(font_size);
+ }
+
+ public void units_changed(boolean imperial_units) {
+ map.units_changed(imperial_units);
+ }
+
AltosGraphUI(AltosStateIterable states, File file) throws InterruptedException, IOException {
super(file.getName());
state = null;
@@ -66,9 +89,20 @@ public class AltosGraphUI extends AltosUIFrame
setContentPane (pane);
+ AltosUIPreferences.register_font_listener(this);
+ AltosPreferences.register_units_listener(this);
+
+ addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowClosing(WindowEvent e) {
+ setVisible(false);
+ dispose();
+ AltosUIPreferences.unregister_font_listener(AltosGraphUI.this);
+ AltosPreferences.unregister_units_listener(AltosGraphUI.this);
+ }
+ });
pack();
- setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setVisible(true);
if (state != null && has_gps)
map.centre(state);
diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java
index 7ca935b6..042111ec 100644
--- a/altosui/AltosIdleMonitorUI.java
+++ b/altosui/AltosIdleMonitorUI.java
@@ -24,10 +24,10 @@ import javax.swing.event.*;
import java.io.*;
import java.util.concurrent.*;
import java.util.Arrays;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
-public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDisplay, AltosFontListener, AltosIdleMonitorListener, DocumentListener {
+public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDisplay, AltosIdleMonitorListener, DocumentListener {
AltosDevice device;
JTabbedPane pane;
AltosPad pad;
@@ -56,13 +56,14 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl
flightInfo.clear();
}
- public void set_font() {
- pad.set_font();
- flightInfo.set_font();
+ public void font_size_changed(int font_size) {
+ pad.font_size_changed(font_size);
+ flightInfo.font_size_changed(font_size);
}
- public void font_size_changed(int font_size) {
- set_font();
+ public void units_changed(boolean imperial_units) {
+ pad.units_changed(imperial_units);
+ flightInfo.units_changed(imperial_units);
}
AltosFlightStatusUpdate status_update;
@@ -234,7 +235,9 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl
try {
disconnect();
} catch (Exception ex) {
- System.out.println(Arrays.toString(ex.getStackTrace()));
+ System.out.printf("Exception %s\n", ex.toString());
+ for (StackTraceElement el : ex.getStackTrace())
+ System.out.printf("%s\n", el.toString());
}
setVisible(false);
dispose();
diff --git a/altosui/AltosIgniteUI.java b/altosui/AltosIgniteUI.java
index 2e69249f..c251bbe2 100644
--- a/altosui/AltosIgniteUI.java
+++ b/altosui/AltosIgniteUI.java
@@ -24,8 +24,8 @@ import java.io.*;
import java.text.*;
import java.util.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
public class AltosIgniteUI
extends AltosUIDialog
@@ -486,7 +486,7 @@ public class AltosIgniteUI
pane.add(close, c);
close.addActionListener(this);
close.setActionCommand("close");
-
+
pack();
setLocationRelativeTo(owner);
diff --git a/altosui/AltosIgnitor.java b/altosui/AltosIgnitor.java
new file mode 100644
index 00000000..990a87e6
--- /dev/null
+++ b/altosui/AltosIgnitor.java
@@ -0,0 +1,91 @@
+/*
+ * 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 altosui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
+
+public class AltosIgnitor extends AltosUIFlightTab {
+
+ public class Ignitor extends AltosUIUnitsIndicator {
+ int ignitor;
+
+ public double value(AltosState state, int i) {
+ if (state.ignitor_voltage == null ||
+ state.ignitor_voltage.length < ignitor)
+ return AltosLib.MISSING;
+ return state.ignitor_voltage[ignitor];
+ }
+
+ public double good() { return AltosLib.ao_igniter_good; }
+
+ public Ignitor (AltosUIFlightTab container, int y) {
+ super(container, y, AltosConvert.voltage, String.format ("%s Voltage", AltosLib.ignitor_name(y)), 1, true, 1);
+ ignitor = y;
+ }
+ }
+
+ Ignitor[] ignitors;
+
+ public void show(AltosState state, AltosListenerState listener_state) {
+ if (isShowing())
+ make_ignitors(state);
+ super.show(state, listener_state);
+ }
+
+ public boolean should_show(AltosState state) {
+ if (state == null)
+ return false;
+ if (state.ignitor_voltage == null)
+ return false;
+ return state.ignitor_voltage.length > 0;
+ }
+
+ void make_ignitors(AltosState state) {
+ int n = (state == null || state.ignitor_voltage == null) ? 0 : state.ignitor_voltage.length;
+ int old_n = ignitors == null ? 0 : ignitors.length;
+
+ if (n != old_n) {
+
+ if (ignitors != null) {
+ for (int i = 0; i < ignitors.length; i++) {
+ remove(ignitors[i]);
+ ignitors[i].remove(this);
+ ignitors = null;
+ }
+ }
+
+ if (n > 0) {
+ setVisible(true);
+ ignitors = new Ignitor[n];
+ for (int i = 0; i < n; i++) {
+ ignitors[i] = new Ignitor(this, i);
+ add(ignitors[i]);
+ }
+ } else
+ setVisible(false);
+ }
+ }
+
+ public String getName() {
+ return "Ignitors";
+ }
+}
diff --git a/altosui/AltosLanded.java b/altosui/AltosLanded.java
index 74177753..dd5cf9ab 100644
--- a/altosui/AltosLanded.java
+++ b/altosui/AltosLanded.java
@@ -21,216 +21,94 @@ import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
-import org.altusmetrum.altoslib_3.*;
-
-public class AltosLanded extends JComponent implements AltosFlightDisplay, ActionListener {
- GridBagLayout layout;
-
- public class LandedValue {
- JLabel label;
- JTextField value;
- void show(AltosState state, AltosListenerState listener_state) {}
-
- void reset() {
- value.setText("");
- }
-
- void show() {
- label.setVisible(true);
- value.setVisible(true);
- }
-
- void show(String s) {
- show();
- value.setText(s);
- }
-
- void show(AltosUnits units, double v) {
- show(units.show(8, v));
- }
-
- void show(String format, double v) {
- show(String.format(format, v));
- }
-
- public void set_font() {
- label.setFont(Altos.label_font);
- value.setFont(Altos.value_font);
- }
-
- void hide() {
- label.setVisible(false);
- value.setVisible(false);
- }
-
- public LandedValue (GridBagLayout layout, int y, String text) {
- GridBagConstraints c = new GridBagConstraints();
- c.weighty = 1;
-
- label = new JLabel(text);
- label.setFont(Altos.label_font);
- label.setHorizontalAlignment(SwingConstants.LEFT);
- c.gridx = 0; c.gridy = y;
- c.insets = new Insets(10, 10, 10, 10);
- c.anchor = GridBagConstraints.WEST;
- c.weightx = 0;
- c.fill = GridBagConstraints.VERTICAL;
- layout.setConstraints(label, c);
- add(label);
-
- value = new JTextField(Altos.text_width);
- value.setFont(Altos.value_font);
- value.setHorizontalAlignment(SwingConstants.RIGHT);
- c.gridx = 1; c.gridy = y;
- c.anchor = GridBagConstraints.WEST;
- c.weightx = 1;
- c.fill = GridBagConstraints.BOTH;
- layout.setConstraints(value, c);
- add(value);
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
+
+public class AltosLanded extends AltosUIFlightTab implements ActionListener {
+
+ class Bearing extends AltosUIIndicator {
+ public void show (AltosState state, AltosListenerState listener_state) {
+ if (state.from_pad != null && state.from_pad.bearing != AltosLib.MISSING) {
+ show( String.format("%3.0f°", state.from_pad.bearing),
+ state.from_pad.bearing_words(
+ AltosGreatCircle.BEARING_LONG));
+ } else {
+ show("Missing", "Missing");
+ }
}
- }
-
- String pos(double p, String pos, String neg) {
- String h = pos;
- if (p < 0) {
- h = neg;
- p = -p;
+ public Bearing (Container container, int y) {
+ super (container, y, "Bearing", 2);
}
- int deg = (int) Math.floor(p);
- double min = (p - Math.floor(p)) * 60.0;
- return String.format("%s %4d° %9.6f", h, deg, min);
}
- class Lat extends LandedValue {
- void show (AltosState state, AltosListenerState listener_state) {
- show();
- if (state.gps != null && state.gps.connected && state.gps.lat != AltosLib.MISSING)
- show(pos(state.gps.lat,"N", "S"));
+ class Distance extends AltosUIUnitsIndicator {
+ public double value(AltosState state, int i) {
+ if (state.from_pad != null)
+ return state.from_pad.distance;
else
- show("???");
- }
- public Lat (GridBagLayout layout, int y) {
- super (layout, y, "Latitude");
+ return AltosLib.MISSING;
}
- }
-
- Lat lat;
- class Lon extends LandedValue {
- void show (AltosState state, AltosListenerState listener_state) {
- show();
- if (state.gps != null && state.gps.connected && state.gps.lon != AltosLib.MISSING)
- show(pos(state.gps.lon,"E", "W"));
- else
- show("???");
- }
- public Lon (GridBagLayout layout, int y) {
- super (layout, y, "Longitude");
+ public Distance(Container container, int y) {
+ super(container, y, AltosConvert.distance, "Ground Distance", 2);
}
}
- Lon lon;
+ class Lat extends AltosUIUnitsIndicator {
- class Bearing extends LandedValue {
- void show (AltosState state, AltosListenerState listener_state) {
- show();
- if (state.from_pad != null)
- show("%3.0f°", state.from_pad.bearing);
- else
- show("???");
- }
- public Bearing (GridBagLayout layout, int y) {
- super (layout, y, "Bearing");
- }
- }
+ public boolean hide (AltosState state, int i) { return state.gps == null || !state.gps.connected; }
- Bearing bearing;
-
- class Distance extends LandedValue {
- void show (AltosState state, AltosListenerState listener_state) {
- show();
- if (state.from_pad != null)
- show(AltosConvert.distance, state.from_pad.distance);
- else
- show("???");
- }
- public Distance (GridBagLayout layout, int y) {
- super (layout, y, "Distance");
+ public double value(AltosState state, int i) {
+ if (state.gps == null)
+ return AltosLib.MISSING;
+ if (!state.gps.connected)
+ return AltosLib.MISSING;
+ return state.gps.lat;
}
- }
- Distance distance;
-
- class Height extends LandedValue {
- void show (AltosState state, AltosListenerState listener_state) {
- show(AltosConvert.height, state.max_height());
- }
- public Height (GridBagLayout layout, int y) {
- super (layout, y, "Maximum Height");
+ public Lat (Container container, int y) {
+ super (container, y, AltosConvert.latitude, "Latitude", 2);
}
}
- Height height;
+ class Lon extends AltosUIUnitsIndicator {
+ public boolean hide (AltosState state, int i) { return state.gps == null || !state.gps.connected; }
- class Speed extends LandedValue {
- void show (AltosState state, AltosListenerState listener_state) {
- show(AltosConvert.speed, state.max_speed());
+ public double value(AltosState state, int i) {
+ if (state.gps == null)
+ return AltosLib.MISSING;
+ if (!state.gps.connected)
+ return AltosLib.MISSING;
+ return state.gps.lon;
}
- public Speed (GridBagLayout layout, int y) {
- super (layout, y, "Maximum Speed");
+
+ public Lon (Container container, int y) {
+ super (container, y, AltosConvert.longitude, "Longitude", 2);
}
}
- Speed speed;
+ class MaxHeight extends AltosUIUnitsIndicator {
+ public double value(AltosState state, int i) { return state.max_height(); }
- class Accel extends LandedValue {
- void show (AltosState state, AltosListenerState listener_state) {
- show(AltosConvert.accel, state.max_acceleration());
- }
- public Accel (GridBagLayout layout, int y) {
- super (layout, y, "Maximum Acceleration");
+ public MaxHeight (Container container, int y) {
+ super (container, y, AltosConvert.height, "Maximum Height", 2);
}
}
- Accel accel;
+ class MaxSpeed extends AltosUIUnitsIndicator {
+ public double value(AltosState state, int i) { return state.max_speed(); }
- public void reset() {
- lat.reset();
- lon.reset();
- bearing.reset();
- distance.reset();
- height.reset();
- speed.reset();
- accel.reset();
+ public MaxSpeed (Container container, int y) {
+ super (container, y, AltosConvert.speed, "Maximum Speed", 2);
+ }
}
- public void set_font() {
- lat.set_font();
- lon.set_font();
- bearing.set_font();
- distance.set_font();
- height.set_font();
- speed.set_font();
- accel.set_font();
- }
+ class MaxAccel extends AltosUIUnitsIndicator {
+ public double value(AltosState state, int i) { return state.max_acceleration(); }
- public void show(AltosState state, AltosListenerState listener_state) {
- if (state.gps != null && state.gps.connected) {
- bearing.show(state, listener_state);
- distance.show(state, listener_state);
- lat.show(state, listener_state);
- lon.show(state, listener_state);
- } else {
- bearing.hide();
- distance.hide();
- lat.hide();
- lon.hide();
+ public MaxAccel (Container container, int y) {
+ super (container, y, AltosConvert.speed, "Maximum acceleration", 2);
}
- height.show(state, listener_state);
- speed.show(state, listener_state);
- accel.show(state, listener_state);
- if (reader.backing_file() != null)
- graph.setEnabled(true);
}
JButton graph;
@@ -274,20 +152,16 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio
}
public AltosLanded(AltosFlightReader in_reader) {
- layout = new GridBagLayout();
-
reader = in_reader;
- setLayout(layout);
-
/* Elements in descent display */
- bearing = new Bearing(layout, 0);
- distance = new Distance(layout, 1);
- lat = new Lat(layout, 2);
- lon = new Lon(layout, 3);
- height = new Height(layout, 4);
- speed = new Speed(layout, 5);
- accel = new Accel(layout, 6);
+ add(new Bearing(this, 0));
+ add(new Distance(this, 1));
+ add(new Lat(this, 2));
+ add(new Lon(this, 3));
+ add(new MaxHeight(this, 4));
+ add(new MaxSpeed(this, 5));
+ add(new MaxAccel(this, 6));
graph = new JButton ("Graph Flight");
graph.setActionCommand("graph");
@@ -296,12 +170,13 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio
GridBagConstraints c = new GridBagConstraints();
- c.gridx = 0; c.gridy = 7;
+ c.gridx = 1; c.gridy = 7;
c.insets = new Insets(10, 10, 10, 10);
c.anchor = GridBagConstraints.WEST;
c.weightx = 0;
c.weighty = 0;
c.fill = GridBagConstraints.VERTICAL;
add(graph, c);
+ addHierarchyListener(this);
}
}
diff --git a/altosui/AltosLaunch.java b/altosui/AltosLaunch.java
index 04948ee6..9ac1e44c 100644
--- a/altosui/AltosLaunch.java
+++ b/altosui/AltosLaunch.java
@@ -20,7 +20,7 @@ package altosui;
import java.io.*;
import java.util.concurrent.*;
import java.awt.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altosuilib_2.*;
public class AltosLaunch {
AltosDevice device;
diff --git a/altosui/AltosLaunchUI.java b/altosui/AltosLaunchUI.java
index 4d9fbda5..cc082542 100644
--- a/altosui/AltosLaunchUI.java
+++ b/altosui/AltosLaunchUI.java
@@ -23,7 +23,7 @@ import javax.swing.*;
import java.io.*;
import java.text.*;
import java.util.concurrent.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altosuilib_2.*;
class FireButton extends JButton {
protected void processMouseEvent(MouseEvent e) {
diff --git a/altosui/AltosPad.java b/altosui/AltosPad.java
index 7baf0eb2..6b5fd150 100644
--- a/altosui/AltosPad.java
+++ b/altosui/AltosPad.java
@@ -17,253 +17,73 @@
package altosui;
-import java.awt.*;
-import javax.swing.*;
-import org.altusmetrum.altoslib_3.*;
+import java.util.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
-public class AltosPad extends JComponent implements AltosFlightDisplay {
- GridBagLayout layout;
+public class AltosPad extends AltosUIFlightTab {
- public class LaunchStatus {
- JLabel label;
- JTextField value;
- AltosLights lights;
-
- void show(AltosState state, AltosListenerState listener_state) {}
-
- void reset() {
- value.setText("");
- lights.set(false);
- }
-
- public void show() {
- label.setVisible(true);
- value.setVisible(true);
- lights.setVisible(true);
- }
-
- void show(String s) {
- show();
- value.setText(s);
- }
-
- void show(String format, double value) {
- show(String.format(format, value));
- }
-
- void show(String format, int value) {
- show(String.format(format, value));
- }
-
- public void hide() {
- label.setVisible(false);
- value.setVisible(false);
- lights.setVisible(false);
- }
-
- public void set_font() {
- label.setFont(Altos.label_font);
- value.setFont(Altos.value_font);
- }
-
- public void set_label(String text) {
- label.setText(text);
- }
-
- public LaunchStatus (GridBagLayout layout, int y, String text) {
- GridBagConstraints c = new GridBagConstraints();
- c.weighty = 1;
-
- lights = new AltosLights();
- c.gridx = 0; c.gridy = y;
- c.anchor = GridBagConstraints.CENTER;
- c.fill = GridBagConstraints.VERTICAL;
- c.weightx = 0;
- layout.setConstraints(lights, c);
- add(lights);
-
- label = new JLabel(text);
- label.setFont(Altos.label_font);
- label.setHorizontalAlignment(SwingConstants.LEFT);
- c.gridx = 1; c.gridy = y;
- c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
- c.anchor = GridBagConstraints.WEST;
- c.fill = GridBagConstraints.VERTICAL;
- c.weightx = 0;
- layout.setConstraints(label, c);
- add(label);
-
- value = new JTextField(Altos.text_width);
- value.setFont(Altos.value_font);
- value.setHorizontalAlignment(SwingConstants.RIGHT);
- c.gridx = 2; c.gridy = y;
- c.anchor = GridBagConstraints.WEST;
- c.fill = GridBagConstraints.BOTH;
- c.weightx = 1;
- layout.setConstraints(value, c);
- add(value);
-
- }
+ class Battery extends AltosUIVoltageIndicator {
+ public double voltage(AltosState state) { return state.battery_voltage; }
+ public double good() { return AltosLib.ao_battery_good; }
+ public Battery (AltosUIFlightTab container, int y) { super(container, y, "Battery Voltage", 2); }
}
- public class LaunchValue {
- JLabel label;
- JTextField value;
- void show(AltosState state, AltosListenerState listener_state) {}
-
- void show() {
- label.setVisible(true);
- value.setVisible(true);
- }
-
- void hide() {
- label.setVisible(false);
- value.setVisible(false);
- }
-
- public void set_font() {
- label.setFont(Altos.label_font);
- value.setFont(Altos.value_font);
- }
-
- void show(String s) {
- show();
- value.setText(s);
- }
-
- void show(AltosUnits units, double v) {
- show(units.show(8, v));
- }
-
- void show(String format, double v) {
- show(String.format(format, v));
- }
-
- public void set_label(String text) {
- label.setText(text);
- }
-
- void reset() {
- value.setText("");
- }
-
- public LaunchValue (GridBagLayout layout, int y, String text) {
- GridBagConstraints c = new GridBagConstraints();
- c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
- c.weighty = 1;
-
- label = new JLabel(text);
- label.setFont(Altos.label_font);
- label.setHorizontalAlignment(SwingConstants.LEFT);
- c.gridx = 1; c.gridy = y;
- c.anchor = GridBagConstraints.WEST;
- c.fill = GridBagConstraints.VERTICAL;
- c.weightx = 0;
- layout.setConstraints(label, c);
- add(label);
-
- value = new JTextField(Altos.text_width);
- value.setFont(Altos.value_font);
- value.setHorizontalAlignment(SwingConstants.RIGHT);
- c.gridx = 2; c.gridy = y;
- c.anchor = GridBagConstraints.EAST;
- c.fill = GridBagConstraints.BOTH;
- c.weightx = 1;
- layout.setConstraints(value, c);
- add(value);
- }
+ class Apogee extends AltosUIVoltageIndicator {
+ public boolean hide(double v) { return v == AltosLib.MISSING; }
+ public double voltage(AltosState state) { return state.apogee_voltage; }
+ public double good() { return AltosLib.ao_igniter_good; }
+ public Apogee (AltosUIFlightTab container, int y) { super(container, y, "Apogee Igniter Voltage", 2); }
}
- class Battery extends LaunchStatus {
- void show (AltosState state, AltosListenerState listener_state) {
- if (state == null || state.battery_voltage == AltosLib.MISSING)
- hide();
- else {
- show("%4.2f V", state.battery_voltage);
- lights.set(state.battery_voltage >= AltosLib.ao_battery_good);
- }
- }
- public Battery (GridBagLayout layout, int y) {
- super(layout, y, "Battery Voltage");
- }
+ class Main extends AltosUIVoltageIndicator {
+ public boolean hide(double v) { return v == AltosLib.MISSING; }
+ public double voltage(AltosState state) { return state.main_voltage; }
+ public double good() { return AltosLib.ao_igniter_good; }
+ public Main (AltosUIFlightTab container, int y) { super(container, y, "Main Igniter Voltage", 2); }
}
- Battery battery;
-
- class Apogee extends LaunchStatus {
- void show (AltosState state, AltosListenerState listener_state) {
- if (state == null || state.apogee_voltage == AltosLib.MISSING)
- hide();
- else {
- show("%4.2f V", state.apogee_voltage);
- lights.set(state.apogee_voltage >= AltosLib.ao_igniter_good);
- }
- }
- public Apogee (GridBagLayout layout, int y) {
- super(layout, y, "Apogee Igniter Voltage");
- }
- }
-
- Apogee apogee;
-
- class Main extends LaunchStatus {
- void show (AltosState state, AltosListenerState listener_state) {
- if (state == null || state.main_voltage == AltosLib.MISSING)
- hide();
- else {
- show("%4.2f V", state.main_voltage);
- lights.set(state.main_voltage >= AltosLib.ao_igniter_good);
- }
- }
- public Main (GridBagLayout layout, int y) {
- super(layout, y, "Main Igniter Voltage");
- }
- }
-
- Main main;
-
- class LoggingReady extends LaunchStatus {
- void show (AltosState state, AltosListenerState listener_state) {
+ class LoggingReady extends AltosUIIndicator {
+ public void show (AltosState state, AltosListenerState listener_state) {
if (state == null || state.flight == AltosLib.MISSING) {
hide();
} else {
if (state.flight != 0) {
if (state.state <= Altos.ao_flight_pad)
show("Ready to record");
- else if (state.state < Altos.ao_flight_landed)
+ else if (state.state < Altos.ao_flight_landed ||
+ state.state == AltosLib.ao_flight_stateless)
show("Recording data");
else
show("Recorded data");
} else
show("Storage full");
- lights.set(state.flight != 0);
+ set_lights(state.flight != 0);
}
}
- public LoggingReady (GridBagLayout layout, int y) {
- super(layout, y, "On-board Data Logging");
+ public LoggingReady (AltosUIFlightTab container, int y) {
+ super(container, y, "On-board Data Logging", 1, true, 2);
}
}
- LoggingReady logging_ready;
-
- class GPSLocked extends LaunchStatus {
- void show (AltosState state, AltosListenerState listener_state) {
+ class GPSLocked extends AltosUIIndicator {
+ public void show (AltosState state, AltosListenerState listener_state) {
if (state == null || state.gps == null)
hide();
else {
- show("%4d sats", state.gps.nsat);
- lights.set(state.gps.locked && state.gps.nsat >= 4);
+ int sol = state.gps.nsat;
+ int sat = state.gps.cc_gps_sat == null ? 0 : state.gps.cc_gps_sat.length;
+ show("%d in solution", sol, "%d in view", sat);
+ set_lights(state.gps.locked && sol >= 4);
}
}
- public GPSLocked (GridBagLayout layout, int y) {
- super (layout, y, "GPS Locked");
+ public GPSLocked (AltosUIFlightTab container, int y) {
+ super (container, y, "GPS Locked", 2, true, 1);
}
}
- GPSLocked gps_locked;
-
- class GPSReady extends LaunchStatus {
- void show (AltosState state, AltosListenerState listener_state) {
+ class GPSReady extends AltosUIIndicator {
+ public void show (AltosState state, AltosListenerState listener_state) {
if (state == null || state.gps == null)
hide();
else {
@@ -271,45 +91,37 @@ public class AltosPad extends JComponent implements AltosFlightDisplay {
show("Ready");
else
show("Waiting %d", state.gps_waiting);
- lights.set(state.gps_ready);
+ set_lights(state.gps_ready);
}
}
- public GPSReady (GridBagLayout layout, int y) {
- super (layout, y, "GPS Ready");
+ public GPSReady (AltosUIFlightTab container, int y) {
+ super (container, y, "GPS Ready", 1, true, 2);
}
}
- GPSReady gps_ready;
+ class ReceiverBattery extends AltosUIVoltageIndicator {
- class ReceiverBattery extends LaunchStatus {
- void show (AltosState state, AltosListenerState listener_state) {
- if (listener_state == null || listener_state.battery == AltosLib.MISSING)
- hide();
- else {
- show("%4.2f V", listener_state.battery);
- lights.set(listener_state.battery > AltosLib.ao_battery_good);
- }
+ public double voltage(AltosState state) { return AltosLib.MISSING; }
+
+ public boolean hide(double v) { return v == AltosLib.MISSING; }
+ public double good() { return AltosLib.ao_battery_good; }
+
+ public double value(AltosState state, AltosListenerState listener_state, int i) {
+ if (listener_state == null)
+ return AltosLib.MISSING;
+ return listener_state.battery;
}
- public ReceiverBattery (GridBagLayout layout, int y) {
- super(layout, y, "Receiver Battery");
+
+ public ReceiverBattery (AltosUIFlightTab container, int y) {
+ super(container, y, "Receiver Battery", 2);
}
}
- ReceiverBattery receiver_battery;
+ class PadLat extends AltosUIIndicator {
- String pos(double p, String pos, String neg) {
- String h = pos;
- if (p < 0) {
- h = neg;
- p = -p;
- }
- int deg = (int) Math.floor(p);
- double min = (p - Math.floor(p)) * 60.0;
- return String.format("%s %4d° %9.6f", h, deg, min);
- }
+ double last_lat = AltosLib.MISSING - 1;
- class PadLat extends LaunchValue {
- void show (AltosState state, AltosListenerState listener_state) {
+ public void show (AltosState state, AltosListenerState listener_state) {
double lat = AltosLib.MISSING;
String label = null;
@@ -322,21 +134,31 @@ public class AltosPad extends JComponent implements AltosFlightDisplay {
label = "Pad Latitude";
}
}
- if (lat != AltosLib.MISSING) {
- show(pos(lat,"N", "S"));
- set_label(label);
- } else
- hide();
+ if (lat != last_lat) {
+ if (lat != AltosLib.MISSING) {
+ show(AltosConvert.latitude.show(10, lat));
+ set_label(label);
+ } else
+ hide();
+ last_lat = lat;
+ }
+ }
+
+ public void reset() {
+ super.reset();
+ last_lat = AltosLib.MISSING - 1;
}
- public PadLat (GridBagLayout layout, int y) {
- super (layout, y, "Pad Latitude");
+
+ public PadLat (AltosUIFlightTab container, int y) {
+ super (container, y, "Pad Latitude", 1, false, 2);
}
}
- PadLat pad_lat;
+ class PadLon extends AltosUIIndicator {
+
+ double last_lon = AltosLib.MISSING - 1;
- class PadLon extends LaunchValue {
- void show (AltosState state, AltosListenerState listener_state) {
+ public void show (AltosState state, AltosListenerState listener_state) {
double lon = AltosLib.MISSING;
String label = null;
@@ -349,21 +171,31 @@ public class AltosPad extends JComponent implements AltosFlightDisplay {
label = "Pad Longitude";
}
}
- if (lon != AltosLib.MISSING) {
- show(pos(lon,"E", "W"));
- set_label(label);
- } else
- hide();
+ if (lon != last_lon) {
+ if (lon != AltosLib.MISSING) {
+ show(AltosConvert.longitude.show(10, lon));
+ set_label(label);
+ } else
+ hide();
+ last_lon = lon;
+ }
+ }
+
+ public void reset() {
+ super.reset();
+ last_lon = AltosLib.MISSING - 1;
}
- public PadLon (GridBagLayout layout, int y) {
- super (layout, y, "Pad Longitude");
+
+ public PadLon (AltosUIFlightTab container, int y) {
+ super (container, y, "Pad Longitude", 1, false, 2);
}
}
- PadLon pad_lon;
+ class PadAlt extends AltosUIIndicator {
+
+ double last_alt = AltosLib.MISSING - 1;
- class PadAlt extends LaunchValue {
- void show (AltosState state, AltosListenerState listener_state) {
+ public void show (AltosState state, AltosListenerState listener_state) {
double alt = AltosLib.MISSING;
String label = null;
@@ -376,83 +208,38 @@ public class AltosPad extends JComponent implements AltosFlightDisplay {
label = "Pad Altitude";
}
}
- if (alt != AltosLib.MISSING) {
- show("%4.0f m", state.gps.alt);
- set_label(label);
- } else
- hide();
- }
- public PadAlt (GridBagLayout layout, int y) {
- super (layout, y, "Pad Altitude");
+ if (alt != last_alt) {
+ if (alt != AltosLib.MISSING) {
+ show(AltosConvert.height.show(5, alt));
+ set_label(label);
+ } else
+ hide();
+ last_alt = alt;
+ }
}
- }
- PadAlt pad_alt;
-
- public void reset() {
- battery.reset();
- apogee.reset();
- main.reset();
- logging_ready.reset();
- gps_locked.reset();
- gps_ready.reset();
- receiver_battery.reset();
- pad_lat.reset();
- pad_lon.reset();
- pad_alt.reset();
- }
+ public void reset() {
+ super.reset();
+ last_alt = AltosLib.MISSING - 1;
+ }
- public void set_font() {
- battery.set_font();
- apogee.set_font();
- main.set_font();
- logging_ready.set_font();
- gps_locked.set_font();
- gps_ready.set_font();
- receiver_battery.set_font();
- pad_lat.set_font();
- pad_lon.set_font();
- pad_alt.set_font();
- }
-
- public void show(AltosState state, AltosListenerState listener_state) {
- battery.show(state, listener_state);
- apogee.show(state, listener_state);
- main.show(state, listener_state);
- logging_ready.show(state, listener_state);
- pad_alt.show(state, listener_state);
- receiver_battery.show(state, listener_state);
- gps_locked.show(state, listener_state);
- gps_ready.show(state, listener_state);
- pad_lat.show(state, listener_state);
- pad_lon.show(state, listener_state);
+ public PadAlt (AltosUIFlightTab container, int y) {
+ super (container, y, "Pad Altitude", 1, false, 2);
+ }
}
+ public String getName() { return "Pad"; }
public AltosPad() {
- layout = new GridBagLayout();
-
- setLayout(layout);
-
- /* Elements in pad display:
- *
- * Battery voltage
- * Igniter continuity
- * GPS lock status
- * GPS ready status
- * GPS location
- * Pad altitude
- * RSSI
- */
- battery = new Battery(layout, 0);
- apogee = new Apogee(layout, 1);
- main = new Main(layout, 2);
- logging_ready = new LoggingReady(layout, 3);
- gps_locked = new GPSLocked(layout, 4);
- gps_ready = new GPSReady(layout, 5);
- receiver_battery = new ReceiverBattery(layout, 6);
- pad_lat = new PadLat(layout, 7);
- pad_lon = new PadLon(layout, 8);
- pad_alt = new PadAlt(layout, 9);
- show(null, null);
+ int y = 0;
+ add(new Battery(this, y++));
+ add(new Apogee(this, y++));
+ add(new Main(this, y++));
+ add(new LoggingReady(this, y++));
+ add(new GPSLocked(this, y++));
+ add(new GPSReady(this, y++));
+ add(new ReceiverBattery(this, y++));
+ add(new PadLat(this, y++));
+ add(new PadLon(this, y++));
+ add(new PadAlt(this, y++));
}
}
diff --git a/altosui/AltosSiteMap.java b/altosui/AltosSiteMap.java
deleted file mode 100644
index 105afade..00000000
--- a/altosui/AltosSiteMap.java
+++ /dev/null
@@ -1,476 +0,0 @@
-/*
- * Copyright © 2010 Anthony Towns <aj@erisian.com.au>
- *
- * 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 altosui;
-
-import java.awt.*;
-import javax.swing.*;
-import java.io.*;
-import java.lang.Math;
-import java.awt.geom.Point2D;
-import java.util.concurrent.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
-
-public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay {
- // preferred vertical step in a tile in naut. miles
- // will actually choose a step size between x and 2x, where this
- // is 1.5x
- static final double tile_size_nmi = 0.75;
-
- static final int px_size = 512;
-
- static final int MAX_TILE_DELTA = 100;
-
- private static Point2D.Double translatePoint(Point2D.Double p,
- Point2D.Double d)
- {
- return new Point2D.Double(p.x + d.x, p.y + d.y);
- }
-
- static class LatLng {
- public double lat, lng;
- public LatLng(double lat, double lng) {
- this.lat = lat;
- this.lng = lng;
- }
- }
-
- // based on google js
- // http://maps.gstatic.com/intl/en_us/mapfiles/api-3/2/10/main.js
- // search for fromLatLngToPoint and fromPointToLatLng
- /*
- private static Point2D.Double pt(LatLng latlng, int zoom) {
- double scale_x = 256/360.0 * Math.pow(2, zoom);
- double scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom);
- return pt(latlng, scale_x, scale_y);
- }
- */
-
- private static Point2D.Double pt(LatLng latlng,
- double scale_x, double scale_y)
- {
- Point2D.Double res = new Point2D.Double();
- double e;
-
- res.x = latlng.lng * scale_x;
-
- e = Math.sin(Math.toRadians(latlng.lat));
- e = Math.max(e,-(1-1.0E-15));
- e = Math.min(e, 1-1.0E-15 );
-
- res.y = 0.5*Math.log((1+e)/(1-e))*-scale_y;
- return res;
- }
-
- static private LatLng latlng(Point2D.Double pt,
- double scale_x, double scale_y)
- {
- double lat, lng;
- double rads;
-
- lng = pt.x/scale_x;
- rads = 2 * Math.atan(Math.exp(-pt.y/scale_y));
- lat = Math.toDegrees(rads - Math.PI/2);
-
- return new LatLng(lat,lng);
- }
-
- int zoom;
- double scale_x, scale_y;
-
- int radius; /* half width/height of tiles to load */
-
- private Point2D.Double pt(double lat, double lng) {
- return pt(new LatLng(lat, lng), scale_x, scale_y);
- }
-
- private LatLng latlng(double x, double y) {
- return latlng(new Point2D.Double(x,y), scale_x, scale_y);
- }
- /*
- private LatLng latlng(Point2D.Double pt) {
- return latlng(pt, scale_x, scale_y);
- }
- */
-
- ConcurrentHashMap<Point,AltosSiteMapTile> mapTiles = new ConcurrentHashMap<Point,AltosSiteMapTile>();
- Point2D.Double centre;
-
- private Point2D.Double tileCoordOffset(Point p) {
- return new Point2D.Double(centre.x - p.x*px_size,
- centre.y - p.y * px_size);
- }
-
- private Point tileOffset(Point2D.Double p) {
- return new Point((int)Math.floor((centre.x+p.x)/px_size),
- (int)Math.floor((centre.y+p.y)/px_size));
- }
-
- private Point2D.Double getBaseLocation(double lat, double lng) {
- Point2D.Double locn, north_step;
-
- zoom = 2;
- // stupid loop structure to please Java's control flow analysis
- do {
- zoom++;
- scale_x = 256/360.0 * Math.pow(2, zoom);
- scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom);
- locn = pt(lat, lng);
- north_step = pt(lat+tile_size_nmi*4/3/60.0, lng);
- if (locn.y - north_step.y > px_size)
- break;
- } while (zoom < 22);
- locn.x = -px_size * Math.floor(locn.x/px_size);
- locn.y = -px_size * Math.floor(locn.y/px_size);
- return locn;
- }
-
- public void reset() {
- // nothing
- }
-
- public void set_font() {
- // nothing
- }
-
- private void loadMap(final AltosSiteMapTile tile,
- File pngfile, String pngurl)
- {
- final ImageIcon res = AltosSiteMapCache.fetchAndLoadMap(pngfile, pngurl);
- if (res != null) {
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- tile.loadMap(res);
- }
- });
- } else {
- System.out.printf("# Failed to fetch file %s\n", pngfile);
- System.out.printf(" wget -O '%s' '%s'\n", pngfile, pngurl);
- }
- }
-
- File pngfile;
- String pngurl;
-
- public int prefetchMap(int x, int y) {
- LatLng map_latlng = latlng(
- -centre.x + x*px_size + px_size/2,
- -centre.y + y*px_size + px_size/2);
- pngfile = MapFile(map_latlng.lat, map_latlng.lng, zoom);
- pngurl = MapURL(map_latlng.lat, map_latlng.lng, zoom);
- if (pngfile.exists()) {
- return 1;
- } else if (AltosSiteMapCache.fetchMap(pngfile, pngurl)) {
- return 0;
- } else {
- return -1;
- }
- }
-
- public static void prefetchMaps(double lat, double lng) {
- int w = AltosSiteMapPreload.width;
- int h = AltosSiteMapPreload.height;
- AltosSiteMap asm = new AltosSiteMap(true);
- asm.centre = asm.getBaseLocation(lat, lng);
-
- //Point2D.Double p = new Point2D.Double();
- //Point2D.Double p2;
- int dx = -w/2, dy = -h/2;
- for (int y = dy; y < h+dy; y++) {
- for (int x = dx; x < w+dx; x++) {
- int r = asm.prefetchMap(x, y);
- switch (r) {
- case 1:
- System.out.printf("Already have %s\n", asm.pngfile);
- break;
- case 0:
- System.out.printf("Fetched map %s\n", asm.pngfile);
- break;
- case -1:
- System.out.printf("# Failed to fetch file %s\n", asm.pngfile);
- System.out.printf(" wget -O '%s' ''\n", asm.pngfile, asm.pngurl);
- break;
- }
- }
- }
- }
-
- public String initMap(Point offset) {
- AltosSiteMapTile tile = mapTiles.get(offset);
- Point2D.Double coord = tileCoordOffset(offset);
-
- LatLng map_latlng = latlng(px_size/2-coord.x, px_size/2-coord.y);
-
- File pngfile = MapFile(map_latlng.lat, map_latlng.lng, zoom);
- String pngurl = MapURL(map_latlng.lat, map_latlng.lng, zoom);
- loadMap(tile, pngfile, pngurl);
- return pngfile.toString();
- }
-
- public void initAndFinishMapAsync (final AltosSiteMapTile tile, final Point offset) {
- Thread thread = new Thread() {
- public void run() {
- initMap(offset);
- finishTileLater(tile, offset);
- }
- };
- thread.start();
- }
-
- public void setBaseLocation(double lat, double lng) {
- for (Point k : mapTiles.keySet()) {
- AltosSiteMapTile tile = mapTiles.get(k);
- tile.clearMap();
- }
-
- centre = getBaseLocation(lat, lng);
- scrollRocketToVisible(pt(lat,lng));
- }
-
- private void initMaps(double lat, double lng) {
- setBaseLocation(lat, lng);
-
- Thread thread = new Thread() {
- public void run() {
- for (Point k : mapTiles.keySet())
- initMap(k);
- }
- };
- thread.start();
- }
-
- private static File MapFile(double lat, double lng, int zoom) {
- char chlat = lat < 0 ? 'S' : 'N';
- char chlng = lng < 0 ? 'W' : 'E';
- if (lat < 0) lat = -lat;
- if (lng < 0) lng = -lng;
- return new File(AltosUIPreferences.mapdir(),
- String.format("map-%c%.6f,%c%.6f-%d.png",
- chlat, lat, chlng, lng, zoom));
- }
-
- private static String MapURL(double lat, double lng, int zoom) {
- return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=hybrid&format=png32", lat, lng, zoom, px_size, px_size);
- }
-
- boolean initialised = false;
- Point2D.Double last_pt = null;
- int last_state = -1;
-
- public void show(double lat, double lon) {
- System.out.printf ("show %g %g\n", lat, lon);
- return;
-// initMaps(lat, lon);
-// scrollRocketToVisible(pt(lat, lon));
- }
- public void show(final AltosState state, final AltosListenerState listener_state) {
- // if insufficient gps data, nothing to update
- AltosGPS gps = state.gps;
-
- if (gps == null)
- return;
-
- if (!gps.locked && gps.nsat < 4)
- return;
-
- if (!initialised) {
- if (state.pad_lat != AltosLib.MISSING && state.pad_lon != AltosLib.MISSING) {
- initMaps(state.pad_lat, state.pad_lon);
- initialised = true;
- } else if (gps.lat != AltosLib.MISSING && gps.lon != AltosLib.MISSING) {
- initMaps(gps.lat, gps.lon);
- initialised = true;
- } else {
- return;
- }
- }
-
- final Point2D.Double pt = pt(gps.lat, gps.lon);
- if (last_pt == pt && last_state == state.state)
- return;
-
- if (last_pt == null) {
- last_pt = pt;
- }
- boolean in_any = false;
- for (Point offset : mapTiles.keySet()) {
- AltosSiteMapTile tile = mapTiles.get(offset);
- Point2D.Double ref, lref;
- ref = translatePoint(pt, tileCoordOffset(offset));
- lref = translatePoint(last_pt, tileCoordOffset(offset));
- tile.show(state, listener_state, lref, ref);
- if (0 <= ref.x && ref.x < px_size)
- if (0 <= ref.y && ref.y < px_size)
- in_any = true;
- }
-
- Point offset = tileOffset(pt);
- if (!in_any) {
- Point2D.Double ref, lref;
- ref = translatePoint(pt, tileCoordOffset(offset));
- lref = translatePoint(last_pt, tileCoordOffset(offset));
-
- AltosSiteMapTile tile = createTile(offset);
- tile.show(state, listener_state, lref, ref);
- initAndFinishMapAsync(tile, offset);
- }
-
- scrollRocketToVisible(pt);
-
- if (offset != tileOffset(last_pt)) {
- ensureTilesAround(offset);
- }
-
- last_pt = pt;
- last_state = state.state;
- }
-
- public void centre(Point2D.Double pt) {
- Rectangle r = comp.getVisibleRect();
- Point2D.Double copt = translatePoint(pt, tileCoordOffset(topleft));
- int dx = (int)copt.x - r.width/2 - r.x;
- int dy = (int)copt.y - r.height/2 - r.y;
- r.x += dx;
- r.y += dy;
- comp.scrollRectToVisible(r);
- }
-
- public void centre(AltosState state) {
- if (!state.gps.locked && state.gps.nsat < 4)
- return;
- centre(pt(state.gps.lat, state.gps.lon));
- }
-
- public void draw_circle(double lat, double lon) {
- final Point2D.Double pt = pt(lat, lon);
-
- for (Point offset : mapTiles.keySet()) {
- AltosSiteMapTile tile = mapTiles.get(offset);
- Point2D.Double ref = translatePoint(pt, tileCoordOffset(offset));
- tile.draw_circle(ref);
- }
- }
-
- private AltosSiteMapTile createTile(Point offset) {
- AltosSiteMapTile tile = new AltosSiteMapTile(px_size);
- mapTiles.put(offset, tile);
- return tile;
- }
- private void finishTileLater(final AltosSiteMapTile tile,
- final Point offset)
- {
- SwingUtilities.invokeLater( new Runnable() {
- public void run() {
- addTileAt(tile, offset);
- }
- } );
- }
-
- private void ensureTilesAround(Point base_offset) {
- for (int x = -radius; x <= radius; x++) {
- for (int y = -radius; y <= radius; y++) {
- Point offset = new Point(base_offset.x + x, base_offset.y + y);
- if (mapTiles.containsKey(offset))
- continue;
- AltosSiteMapTile tile = createTile(offset);
- initAndFinishMapAsync(tile, offset);
- }
- }
- }
-
- private Point topleft = new Point(0,0);
- private void scrollRocketToVisible(Point2D.Double pt) {
- Rectangle r = comp.getVisibleRect();
- Point2D.Double copt = translatePoint(pt, tileCoordOffset(topleft));
- int dx = (int)copt.x - r.width/2 - r.x;
- int dy = (int)copt.y - r.height/2 - r.y;
- if (Math.abs(dx) > r.width/4 || Math.abs(dy) > r.height/4) {
- r.x += dx;
- r.y += dy;
- comp.scrollRectToVisible(r);
- }
- }
-
- private void addTileAt(AltosSiteMapTile tile, Point offset) {
- if (Math.abs(offset.x) >= MAX_TILE_DELTA ||
- Math.abs(offset.y) >= MAX_TILE_DELTA)
- {
- System.out.printf("Rocket too far away from pad (tile %d,%d)\n",
- offset.x, offset.y);
- return;
- }
-
- boolean review = false;
- Rectangle r = comp.getVisibleRect();
- if (offset.x < topleft.x) {
- r.x += (topleft.x - offset.x) * px_size;
- topleft.x = offset.x;
- review = true;
- }
- if (offset.y < topleft.y) {
- r.y += (topleft.y - offset.y) * px_size;
- topleft.y = offset.y;
- review = true;
- }
- GridBagConstraints c = new GridBagConstraints();
- c.anchor = GridBagConstraints.CENTER;
- c.fill = GridBagConstraints.BOTH;
- // put some space between the map tiles, debugging only
- // c.insets = new Insets(5, 5, 5, 5);
-
- c.gridx = offset.x + MAX_TILE_DELTA;
- c.gridy = offset.y + MAX_TILE_DELTA;
- layout.setConstraints(tile, c);
-
- comp.add(tile);
- if (review) {
- comp.scrollRectToVisible(r);
- }
- }
-
- private AltosSiteMap(boolean knowWhatYouAreDoing) {
- if (!knowWhatYouAreDoing) {
- throw new RuntimeException("Arggh.");
- }
- }
-
- JComponent comp = new JComponent() { };
- private GridBagLayout layout = new GridBagLayout();
-
- public AltosSiteMap(int in_radius) {
- radius = in_radius;
-
- GrabNDrag scroller = new GrabNDrag(comp);
-
- comp.setLayout(layout);
-
- for (int x = -radius; x <= radius; x++) {
- for (int y = -radius; y <= radius; y++) {
- Point offset = new Point(x, y);
- AltosSiteMapTile t = createTile(offset);
- addTileAt(t, offset);
- }
- }
- setViewportView(comp);
- setPreferredSize(new Dimension(500,500));
- }
-
- public AltosSiteMap() {
- this(1);
- }
-}
diff --git a/altosui/AltosSiteMapCache.java b/altosui/AltosSiteMapCache.java
deleted file mode 100644
index 03dc3cf5..00000000
--- a/altosui/AltosSiteMapCache.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright © 2010 Anthony Towns <aj@erisian.com.au>
- *
- * 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 altosui;
-
-import javax.swing.*;
-import javax.imageio.ImageIO;
-import java.awt.image.*;
-import java.io.*;
-import java.net.URL;
-import java.net.URLConnection;
-
-public class AltosSiteMapCache extends JLabel {
- static final long google_maps_ratelimit_ms = 1200;
- // Google limits static map queries to 50 per minute per IP, so
- // each query should take at least 1.2 seconds.
-
- public static boolean fetchMap(File file, String url) {
- URL u;
- long startTime = System.nanoTime();
-
- try {
- u = new URL(url);
- } catch (java.net.MalformedURLException e) {
- return false;
- }
-
- byte[] data;
- try {
- URLConnection uc = u.openConnection();
- int contentLength = uc.getContentLength();
- InputStream in = new BufferedInputStream(uc.getInputStream());
- int bytesRead = 0;
- int offset = 0;
- data = new byte[contentLength];
- while (offset < contentLength) {
- bytesRead = in.read(data, offset, data.length - offset);
- if (bytesRead == -1)
- break;
- offset += bytesRead;
- }
- in.close();
-
- if (offset != contentLength) {
- return false;
- }
- } catch (IOException e) {
- return false;
- }
-
- try {
- FileOutputStream out = new FileOutputStream(file);
- out.write(data);
- out.flush();
- out.close();
- } catch (FileNotFoundException e) {
- return false;
- } catch (IOException e) {
- if (file.exists()) {
- file.delete();
- }
- return false;
- }
-
- long duration_ms = (System.nanoTime() - startTime) / 1000000;
- if (duration_ms < google_maps_ratelimit_ms) {
- try {
- Thread.sleep(google_maps_ratelimit_ms - duration_ms);
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- }
- }
-
- return true;
- }
-
- public static ImageIcon fetchAndLoadMap(File pngfile, String url) {
- if (!pngfile.exists()) {
- if (!fetchMap(pngfile, url)) {
- return null;
- }
- }
- return loadMap(pngfile, url);
- }
-
- public static ImageIcon loadMap(File pngfile, String url) {
- if (!pngfile.exists()) {
- return null;
- }
-
- try {
- BufferedImage img;
-
- img = ImageIO.read(pngfile);
- if (img == null) {
- System.out.printf("# Can't read pngfile %s\n", pngfile);
- return null;
- }
- return new ImageIcon(img);
- } catch (IOException e) {
- System.out.printf("# IO error trying to load %s\n", pngfile);
- return null;
- }
- }
-}
diff --git a/altosui/AltosSiteMapTile.java b/altosui/AltosSiteMapTile.java
deleted file mode 100644
index 7d5b65e1..00000000
--- a/altosui/AltosSiteMapTile.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright © 2010 Anthony Towns <aj@erisian.com.au>
- *
- * 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 altosui;
-
-import java.awt.*;
-import java.awt.image.*;
-import javax.swing.*;
-import java.awt.geom.Point2D;
-import java.awt.geom.Line2D;
-import org.altusmetrum.altoslib_3.*;
-
-public class AltosSiteMapTile extends JLayeredPane {
- JLabel mapLabel;
- JLabel draw;
- Graphics2D g2d;
- int px_size;
-
- public void loadMap(ImageIcon icn) {
- mapLabel.setIcon(icn);
- }
-
- public void clearMap() {
- fillLabel(mapLabel, Color.GRAY, px_size);
- g2d = fillLabel(draw, new Color(127,127,127,0), px_size);
- g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
- RenderingHints.VALUE_ANTIALIAS_ON);
- g2d.setStroke(new BasicStroke(6, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
- }
-
- static Color stateColors[] = {
- Color.WHITE, // startup
- Color.WHITE, // idle
- Color.WHITE, // pad
- Color.RED, // boost
- Color.PINK, // fast
- Color.YELLOW, // coast
- Color.CYAN, // drogue
- Color.BLUE, // main
- Color.BLACK // landed
- };
-
- private boolean drawn_landed_circle = false;
- private boolean drawn_boost_circle = false;
- public synchronized void show(AltosState state, AltosListenerState listener_state,
- Point2D.Double last_pt, Point2D.Double pt)
- {
- if (0 <= state.state && state.state < stateColors.length) {
- g2d.setColor(stateColors[state.state]);
- }
- g2d.draw(new Line2D.Double(last_pt, pt));
-
- if (state.state == 3 && !drawn_boost_circle) {
- drawn_boost_circle = true;
- g2d.setColor(Color.RED);
- g2d.drawOval((int)last_pt.x-5, (int)last_pt.y-5, 10, 10);
- g2d.drawOval((int)last_pt.x-20, (int)last_pt.y-20, 40, 40);
- g2d.drawOval((int)last_pt.x-35, (int)last_pt.y-35, 70, 70);
- }
- if (state.state == 8 && !drawn_landed_circle) {
- drawn_landed_circle = true;
- g2d.setColor(Color.BLACK);
- g2d.drawOval((int)pt.x-5, (int)pt.y-5, 10, 10);
- g2d.drawOval((int)pt.x-20, (int)pt.y-20, 40, 40);
- g2d.drawOval((int)pt.x-35, (int)pt.y-35, 70, 70);
- }
-
- repaint();
- }
-
- public void draw_circle(Point2D.Double pt) {
- g2d.setColor(Color.RED);
- g2d.drawOval((int)pt.x-5, (int)pt.y-5, 10, 10);
- g2d.drawOval((int)pt.x-20, (int)pt.y-20, 40, 40);
- g2d.drawOval((int)pt.x-35, (int)pt.y-35, 70, 70);
- }
-
- public static Graphics2D fillLabel(JLabel l, Color c, int px_size) {
- BufferedImage img = new BufferedImage(px_size, px_size,
- BufferedImage.TYPE_INT_ARGB);
- Graphics2D g = img.createGraphics();
- g.setColor(c);
- g.fillRect(0, 0, px_size, px_size);
- l.setIcon(new ImageIcon(img));
- return g;
- }
-
- public AltosSiteMapTile(int in_px_size) {
- px_size = in_px_size;
- setPreferredSize(new Dimension(px_size, px_size));
-
- mapLabel = new JLabel();
- fillLabel(mapLabel, Color.GRAY, px_size);
- mapLabel.setOpaque(true);
- mapLabel.setBounds(0, 0, px_size, px_size);
- add(mapLabel, new Integer(0));
-
- draw = new JLabel();
- g2d = fillLabel(draw, new Color(127, 127, 127, 0), px_size);
- g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
- RenderingHints.VALUE_ANTIALIAS_ON);
- g2d.setStroke(new BasicStroke(6, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
- draw.setBounds(0, 0, px_size, px_size);
- draw.setOpaque(false);
-
- add(draw, new Integer(1));
- }
-}
diff --git a/altosui/AltosUI.app/Contents/Resources/AltosUIIcon.icns b/altosui/AltosUI.app/Contents/Resources/AltosUIIcon.icns
deleted file mode 100644
index fe49f362..00000000
--- a/altosui/AltosUI.app/Contents/Resources/AltosUIIcon.icns
+++ /dev/null
Binary files differ
diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java
index 5d459947..6137487c 100644
--- a/altosui/AltosUI.java
+++ b/altosui/AltosUI.java
@@ -22,8 +22,8 @@ import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
public class AltosUI extends AltosUIFrame {
public AltosVoice voice = new AltosVoice();
@@ -74,6 +74,10 @@ public class AltosUI extends AltosUIFrame {
}
}
+ public void scan_device_selected(AltosDevice device) {
+ telemetry_window(device);
+ }
+
Container pane;
GridBagLayout gridbag;
@@ -233,7 +237,7 @@ public class AltosUI extends AltosUIFrame {
});
setLocationByPlatform(false);
-
+
/* Insets aren't set before the window is visible */
setVisible(true);
}
@@ -272,11 +276,11 @@ public class AltosUI extends AltosUIFrame {
}
void ScanChannels() {
- new AltosScanUI(AltosUI.this);
+ new AltosScanUI(AltosUI.this, true);
}
void LoadMaps() {
- new AltosSiteMapPreload(AltosUI.this);
+ new AltosUIMapPreload(AltosUI.this);
}
void LaunchController() {
@@ -302,7 +306,7 @@ public class AltosUI extends AltosUIFrame {
* a TeleDongle over the packet link
*/
private void SaveFlightData() {
- new AltosEepromManage(AltosUI.this);
+ new AltosEepromManage(AltosUI.this, AltosLib.product_any);
}
/* Load a flight log file and write out a CSV file containing
@@ -468,7 +472,7 @@ public class AltosUI extends AltosUIFrame {
}
return false;
}
-
+
static boolean process_summary(File file) {
AltosStateIterable states = record_iterable(file);
if (states == null)
@@ -547,7 +551,7 @@ public class AltosUI extends AltosUIFrame {
System.out.printf(" --kml\tgenerate KML output for use with Google Earth\n");
System.exit(code);
}
-
+
public static void main(final String[] args) {
int errors = 0;
load_library(null);
@@ -574,7 +578,7 @@ public class AltosUI extends AltosUIFrame {
} else {
double lat = Double.parseDouble(args[i+1]);
double lon = Double.parseDouble(args[i+2]);
- AltosSiteMap.prefetchMaps(lat, lon);
+// AltosSiteMap.prefetchMaps(lat, lon);
i += 2;
}
} else if (args[i].equals("--replay"))
diff --git a/altosui/AltosUIPreferencesBackend.java b/altosui/AltosUIPreferencesBackend.java
index 697d9902..28047086 100644
--- a/altosui/AltosUIPreferencesBackend.java
+++ b/altosui/AltosUIPreferencesBackend.java
@@ -19,13 +19,13 @@ package altosui;
import java.io.File;
import java.util.prefs.*;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
import javax.swing.filechooser.FileSystemView;
public class AltosUIPreferencesBackend implements AltosPreferencesBackend {
private Preferences _preferences = null;
-
+
public AltosUIPreferencesBackend() {
_preferences = Preferences.userRoot().node("/org/altusmetrum/altosui");
}
diff --git a/altosui/Makefile-standalone b/altosui/Makefile-standalone
index 23163e40..cbaf9743 100644
--- a/altosui/Makefile-standalone
+++ b/altosui/Makefile-standalone
@@ -181,7 +181,7 @@ $(DARWIN_ZIP): $(DARWIN_FILES)
cp $(DARWIN_EXTRA) darwin/AltOS
cd darwin && zip -r ../$@ AltosUI.app AltOS
-WINDOWS_FILES = $(FAT_FILES) libaltos/altos.dll ../telemetrum.inf $(WINDOWS_ICON)
+WINDOWS_FILES = $(FAT_FILES) libaltos/altos.dll ../altusmetrum.inf $(WINDOWS_ICON)
$(WINDOWS_EXE): $(WINDOWS_FILES) altos-windows.nsi
rm -f $@
diff --git a/altosui/Makefile.am b/altosui/Makefile.am
index 32a3df97..98a5e193 100644
--- a/altosui/Makefile.am
+++ b/altosui/Makefile.am
@@ -1,6 +1,6 @@
JAVAROOT=classes
-AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -source 6
+AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked -source 6
man_MANS=altosui.1
@@ -10,71 +10,31 @@ CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH="$(JAVAROOT):../altoslib/*:../alto
bin_SCRIPTS=altosui
-altosui_BT = \
- AltosBTDevice.java \
- AltosBTDeviceIterator.java \
- AltosBTManage.java \
- AltosBTKnown.java
-
altosui_JAVA = \
- GrabNDrag.java \
AltosAscent.java \
AltosChannelMenu.java \
AltosCompanionInfo.java \
AltosConfig.java \
- AltosConfigFreqUI.java \
AltosConfigUI.java \
AltosConfigPyroUI.java \
AltosConfigureUI.java \
AltosConfigTD.java \
AltosConfigTDUI.java \
- AltosCSV.java \
- AltosCSVUI.java \
AltosDescent.java \
- AltosDeviceUIDialog.java \
- AltosDisplayThread.java \
- AltosEepromDelete.java \
- AltosEepromManage.java \
- AltosEepromMonitorUI.java \
- AltosEepromSelect.java \
- AltosFlashUI.java \
- AltosFlightDisplay.java \
- AltosFlightInfoTableModel.java \
- AltosFlightStats.java \
- AltosFlightStatsTable.java \
AltosFlightStatus.java \
AltosFlightStatusUpdate.java \
AltosFlightUI.java \
- AltosFreqList.java \
Altos.java \
AltosIdleMonitorUI.java \
AltosIgniteUI.java \
+ AltosIgnitor.java \
AltosLaunch.java \
AltosLaunchUI.java \
- AltosInfoTable.java \
- AltosKML.java \
AltosLanded.java \
- AltosLed.java \
- AltosLights.java \
AltosPad.java \
AltosUIPreferencesBackend.java \
- AltosRomconfigUI.java \
- AltosScanUI.java \
- AltosSerial.java \
- AltosSerialInUseException.java \
- AltosSiteMap.java \
- AltosSiteMapPreload.java \
- AltosSiteMapCache.java \
- AltosSiteMapTile.java \
AltosUI.java \
- AltosWriter.java \
- AltosGraph.java \
- AltosGraphDataPoint.java \
- AltosGraphDataSet.java \
- AltosGraphUI.java \
- AltosDataChooser.java \
- AltosVoice.java \
- $(altosui_BT)
+ AltosGraphUI.java
JFREECHART_CLASS= \
jfreechart.jar
@@ -103,6 +63,10 @@ LIBALTOS= \
libaltos.dylib \
altos.dll
+desktopdir = $(datadir)/applications
+desktop_file = altos.desktop
+desktop_SCRIPTS = $(desktop_file)
+
JAR=altosui.jar
FATJAR=altosui-fat.jar
@@ -118,22 +82,16 @@ JAVA_ICONS=\
$(ICONDIR)/altus-metrum-128.png \
$(ICONDIR)/altus-metrum-256.png
-ICONS= $(ICONDIR)/redled.png $(ICONDIR)/redoff.png \
- $(ICONDIR)/greenled.png $(ICONDIR)/greenoff.png \
- $(ICONDIR)/grayled.png $(ICONDIR)/grayoff.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 \
- -C $(ICONDIR) redled.png -C $(ICONDIR) redoff.png \
- -C $(ICONDIR) greenled.png -C $(ICONDIR) greenoff.png \
- -C $(ICONDIR) grayon.png -C $(ICONDIR) grayled.png
+ -C $(ICONDIR) altus-metrum-256.png
WINDOWS_ICON=$(ICONDIR)/altus-metrum.ico
+MACOSX_ICON=$(ICONDIR)/AltosUIIcon.icns
# Firmware
FIRMWARE_TD_0_2=$(top_srcdir)/src/teledongle-v0.2/teledongle-v0.2-$(VERSION).ihx
@@ -156,7 +114,10 @@ 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=$(FIRMWARE_TM) $(FIRMWARE_TELEMINI) $(FIRMWARE_TD) $(FIRMWARE_TBT) $(FIRMWARE_TMEGA) $(FIRMWARE_EMINI)
+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)
ALTUSMETRUM_DOC=$(top_srcdir)/doc/altusmetrum.pdf
ALTOS_DOC=$(top_srcdir)/doc/altos.pdf
@@ -171,6 +132,7 @@ DOC=$(ALTUSMETRUM_DOC) $(ALTOS_DOC) $(TELEMETRY_DOC) $(TEMPLATE_DOC)
# Distribution targets
LINUX_DIST=Altos-Linux-$(VERSION).tar.bz2
+LINUX_SH=Altos-Linux-$(VERSION).sh
MACOSX_DIST=Altos-Mac-$(VERSION).dmg
WINDOWS_DIST=Altos-Windows-$(VERSION_DASH).exe
@@ -178,37 +140,48 @@ FAT_FILES=$(FATJAR) $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) $(FREETTS_CLASS) $(JFR
LINUX_LIBS=libaltos32.so libaltos64.so
-LINUX_FILES=$(FAT_FILES) $(LINUX_LIBS) $(FIRMWARE) $(DOC)
+LINUX_FILES=$(FAT_FILES) $(LINUX_LIBS) $(FIRMWARE) $(DOC) altos.desktop.in ../icon/altusmetrum.svg
LINUX_EXTRA=altosui-fat
MACOSX_INFO_PLIST=Info.plist
-MACOSX_FILES=$(FAT_FILES) libaltos.dylib $(MACOSX_INFO_PLIST) $(DOC) ReadMe-Mac.rtf
+MACOSX_FILES=$(FAT_FILES) libaltos.dylib $(MACOSX_INFO_PLIST) $(DOC) ReadMe-Mac.rtf $(MACOSX_ICON)
MACOSX_EXTRA=$(FIRMWARE)
-WINDOWS_FILES=$(FAT_FILES) altos.dll altos64.dll $(top_srcdir)/telemetrum.inf $(WINDOWS_ICON)
+WINDOWS_FILES=$(FAT_FILES) $(FIRMWARE) altos.dll altos64.dll $(top_srcdir)/altusmetrum.inf $(top_srcdir)/altusmetrum.cat $(WINDOWS_ICON)
all-local: classes/altosui $(JAR) altosui altosui-test altosui-jdb
clean-local:
-rm -rf classes $(JAR) $(FATJAR) \
- $(LINUX_DIST) $(MACOSX_DIST) windows $(WINDOWS_DIST) $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) $(FREETTS_CLASS) \
+ $(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
+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 > $@
+ chmod +x $@
+
if FATINSTALL
FATTARGET=$(FATDIR)/$(VERSION)
LINUX_DIST_TARGET=$(FATTARGET)/$(LINUX_DIST)
+LINUX_SH_TARGET=$(FATTARGET)/$(LINUX_SH)
MACOSX_DIST_TARGET=$(FATTARGET)/$(MACOSX_DIST)
WINDOWS_DIST_TARGET=$(FATTARGET)/$(WINDOWS_DIST)
-fat: $(LINUX_DIST_TARGET) $(MACOSX_DIST_TARGET) $(WINDOWS_DIST_TARGET)
+fat: $(LINUX_DIST_TARGET) $(LINUX_SH_TARGET) $(MACOSX_DIST_TARGET) $(WINDOWS_DIST_TARGET)
$(LINUX_DIST_TARGET): $(LINUX_DIST)
mkdir -p $(FATTARGET)
cp -p $< $@
+$(LINUX_SH_TARGET): $(LINUX_SH)
+ mkdir -p $(FATTARGET)
+ cp -p $< $@
+
$(MACOSX_DIST_TARGET): $(MACOSX_DIST)
mkdir -p $(FATTARGET)
cp -p $< $@
@@ -218,7 +191,7 @@ $(WINDOWS_DIST_TARGET): $(WINDOWS_DIST)
cp -p $< $@
else
-fat: $(LINUX_DIST) $(MACOSX_DIST) $(WINDOWS_DIST)
+fat: $(LINUX_DIST) $(LINUX_SH) $(MACOSX_DIST) $(WINDOWS_DIST)
endif
@@ -259,8 +232,12 @@ altosui: Makefile
chmod +x $@
altosui-test: Makefile
- echo "#!/bin/sh" > $@
- echo 'exec java -Djava.library.path="../libaltos/.libs" -jar altosui.jar "$$@"' >> $@
+ echo '#!/bin/sh' > $@
+ echo 'dir="$$(dirname $$0)"' >> $@
+ echo 'cd "$$dir"' >> $@
+ echo 'altosui="$$(pwd -P)"' >> $@
+ echo 'altos="$$(dirname $$altosui)"' >> $@
+ echo 'exec java -Djava.library.path="$$altos/libaltos/.libs" -jar "$$altosui/altosui.jar" "$$@"' >> $@
chmod +x $@
altosui-jdb: Makefile
@@ -333,6 +310,10 @@ $(LINUX_DIST): $(LINUX_FILES) $(LINUX_EXTRA)
chmod +x linux/AltOS/altosui
tar cjf $@ -C linux AltOS
+$(LINUX_SH): $(LINUX_DIST) linux-install.sh
+ cat linux-install.sh $(LINUX_DIST) > $@
+ chmod +x $@
+
$(MACOSX_DIST): $(MACOSX_FILES) $(MACOSX_EXTRA) Makefile
-rm -f $@
-rm -rf macosx
@@ -343,6 +324,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 $(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
@@ -355,5 +337,4 @@ $(MACOSX_DIST): $(MACOSX_FILES) $(MACOSX_EXTRA) Makefile
$(WINDOWS_DIST): $(WINDOWS_FILES) altos-windows.nsi
-rm -f $@
- makensis -Oaltos-windows.log "-XOutFile $@" "-DVERSION=$(VERSION)" altos-windows.nsi
-
+ makensis -Oaltos-windows.log "-XOutFile $@" "-DVERSION=$(VERSION)" altos-windows.nsi || (cat altos-windows.log && exit 1)
diff --git a/altosui/altos-windows.nsi.in b/altosui/altos-windows.nsi.in
index 3832e901..b72772e2 100644
--- a/altosui/altos-windows.nsi.in
+++ b/altosui/altos-windows.nsi.in
@@ -1,8 +1,10 @@
!addplugindir Instdrv/NSIS/Plugins
-; Definitions for Java 1.6 Detection
-!define JRE_VERSION "1.6"
-!define JRE_ALTERNATE "1.7"
-!define JRE_URL "http://javadl.sun.com/webapps/download/AutoDL?BundleId=52247&/jre-6u27-windows-i586-p.exe"
+!include x64.nsh
+; Definitions for Java 1.7 Detection
+!define JRE_VERSION "1.7"
+!define JRE_ALTERNATE "1.6"
+!define JRE32_URL "http://javadl.sun.com/webapps/download/AutoDL?BundleId=83383&/jre-7u51-windows-i586.exe"
+!define JRE64_URL "http://javadl.sun.com/webapps/download/AutoDL?BundleId=83385&/jre-7u51-windows-x64.exe"
!define PRODUCT_NAME "Altus Metrum Windows Software"
Name "Altus Metrum Installer"
@@ -23,12 +25,34 @@ ShowInstDetails Show
ComponentText "Altus Metrum Software and Driver Installer"
+Function .onInit
+ DetailPrint "Checking host operating system"
+ ${If} ${RunningX64}
+ DetailPrint "Installer running on 64-bit host"
+ SetRegView 64
+ StrCpy $INSTDIR "$PROGRAMFILES64\AltusMetrum"
+ ${DisableX64FSRedirection}
+ ${EndIf}
+FunctionEnd
+
+Var JavaDownload
+Var JavaBits
+
Function GetJRE
- MessageBox MB_OK "${PRODUCT_NAME} uses Java ${JRE_VERSION} 32-bit, it will now \
- be downloaded and installed"
+ ${If} ${RunningX64}
+ StrCpy $JavaDownload ${JRE64_URL}
+ StrCpy $JavaBits "64"
+ ${Else}
+ StrCpy $JavaDownload ${JRE32_URL}
+ StrCpy $JavaBits "32"
+ ${EndIf}
+
+ MessageBox MB_OK "${PRODUCT_NAME} uses Java ${JRE_VERSION}, \
+ $JavaBits bits, it will now \
+ be downloaded and installed"
StrCpy $2 "$TEMP\Java Runtime Environment.exe"
- nsisdl::download /TIMEOUT=30000 ${JRE_URL} $2
+ nsisdl::download /TIMEOUT=30000 $JavaDownload $2
Pop $R0 ;Get the return value
StrCmp $R0 "success" +3
MessageBox MB_OK "Download failed: $R0"
@@ -37,10 +61,10 @@ Function GetJRE
Delete $2
FunctionEnd
-
Function DetectJRE
ReadRegStr $2 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment" \
"CurrentVersion"
+
StrCmp $2 ${JRE_VERSION} done
StrCmp $2 ${JRE_ALTERNATE} done
@@ -70,15 +94,18 @@ Section "Install Driver" InstDriver
InstDrv::DeleteOemInfFiles /NOUNLOAD
InstDrv::CreateDevice /NOUNLOAD
- SetOutPath $TEMP
- File "../telemetrum.inf"
- InstDrv::InstallDriver /NOUNLOAD "$TEMP\telemetrum.inf"
-
SetOutPath $INSTDIR
- File "../telemetrum.inf"
-
- SetOutPath $WINDIR\Inf
- File "../telemetrum.inf"
+ File "../altusmetrum.inf"
+ File "../altusmetrum.cat"
+
+ ${DisableX64FSRedirection}
+ IfFileExists $WINDIR\System32\PnPutil.exe 0 nopnp
+ ${DisableX64FSRedirection}
+ nsExec::ExecToLog '"$WINDIR\System32\PnPutil.exe" -i -a "$INSTDIR\altusmetrum.inf"'
+ Goto done
+nopnp:
+ InstDrv::InstallDriver /NOUNLOAD "$INSTDIR\altusmetrum.inf"
+done:
SectionEnd
@@ -119,6 +146,7 @@ Section "TeleMetrum, TeleDongle and TeleBT Firmware"
File "../src/telemetrum-v1.1/telemetrum-v1.1-${VERSION}.ihx"
File "../src/telemetrum-v1.2/telemetrum-v1.2-${VERSION}.ihx"
File "../src/telemini-v1.0/telemini-v1.0-${VERSION}.ihx"
+ File "../src/telegps-v1.0/telegps-v1.0-${VERSION}.ihx"
File "../src/teledongle-v0.2/teledongle-v0.2-${VERSION}.ihx"
File "../src/telebt-v1.0/telebt-v1.0-${VERSION}.ihx"
File "../src/telemega-v1.0/telemega-v1.0-${VERSION}.ihx"
@@ -164,9 +192,6 @@ Section "Uninstall"
Delete "$INSTDIR\*.*"
RMDir "$INSTDIR"
- ; Remove .inf file
- Delete "$WINDIR\Inf\telemetrum.inf"
-
; Remove devices
InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} AltusMetrumSerial
InstDrv::DeleteOemInfFiles /NOUNLOAD
diff --git a/debian/altos.desktop b/altosui/altos.desktop.in
index 88b99f97..66114348 100644
--- a/debian/altos.desktop
+++ b/altosui/altos.desktop.in
@@ -3,8 +3,8 @@ Type=Application
Name=AltOS UI
GenericName=Altus Metrum Ground Station
Comment=View and log downlink data from Altus Metrum products
-Icon=/usr/share/pixmaps/altusmetrum.xpm
-Exec=/usr/bin/altosui %f
+Icon=%icondir%/altusmetrum.svg
+Exec=%bindir%/altosui %f
Terminal=false
MimeType=text/plain;
Categories=Education;Electronics;Science;
diff --git a/altosui/linux-install.sh b/altosui/linux-install.sh
new file mode 100644
index 00000000..957b1aad
--- /dev/null
+++ b/altosui/linux-install.sh
@@ -0,0 +1,239 @@
+#!/bin/sh
+
+can_ask=y
+
+finish()
+{
+ if [ "$can_ask" = "y" ]; then
+ echo ""
+ echo -n "Press enter to continue..."
+ read foo
+ fi
+ exit $1
+}
+
+#
+# Make sure we have a terminal to talk to
+#
+
+if tty -s; then
+ :
+else
+ case "$DISPLAY" in
+ "")
+ echo 'No user input available'
+ can_ask=n
+ ;;
+ *)
+ GUESS_XTERMS="x-terminal-emulator xterm rxvt roxterm gnome-terminal dtterm eterm Eterm kvt konsole aterm"
+ for a in $GUESS_XTERMS; do
+ if type $a >/dev/null 2>&1; then
+ XTERM=$a
+ break
+ fi
+ done
+ case "$XTERM" in
+ "")
+ echo 'No terminal emulator available'
+ can_ask=n
+ ;;
+ *)
+ exec "$XTERM" -e "sh '$0'"
+ ;;
+ esac
+ ;;
+ esac
+fi
+
+#
+# Make sure we can run java
+#
+
+echo -n "Checking for java..."
+
+if java -version > /dev/null 2>&1; then
+ echo " found it."
+else
+ echo " java isn't working."
+ echo ""
+ echo "You'll need to install a java runtime system"
+ echo "on this computer before AltOS will work properly."
+ finish 1
+fi
+
+#
+# Pick an installation target
+#
+
+if [ '(' -d /opt -a -w /opt ')' -o '(' -d /opt/AltOS -a -w /opt/AltOS ')' ]; then
+ target_default=/opt
+else
+ target_default="$HOME"
+fi
+
+case "$#" in
+0)
+ echo -n "Installation location [default: $target_default] "
+ if [ "$can_ask" = "y" ]; then
+ read target
+ else
+ echo ""
+ target=""
+ fi
+ case "$target" in
+ "")
+ target="$target_default"
+ ;;
+ esac
+ ;;
+*)
+ target="$1"
+ ;;
+esac
+
+target_altos="$target"/AltOS
+
+echo -n "Installing to $target..."
+
+#
+# Make sure the target exists
+#
+mkdir -p "$target_altos"
+
+if [ ! -d "$target_altos" ]; then
+ echo "$target_altos does not exist and cannot be created"
+ finish 1
+fi
+
+if [ ! -w "$target_altos" ]; then
+ echo "$target_altos cannot be written"
+ finish 1
+fi
+
+#
+# Unpack the tar archive appended to the end of this script
+#
+archive_line=`awk '/^__ARCHIVE_BELOW__/ {print NR + 1; exit 0; }' "$0"`
+
+tail -n+$archive_line "$0" | tar xjf - -C "$target"
+
+case $? in
+0)
+ echo " done."
+ ;;
+*)
+ echo "Install failed."
+ finish 1
+ ;;
+esac
+
+#
+# Create the .desktop file by editing the paths
+#
+case "$target" in
+/*)
+ target_abs="$target"
+ ;;
+*)
+ target_abs=`pwd`/$target
+ ;;
+esac
+
+BIN="$target_abs"/AltOS
+
+for infile in "$target"/AltOS/*.desktop.in; do
+ desktop="$target"/AltOS/`basename "$infile" .in`
+ rm -f "$desktop"
+ sed -e "s;%bindir%;$BIN;" -e "s;%icondir%;$BIN;" "$infile" > "$desktop"
+ chmod +x "$desktop"
+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
+#
+
+public=/usr/share/applications
+private=$HOME/.local/share/applications
+apps=""
+
+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
+
+echo -n "Installing .desktop files to $apps..."
+
+cp "$target"/AltOS/*.desktop "$apps"
+
+case "$?" in
+0)
+ echo " done."
+ ;;
+*)
+ echo " failed."
+ ;;
+esac
+
+#
+# Install icon to desktop if desired
+#
+
+if [ -d $HOME/Desktop ]; then
+ default_desktop=n
+ if [ "$can_ask" = "y" ]; then
+ :
+ else
+ default_desktop=y
+ fi
+
+ answered=n
+ while [ "$answered" = "n" ]; do
+ echo -n "Install icons to desktop? [default: $default_desktop] "
+ if [ "$can_ask" = "y" ]; then
+ read do_desktop
+ else
+ echo
+ do_desktop=""
+ fi
+
+ case "$do_desktop" in
+ "")
+ do_desktop=$default_desktop
+ ;;
+ esac
+
+ case "$do_desktop" in
+ [yYnN]*)
+ answered=y
+ ;;
+ 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
+ ;;
+ esac
+
+ echo " done."
+fi
+
+finish 0
+
+__ARCHIVE_BELOW__
diff --git a/altosui/AltosBTDevice.java b/altosuilib/AltosBTDevice.java
index 727a9f66..beefa532 100644
--- a/altosui/AltosBTDevice.java
+++ b/altosuilib/AltosBTDevice.java
@@ -15,9 +15,10 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altosuilib_2;
+
import libaltosJNI.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
public class AltosBTDevice extends altos_bt_device implements AltosDevice {
@@ -32,8 +33,8 @@ public class AltosBTDevice extends altos_bt_device implements AltosDevice {
}
public int getProduct() {
- if (Altos.bt_product_telebt.equals(getProductName()))
- return Altos.product_telebt;
+ if (AltosLib.bt_product_telebt.equals(getProductName()))
+ return AltosLib.product_telebt;
return 0;
}
@@ -91,11 +92,11 @@ public class AltosBTDevice extends altos_bt_device implements AltosDevice {
// if (!isAltusMetrum())
// return false;
- if (want_product == Altos.product_any)
+ if (want_product == AltosLib.product_any)
return true;
- if (want_product == Altos.product_basestation)
- return matchProduct(Altos.product_telebt);
+ if (want_product == AltosLib.product_basestation)
+ return matchProduct(AltosLib.product_telebt);
if (want_product == getProduct())
return true;
@@ -115,10 +116,10 @@ public class AltosBTDevice extends altos_bt_device implements AltosDevice {
}
public AltosBTDevice(String name, String addr) {
- Altos.load_library();
+ AltosUILib.load_library();
libaltos.altos_bt_fill_in(name, addr,this);
}
public AltosBTDevice() {
}
-} \ No newline at end of file
+}
diff --git a/altosui/AltosBTDeviceIterator.java b/altosuilib/AltosBTDeviceIterator.java
index 4be5edf5..cad60ffb 100644
--- a/altosui/AltosBTDeviceIterator.java
+++ b/altosuilib/AltosBTDeviceIterator.java
@@ -15,9 +15,11 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altosuilib_2;
+
import java.util.*;
import libaltosJNI.*;
+import org.altusmetrum.altoslib_4.*;
public class AltosBTDeviceIterator implements Iterator<AltosBTDevice> {
AltosBTDevice current;
diff --git a/altosui/AltosBTKnown.java b/altosuilib/AltosBTKnown.java
index 968d72d5..02883c75 100644
--- a/altosui/AltosBTKnown.java
+++ b/altosuilib/AltosBTKnown.java
@@ -15,10 +15,10 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altosuilib_2;
+
import java.util.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
public class AltosBTKnown implements Iterable<AltosBTDevice> {
LinkedList<AltosBTDevice> devices = new LinkedList<AltosBTDevice>();
diff --git a/altosui/AltosBTManage.java b/altosuilib/AltosBTManage.java
index 1015f7c3..6da0a3eb 100644
--- a/altosui/AltosBTManage.java
+++ b/altosuilib/AltosBTManage.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altosuilib_2;
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.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
public class AltosBTManage extends AltosUIDialog implements ActionListener, Iterable<AltosBTDevice> {
LinkedBlockingQueue<AltosBTDevice> found_devices;
@@ -31,9 +31,9 @@ public class AltosBTManage extends AltosUIDialog implements ActionListener, Iter
LinkedList<ActionListener> listeners;
AltosBTKnown bt_known;
- class DeviceList extends JList implements Iterable<AltosBTDevice> {
- LinkedList<AltosBTDevice> devices;
- DefaultListModel list_model;
+ class DeviceList extends JList<AltosBTDevice> implements Iterable<AltosBTDevice> {
+ LinkedList<AltosBTDevice> devices;
+ DefaultListModel<AltosBTDevice> list_model;
public void add (AltosBTDevice device) {
if (!devices.contains(device)) {
@@ -86,16 +86,12 @@ public class AltosBTManage extends AltosUIDialog implements ActionListener, Iter
}
public java.util.List<AltosBTDevice> selected_list() throws InterruptedException {
- java.util.LinkedList<AltosBTDevice> l = new java.util.LinkedList<AltosBTDevice>();
- Object[] a = getSelectedValues();
- for (int i = 0; i < a.length; i++)
- l.add((AltosBTDevice)a[i]);
- return l;
+ return getSelectedValuesList();
}
public DeviceList() {
devices = new LinkedList<AltosBTDevice>();
- list_model = new DefaultListModel();
+ list_model = new DefaultListModel<AltosBTDevice>();
setModel(list_model);
setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
setLayoutOrientation(JList.HORIZONTAL_WRAP);
diff --git a/altosui/AltosCSVUI.java b/altosuilib/AltosCSVUI.java
index 05cabcdf..0a5e4fa2 100644
--- a/altosui/AltosCSVUI.java
+++ b/altosuilib/AltosCSVUI.java
@@ -15,14 +15,13 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altosuilib_2;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
public class AltosCSVUI
extends AltosUIDialog
@@ -30,7 +29,7 @@ public class AltosCSVUI
{
JFileChooser csv_chooser;
JPanel accessory;
- JComboBox combo_box;
+ JComboBox<String> combo_box;
Iterable<AltosState> states;
AltosWriter writer;
@@ -43,9 +42,9 @@ public class AltosCSVUI
String selected = (String) combo_box.getSelectedItem();
if (selected.contains("CSV"))
- new_name = Altos.replace_extension(current_name, ".csv");
+ new_name = AltosLib.replace_extension(current_name, ".csv");
else if (selected.contains("KML"))
- new_name = Altos.replace_extension(current_name, ".kml");
+ new_name = AltosLib.replace_extension(current_name, ".kml");
if (new_name != null)
csv_chooser.setSelectedFile(new File(new_name));
}
@@ -73,7 +72,7 @@ public class AltosCSVUI
c.gridy = 0;
accessory.add(accessory_label, c);
- combo_box = new JComboBox(combo_box_items);
+ combo_box = new JComboBox<String>(combo_box_items);
combo_box.addActionListener(this);
c.gridx = 0;
c.gridy = 1;
diff --git a/altosui/AltosConfigFreqUI.java b/altosuilib/AltosConfigFreqUI.java
index e9923a32..6dcd63b8 100644
--- a/altosui/AltosConfigFreqUI.java
+++ b/altosuilib/AltosConfigFreqUI.java
@@ -15,14 +15,13 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altosuilib_2;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
class AltosEditFreqUI extends AltosUIDialog implements ActionListener {
Frame frame;
@@ -71,7 +70,7 @@ class AltosEditFreqUI extends AltosUIDialog implements ActionListener {
GridBagConstraints c = new GridBagConstraints();
c.insets = new Insets (4,4,4,4);
-
+
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.WEST;
c.gridx = 0;
@@ -126,7 +125,7 @@ class AltosEditFreqUI extends AltosUIDialog implements ActionListener {
c.weightx = 0;
c.weighty = 0;
pane.add(ok_button, c);
-
+
cancel_button = new JButton("Cancel");
cancel_button.setActionCommand("cancel");
cancel_button.addActionListener(this);
@@ -139,7 +138,7 @@ class AltosEditFreqUI extends AltosUIDialog implements ActionListener {
c.weightx = 0;
c.weighty = 0;
pane.add(cancel_button, c);
-
+
if (existing == null)
setTitle("Add New Frequency");
else {
@@ -151,7 +150,7 @@ class AltosEditFreqUI extends AltosUIDialog implements ActionListener {
pack();
setLocationRelativeTo(frame);
-
+
}
public AltosEditFreqUI(Frame in_frame) {
@@ -164,8 +163,8 @@ public class AltosConfigFreqUI extends AltosUIDialog implements ActionListener {
Frame frame;
LinkedList<ActionListener> listeners;
- class FrequencyList extends JList {
- DefaultListModel list_model;
+ class FrequencyList extends JList<AltosFrequency> {
+ DefaultListModel<AltosFrequency> list_model;
public void add(AltosFrequency frequency) {
int i;
@@ -226,7 +225,7 @@ public class AltosConfigFreqUI extends AltosUIDialog implements ActionListener {
}
public FrequencyList(AltosFrequency[] in_frequencies) {
- list_model = new DefaultListModel();
+ list_model = new DefaultListModel<AltosFrequency>();
setModel(list_model);
setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
setLayoutOrientation(JList.HORIZONTAL_WRAP);
@@ -290,7 +289,7 @@ public class AltosConfigFreqUI extends AltosUIDialog implements ActionListener {
public AltosFrequency[] frequencies() {
return frequencies.frequencies();
}
-
+
public AltosConfigFreqUI(Frame in_frame,
AltosFrequency[] in_frequencies) {
super(in_frame, "Manage Frequencies", true);
diff --git a/altosui/AltosDataChooser.java b/altosuilib/AltosDataChooser.java
index a9344a01..59891c4a 100644
--- a/altosui/AltosDataChooser.java
+++ b/altosuilib/AltosDataChooser.java
@@ -15,13 +15,12 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altosuilib_2;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.io.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
public class AltosDataChooser extends JFileChooser {
JFrame frame;
@@ -68,16 +67,12 @@ public class AltosDataChooser extends JFileChooser {
public AltosDataChooser(JFrame in_frame) {
frame = in_frame;
setDialogTitle("Select Flight Record File");
- setFileFilter(new FileNameExtensionFilter("TeleMetrum eeprom file",
+ setFileFilter(new FileNameExtensionFilter("On-board Log file",
"eeprom"));
setFileFilter(new FileNameExtensionFilter("Telemetry file",
"telem"));
- setFileFilter(new FileNameExtensionFilter("TeleMega eeprom file",
- "mega"));
- setFileFilter(new FileNameExtensionFilter("EasyMini eeprom file",
- "mini"));
setFileFilter(new FileNameExtensionFilter("Flight data file",
- "telem", "eeprom", "mega", "mini"));
+ "telem", "eeprom"));
setCurrentDirectory(AltosUIPreferences.logdir());
}
}
diff --git a/altosuilib/AltosDevice.java b/altosuilib/AltosDevice.java
index 2461df1b..251ae994 100644
--- a/altosuilib/AltosDevice.java
+++ b/altosuilib/AltosDevice.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_1;
+package org.altusmetrum.altosuilib_2;
import libaltosJNI.*;
diff --git a/altosuilib/AltosDeviceDialog.java b/altosuilib/AltosDeviceDialog.java
index 73bc0b2f..0bedea97 100644
--- a/altosuilib/AltosDeviceDialog.java
+++ b/altosuilib/AltosDeviceDialog.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_1;
+package org.altusmetrum.altosuilib_2;
import javax.swing.*;
import java.awt.*;
@@ -23,14 +23,14 @@ import java.awt.event.*;
public abstract class AltosDeviceDialog extends AltosUIDialog implements ActionListener {
- private AltosDevice value;
- private JList list;
- private JButton cancel_button;
- private JButton select_button;
- public Frame frame;
- public int product;
- public JPanel buttonPane;
-
+ private AltosDevice value;
+ private JList<AltosDevice> list;
+ private JButton cancel_button;
+ private JButton select_button;
+ public Frame frame;
+ public int product;
+ public JPanel buttonPane;
+
public AltosDevice getValue() {
return value;
}
@@ -65,7 +65,7 @@ public abstract class AltosDeviceDialog extends AltosUIDialog implements ActionL
select_button.setEnabled(false);
getRootPane().setDefaultButton(select_button);
- list = new JList(devices) {
+ list = new JList<AltosDevice>(devices) {
//Subclass JList to workaround bug 4832765, which can cause the
//scroll pane to not let the user easily scroll up to the beginning
//of the list. An alternative would be to set the unitIncrement
diff --git a/altosui/AltosDeviceUIDialog.java b/altosuilib/AltosDeviceUIDialog.java
index ceabe843..3013612a 100644
--- a/altosui/AltosDeviceUIDialog.java
+++ b/altosuilib/AltosDeviceUIDialog.java
@@ -15,12 +15,11 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altosuilib_2;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
-import org.altusmetrum.altosuilib_1.*;
public class AltosDeviceUIDialog extends AltosDeviceDialog {
@@ -46,7 +45,7 @@ public class AltosDeviceUIDialog extends AltosDeviceDialog {
buttonPane.add(manage_bluetooth_button);
buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
}
-
+
public void actionPerformed(ActionEvent e) {
super.actionPerformed(e);
if ("manage".equals(e.getActionCommand())) {
diff --git a/altosui/AltosDisplayThread.java b/altosuilib/AltosDisplayThread.java
index 2a33f996..06bc68a9 100644
--- a/altosui/AltosDisplayThread.java
+++ b/altosuilib/AltosDisplayThread.java
@@ -15,13 +15,13 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altosuilib_2;
import java.awt.*;
import javax.swing.*;
import java.io.*;
import java.text.*;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
public class AltosDisplayThread extends Thread {
@@ -78,7 +78,7 @@ public class AltosDisplayThread extends Thread {
return;
/* reset the landing count once we hear about a new flight */
- if (state.state < Altos.ao_flight_drogue)
+ if (state.state < AltosLib.ao_flight_drogue)
reported_landing = 0;
/* Shut up once the rocket is on the ground */
@@ -87,8 +87,8 @@ public class AltosDisplayThread extends Thread {
}
/* If the rocket isn't on the pad, then report height */
- if (Altos.ao_flight_drogue <= state.state &&
- state.state < Altos.ao_flight_landed &&
+ if (AltosLib.ao_flight_drogue <= state.state &&
+ state.state < AltosLib.ao_flight_landed &&
state.from_pad != null &&
state.range >= 0)
{
@@ -99,7 +99,7 @@ public class AltosDisplayThread extends Thread {
(int) (state.from_pad.bearing + 0.5),
(int) (state.elevation + 0.5),
AltosConvert.distance.say(state.range));
- } else if (state.state > Altos.ao_flight_pad) {
+ } else if (state.state > AltosLib.ao_flight_pad && state.height() != AltosLib.MISSING) {
voice.speak(AltosConvert.height.say_units(state.height()));
} else {
reported_landing = 0;
@@ -109,10 +109,11 @@ public class AltosDisplayThread extends Thread {
* either we've got a landed report or we haven't heard from it in
* a long time
*/
- if (state.state >= Altos.ao_flight_drogue &&
+ if (state.state != AltosLib.ao_flight_stateless &&
+ state.state >= AltosLib.ao_flight_drogue &&
(last ||
System.currentTimeMillis() - state.received_time >= 15000 ||
- state.state == Altos.ao_flight_landed))
+ state.state == AltosLib.ao_flight_landed))
{
if (Math.abs(state.speed()) < 20 && state.height() < 100)
voice.speak("rocket landed safely");
@@ -123,8 +124,8 @@ public class AltosDisplayThread extends Thread {
(int) (state.from_pad.bearing + 0.5),
AltosConvert.distance.say_units(state.from_pad.distance));
++reported_landing;
- if (state.state != Altos.ao_flight_landed) {
- state.state = Altos.ao_flight_landed;
+ if (state.state != AltosLib.ao_flight_landed) {
+ state.state = AltosLib.ao_flight_landed;
show_safely();
}
}
@@ -155,7 +156,7 @@ public class AltosDisplayThread extends Thread {
wait(sleep_time);
}
}
-
+
report(false);
}
} catch (InterruptedException ie) {
@@ -182,16 +183,19 @@ public class AltosDisplayThread extends Thread {
synchronized boolean tell() {
boolean ret = false;
if (old_state == null || old_state.state != state.state) {
- voice.speak(state.state_name());
- if ((old_state == null || old_state.state <= Altos.ao_flight_boost) &&
- state.state > Altos.ao_flight_boost) {
- voice.speak("max speed: %s.",
- AltosConvert.speed.say_units(state.max_speed() + 0.5));
+ if (state.state != AltosLib.ao_flight_stateless)
+ voice.speak(state.state_name());
+ if ((old_state == null || old_state.state <= AltosLib.ao_flight_boost) &&
+ state.state > AltosLib.ao_flight_boost) {
+ if (state.max_speed() != AltosLib.MISSING)
+ voice.speak("max speed: %s.",
+ AltosConvert.speed.say_units(state.max_speed() + 0.5));
ret = true;
- } else if ((old_state == null || old_state.state < Altos.ao_flight_drogue) &&
- state.state >= Altos.ao_flight_drogue) {
- voice.speak("max height: %s.",
- AltosConvert.height.say_units(state.max_height() + 0.5));
+ } else if ((old_state == null || old_state.state < AltosLib.ao_flight_drogue) &&
+ state.state >= AltosLib.ao_flight_drogue) {
+ if (state.max_height() != AltosLib.MISSING)
+ voice.speak("max height: %s.",
+ AltosConvert.height.say_units(state.max_height() + 0.5));
ret = true;
}
}
diff --git a/altosui/AltosEepromDelete.java b/altosuilib/AltosEepromDelete.java
index b2d2e291..981daddf 100644
--- a/altosui/AltosEepromDelete.java
+++ b/altosuilib/AltosEepromDelete.java
@@ -15,13 +15,13 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altosuilib_2;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
public class AltosEepromDelete implements Runnable {
AltosEepromList flights;
@@ -140,4 +140,4 @@ public class AltosEepromDelete implements Runnable {
flights = given_flights;
success = false;
}
-} \ No newline at end of file
+}
diff --git a/altosui/AltosEepromManage.java b/altosuilib/AltosEepromManage.java
index e3635571..2b967339 100644
--- a/altosui/AltosEepromManage.java
+++ b/altosuilib/AltosEepromManage.java
@@ -15,14 +15,13 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altosuilib_2;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
public class AltosEepromManage implements ActionListener {
@@ -205,19 +204,19 @@ public class AltosEepromManage implements ActionListener {
}
}
- public AltosEepromManage(JFrame given_frame) {
+ public AltosEepromManage(JFrame given_frame, int product) {
//boolean running = false;
frame = given_frame;
- device = AltosDeviceUIDialog.show(frame, Altos.product_any);
+ device = AltosDeviceUIDialog.show(frame, product);
remote = false;
if (device != null) {
try {
serial_line = new AltosSerial(device);
- if (device.matchProduct(Altos.product_basestation))
+ if (device.matchProduct(AltosLib.product_basestation))
remote = true;
serial_line.set_frame(frame);
diff --git a/altosui/AltosEepromMonitor.java b/altosuilib/AltosEepromMonitor.java
index 50921da1..b1e85622 100644
--- a/altosui/AltosEepromMonitor.java
+++ b/altosuilib/AltosEepromMonitor.java
@@ -15,12 +15,11 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altosuilib_2;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altosuilib_1.*;
public class AltosEepromMonitor extends AltosUIDialog {
diff --git a/altosui/AltosEepromMonitorUI.java b/altosuilib/AltosEepromMonitorUI.java
index c2e925a2..02c71cd9 100644
--- a/altosui/AltosEepromMonitorUI.java
+++ b/altosuilib/AltosEepromMonitorUI.java
@@ -15,13 +15,12 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altosuilib_2;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altosuilib_1.*;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMonitor {
JFrame owner;
diff --git a/altosui/AltosEepromSelect.java b/altosuilib/AltosEepromSelect.java
index b7cdbb72..293d3045 100644
--- a/altosui/AltosEepromSelect.java
+++ b/altosuilib/AltosEepromSelect.java
@@ -15,14 +15,13 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altosuilib_2;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
class AltosEepromItem implements ActionListener {
AltosEepromLog log;
diff --git a/altosui/AltosFlashUI.java b/altosuilib/AltosFlashUI.java
index 5913e506..3f120617 100644
--- a/altosui/AltosFlashUI.java
+++ b/altosuilib/AltosFlashUI.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altosuilib_2;
import java.awt.*;
import java.awt.event.*;
@@ -23,8 +23,7 @@ import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.io.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
public class AltosFlashUI
extends AltosUIDialog
@@ -39,7 +38,7 @@ public class AltosFlashUI
JProgressBar pbar;
JButton cancel;
- JFrame frame;
+ AltosUIFrame frame;
// Hex file with rom image
File file;
@@ -231,7 +230,7 @@ public class AltosFlashUI
javax.swing.filechooser.FileFilter ihx_filter = new FileNameExtensionFilter("Flash Image", "ihx");
hexfile_chooser.addChoosableFileFilter(ihx_filter);
hexfile_chooser.setFileFilter(ihx_filter);
-
+
if (!is_pair_programmed() && !device.matchProduct(AltosLib.product_altusmetrum)) {
for (int i = 0; i < filters.length; i++) {
if (device != null && device.matchProduct(filters[i].product))
@@ -247,14 +246,14 @@ public class AltosFlashUI
if (file == null)
return false;
AltosUIPreferences.set_firmwaredir(file.getParentFile());
-
+
return true;
}
boolean select_device() {
- int product = Altos.product_any;
+ int product = AltosLib.product_any;
- device = AltosDeviceUIDialog.show(frame, Altos.product_any);
+ device = AltosDeviceUIDialog.show(frame, AltosLib.product_any);
if (device == null)
return false;
@@ -377,7 +376,15 @@ public class AltosFlashUI
while (!link.is_loader()) {
link.to_loader();
- java.util.List<AltosDevice> devices = AltosUSBDevice.list(AltosLib.product_altusmetrum);
+ java.util.List<AltosDevice> devices = null;
+
+ for (int tries = 0; tries < 10; tries++) {
+ Thread.sleep(100);
+ devices = AltosUSBDevice.list(AltosLib.product_altusmetrum);
+ if (devices.size() != 0)
+ break;
+ }
+
if (devices.size() == 1)
device = devices.get(0);
else {
@@ -418,15 +425,14 @@ public class AltosFlashUI
flash_task f = new flash_task(this);
}
- static void show(JFrame frame) {
+ public static void show(AltosUIFrame frame) {
AltosFlashUI ui = new AltosFlashUI(frame);
-
ui.showDialog();
}
- public AltosFlashUI(JFrame in_frame) {
+ public AltosFlashUI(AltosUIFrame in_frame) {
super(in_frame, "Program Altusmetrum Device", false);
frame = in_frame;
}
-} \ No newline at end of file
+}
diff --git a/altosui/AltosFlightDisplay.java b/altosuilib/AltosFlightDisplay.java
index c1264259..55b74034 100644
--- a/altosui/AltosFlightDisplay.java
+++ b/altosuilib/AltosFlightDisplay.java
@@ -15,14 +15,14 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altosuilib_2;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
-public interface AltosFlightDisplay {
+public interface AltosFlightDisplay extends AltosUnitsListener, AltosFontListener {
void reset();
void show(AltosState state, AltosListenerState listener_state);
- void set_font();
+ String getName();
}
diff --git a/altosui/AltosFlightInfoTableModel.java b/altosuilib/AltosFlightInfoTableModel.java
index 249f6497..3995efb3 100644
--- a/altosui/AltosFlightInfoTableModel.java
+++ b/altosuilib/AltosFlightInfoTableModel.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altosuilib_2;
import javax.swing.table.*;
diff --git a/altosui/AltosFlightStatsTable.java b/altosuilib/AltosFlightStatsTable.java
index cb0c1562..703dfb9d 100644
--- a/altosui/AltosFlightStatsTable.java
+++ b/altosuilib/AltosFlightStatsTable.java
@@ -15,26 +15,35 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altosuilib_2;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_3.*;
+import java.util.*;
+import org.altusmetrum.altoslib_4.*;
-public class AltosFlightStatsTable extends JComponent {
+public class AltosFlightStatsTable extends JComponent implements AltosFontListener {
GridBagLayout layout;
- class FlightStat {
+ LinkedList<FlightStat> flight_stats = new LinkedList<FlightStat>();
+
+ class FlightStat implements AltosFontListener {
JLabel label;
- JTextField value;
+ JTextField[] value;
+
+ public void font_size_changed(int font_size) {
+ label.setFont(AltosUILib.label_font);
+ for (int i = 0; i < value.length; i++)
+ value[i].setFont(AltosUILib.value_font);
+ }
public FlightStat(GridBagLayout layout, int y, String label_text, String ... values) {
GridBagConstraints c = new GridBagConstraints();
- c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
+ c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad);
c.weighty = 1;
label = new JLabel(label_text);
- label.setFont(Altos.label_font);
+ label.setFont(AltosUILib.label_font);
label.setHorizontalAlignment(SwingConstants.LEFT);
c.gridx = 0; c.gridy = y;
c.anchor = GridBagConstraints.WEST;
@@ -43,21 +52,29 @@ public class AltosFlightStatsTable extends JComponent {
layout.setConstraints(label, c);
add(label);
+ value = new JTextField[values.length];
for (int j = 0; j < values.length; j++) {
- value = new JTextField(values[j]);
- value.setFont(Altos.value_font);
- value.setHorizontalAlignment(SwingConstants.RIGHT);
+ value[j] = new JTextField(values[j]);
+ value[j].setEditable(false);
+ value[j].setFont(AltosUILib.value_font);
+ value[j].setHorizontalAlignment(SwingConstants.RIGHT);
c.gridx = j+1; c.gridy = y;
c.anchor = GridBagConstraints.EAST;
c.fill = GridBagConstraints.BOTH;
c.weightx = 1;
- layout.setConstraints(value, c);
- add(value);
+ layout.setConstraints(value[j], c);
+ add(value[j]);
}
+ flight_stats.add(this);
}
}
+ public void font_size_changed(int font_size) {
+ for (FlightStat f : flight_stats)
+ f.font_size_changed(font_size);
+ }
+
static String pos(double p, String pos, String neg) {
String h = pos;
if (p < 0) {
@@ -88,9 +105,11 @@ public class AltosFlightStatsTable extends JComponent {
new FlightStat(layout, y++, "Time",
String.format("%02d:%02d:%02d UTC", stats.hour, stats.minute, stats.second));
}
- new FlightStat(layout, y++, "Maximum height",
- String.format("%5.0f m", stats.max_height),
- String.format("%5.0f ft", AltosConvert.meters_to_feet(stats.max_height)));
+ if (stats.max_height != AltosLib.MISSING) {
+ new FlightStat(layout, y++, "Maximum height",
+ String.format("%5.0f m", stats.max_height),
+ String.format("%5.0f ft", AltosConvert.meters_to_feet(stats.max_height)));
+ }
if (stats.max_gps_height != AltosLib.MISSING) {
new FlightStat(layout, y++, "Maximum GPS height",
String.format("%5.0f m", stats.max_gps_height),
@@ -106,31 +125,36 @@ public class AltosFlightStatsTable extends JComponent {
String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.max_acceleration)),
String.format("%5.0f G", AltosConvert.meters_to_g(stats.max_acceleration)));
new FlightStat(layout, y++, "Average boost acceleration",
- String.format("%5.0f m/s²", stats.state_accel[Altos.ao_flight_boost]),
- String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.state_accel[Altos.ao_flight_boost])),
- String.format("%5.0f G", AltosConvert.meters_to_g(stats.state_accel[Altos.ao_flight_boost])));
+ String.format("%5.0f m/s²", stats.state_accel[AltosLib.ao_flight_boost]),
+ String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.state_accel[AltosLib.ao_flight_boost])),
+ String.format("%5.0f G", AltosConvert.meters_to_g(stats.state_accel[AltosLib.ao_flight_boost])));
}
- new FlightStat(layout, y++, "Drogue descent rate",
- String.format("%5.0f m/s", stats.state_speed[Altos.ao_flight_drogue]),
- String.format("%5.0f ft/s", AltosConvert.meters_to_feet(stats.state_speed[Altos.ao_flight_drogue])));
- new FlightStat(layout, y++, "Main descent rate",
- String.format("%5.0f m/s", stats.state_speed[Altos.ao_flight_main]),
- String.format("%5.0f ft/s", AltosConvert.meters_to_feet(stats.state_speed[Altos.ao_flight_main])));
- new FlightStat(layout, y++, "Ascent time",
- String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_boost] - stats.state_start[AltosLib.ao_flight_boost],
- AltosLib.state_name(Altos.ao_flight_boost)),
- String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_fast] - stats.state_start[AltosLib.ao_flight_fast],
- AltosLib.state_name(Altos.ao_flight_fast)),
- String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_coast] - stats.state_start[AltosLib.ao_flight_coast],
- AltosLib.state_name(Altos.ao_flight_coast)));
- new FlightStat(layout, y++, "Descent time",
- String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_drogue] - stats.state_start[AltosLib.ao_flight_drogue],
- AltosLib.state_name(Altos.ao_flight_drogue)),
- String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_main] - stats.state_start[AltosLib.ao_flight_main],
- AltosLib.state_name(Altos.ao_flight_main)));
- new FlightStat(layout, y++, "Flight time",
- String.format("%6.1f s", stats.state_end[Altos.ao_flight_main] -
- stats.state_start[Altos.ao_flight_boost]));
+ if (stats.state_speed[AltosLib.ao_flight_drogue] != AltosLib.MISSING)
+ new FlightStat(layout, y++, "Drogue descent rate",
+ String.format("%5.0f m/s", stats.state_speed[AltosLib.ao_flight_drogue]),
+ String.format("%5.0f ft/s", AltosConvert.meters_to_feet(stats.state_speed[AltosLib.ao_flight_drogue])));
+ if (stats.state_speed[AltosLib.ao_flight_main] != AltosLib.MISSING)
+ new FlightStat(layout, y++, "Main descent rate",
+ String.format("%5.0f m/s", stats.state_speed[AltosLib.ao_flight_main]),
+ String.format("%5.0f ft/s", AltosConvert.meters_to_feet(stats.state_speed[AltosLib.ao_flight_main])));
+ if (stats.state_start[AltosLib.ao_flight_boost] < stats.state_end[AltosLib.ao_flight_coast])
+ new FlightStat(layout, y++, "Ascent time",
+ String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_boost] - stats.state_start[AltosLib.ao_flight_boost],
+ AltosLib.state_name(AltosLib.ao_flight_boost)),
+ String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_fast] - stats.state_start[AltosLib.ao_flight_fast],
+ AltosLib.state_name(AltosLib.ao_flight_fast)),
+ String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_coast] - stats.state_start[AltosLib.ao_flight_coast],
+ AltosLib.state_name(AltosLib.ao_flight_coast)));
+ if (stats.state_start[AltosLib.ao_flight_drogue] < stats.state_end[AltosLib.ao_flight_main])
+ new FlightStat(layout, y++, "Descent time",
+ String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_drogue] - stats.state_start[AltosLib.ao_flight_drogue],
+ AltosLib.state_name(AltosLib.ao_flight_drogue)),
+ String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_main] - stats.state_start[AltosLib.ao_flight_main],
+ AltosLib.state_name(AltosLib.ao_flight_main)));
+ if (stats.state_start[AltosLib.ao_flight_boost] < stats.state_end[AltosLib.ao_flight_main])
+ new FlightStat(layout, y++, "Flight time",
+ String.format("%6.1f s", stats.state_end[AltosLib.ao_flight_main] -
+ stats.state_start[AltosLib.ao_flight_boost]));
if (stats.has_gps) {
new FlightStat(layout, y++, "Pad location",
pos(stats.pad_lat,"N","S"),
@@ -140,5 +164,4 @@ public class AltosFlightStatsTable extends JComponent {
pos(stats.lon,"E","W"));
}
}
-
-} \ No newline at end of file
+}
diff --git a/altosuilib/AltosFontListener.java b/altosuilib/AltosFontListener.java
index da903352..a98cc131 100644
--- a/altosuilib/AltosFontListener.java
+++ b/altosuilib/AltosFontListener.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_1;
+package org.altusmetrum.altosuilib_2;
public interface AltosFontListener {
void font_size_changed(int font_size);
diff --git a/altosui/AltosFreqList.java b/altosuilib/AltosFreqList.java
index 039b5f22..e1299aae 100644
--- a/altosui/AltosFreqList.java
+++ b/altosuilib/AltosFreqList.java
@@ -15,13 +15,12 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altosuilib_2;
import javax.swing.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
-public class AltosFreqList extends JComboBox {
+public class AltosFreqList extends JComboBox<AltosFrequency> {
String product;
int serial;
@@ -37,7 +36,7 @@ public class AltosFreqList extends JComboBox {
for (i = 0; i < getItemCount(); i++) {
AltosFrequency f = (AltosFrequency) getItemAt(i);
-
+
if (f.close(new_frequency)) {
setSelectedIndex(i);
return;
@@ -45,7 +44,7 @@ public class AltosFreqList extends JComboBox {
}
for (i = 0; i < getItemCount(); i++) {
AltosFrequency f = (AltosFrequency) getItemAt(i);
-
+
if (new_frequency < f.frequency)
break;
}
@@ -59,7 +58,7 @@ public class AltosFreqList extends JComboBox {
public void set_product(String new_product) {
product = new_product;
}
-
+
public void set_serial(int new_serial) {
serial = new_serial;
}
diff --git a/altosui/AltosGraph.java b/altosuilib/AltosGraph.java
index 42334e31..f8c8b27b 100644
--- a/altosui/AltosGraph.java
+++ b/altosuilib/AltosGraph.java
@@ -15,15 +15,14 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altosuilib_2;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
@@ -189,6 +188,9 @@ public class AltosGraph extends AltosUIGraph {
static final private Color gps_nsat_color = new Color (194, 31, 194);
static final private Color gps_nsat_solution_color = new Color (194, 31, 194);
static final private Color gps_nsat_view_color = new Color (150, 31, 150);
+ 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 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);
@@ -214,6 +216,7 @@ public class AltosGraph extends AltosUIGraph {
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;
public AltosGraph(AltosUIEnable enable, AltosFlightStats stats, AltosGraphDataSet dataSet) {
super(enable);
@@ -232,33 +235,42 @@ public class AltosGraph extends AltosUIGraph {
gyro_axis = newAxis("Rotation Rate", gyro_units, gyro_z_color, 0);
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);
addMarker("State", AltosGraphDataPoint.data_state, state_color);
- addSeries("Height",
- AltosGraphDataPoint.data_height,
- AltosConvert.height,
- height_color,
- true,
- height_axis);
- addSeries("Pressure",
- AltosGraphDataPoint.data_pressure,
- pressure_units,
- pressure_color,
- false,
- pressure_axis);
- addSeries("Speed",
- AltosGraphDataPoint.data_speed,
- AltosConvert.speed,
- speed_color,
- true,
- speed_axis);
- addSeries("Acceleration",
- AltosGraphDataPoint.data_accel,
- AltosConvert.accel,
- accel_color,
- true,
- accel_axis);
+
+ if (stats.has_flight_data) {
+ addSeries("Height",
+ AltosGraphDataPoint.data_height,
+ AltosConvert.height,
+ height_color,
+ true,
+ height_axis);
+ addSeries("Pressure",
+ AltosGraphDataPoint.data_pressure,
+ pressure_units,
+ pressure_color,
+ false,
+ pressure_axis);
+ addSeries("Speed",
+ AltosGraphDataPoint.data_speed,
+ AltosConvert.speed,
+ speed_color,
+ true,
+ speed_axis);
+ addSeries("Acceleration",
+ AltosGraphDataPoint.data_accel,
+ AltosConvert.accel,
+ accel_color,
+ true,
+ accel_axis);
+ }
if (stats.has_gps) {
+ boolean enable_gps = false;
+
+ if (!stats.has_flight_data)
+ enable_gps = true;
+
addSeries("Range",
AltosGraphDataPoint.data_range,
AltosConvert.distance,
@@ -269,12 +281,18 @@ public class AltosGraph extends AltosUIGraph {
AltosGraphDataPoint.data_distance,
AltosConvert.distance,
distance_color,
- false,
+ enable_gps,
distance_axis);
addSeries("GPS Height",
AltosGraphDataPoint.data_gps_height,
AltosConvert.height,
gps_height_color,
+ enable_gps,
+ height_axis);
+ addSeries("GPS Altitude",
+ AltosGraphDataPoint.data_gps_altitude,
+ AltosConvert.height,
+ gps_height_color,
false,
height_axis);
addSeries("GPS Satellites in Solution",
@@ -288,7 +306,25 @@ public class AltosGraph extends AltosUIGraph {
nsat_units,
gps_nsat_view_color,
false,
- nsat_axis);
+ nsat_axis);
+ addSeries("GPS Course",
+ AltosGraphDataPoint.data_gps_course,
+ orient_units,
+ gps_course_color,
+ false,
+ course_axis);
+ addSeries("GPS Ground Speed",
+ AltosGraphDataPoint.data_gps_ground_speed,
+ AltosConvert.speed,
+ gps_ground_speed_color,
+ enable_gps,
+ speed_axis);
+ addSeries("GPS Climb Rate",
+ AltosGraphDataPoint.data_gps_climb_rate,
+ AltosConvert.speed,
+ gps_climb_rate_color,
+ enable_gps,
+ speed_axis);
}
if (stats.has_rssi)
addSeries("Received Signal Strength",
@@ -297,19 +333,22 @@ public class AltosGraph extends AltosUIGraph {
dbm_color,
false,
dbm_axis);
- if (stats.has_other_adc) {
- addSeries("Temperature",
- AltosGraphDataPoint.data_temperature,
- AltosConvert.temperature,
- temperature_color,
- false,
- temperature_axis);
+
+ if (stats.has_battery)
addSeries("Battery Voltage",
AltosGraphDataPoint.data_battery_voltage,
voltage_units,
battery_voltage_color,
false,
voltage_axis);
+
+ if (stats.has_flight_adc) {
+ addSeries("Temperature",
+ AltosGraphDataPoint.data_temperature,
+ AltosConvert.temperature,
+ temperature_color,
+ false,
+ temperature_axis);
addSeries("Drogue Voltage",
AltosGraphDataPoint.data_drogue_voltage,
voltage_units,
@@ -389,7 +428,18 @@ public class AltosGraph extends AltosUIGraph {
orient_color,
false,
orient_axis);
+ if (stats.num_ignitor > 0) {
+ for (int i = 0; i < stats.num_ignitor; i++)
+ addSeries(AltosLib.ignitor_name(i),
+ AltosGraphDataPoint.data_ignitor_0 + i,
+ voltage_units,
+ main_voltage_color,
+ false,
+ voltage_axis);
+ for (int i = 0; i < stats.num_ignitor; i++)
+ addMarker(AltosLib.ignitor_name(i), AltosGraphDataPoint.data_ignitor_fired_0 + i, state_color);
+ }
setDataSet(dataSet);
}
-} \ No newline at end of file
+}
diff --git a/altosui/AltosGraphDataPoint.java b/altosuilib/AltosGraphDataPoint.java
index 61a1a227..3aff1e82 100644
--- a/altosui/AltosGraphDataPoint.java
+++ b/altosuilib/AltosGraphDataPoint.java
@@ -15,10 +15,9 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altosuilib_2;
-import org.altusmetrum.altosuilib_1.*;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
public class AltosGraphDataPoint implements AltosUIDataPoint {
@@ -36,20 +35,29 @@ public class AltosGraphDataPoint implements AltosUIDataPoint {
public static final int data_gps_height = 9;
public static final int data_gps_nsat_solution = 10;
public static final int data_gps_nsat_view = 11;
- public static final int data_temperature = 12;
- public static final int data_range = 13;
- public static final int data_distance = 14;
- public static final int data_pressure = 15;
- public static final int data_accel_x = 16;
- public static final int data_accel_y = 17;
- public static final int data_accel_z = 18;
- public static final int data_gyro_x = 19;
- public static final int data_gyro_y = 20;
- public static final int data_gyro_z = 21;
- public static final int data_mag_x = 22;
- public static final int data_mag_y = 23;
- public static final int data_mag_z = 24;
- public static final int data_orient = 25;
+ public static final int data_gps_altitude = 12;
+ public static final int data_temperature = 13;
+ public static final int data_range = 14;
+ public static final int data_distance = 15;
+ public static final int data_pressure = 16;
+ public static final int data_accel_x = 17;
+ public static final int data_accel_y = 18;
+ public static final int data_accel_z = 19;
+ public static final int data_gyro_x = 20;
+ public static final int data_gyro_y = 21;
+ public static final int data_gyro_z = 22;
+ public static final int data_mag_x = 23;
+ public static final int data_mag_y = 24;
+ public static final int data_mag_z = 25;
+ public static final int data_orient = 26;
+ 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_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;
+ public static final int data_ignitor_fired_max = data_ignitor_fired_0 + data_ignitor_num - 1;
public double x() throws AltosUIDataMissing {
double time = state.time_since_boost();
@@ -87,14 +95,21 @@ public class AltosGraphDataPoint implements AltosUIDataPoint {
break;
case data_gps_height:
y = state.gps_height;
- break;
+ break;
case data_gps_nsat_solution:
if (state.gps != null)
y = state.gps.nsat;
break;
case data_gps_nsat_view:
- if (state.gps != null && state.gps.cc_gps_sat != null)
- y = state.gps.cc_gps_sat.length;
+ if (state.gps != null) {
+ if (state.gps.cc_gps_sat != null)
+ y = state.gps.cc_gps_sat.length;
+ else
+ y = 0;
+ }
+ break;
+ case data_gps_altitude:
+ y = state.gps_altitude();
break;
case data_temperature:
y = state.temperature;
@@ -109,7 +124,7 @@ public class AltosGraphDataPoint implements AltosUIDataPoint {
case data_pressure:
y = state.pressure();
break;
-
+
case data_accel_x:
case data_accel_y:
case data_accel_z:
@@ -161,6 +176,39 @@ public class AltosGraphDataPoint implements AltosUIDataPoint {
case data_orient:
y = state.orient();
break;
+ case data_gps_course:
+ if (state.gps != null)
+ y = state.gps.course;
+ else
+ y = AltosLib.MISSING;
+ break;
+ case data_gps_ground_speed:
+ if (state.gps != null)
+ y = state.gps.ground_speed;
+ else
+ y = AltosLib.MISSING;
+ break;
+ case data_gps_climb_rate:
+ if (state.gps != null)
+ y = state.gps.climb_rate;
+ else
+ y = AltosLib.MISSING;
+ break;
+ default:
+ if (data_ignitor_0 <= index && index <= data_ignitor_max) {
+ int ignitor = index - data_ignitor_0;
+ if (state.ignitor_voltage != null && ignitor < state.ignitor_voltage.length)
+ y = state.ignitor_voltage[ignitor];
+ } else if (data_ignitor_fired_0 <= index && index <= data_ignitor_fired_max) {
+ int ignitor = index - data_ignitor_fired_0;
+ if (state.ignitor_voltage != null && ignitor < state.ignitor_voltage.length) {
+ if ((state.pyro_fired & (1 << ignitor)) != 0)
+ y = 1;
+ else
+ y = 0;
+ }
+ }
+ break;
}
if (y == AltosLib.MISSING)
throw new AltosUIDataMissing(index);
@@ -170,20 +218,32 @@ public class AltosGraphDataPoint implements AltosUIDataPoint {
public int id(int index) {
if (index == data_state) {
int s = state.state;
- if (s < Altos.ao_flight_boost || s > Altos.ao_flight_landed)
- return -1;
- return s;
+ if (AltosLib.ao_flight_boost <= s && s <= AltosLib.ao_flight_landed)
+ return s;
+ } else if (data_ignitor_fired_0 <= index && index <= data_ignitor_fired_max) {
+ int ignitor = index - data_ignitor_fired_0;
+ if (state.ignitor_voltage != null && ignitor < state.ignitor_voltage.length) {
+ if (state.ignitor_voltage != null && ignitor < state.ignitor_voltage.length) {
+ if ((state.pyro_fired & (1 << ignitor)) != 0)
+ return 1;
+ }
+ }
}
- return 0;
+ return -1;
}
public String id_name(int index) {
- if (index == data_state)
+ if (index == data_state) {
return state.state_name();
+ } else if (data_ignitor_fired_0 <= index && index <= data_ignitor_fired_max) {
+ int ignitor = index - data_ignitor_fired_0;
+ if (state.ignitor_voltage != null && ignitor < state.ignitor_voltage.length)
+ return AltosLib.ignitor_name(ignitor);
+ }
return "";
}
public AltosGraphDataPoint (AltosState state) {
this.state = state;
}
-} \ No newline at end of file
+}
diff --git a/altosui/AltosGraphDataSet.java b/altosuilib/AltosGraphDataSet.java
index d2773a3f..36933e9b 100644
--- a/altosui/AltosGraphDataSet.java
+++ b/altosuilib/AltosGraphDataSet.java
@@ -15,13 +15,12 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altosuilib_2;
import java.lang.*;
import java.io.*;
import java.util.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
class AltosGraphIterator implements Iterator<AltosUIDataPoint> {
AltosGraphDataSet dataSet;
diff --git a/altosui/AltosInfoTable.java b/altosuilib/AltosInfoTable.java
index 158b61f0..23ae4ae5 100644
--- a/altosui/AltosInfoTable.java
+++ b/altosuilib/AltosInfoTable.java
@@ -15,26 +15,30 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altosuilib_2;
import java.awt.*;
+import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
-public class AltosInfoTable extends JTable {
+public class AltosInfoTable extends JTable implements AltosFlightDisplay, HierarchyListener {
private AltosFlightInfoTableModel model;
static final int info_columns = 3;
static final int info_rows = 17;
+ private AltosState last_state;
+ private AltosListenerState last_listener_state;
+
int desired_row_height() {
- FontMetrics infoValueMetrics = getFontMetrics(Altos.table_value_font);
+ FontMetrics infoValueMetrics = getFontMetrics(AltosUILib.table_value_font);
return (infoValueMetrics.getHeight() + infoValueMetrics.getLeading()) * 18 / 10;
}
int text_width(String t) {
- FontMetrics infoValueMetrics = getFontMetrics(Altos.table_value_font);
+ FontMetrics infoValueMetrics = getFontMetrics(AltosUILib.table_value_font);
return infoValueMetrics.stringWidth(t);
}
@@ -55,24 +59,39 @@ public class AltosInfoTable extends JTable {
public AltosInfoTable() {
super(new AltosFlightInfoTableModel(info_rows, info_columns));
model = (AltosFlightInfoTableModel) getModel();
- setFont(Altos.table_value_font);
+ setFont(AltosUILib.table_value_font);
+ addHierarchyListener(this);
setAutoResizeMode(AUTO_RESIZE_ALL_COLUMNS);
setShowGrid(true);
set_layout();
doLayout();
}
- public void set_font() {
- setFont(Altos.table_value_font);
+ public void font_size_changed(int font_size) {
+ setFont(AltosUILib.table_value_font);
set_layout();
doLayout();
}
+ public void units_changed(boolean imperial_units) {
+ }
+
+ public void hierarchyChanged(HierarchyEvent e) {
+ if (last_state != null && isShowing()) {
+ AltosState state = last_state;
+ AltosListenerState listener_state = last_listener_state;
+
+ last_state = null;
+ last_listener_state = null;
+ show(state, listener_state);
+ }
+ }
+
public Dimension getPreferredScrollableViewportSize() {
return getPreferredSize();
}
- void info_reset() {
+ public void reset() {
model.reset();
}
@@ -104,8 +123,17 @@ public class AltosInfoTable extends JTable {
model.clear();
}
+ public String getName() { return "Table"; }
+
public void show(AltosState state, AltosListenerState listener_state) {
- info_reset();
+
+ if (!isShowing()) {
+ last_state = state;
+ last_listener_state = listener_state;
+ return;
+ }
+
+ reset();
if (state != null) {
if (state.device_type != AltosLib.MISSING)
info_add_row(0, "Device", "%s", AltosLib.product_name(state.device_type));
@@ -205,7 +233,7 @@ public class AltosInfoTable extends JTable {
info_add_deg(1, "Pad longitude", state.pad_lon, 'E', 'W');
info_add_row(1, "Pad GPS alt", "%6.0f m", state.pad_alt);
}
- if (state.gps.year != AltosLib.MISSING)
+ if (state.gps.year != AltosLib.MISSING)
info_add_row(1, "GPS date", "%04d-%02d-%02d",
state.gps.year,
state.gps.month,
diff --git a/altosui/AltosLed.java b/altosuilib/AltosLed.java
index 93064f1e..2debb62a 100644
--- a/altosui/AltosLed.java
+++ b/altosuilib/AltosLed.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altosuilib_2;
import javax.swing.*;
@@ -23,7 +23,7 @@ public class AltosLed extends JLabel {
ImageIcon on, off;
ImageIcon create_icon(String path) {
- java.net.URL imgURL = AltosUI.class.getResource(path);
+ java.net.URL imgURL = AltosUILib.class.getResource(path);
if (imgURL != null)
return new ImageIcon(imgURL);
System.err.printf("Cannot find icon \"%s\"\n", path);
diff --git a/altosui/AltosLights.java b/altosuilib/AltosLights.java
index 7ad22f3e..c91b70e9 100644
--- a/altosui/AltosLights.java
+++ b/altosuilib/AltosLights.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altosuilib_2;
import java.awt.*;
import javax.swing.*;
@@ -27,7 +27,7 @@ public class AltosLights extends JComponent {
AltosLed red, green;
ImageIcon create_icon(String path, String description) {
- java.net.URL imgURL = AltosUI.class.getResource(path);
+ java.net.URL imgURL = AltosUILib.class.getResource(path);
if (imgURL != null)
return new ImageIcon(imgURL, description);
System.err.printf("Cannot find icon \"%s\"\n", path);
diff --git a/altosuilib/AltosPositionListener.java b/altosuilib/AltosPositionListener.java
index e75d2de5..34cf1650 100644
--- a/altosuilib/AltosPositionListener.java
+++ b/altosuilib/AltosPositionListener.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_1;
+package org.altusmetrum.altosuilib_2;
public interface AltosPositionListener {
public void position_changed(int position);
diff --git a/altosui/AltosRomconfigUI.java b/altosuilib/AltosRomconfigUI.java
index 89994679..8f002c4a 100644
--- a/altosui/AltosRomconfigUI.java
+++ b/altosuilib/AltosRomconfigUI.java
@@ -15,13 +15,12 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altosuilib_2;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
public class AltosRomconfigUI
extends AltosUIDialog
diff --git a/altosui/AltosScanUI.java b/altosuilib/AltosScanUI.java
index e4a93362..b0cde059 100644
--- a/altosui/AltosScanUI.java
+++ b/altosuilib/AltosScanUI.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altosuilib_2;
import java.awt.*;
import java.awt.event.*;
@@ -25,8 +25,7 @@ import java.io.*;
import java.util.*;
import java.text.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
class AltosScanResult {
String callsign;
@@ -34,12 +33,12 @@ class AltosScanResult {
int flight;
AltosFrequency frequency;
int telemetry;
-
+
boolean interrupted = false;
-
+
public String toString() {
return String.format("%-9.9s serial %-4d flight %-4d (%s %s)",
- callsign, serial, flight, frequency.toShortString(), Altos.telemetry_name(telemetry));
+ callsign, serial, flight, frequency.toShortString(), AltosLib.telemetry_name(telemetry));
}
public String toShortString() {
@@ -75,8 +74,8 @@ class AltosScanResult {
}
}
-class AltosScanResults extends LinkedList<AltosScanResult> implements ListModel {
-
+class AltosScanResults extends LinkedList<AltosScanResult> implements ListModel<AltosScanResult> {
+
LinkedList<ListDataListener> listeners = new LinkedList<ListDataListener>();
void changed(ListDataEvent de) {
@@ -107,7 +106,7 @@ class AltosScanResults extends LinkedList<AltosScanResult> implements ListModel
public void addListDataListener(ListDataListener l) {
listeners.add(l);
}
-
+
public void removeListDataListener(ListDataListener l) {
listeners.remove(l);
}
@@ -125,11 +124,11 @@ public class AltosScanUI
extends AltosUIDialog
implements ActionListener
{
- AltosUI owner;
+ AltosUIFrame owner;
AltosDevice device;
AltosConfigData config_data;
AltosTelemetryReader reader;
- private JList list;
+ private JList<AltosScanResult> list;
private JLabel scanning_label;
private JLabel frequency_label;
private JLabel telemetry_label;
@@ -140,6 +139,7 @@ public class AltosScanUI
AltosScanResults results = new AltosScanResults();
int telemetry;
+ boolean select_telemetry = false;
final static int timeout = 1200;
TelemetryHandler handler;
@@ -215,32 +215,38 @@ public class AltosScanUI
void set_label() {
frequency_label.setText(String.format("Frequency: %s", frequencies[frequency_index].toString()));
- telemetry_label.setText(String.format("Telemetry: %s", Altos.telemetry_name(telemetry)));
+ if (select_telemetry)
+ telemetry_label.setText(String.format("Telemetry: %s", AltosLib.telemetry_name(telemetry)));
}
void set_telemetry() {
reader.set_telemetry(telemetry);
}
-
+
void set_frequency() throws InterruptedException, TimeoutException {
reader.set_frequency(frequencies[frequency_index].frequency);
reader.reset();
}
-
+
void next() throws InterruptedException, TimeoutException {
reader.set_monitor(false);
Thread.sleep(100);
++frequency_index;
- if (frequency_index >= frequencies.length ||
- !telemetry_boxes[telemetry - Altos.ao_telemetry_min].isSelected())
- {
- frequency_index = 0;
- do {
- ++telemetry;
- if (telemetry > Altos.ao_telemetry_max)
- telemetry = Altos.ao_telemetry_min;
- } while (!telemetry_boxes[telemetry - Altos.ao_telemetry_min].isSelected());
- set_telemetry();
+ 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();
+ }
+ } else {
+ if (frequency_index >= frequencies.length)
+ frequency_index = 0;
}
set_frequency();
set_label();
@@ -279,14 +285,14 @@ public class AltosScanUI
if (cmd.equals("telemetry")) {
int k;
int scanning_telemetry = 0;
- for (k = Altos.ao_telemetry_min; k <= Altos.ao_telemetry_max; k++) {
- int j = k - Altos.ao_telemetry_min;
+ for (k = AltosLib.ao_telemetry_min; k <= AltosLib.ao_telemetry_max; k++) {
+ int j = k - AltosLib.ao_telemetry_min;
if (telemetry_boxes[j].isSelected())
scanning_telemetry |= (1 << k);
}
if (scanning_telemetry == 0) {
- scanning_telemetry |= (1 << Altos.ao_telemetry_standard);
- telemetry_boxes[Altos.ao_telemetry_standard - Altos.ao_telemetry_min].setSelected(true);
+ scanning_telemetry |= (1 << AltosLib.ao_telemetry_standard);
+ telemetry_boxes[AltosLib.ao_telemetry_standard - AltosLib.ao_telemetry_min].setSelected(true);
}
AltosUIPreferences.set_scanning_telemetry(scanning_telemetry);
}
@@ -300,7 +306,7 @@ public class AltosScanUI
reader.set_telemetry(r.telemetry);
reader.set_frequency(r.frequency.frequency);
reader.save_frequency();
- owner.telemetry_window(device);
+ owner.scan_device_selected(device);
}
}
}
@@ -328,7 +334,7 @@ public class AltosScanUI
}
private boolean open() {
- device = AltosDeviceUIDialog.show(owner, Altos.product_basestation);
+ device = AltosDeviceUIDialog.show(owner, AltosLib.product_basestation);
if (device == null)
return false;
try {
@@ -376,13 +382,15 @@ public class AltosScanUI
return false;
}
- public AltosScanUI(AltosUI in_owner) {
+ public AltosScanUI(AltosUIFrame in_owner, boolean in_select_telemetry) {
owner = in_owner;
+ select_telemetry = in_select_telemetry;
frequencies = AltosUIPreferences.common_frequencies();
frequency_index = 0;
- telemetry = Altos.ao_telemetry_min;
+
+ telemetry = AltosLib.ao_telemetry_standard;
if (!open())
return;
@@ -401,8 +409,14 @@ public class AltosScanUI
scanning_label = new JLabel("Scanning:");
frequency_label = new JLabel("");
- telemetry_label = new JLabel("");
-
+
+ if (select_telemetry) {
+ telemetry_label = new JLabel("");
+ telemetry = AltosLib.ao_telemetry_min;
+ } else {
+ telemetry = AltosLib.ao_telemetry_standard;
+ }
+
set_label();
c.fill = GridBagConstraints.HORIZONTAL;
@@ -418,24 +432,28 @@ public class AltosScanUI
pane.add(scanning_label, c);
c.gridy = 1;
pane.add(frequency_label, c);
- c.gridy = 2;
- pane.add(telemetry_label, c);
-
- int scanning_telemetry = AltosUIPreferences.scanning_telemetry();
- telemetry_boxes = new JCheckBox[Altos.ao_telemetry_max - Altos.ao_telemetry_min + 1];
- for (int k = Altos.ao_telemetry_min; k <= Altos.ao_telemetry_max; k++) {
- int j = k - Altos.ao_telemetry_min;
- telemetry_boxes[j] = new JCheckBox(AltosLib.telemetry_name(k));
- c.gridy = 3 + 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);
+
+ int y_offset = 3;
+
+ if (select_telemetry) {
+ c.gridy = 2;
+ pane.add(telemetry_label, c);
+
+ int scanning_telemetry = AltosUIPreferences.scanning_telemetry();
+ telemetry_boxes = new JCheckBox[AltosLib.ao_telemetry_max - AltosLib.ao_telemetry_min + 1];
+ 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;
+ 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);
}
- int y_offset = 3 + (Altos.ao_telemetry_max - Altos.ao_telemetry_min + 1);
-
- list = new JList(results) {
+ 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
//of the list. An alternative would be to set the unitIncrement
@@ -548,4 +566,4 @@ public class AltosScanUI
setVisible(true);
}
-} \ No newline at end of file
+}
diff --git a/altosui/AltosSerial.java b/altosuilib/AltosSerial.java
index 2c5d2dfd..60e15bdb 100644
--- a/altosui/AltosSerial.java
+++ b/altosuilib/AltosSerial.java
@@ -19,15 +19,13 @@
* Deal with TeleDongle on a serial port
*/
-package altosui;
+package org.altusmetrum.altosuilib_2;
import java.io.*;
import java.util.*;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
-
+import org.altusmetrum.altoslib_4.*;
import libaltosJNI.*;
/*
@@ -40,7 +38,7 @@ public class AltosSerial extends AltosLink {
static java.util.List<String> devices_opened = Collections.synchronizedList(new LinkedList<String>());
- AltosDevice device;
+ public AltosDevice device;
SWIGTYPE_p_altos_file altos;
Thread input_thread;
String line;
@@ -119,7 +117,7 @@ public class AltosSerial extends AltosLink {
SwingUtilities.invokeLater(r);
}
- private void close_serial() {
+ private synchronized void close_serial() {
synchronized (devices_opened) {
devices_opened.remove(device.getPath());
}
diff --git a/altosui/AltosSerialInUseException.java b/altosuilib/AltosSerialInUseException.java
index b45d9157..1e8207d1 100644
--- a/altosui/AltosSerialInUseException.java
+++ b/altosuilib/AltosSerialInUseException.java
@@ -15,8 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
-import org.altusmetrum.altosuilib_1.*;
+package org.altusmetrum.altosuilib_2;
public class AltosSerialInUseException extends Exception {
public AltosDevice device;
diff --git a/altosuilib/AltosUIAxis.java b/altosuilib/AltosUIAxis.java
index 1638ea29..74561673 100644
--- a/altosuilib/AltosUIAxis.java
+++ b/altosuilib/AltosUIAxis.java
@@ -15,14 +15,14 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_1;
+package org.altusmetrum.altosuilib_2;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
@@ -50,7 +50,7 @@ public class AltosUIAxis extends NumberAxis {
public void set_units() {
setLabel(String.format("%s (%s)", label, units.show_units()));
}
-
+
public void set_enable(boolean enable) {
if (enable) {
visible++;
diff --git a/altosuilib/AltosUIConfigure.java b/altosuilib/AltosUIConfigure.java
index 9e72e403..920ed8e2 100644
--- a/altosuilib/AltosUIConfigure.java
+++ b/altosuilib/AltosUIConfigure.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_1;
+package org.altusmetrum.altosuilib_2;
import java.awt.*;
import java.awt.event.*;
@@ -23,10 +23,10 @@ import java.beans.*;
import javax.swing.*;
import javax.swing.event.*;
-class DelegatingRenderer implements ListCellRenderer {
+class DelegatingRenderer implements ListCellRenderer<Object> {
// ...
- public static void install(JComboBox comboBox) {
+ public static void install(JComboBox<Object> comboBox) {
DelegatingRenderer renderer = new DelegatingRenderer(comboBox);
renderer.initialise();
comboBox.setRenderer(renderer);
@@ -36,7 +36,7 @@ class DelegatingRenderer implements ListCellRenderer {
private final JComboBox comboBox;
// ...
- private ListCellRenderer delegate;
+ private ListCellRenderer<? super Object> delegate;
// ...
private DelegatingRenderer(JComboBox comboBox) {
@@ -45,21 +45,22 @@ class DelegatingRenderer implements ListCellRenderer {
// ...
private void initialise() {
- delegate = new JComboBox().getRenderer();
+ JComboBox<Object> c = new JComboBox<Object>();
+ delegate = c.getRenderer();
comboBox.addPropertyChangeListener("UI", new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
- delegate = new JComboBox().getRenderer();
+ delegate = new JComboBox<Object>().getRenderer();
}
});
}
// ...
- public Component getListCellRendererComponent(JList list,
+ public Component getListCellRendererComponent(JList<?> list,
Object value, int index, boolean isSelected, boolean cellHasFocus) {
return delegate.getListCellRendererComponent(list,
- ((UIManager.LookAndFeelInfo) value).getName(),
+ ((UIManager.LookAndFeelInfo)value).getName(),
index, isSelected, cellHasFocus);
}
}
@@ -139,7 +140,7 @@ public class AltosUIConfigure
/* Font size setting */
pane.add(new JLabel("Font size"), constraints(0, 1));
- final JComboBox font_size_value = new JComboBox(font_size_names);
+ final JComboBox<String> font_size_value = new JComboBox<String>(font_size_names);
int font_size = AltosUIPreferences.font_size();
font_size_value.setSelectedIndex(font_size - AltosUILib.font_size_small);
font_size_value.addActionListener(new ActionListener() {
@@ -181,7 +182,7 @@ public class AltosUIConfigure
final UIManager.LookAndFeelInfo[] look_and_feels = UIManager.getInstalledLookAndFeels();
- final JComboBox look_and_feel_value = new JComboBox(look_and_feels);
+ final JComboBox<Object> look_and_feel_value = new JComboBox<Object>(look_and_feels);
DelegatingRenderer.install(look_and_feel_value);
@@ -228,8 +229,8 @@ public class AltosUIConfigure
public void add_frequencies() {
}
- public AltosUIConfigure(JFrame in_owner) {
- super(in_owner, "Configure AltosUI", false);
+ public AltosUIConfigure(JFrame in_owner, String name, String label) {
+ super(in_owner, name, false);
owner = in_owner;
pane = getContentPane();
@@ -238,7 +239,7 @@ public class AltosUIConfigure
row = 0;
/* Nice label at the top */
- pane.add(new JLabel ("Configure AltOS UI"),
+ pane.add(new JLabel (label),
constraints(0, 3));
row++;
@@ -270,4 +271,8 @@ public class AltosUIConfigure
setLocationRelativeTo(owner);
setVisible(true);
}
+
+ public AltosUIConfigure(JFrame in_owner) {
+ this(in_owner, "Configure AltosUI", "Configure AltOS UI");
+ }
}
diff --git a/altosuilib/AltosUIDataMissing.java b/altosuilib/AltosUIDataMissing.java
index c7b01859..353ff30f 100644
--- a/altosuilib/AltosUIDataMissing.java
+++ b/altosuilib/AltosUIDataMissing.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_1;
+package org.altusmetrum.altosuilib_2;
public class AltosUIDataMissing extends Exception {
public int id;
diff --git a/altosuilib/AltosUIDataPoint.java b/altosuilib/AltosUIDataPoint.java
index d3020410..3f16500e 100644
--- a/altosuilib/AltosUIDataPoint.java
+++ b/altosuilib/AltosUIDataPoint.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_1;
+package org.altusmetrum.altosuilib_2;
public interface AltosUIDataPoint {
public abstract double x() throws AltosUIDataMissing;
diff --git a/altosuilib/AltosUIDataSet.java b/altosuilib/AltosUIDataSet.java
index 6f23ef9a..ee70a3fd 100644
--- a/altosuilib/AltosUIDataSet.java
+++ b/altosuilib/AltosUIDataSet.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_1;
+package org.altusmetrum.altosuilib_2;
public interface AltosUIDataSet {
public abstract String name();
diff --git a/altosuilib/AltosUIDialog.java b/altosuilib/AltosUIDialog.java
index e1e699a7..dc737414 100644
--- a/altosuilib/AltosUIDialog.java
+++ b/altosuilib/AltosUIDialog.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_1;
+package org.altusmetrum.altosuilib_2;
import java.awt.*;
import java.awt.event.*;
diff --git a/altosuilib/AltosUIEnable.java b/altosuilib/AltosUIEnable.java
index ea4bd00a..da98797a 100644
--- a/altosuilib/AltosUIEnable.java
+++ b/altosuilib/AltosUIEnable.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_1;
+package org.altusmetrum.altosuilib_2;
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_3.*;
+import org.altusmetrum.altoslib_4.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
@@ -45,7 +45,7 @@ public class AltosUIEnable extends Container {
class GraphElement implements ActionListener {
AltosUIGrapher grapher;
- JRadioButton enable;
+ JCheckBox enable;
String name;
public void actionPerformed(ActionEvent ae) {
@@ -55,8 +55,8 @@ public class AltosUIEnable extends Container {
GraphElement (String name, AltosUIGrapher grapher, boolean enabled) {
this.name = name;
this.grapher = grapher;
- enable = new JRadioButton(name, enabled);
- grapher.set_enable(enabled);
+ enable = new JCheckBox(name, enabled);
+ grapher.set_enable(enabled);
enable.addActionListener(this);
}
}
@@ -86,10 +86,10 @@ public class AltosUIEnable extends Container {
/* Imperial units setting */
/* Add label */
- JRadioButton imperial_units = new JRadioButton("Imperial Units", AltosUIPreferences.imperial_units());
+ JCheckBox imperial_units = new JCheckBox("Imperial Units", AltosUIPreferences.imperial_units());
imperial_units.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
- JRadioButton item = (JRadioButton) e.getSource();
+ JCheckBox item = (JCheckBox) e.getSource();
boolean enabled = item.isSelected();
AltosUIPreferences.set_imperial_units(enabled);
}
diff --git a/altosuilib/AltosUIFlightTab.java b/altosuilib/AltosUIFlightTab.java
new file mode 100644
index 00000000..039d83e0
--- /dev/null
+++ b/altosuilib/AltosUIFlightTab.java
@@ -0,0 +1,88 @@
+/*
+ * 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_2;
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import org.altusmetrum.altoslib_4.*;
+
+public abstract class AltosUIFlightTab extends JComponent implements AltosFlightDisplay, HierarchyListener {
+ public GridBagLayout layout;
+
+ AltosState last_state;
+ AltosListenerState last_listener_state;
+
+ LinkedList<AltosUIIndicator> indicators = new LinkedList<AltosUIIndicator>();
+
+ public void add (AltosUIIndicator indicator) {
+ indicators.add(indicator);
+ }
+
+ public void remove(AltosUIIndicator indicator) {
+ indicators.remove(indicator);
+ }
+
+ public void reset() {
+ for (AltosUIIndicator i : indicators)
+ i.reset();
+ }
+
+ public void font_size_changed(int font_size) {
+ for (AltosUIIndicator i : indicators)
+ i.font_size_changed(font_size);
+ }
+
+ public void units_changed(boolean imperial_units) {
+ for (AltosUIIndicator i : indicators)
+ i.units_changed(imperial_units);
+ }
+
+ public void show(AltosState state, AltosListenerState listener_state) {
+ if (!isShowing()) {
+ last_state = state;
+ last_listener_state = listener_state;
+ return;
+ }
+
+ for (AltosUIIndicator i : indicators)
+ i.show(state, listener_state);
+ }
+
+ public void hierarchyChanged(HierarchyEvent e) {
+ if (last_state != null && isShowing()) {
+ AltosState state = last_state;
+ AltosListenerState listener_state = last_listener_state;
+
+ last_state = null;
+ last_listener_state = null;
+ show(state, listener_state);
+ }
+ }
+
+ abstract public String getName();
+
+ public AltosUIFlightTab() {
+ layout = new GridBagLayout();
+
+ setLayout(layout);
+
+ addHierarchyListener(this);
+ }
+}
diff --git a/altosuilib/AltosUIFrame.java b/altosuilib/AltosUIFrame.java
index 3fc99910..6e62c762 100644
--- a/altosuilib/AltosUIFrame.java
+++ b/altosuilib/AltosUIFrame.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_1;
+package org.altusmetrum.altosuilib_2;
import java.awt.*;
import java.awt.event.*;
@@ -45,7 +45,7 @@ public class AltosUIFrame extends JFrame implements AltosUIListener, AltosPositi
};
static public String[] icon_names;
-
+
static public void set_icon_names(String[] new_icon_names) { icon_names = new_icon_names; }
public String[] icon_names() {
@@ -57,7 +57,7 @@ public class AltosUIFrame extends JFrame implements AltosUIListener, AltosPositi
public void set_icon() {
ArrayList<Image> icons = new ArrayList<Image>();
String[] icon_names = icon_names();
-
+
for (int i = 0; i < icon_names.length; i++) {
java.net.URL imgURL = AltosUIFrame.class.getResource(icon_names[i]);
if (imgURL != null)
@@ -65,14 +65,17 @@ public class AltosUIFrame extends JFrame implements AltosUIListener, AltosPositi
}
setIconImages(icons);
}
-
+
private boolean location_by_platform = true;
public void setLocationByPlatform(boolean lbp) {
location_by_platform = lbp;
super.setLocationByPlatform(lbp);
}
-
+
+ public void scan_device_selected(AltosDevice device) {
+ }
+
public void setSize() {
/* Smash sizes around so that the window comes up in the right shape */
Insets i = getInsets();
@@ -153,7 +156,7 @@ public class AltosUIFrame extends JFrame implements AltosUIListener, AltosPositi
setPosition(position);
}
}
-
+
void init() {
AltosUIPreferences.register_ui_listener(this);
AltosUIPreferences.register_position_listener(this);
diff --git a/altosuilib/AltosUIGraph.java b/altosuilib/AltosUIGraph.java
index 061a7629..9cca088d 100644
--- a/altosuilib/AltosUIGraph.java
+++ b/altosuilib/AltosUIGraph.java
@@ -15,14 +15,14 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_1;
+package org.altusmetrum.altosuilib_2;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
@@ -82,11 +82,9 @@ public class AltosUIGraph implements AltosUnitsListener {
public void addSeries(String label, int fetch, AltosUnits units, Color color) {
addSeries(label, fetch, units, color, true, newAxis(label, units, color));
}
-
+
public void addMarker(String label, int fetch, Color color) {
AltosUIMarker marker = new AltosUIMarker(fetch, color, plot);
- if (enable != null)
- enable.add(label, marker, true);
this.graphers.add(marker);
}
@@ -131,7 +129,7 @@ public class AltosUIGraph implements AltosUnitsListener {
this.axis_index = 0;
xAxis = new NumberAxis("Time (s)");
-
+
xAxis.setAutoRangeIncludesZero(true);
plot = new XYPlot();
@@ -158,4 +156,4 @@ public class AltosUIGraph implements AltosUnitsListener {
AltosPreferences.register_units_listener(this);
}
-} \ No newline at end of file
+}
diff --git a/altosuilib/AltosUIGrapher.java b/altosuilib/AltosUIGrapher.java
index 23e7d9f0..724fac18 100644
--- a/altosuilib/AltosUIGrapher.java
+++ b/altosuilib/AltosUIGrapher.java
@@ -15,14 +15,14 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_1;
+package org.altusmetrum.altosuilib_2;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
@@ -37,7 +37,7 @@ import org.jfree.data.*;
interface AltosUIGrapher {
public abstract void set_units();
-
+
public abstract void clear();
public abstract void add(AltosUIDataPoint dataPoint);
diff --git a/altosuilib/AltosUIIndicator.java b/altosuilib/AltosUIIndicator.java
new file mode 100644
index 00000000..b1626cba
--- /dev/null
+++ b/altosuilib/AltosUIIndicator.java
@@ -0,0 +1,181 @@
+/*
+ * 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_2;
+
+import java.awt.*;
+import javax.swing.*;
+import org.altusmetrum.altoslib_4.*;
+
+public abstract class AltosUIIndicator implements AltosFontListener, AltosUnitsListener {
+ JLabel label;
+ JTextField[] values;
+ AltosLights lights;
+ int number_values;
+ boolean has_lights;
+ int value_width;
+
+ abstract public void show(AltosState state, AltosListenerState listener_state);
+
+ public void set_lights(boolean on) {
+ lights.set(on);
+ }
+
+ public void setVisible(boolean visible) {
+ if (lights != null)
+ lights.setVisible(visible);
+ label.setVisible(visible);
+ for (int i = 0; i < values.length; i++)
+ values[i].setVisible(visible);
+ }
+
+ public void reset() {
+ for (int i = 0; i < values.length; i++)
+ values[i].setText("");
+ if (lights != null)
+ lights.set(false);
+ }
+
+ public void show() {
+ if (lights != null)
+ lights.setVisible(true);
+ label.setVisible(true);
+ for (int i = 0; i < values.length; i++)
+ values[i].setVisible(true);
+ }
+
+ public void show(String... s) {
+ int n = Math.min(s.length, values.length);
+
+ show();
+ for (int i = 0; i < n; i++)
+ values[i].setText(s[i]);
+ }
+
+ public void show(String format, double value) {
+ show(String.format(format, value));
+ }
+
+ public void show(String format, int value) {
+ show(String.format(format, value));
+ }
+
+ public void show(String format1, double value1, String format2, double value2) {
+ show(String.format(format1, value1), String.format(format2, value2));
+ }
+
+ public void show(String format1, int value1, String format2, int value2) {
+ show(String.format(format1, value1), String.format(format2, value2));
+ }
+
+ public void hide() {
+ if (lights != null)
+ lights.setVisible(false);
+ label.setVisible(false);
+ for (int i = 0; i < values.length; i++)
+ values[i].setVisible(false);
+ }
+
+ public void font_size_changed(int font_size) {
+ label.setFont(AltosUILib.label_font);
+ for (int i = 0; i < values.length; i++)
+ values[i].setFont(AltosUILib.value_font);
+ }
+
+ public void units_changed(boolean imperial_units) {
+ }
+
+ public void set_label(String text) {
+ label.setText(text);
+ }
+
+ public void remove(Container container) {
+ if (lights != null)
+ container.remove(lights);
+ container.remove(label);
+ for (int i = 0; i < values.length; i++)
+ container.remove(values[i]);
+ }
+
+ public AltosUIIndicator (Container container, int x, int y, int label_width, String text, int number_values, boolean has_lights, int value_width, int value_space) {
+ GridBagLayout layout = (GridBagLayout)(container.getLayout());
+
+ GridBagConstraints c = new GridBagConstraints();
+ c.weighty = 1;
+
+ if (has_lights) {
+ lights = new AltosLights();
+ c.gridx = x; c.gridy = y;
+ c.anchor = GridBagConstraints.CENTER;
+ c.fill = GridBagConstraints.VERTICAL;
+ c.weightx = 0;
+ layout.setConstraints(lights, c);
+ container.add(lights);
+ }
+
+ label = new JLabel(text);
+ label.setFont(AltosUILib.label_font);
+ label.setHorizontalAlignment(SwingConstants.LEFT);
+ c.gridx = x + 1; c.gridy = y;
+ c.gridwidth = label_width;
+ c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad);
+ c.anchor = GridBagConstraints.WEST;
+ c.fill = GridBagConstraints.VERTICAL;
+ c.weightx = 0;
+ layout.setConstraints(label, c);
+ container.add(label);
+
+ values = new JTextField[number_values];
+ for (int i = 0; i < values.length; i++) {
+ values[i] = new JTextField(AltosUILib.text_width);
+ values[i].setEditable(false);
+ values[i].setFont(AltosUILib.value_font);
+ values[i].setHorizontalAlignment(SwingConstants.RIGHT);
+ c.gridx = 1 + label_width + x + i * value_space; c.gridy = y;
+ c.anchor = GridBagConstraints.WEST;
+ c.fill = GridBagConstraints.BOTH;
+ c.weightx = 1;
+ c.gridwidth = value_width;
+ layout.setConstraints(values[i], c);
+ container.add(values[i]);
+ }
+ }
+
+ public AltosUIIndicator (Container container, int x, int y, int label_width, String text, int number_values, boolean has_lights, int value_width) {
+ this(container, x, y, label_width, text, number_values, has_lights, value_width, 1);
+ }
+
+ public AltosUIIndicator (Container container, int x, int y, String text, int number_values, boolean has_lights, int value_width) {
+ this(container, x, y, 1, text, number_values, has_lights, value_width);
+ }
+
+ public AltosUIIndicator (Container container, int y, String text, int number_values, boolean has_lights, int value_width) {
+ this(container, 0, y, text, number_values, has_lights, value_width);
+ }
+
+ public AltosUIIndicator (Container container, int y, String text, int number_values, boolean has_lights) {
+ this(container, 0, y, text, number_values, has_lights, 1);
+ }
+
+ public AltosUIIndicator (Container container, int y, String text, int number_values) {
+ this(container, 0, y, text, number_values, false, 1);
+ }
+
+ public AltosUIIndicator (Container container, int y, String text) {
+ this(container, 0, y, text, 1, false, 1);
+ }
+}
diff --git a/altosuilib/AltosUILatLon.java b/altosuilib/AltosUILatLon.java
new file mode 100644
index 00000000..688dd58b
--- /dev/null
+++ b/altosuilib/AltosUILatLon.java
@@ -0,0 +1,44 @@
+/*
+ * 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_2;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import java.io.*;
+import java.lang.Math;
+import java.awt.geom.*;
+import java.util.*;
+import java.util.concurrent.*;
+import org.altusmetrum.altoslib_4.*;
+
+public class AltosUILatLon {
+ public double lat;
+ public double lon;
+
+ public boolean equals(AltosUILatLon other) {
+ if (other == null)
+ return false;
+ return lat == other.lat && lon == other.lon;
+ }
+
+ public AltosUILatLon(double lat, double lon) {
+ this.lat = lat;
+ this.lon = lon;
+ }
+}
diff --git a/altosuilib/AltosUILib.java b/altosuilib/AltosUILib.java
index 76782e2e..b51c5963 100644
--- a/altosuilib/AltosUILib.java
+++ b/altosuilib/AltosUILib.java
@@ -15,12 +15,12 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_1;
+package org.altusmetrum.altosuilib_2;
import java.awt.*;
import libaltosJNI.*;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
public class AltosUILib extends AltosLib {
diff --git a/altosuilib/AltosUIListener.java b/altosuilib/AltosUIListener.java
index 450dc0bf..75a0ad94 100644
--- a/altosuilib/AltosUIListener.java
+++ b/altosuilib/AltosUIListener.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_1;
+package org.altusmetrum.altosuilib_2;
public interface AltosUIListener {
public void ui_changed(String look_and_feel);
diff --git a/altosuilib/AltosUIMap.java b/altosuilib/AltosUIMap.java
new file mode 100644
index 00000000..aaa68f23
--- /dev/null
+++ b/altosuilib/AltosUIMap.java
@@ -0,0 +1,250 @@
+/*
+ * Copyright © 2010 Anthony Towns <aj@erisian.com.au>
+ *
+ * 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 java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import java.io.*;
+import java.lang.Math;
+import java.awt.geom.*;
+import java.util.*;
+import java.util.concurrent.*;
+import org.altusmetrum.altoslib_4.*;
+
+public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosUIMapZoomListener {
+
+ static final int px_size = 512;
+
+ static final int maptype_hybrid = 0;
+ static final int maptype_roadmap = 1;
+ static final int maptype_satellite = 2;
+ static final int maptype_terrain = 3;
+ static final int maptype_default = maptype_hybrid;
+
+ static final String[] maptype_names = {
+ "hybrid",
+ "roadmap",
+ "satellite",
+ "terrain"
+ };
+
+ public static final String[] maptype_labels = {
+ "Hybrid",
+ "Roadmap",
+ "Satellite",
+ "Terrain"
+ };
+
+ public static final Color stateColors[] = {
+ Color.WHITE, // startup
+ Color.WHITE, // idle
+ Color.WHITE, // pad
+ Color.RED, // boost
+ Color.PINK, // fast
+ Color.YELLOW, // coast
+ Color.CYAN, // drogue
+ Color.BLUE, // main
+ Color.BLACK, // landed
+ Color.BLACK, // invalid
+ Color.CYAN, // stateless
+ };
+
+ public void reset() {
+ // nothing
+ }
+
+ public void font_size_changed(int font_size) {
+ view.set_font();
+ }
+
+ public void units_changed(boolean imperial_units) {
+ view.set_units();
+ }
+
+ JLabel zoom_label;
+
+ private void set_zoom_label() {
+ zoom_label.setText(String.format("Zoom %d", view.zoom() - view.default_zoom));
+ }
+
+ public void zoom_changed(int zoom) {
+ set_zoom_label();
+ }
+
+ public void set_zoom(int zoom) {
+ view.set_zoom(zoom);
+ }
+
+ public int get_zoom() {
+ return view.zoom();
+ }
+
+ public void set_maptype(int type) {
+ view.set_maptype(type);
+ maptype_combo.setSelectedIndex(type);
+ }
+
+ public void show(AltosState state, AltosListenerState listener_state) {
+ view.show(state, listener_state);
+ }
+
+ public void centre(double lat, double lon) {
+ view.centre(lat, lon);
+ }
+
+ public void centre(AltosState state) {
+ if (!state.gps.locked && state.gps.nsat < 4)
+ return;
+ centre(state.gps.lat, state.gps.lon);
+ }
+
+ public void add_mark(double lat, double lon, int state) {
+ view.add_mark(lat, lon, state);
+ }
+
+ public void clear_marks() {
+ view.clear_marks();
+ }
+
+ AltosUIMapView view;
+
+ private GridBagLayout layout = new GridBagLayout();
+
+ JComboBox<String> maptype_combo;
+
+ public void set_load_params(double lat, double lon, int radius, AltosUIMapTileListener listener) {
+ view.set_load_params(lat, lon, radius, listener);
+ }
+
+ public boolean all_fetched() {
+ return view.all_fetched();
+ }
+
+ public static void prefetch_maps(double lat, double lon) {
+ }
+
+ public String getName() {
+ return "Map";
+ }
+
+ public AltosUIMap() {
+
+ view = new AltosUIMapView();
+
+ view.setPreferredSize(new Dimension(500,500));
+ view.setVisible(true);
+ view.setEnabled(true);
+ view.add_zoom_listener(this);
+
+ GridBagLayout my_layout = new GridBagLayout();
+
+ setLayout(my_layout);
+
+ GridBagConstraints c = new GridBagConstraints();
+ c.anchor = GridBagConstraints.CENTER;
+ c.fill = GridBagConstraints.BOTH;
+ c.gridx = 0;
+ c.gridy = 0;
+ c.gridwidth = 1;
+ c.gridheight = 10;
+ c.weightx = 1;
+ c.weighty = 1;
+ add(view, c);
+
+ int y = 0;
+
+ zoom_label = new JLabel("", JLabel.CENTER);
+ set_zoom_label();
+
+ c = new GridBagConstraints();
+ c.anchor = GridBagConstraints.CENTER;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.gridx = 1;
+ c.gridy = y++;
+ c.weightx = 0;
+ c.weighty = 0;
+ add(zoom_label, c);
+
+ JButton zoom_reset = new JButton("0");
+ zoom_reset.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ set_zoom(view.default_zoom);
+ }
+ });
+
+ c = new GridBagConstraints();
+ c.anchor = GridBagConstraints.CENTER;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.gridx = 1;
+ c.gridy = y++;
+ c.weightx = 0;
+ c.weighty = 0;
+ add(zoom_reset, c);
+
+ JButton zoom_in = new JButton("+");
+ zoom_in.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ set_zoom(get_zoom() + 1);
+ }
+ });
+
+ c = new GridBagConstraints();
+ c.anchor = GridBagConstraints.CENTER;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.gridx = 1;
+ c.gridy = y++;
+ c.weightx = 0;
+ c.weighty = 0;
+ add(zoom_in, c);
+
+ JButton zoom_out = new JButton("-");
+ zoom_out.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ set_zoom(get_zoom() - 1);
+ }
+ });
+ c = new GridBagConstraints();
+ c.anchor = GridBagConstraints.CENTER;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.gridx = 1;
+ c.gridy = y++;
+ c.weightx = 0;
+ c.weighty = 0;
+ add(zoom_out, c);
+
+ maptype_combo = new JComboBox<String>(maptype_labels);
+
+ maptype_combo.setEditable(false);
+ maptype_combo.setMaximumRowCount(maptype_combo.getItemCount());
+ maptype_combo.addItemListener(new ItemListener() {
+ public void itemStateChanged(ItemEvent e) {
+ view.set_maptype(maptype_combo.getSelectedIndex());
+ }
+ });
+
+ c = new GridBagConstraints();
+ c.anchor = GridBagConstraints.CENTER;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.gridx = 1;
+ c.gridy = y++;
+ c.weightx = 0;
+ c.weighty = 0;
+ add(maptype_combo, c);
+ }
+}
diff --git a/altosuilib/AltosUIMapCache.java b/altosuilib/AltosUIMapCache.java
new file mode 100644
index 00000000..55311d8c
--- /dev/null
+++ b/altosuilib/AltosUIMapCache.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright © 2010 Anthony Towns <aj@erisian.com.au>
+ *
+ * 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 javax.imageio.ImageIO;
+import java.awt.image.*;
+import java.awt.*;
+import java.io.*;
+import java.net.*;
+
+public class AltosUIMapCache {
+ 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;
+
+ 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) {
+ 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;
+
+ synchronized(cache_lock) {
+ AltosUIMapImage[] new_images = new AltosUIMapImage[new_size];
+
+ for (int i = 0; i < cache_size; i++) {
+ if (i < new_size)
+ new_images[i] = images[i];
+ else if (images[i] != null)
+ images[i].flush();
+ }
+ images = new_images;
+ cache_size = new_size;
+ }
+ }
+
+ public Image get(AltosUIMapTile tile, AltosUIMapStore store, int width, int height) {
+ int oldest = -1;
+ long age = used;
+
+ synchronized(cache_lock) {
+ AltosUIMapImage image = null;
+ for (int i = 0; i < cache_size; i++) {
+ image = images[i];
+
+ if (image == null) {
+ oldest = i;
+ break;
+ }
+ if (store.equals(image.store)) {
+ image.used = used++;
+ return image.image;
+ }
+ if (image.used < age) {
+ oldest = i;
+ age = image.used;
+ }
+ }
+
+ try {
+ image = new AltosUIMapImage(tile, store);
+ image.used = used++;
+ if (images[oldest] != null)
+ images[oldest].flush();
+
+ images[oldest] = image;
+
+ if (image.image == null)
+ tile.set_status(loading);
+ else
+ tile.set_status(success);
+
+ return image.image;
+ } catch (IOException e) {
+ tile.set_status(failed);
+ return null;
+ }
+ }
+ }
+
+ public AltosUIMapCache() {
+ }
+}
diff --git a/altosuilib/AltosUIMapImage.java b/altosuilib/AltosUIMapImage.java
new file mode 100644
index 00000000..3819d079
--- /dev/null
+++ b/altosuilib/AltosUIMapImage.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright © 2010 Anthony Towns <aj@erisian.com.au>
+ *
+ * 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 javax.imageio.ImageIO;
+import java.awt.image.*;
+import java.awt.*;
+import java.io.*;
+import java.net.*;
+
+public class AltosUIMapImage implements AltosUIMapStoreListener {
+ static final long google_maps_ratelimit_ms = 1200;
+ // Google limits static map queries to 50 per minute per IP, so
+ // each query should take at least 1.2 seconds.
+
+ 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 long forbidden_time;
+ static boolean forbidden_set = false;
+ static final long forbidden_interval = 60l * 1000l * 1000l * 1000l;
+
+ AltosUIMapTile tile; /* Notify when image has been loaded */
+ Image image;
+ AltosUIMapStore store;
+ long used;
+
+ class loader implements Runnable {
+ public void run() {
+ if (image != null)
+ tile.notify_image(image);
+ try {
+ image = ImageIO.read(store.file);
+ } catch (Exception ex) {
+ }
+ if (image == null)
+ tile.set_status(failed);
+ else
+ tile.set_status(success);
+ tile.notify_image(image);
+ }
+ }
+
+ private void load() {
+ loader l = new loader();
+ Thread lt = new Thread(l);
+ lt.start();
+ }
+
+ public void flush() {
+ if (image != null) {
+ image.flush();
+ image = null;
+ }
+ }
+
+ public boolean has_map() {
+ return store.status() == AltosUIMapStore.success;
+ }
+
+ public synchronized void notify_store(AltosUIMapStore store, int status) {
+ switch (status) {
+ case AltosUIMapStore.loading:
+ break;
+ case AltosUIMapStore.success:
+ load();
+ break;
+ default:
+ tile.set_status(status);
+ tile.notify_image(null);
+ }
+ }
+
+ public AltosUIMapImage(AltosUIMapTile tile, AltosUIMapStore store) throws IOException {
+ this.tile = tile;
+ this.image = null;
+ this.store = store;
+ this.used = 0;
+
+ int status = store.status();
+ switch (status) {
+ case AltosUIMapStore.loading:
+ store.add_listener(this);
+ break;
+ case AltosUIMapStore.success:
+ load();
+ break;
+ default:
+ tile.set_status(status);
+ tile.notify_image(null);
+ break;
+ }
+ }
+}
diff --git a/altosuilib/AltosUIMapLine.java b/altosuilib/AltosUIMapLine.java
new file mode 100644
index 00000000..e09a2d9f
--- /dev/null
+++ b/altosuilib/AltosUIMapLine.java
@@ -0,0 +1,116 @@
+/*
+ * 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_2;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import java.io.*;
+import java.lang.Math;
+import java.awt.geom.*;
+import java.util.*;
+import java.util.concurrent.*;
+import org.altusmetrum.altoslib_4.*;
+
+public class AltosUIMapLine {
+ AltosUILatLon start, end;
+
+ private Font font = null;
+
+ public void set_font(Font font) {
+ this.font = font;
+ }
+
+ private AltosUILatLon lat_lon(MouseEvent e, AltosUIMapTransform t) {
+ return t.screen_lat_lon(e.getPoint());
+ }
+
+ public void dragged(MouseEvent e, AltosUIMapTransform t) {
+ end = lat_lon(e, t);
+ }
+
+ public void pressed(MouseEvent e, AltosUIMapTransform t) {
+ start = lat_lon(e, t);
+ end = null;
+ }
+
+ private String line_dist() {
+ String format;
+ AltosGreatCircle g = new AltosGreatCircle(start.lat, start.lon,
+ end.lat, end.lon);
+ double distance = g.distance;
+
+ if (AltosConvert.imperial_units) {
+ distance = AltosConvert.meters_to_feet(distance);
+ if (distance < 10000) {
+ format = "%4.0fft";
+ } else {
+ distance /= 5280;
+ if (distance < 10)
+ format = "%5.3fmi";
+ else if (distance < 100)
+ format = "%5.2fmi";
+ else if (distance < 1000)
+ format = "%5.1fmi";
+ else
+ format = "%5.0fmi";
+ }
+ } else {
+ if (distance < 10000) {
+ format = "%4.0fm";
+ } else {
+ distance /= 1000;
+ if (distance < 100)
+ format = "%5.2fkm";
+ else if (distance < 1000)
+ format = "%5.1fkm";
+ else
+ format = "%5.0fkm";
+ }
+ }
+ return String.format(format, distance);
+ }
+
+ public void paint(Graphics2D g, AltosUIMapTransform t) {
+ g.setColor(Color.BLUE);
+
+ if (start == null || end == null)
+ return;
+
+ Line2D.Double line = new Line2D.Double(t.screen(start),
+ t.screen(end));
+
+ 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());
+
+ float x = (float) line.x1;
+ float y = (float) line.y1 + (float) bounds.getHeight() / 2.0f;
+
+ if (line.x1 < line.x2) {
+ x -= (float) bounds.getWidth() + 2.0f;
+ } else {
+ x += 2.0f;
+ }
+ g.drawString(message, x, y);
+ }
+}
diff --git a/altosuilib/AltosUIMapMark.java b/altosuilib/AltosUIMapMark.java
new file mode 100644
index 00000000..8c640e5f
--- /dev/null
+++ b/altosuilib/AltosUIMapMark.java
@@ -0,0 +1,59 @@
+/*
+ * 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_2;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import java.io.*;
+import java.lang.Math;
+import java.awt.geom.*;
+import java.util.*;
+import java.util.concurrent.*;
+import org.altusmetrum.altoslib_4.*;
+
+public class AltosUIMapMark {
+
+ AltosUILatLon lat_lon;
+ int state;
+
+ static public int stroke_width = 6;
+
+ public void paint(Graphics2D g, AltosUIMapTransform t) {
+
+ Point2D.Double pt = t.screen(lat_lon);
+
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+ g.setStroke(new BasicStroke(stroke_width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
+
+ if (0 <= state && state < AltosUIMap.stateColors.length)
+ g.setColor(AltosUIMap.stateColors[state]);
+ else
+ g.setColor(AltosUIMap.stateColors[AltosLib.ao_flight_invalid]);
+
+ g.drawOval((int)pt.x-5, (int)pt.y-5, 10, 10);
+ g.drawOval((int)pt.x-20, (int)pt.y-20, 40, 40);
+ g.drawOval((int)pt.x-35, (int)pt.y-35, 70, 70);
+ }
+
+ public AltosUIMapMark (double lat, double lon, int state) {
+ lat_lon = new AltosUILatLon(lat, lon);
+ this.state = state;
+ }
+}
diff --git a/altosuilib/AltosUIMapPath.java b/altosuilib/AltosUIMapPath.java
new file mode 100644
index 00000000..ff17be67
--- /dev/null
+++ b/altosuilib/AltosUIMapPath.java
@@ -0,0 +1,96 @@
+/*
+ * 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_2;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import java.io.*;
+import java.lang.Math;
+import java.awt.geom.*;
+import java.util.*;
+import java.util.concurrent.*;
+import org.altusmetrum.altoslib_4.*;
+
+class PathPoint {
+ AltosUILatLon lat_lon;
+ int state;
+
+ public PathPoint(AltosUILatLon lat_lon, int state) {
+ this.lat_lon = lat_lon;
+ this.state = state;
+ }
+
+ public boolean equals(PathPoint other) {
+ if (other == null)
+ return false;
+
+ return lat_lon.equals(other.lat_lon) && state == other.state;
+ }
+}
+
+public class AltosUIMapPath {
+
+ LinkedList<PathPoint> points = new LinkedList<PathPoint>();
+ PathPoint last_point = null;
+
+ static public int stroke_width = 6;
+
+ public void paint(Graphics2D g, AltosUIMapTransform t) {
+ Point2D.Double prev = null;
+
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+ g.setStroke(new BasicStroke(stroke_width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
+
+ for (PathPoint point : points) {
+ Point2D.Double cur = t.screen(point.lat_lon);
+ if (prev != null) {
+ Line2D.Double line = new Line2D.Double (prev, cur);
+ Rectangle bounds = line.getBounds();
+
+ if (g.hitClip(bounds.x, bounds.y, bounds.width, bounds.height)) {
+ if (0 <= point.state && point.state < AltosUIMap.stateColors.length)
+ g.setColor(AltosUIMap.stateColors[point.state]);
+ else
+ g.setColor(AltosUIMap.stateColors[AltosLib.ao_flight_invalid]);
+
+ g.draw(line);
+ }
+ }
+ prev = cur;
+ }
+ }
+
+ public AltosUIMapRectangle add(double lat, double lon, int state) {
+ PathPoint point = new PathPoint(new AltosUILatLon (lat, lon), state);
+ AltosUIMapRectangle rect = null;
+
+ if (!point.equals(last_point)) {
+ if (last_point != null)
+ rect = new AltosUIMapRectangle(last_point.lat_lon, point.lat_lon);
+ points.add (point);
+ last_point = point;
+ }
+ return rect;
+ }
+
+ public void clear () {
+ points = new LinkedList<PathPoint>();
+ }
+}
diff --git a/altosui/AltosSiteMapPreload.java b/altosuilib/AltosUIMapPreload.java
index 66399557..56066d70 100644
--- a/altosui/AltosSiteMapPreload.java
+++ b/altosuilib/AltosUIMapPreload.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altosuilib_2;
import java.awt.*;
import java.awt.event.*;
@@ -26,10 +26,10 @@ import java.text.*;
import java.lang.Math;
import java.net.URL;
import java.net.URLConnection;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
-class AltosMapPos extends Box {
- AltosUI owner;
+class AltosUIMapPos extends Box {
+ AltosUIFrame owner;
JLabel label;
JComboBox hemi;
JTextField deg;
@@ -87,14 +87,14 @@ class AltosMapPos extends Box {
return v;
}
- public AltosMapPos(AltosUI in_owner,
+ public AltosUIMapPos(AltosUIFrame in_owner,
String label_value,
String[] hemi_names,
double default_value) {
super(BoxLayout.X_AXIS);
owner = in_owner;
label = new JLabel(label_value);
- hemi = new JComboBox(hemi_names);
+ hemi = new JComboBox<String>(hemi_names);
hemi.setEditable(false);
deg = new JTextField(5);
deg.setMinimumSize(deg.getPreferredSize());
@@ -118,7 +118,7 @@ class AltosMapPos extends Box {
}
}
-class AltosSite {
+class AltosUISite {
String name;
double latitude;
double longitude;
@@ -127,13 +127,13 @@ class AltosSite {
return name;
}
- public AltosSite(String in_name, double in_latitude, double in_longitude) {
+ public AltosUISite(String in_name, double in_latitude, double in_longitude) {
name = in_name;
latitude = in_latitude;
longitude = in_longitude;
}
- public AltosSite(String line) throws ParseException {
+ public AltosUISite(String line) throws ParseException {
String[] elements = line.split(":");
if (elements.length < 3)
@@ -150,10 +150,10 @@ class AltosSite {
}
}
-class AltosSites extends Thread {
- AltosSiteMapPreload preload;
+class AltosUISites extends Thread {
+ AltosUIMapPreload preload;
URL url;
- LinkedList<AltosSite> sites;
+ LinkedList<AltosUISite> sites;
void notify_complete() {
SwingUtilities.invokeLater(new Runnable() {
@@ -163,13 +163,13 @@ class AltosSites extends Thread {
});
}
- void add(AltosSite site) {
+ void add(AltosUISite site) {
sites.add(site);
}
void add(String line) {
try {
- add(new AltosSite(line));
+ add(new AltosUISite(line));
} catch (ParseException pe) {
}
}
@@ -178,8 +178,8 @@ class AltosSites extends Thread {
try {
URLConnection uc = url.openConnection();
//int length = uc.getContentLength();
-
- InputStreamReader in_stream = new InputStreamReader(uc.getInputStream(), Altos.unicode_set);
+
+ InputStreamReader in_stream = new InputStreamReader(uc.getInputStream(), AltosLib.unicode_set);
BufferedReader in = new BufferedReader(in_stream);
for (;;) {
@@ -194,11 +194,11 @@ class AltosSites extends Thread {
}
}
- public AltosSites(AltosSiteMapPreload in_preload) {
- sites = new LinkedList<AltosSite>();
+ public AltosUISites(AltosUIMapPreload in_preload) {
+ sites = new LinkedList<AltosUISite>();
preload = in_preload;
try {
- url = new URL(Altos.launch_sites_url);
+ url = new URL(AltosLib.launch_sites_url);
} catch (java.net.MalformedURLException e) {
notify_complete();
}
@@ -206,76 +206,159 @@ class AltosSites extends Thread {
}
}
-public class AltosSiteMapPreload extends AltosUIDialog implements ActionListener, ItemListener {
- AltosUI owner;
- AltosSiteMap map;
-
- AltosMapPos lat;
- AltosMapPos lon;
+public class AltosUIMapPreload extends AltosUIFrame implements ActionListener, ItemListener, AltosUIMapTileListener {
+ AltosUIFrame owner;
+ AltosUIMap map;
+ AltosUIMapCache cache = new AltosUIMapCache();
- final static int radius = 5;
- final static int width = (radius * 2 + 1);
- final static int height = (radius * 2 + 1);
+ AltosUIMapPos lat;
+ AltosUIMapPos lon;
JProgressBar pbar;
+ int pbar_max;
+ int pbar_cur;
- AltosSites sites;
+ AltosUISites sites;
JLabel site_list_label;
- JComboBox site_list;
-
+ JComboBox<AltosUISite> site_list;
+
JToggleButton load_button;
boolean loading;
JButton close_button;
+ JCheckBox[] maptypes = new JCheckBox[AltosUIMap.maptype_terrain - AltosUIMap.maptype_hybrid + 1];
+
+ JComboBox<Integer> min_zoom;
+ JComboBox<Integer> max_zoom;
+ JComboBox<Integer> radius;
+
+ Integer[] zooms = { -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6 };
+ Integer[] radii = { 1, 2, 3, 4, 5 };
+
static final String[] lat_hemi_names = { "N", "S" };
static final String[] lon_hemi_names = { "E", "W" };
class updatePbar implements Runnable {
- int n;
String s;
- public updatePbar(int x, int y, String in_s) {
- n = (x + radius) + (y + radius) * width + 1;
+ public updatePbar(String in_s) {
s = in_s;
}
public void run() {
+ int n = ++pbar_cur;
+
+ pbar.setMaximum(pbar_max);
pbar.setValue(n);
pbar.setString(s);
- if (n < width * height) {
- pbar.setValue(n);
- pbar.setString(s);
+ }
+ }
+
+ double latitude, longitude;
+ int min_z;
+ int max_z;
+ int cur_z;
+ int all_types;
+ int cur_type;
+ int r;
+
+ int tiles_per_layer;
+ int tiles_loaded;
+ int layers_total;
+ int layers_loaded;
+
+
+ private void do_load() {
+ tiles_loaded = 0;
+ map.set_zoom(cur_z + AltosUIMapView.default_zoom);
+ map.set_maptype(cur_type);
+ map.set_load_params(latitude, longitude, r, this);
+ }
+
+ private int next_type(int start) {
+ int next_type;
+ for (next_type = start;
+ next_type <= AltosUIMap.maptype_terrain && (all_types & (1 << next_type)) == 0;
+ next_type++)
+ ;
+ return next_type;
+ }
+
+ private void next_load() {
+ int next_type = next_type(cur_type + 1);
+
+ if (next_type > AltosUIMap.maptype_terrain) {
+ if (cur_z == max_z) {
+ return;
} else {
- pbar.setValue(0);
- pbar.setString("");
- load_button.setSelected(false);
- loading = false;
+ cur_z++;
}
+ next_type = next_type(0);
}
+ cur_type = next_type;
+ do_load();
}
- class bgLoad extends Thread {
+ private void start_load() {
+ cur_z = min_z;
+ int ntype = 0;
+ all_types = 0;
+ for (int t = AltosUIMap.maptype_hybrid; t <= AltosUIMap.maptype_terrain; t++)
+ if (maptypes[t].isSelected()) {
+ all_types |= (1 << t);
+ ntype++;
+ }
+ if (ntype == 0) {
+ all_types |= (1 << AltosUIMap.maptype_hybrid);
+ ntype = 1;
+ }
- AltosSiteMap map;
+ cur_type = next_type(0);
+ tiles_per_layer = (r * 2 + 1) * (r * 2 + 1);
+ layers_total = (max_z - min_z + 1) * ntype;
+ layers_loaded = 0;
+ pbar_max = layers_total * tiles_per_layer;
+ pbar_cur = 0;
- public bgLoad(AltosSiteMap in_map) {
- map = in_map;
- }
+ map.clear_marks();
+ map.add_mark(latitude,longitude, AltosLib.ao_flight_boost);
+ do_load();
+ }
- public void run() {
- for (int y = -map.radius; y <= map.radius; y++) {
- for (int x = -map.radius; x <= map.radius; x++) {
- String pngfile;
- pngfile = map.initMap(new Point(x,y));
- SwingUtilities.invokeLater(new updatePbar(x, y, pngfile));
- }
+ /* AltosUIMapTileListener methods */
+
+ public synchronized void notify_tile(AltosUIMapTile tile, int status) {
+ if (status == AltosUIMapStore.loading)
+ return;
+
+ SwingUtilities.invokeLater(new updatePbar(tile.store.file.toString()));
+ ++tiles_loaded;
+ if (tiles_loaded == tiles_per_layer) {
+ ++layers_loaded;
+ if (layers_loaded == layers_total) {
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ pbar.setValue(0);
+ pbar.setString("");
+ load_button.setSelected(false);
+ loading = false;
+ }
+ });
+ } else {
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ next_load();
+ }
+ });
}
}
}
+ public AltosUIMapCache cache() { return cache; }
+
public void set_sites() {
int i = 1;
- for (AltosSite site : sites.sites) {
+ for (AltosUISite site : sites.sites) {
site_list.insertItemAt(site, i);
i++;
}
@@ -286,8 +369,8 @@ public class AltosSiteMapPreload extends AltosUIDialog implements ActionListener
if (state == ItemEvent.SELECTED) {
Object o = e.getItem();
- if (o instanceof AltosSite) {
- AltosSite site = (AltosSite) o;
+ if (o instanceof AltosUISite) {
+ AltosUISite site = (AltosUISite) o;
lat.set_value(site.latitude);
lon.set_value(site.longitude);
}
@@ -303,30 +386,34 @@ public class AltosSiteMapPreload extends AltosUIDialog implements ActionListener
if (cmd.equals("load")) {
if (!loading) {
try {
- final double latitude = lat.get_value();
- final double longitude = lon.get_value();
- map.setBaseLocation(latitude,longitude);
- map.draw_circle(latitude,longitude);
+ latitude = lat.get_value();
+ longitude = lon.get_value();
+ min_z = (Integer) min_zoom.getSelectedItem();
+ max_z = (Integer) max_zoom.getSelectedItem();
+ if (max_z < min_z)
+ max_z = min_z;
+ r = (Integer) radius.getSelectedItem();
loading = true;
- bgLoad thread = new bgLoad(map);
- thread.start();
} catch (NumberFormatException ne) {
load_button.setSelected(false);
}
+ start_load();
}
}
}
- public AltosSiteMapPreload(AltosUI in_owner) {
+ public AltosUIMapPreload(AltosUIFrame in_owner) {
owner = in_owner;
Container pane = getContentPane();
GridBagConstraints c = new GridBagConstraints();
Insets i = new Insets(4,4,4,4);
+ setTitle("AltOS Load Maps");
+
pane.setLayout(new GridBagLayout());
- map = new AltosSiteMap(radius);
+ map = new AltosUIMap();
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.CENTER;
@@ -336,18 +423,18 @@ public class AltosSiteMapPreload extends AltosUIDialog implements ActionListener
c.gridx = 0;
c.gridy = 0;
- c.gridwidth = 2;
+ c.gridwidth = 10;
c.anchor = GridBagConstraints.CENTER;
pane.add(map, c);
pbar = new JProgressBar();
pbar.setMinimum(0);
- pbar.setMaximum(width * height);
+ pbar.setMaximum(1);
pbar.setValue(0);
pbar.setString("");
pbar.setStringPainted(true);
-
+
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.CENTER;
c.insets = i;
@@ -356,7 +443,7 @@ public class AltosSiteMapPreload extends AltosUIDialog implements ActionListener
c.gridx = 0;
c.gridy = 1;
- c.gridwidth = 2;
+ c.gridwidth = 10;
pane.add(pbar, c);
@@ -373,11 +460,11 @@ public class AltosSiteMapPreload extends AltosUIDialog implements ActionListener
c.gridwidth = 1;
pane.add(site_list_label, c);
-
- site_list = new JComboBox(new String[] { "Site List" });
+
+ site_list = new JComboBox<AltosUISite>(new AltosUISite[] { new AltosUISite("Site List", 0, 0) });
site_list.addItemListener(this);
- sites = new AltosSites(this);
+ sites = new AltosUISites(this);
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.CENTER;
@@ -390,11 +477,11 @@ public class AltosSiteMapPreload extends AltosUIDialog implements ActionListener
c.gridwidth = 1;
pane.add(site_list, c);
-
- lat = new AltosMapPos(owner,
- "Latitude:",
- lat_hemi_names,
- 37.167833333);
+
+ lat = new AltosUIMapPos(owner,
+ "Latitude:",
+ lat_hemi_names,
+ 37.167833333);
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.CENTER;
c.insets = i;
@@ -407,11 +494,11 @@ public class AltosSiteMapPreload extends AltosUIDialog implements ActionListener
c.anchor = GridBagConstraints.CENTER;
pane.add(lat, c);
-
- lon = new AltosMapPos(owner,
- "Longitude:",
- lon_hemi_names,
- -97.73975);
+
+ lon = new AltosUIMapPos(owner,
+ "Longitude:",
+ lon_hemi_names,
+ -97.73975);
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.CENTER;
@@ -429,7 +516,7 @@ public class AltosSiteMapPreload extends AltosUIDialog implements ActionListener
load_button = new JToggleButton("Load Map");
load_button.addActionListener(this);
load_button.setActionCommand("load");
-
+
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.CENTER;
c.insets = i;
@@ -446,7 +533,7 @@ public class AltosSiteMapPreload extends AltosUIDialog implements ActionListener
close_button = new JButton("Close");
close_button.addActionListener(this);
close_button.setActionCommand("close");
-
+
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.CENTER;
c.insets = i;
@@ -460,6 +547,59 @@ public class AltosSiteMapPreload extends AltosUIDialog implements ActionListener
pane.add(close_button, c);
+ JLabel types_label = new JLabel("Map Types");
+ c.gridx = 2;
+ c.gridwidth = 2;
+ c.gridy = 2;
+ pane.add(types_label, c);
+
+ c.gridwidth = 1;
+
+ for (int type = AltosUIMap.maptype_hybrid; type <= AltosUIMap.maptype_terrain; type++) {
+ maptypes[type] = new JCheckBox(AltosUIMap.maptype_labels[type],
+ type == AltosUIMap.maptype_hybrid);
+ c.gridx = 2 + (type >> 1);
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.gridy = (type & 1) + 3;
+ pane.add(maptypes[type], c);
+ }
+
+ JLabel min_zoom_label = new JLabel("Minimum Zoom");
+ c.gridx = 4;
+ c.gridy = 2;
+ pane.add(min_zoom_label, c);
+
+ min_zoom = new JComboBox<Integer>(zooms);
+ min_zoom.setSelectedItem(zooms[10]);
+ min_zoom.setEditable(false);
+ c.gridx = 5;
+ c.gridy = 2;
+ pane.add(min_zoom, c);
+
+ JLabel max_zoom_label = new JLabel("Maximum Zoom");
+ c.gridx = 4;
+ c.gridy = 3;
+ pane.add(max_zoom_label, c);
+
+ max_zoom = new JComboBox<Integer>(zooms);
+ max_zoom.setSelectedItem(zooms[14]);
+ max_zoom.setEditable(false);
+ c.gridx = 5;
+ c.gridy = 3;
+ pane.add(max_zoom, c);
+
+ JLabel radius_label = new JLabel("Tile Radius");
+ c.gridx = 4;
+ c.gridy = 4;
+ pane.add(radius_label, c);
+
+ radius = new JComboBox<Integer>(radii);
+ radius.setSelectedItem(radii[4]);
+ radius.setEditable(true);
+ c.gridx = 5;
+ c.gridy = 4;
+ pane.add(radius, c);
+
pack();
setLocationRelativeTo(owner);
setVisible(true);
diff --git a/altosuilib/AltosUIMapRectangle.java b/altosuilib/AltosUIMapRectangle.java
new file mode 100644
index 00000000..8a5b16e1
--- /dev/null
+++ b/altosuilib/AltosUIMapRectangle.java
@@ -0,0 +1,45 @@
+/*
+ * 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_2;
+
+public class AltosUIMapRectangle {
+ AltosUILatLon ul, lr;
+
+ public AltosUIMapRectangle(AltosUILatLon a, AltosUILatLon b) {
+ double ul_lat, ul_lon;
+ double lr_lat, lr_lon;
+
+ if (a.lat > b.lat) {
+ ul_lat = a.lat;
+ lr_lat = b.lat;
+ } else {
+ ul_lat = b.lat;
+ lr_lat = a.lat;
+ }
+ if (a.lon < b.lon) {
+ ul_lon = a.lon;
+ lr_lon = b.lon;
+ } else {
+ ul_lon = b.lon;
+ lr_lon = a.lon;
+ }
+
+ ul = new AltosUILatLon(ul_lat, ul_lon);
+ lr = new AltosUILatLon(lr_lat, lr_lon);
+ }
+}
diff --git a/altosuilib/AltosUIMapStore.java b/altosuilib/AltosUIMapStore.java
new file mode 100644
index 00000000..4cecb54f
--- /dev/null
+++ b/altosuilib/AltosUIMapStore.java
@@ -0,0 +1,203 @@
+/*
+ * 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_2;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+public class AltosUIMapStore {
+ String url;
+ File file;
+ LinkedList<AltosUIMapStoreListener> listeners = new LinkedList<AltosUIMapStoreListener>();
+
+ 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;
+
+ int status;
+
+ public int status() {
+ return status;
+ }
+
+ public synchronized void add_listener(AltosUIMapStoreListener listener) {
+ if (!listeners.contains(listener))
+ listeners.add(listener);
+ }
+
+ public synchronized void remove_listener(AltosUIMapStoreListener listener) {
+ listeners.remove(listener);
+ }
+
+ private synchronized void notify_listeners(int status) {
+ this.status = status;
+ for (AltosUIMapStoreListener listener : listeners)
+ listener.notify_store(this, status);
+ }
+
+ static Object forbidden_lock = new Object();
+ static long forbidden_time;
+ static boolean forbidden_set;
+
+ private int fetch_url() {
+ URL u;
+
+ try {
+ u = new URL(url);
+ } catch (java.net.MalformedURLException e) {
+ return bad_request;
+ }
+
+ byte[] data;
+ URLConnection uc = null;
+ try {
+ uc = u.openConnection();
+ String type = uc.getContentType();
+ int contentLength = uc.getContentLength();
+ if (uc instanceof HttpURLConnection) {
+ int response = ((HttpURLConnection) uc).getResponseCode();
+ switch (response) {
+ case HttpURLConnection.HTTP_FORBIDDEN:
+ case HttpURLConnection.HTTP_PAYMENT_REQUIRED:
+ case HttpURLConnection.HTTP_UNAUTHORIZED:
+ synchronized (forbidden_lock) {
+ forbidden_time = System.nanoTime();
+ forbidden_set = true;
+ return forbidden;
+ }
+ }
+ }
+ InputStream in = new BufferedInputStream(uc.getInputStream());
+ int bytesRead = 0;
+ int offset = 0;
+ data = new byte[contentLength];
+ while (offset < contentLength) {
+ bytesRead = in.read(data, offset, data.length - offset);
+ if (bytesRead == -1)
+ break;
+ offset += bytesRead;
+ }
+ in.close();
+
+ if (offset != contentLength)
+ return failed;
+
+ } catch (IOException e) {
+ return failed;
+ }
+
+ try {
+ FileOutputStream out = new FileOutputStream(file);
+ out.write(data);
+ out.flush();
+ out.close();
+ } catch (FileNotFoundException e) {
+ return bad_request;
+ } catch (IOException e) {
+ if (file.exists())
+ file.delete();
+ return bad_request;
+ }
+ return success;
+ }
+
+ static Object fetch_lock = new Object();
+
+ static final long forbidden_interval = 60l * 1000l * 1000l * 1000l;
+ static final long google_maps_ratelimit_ms = 1200;
+
+ class loader implements Runnable {
+
+ public void run() {
+ if (file.exists()) {
+ notify_listeners(success);
+ return;
+ }
+
+ synchronized(forbidden_lock) {
+ if (forbidden_set && (System.nanoTime() - forbidden_time) < forbidden_interval) {
+ notify_listeners(forbidden);
+ return;
+ }
+ }
+
+ int new_status;
+
+ if (!AltosUIVersion.has_google_maps_api_key()) {
+ synchronized (fetch_lock) {
+ long startTime = System.nanoTime();
+ new_status = fetch_url();
+ if (new_status == success) {
+ long duration_ms = (System.nanoTime() - startTime) / 1000000;
+ if (duration_ms < google_maps_ratelimit_ms) {
+ try {
+ Thread.sleep(google_maps_ratelimit_ms - duration_ms);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+ }
+ } else {
+ new_status = fetch_url();
+ }
+ notify_listeners(new_status);
+ }
+ }
+
+ private void load() {
+ loader l = new loader();
+ Thread lt = new Thread(l);
+ lt.start();
+ }
+
+ private AltosUIMapStore (String url, File file) {
+ this.url = url;
+ this.file = file;
+
+ if (file.exists())
+ status = success;
+ else {
+ status = loading;
+ load();
+ }
+ }
+
+ public boolean equals(AltosUIMapStore other) {
+ return url.equals(other.url);
+ }
+
+ static HashMap<String,AltosUIMapStore> stores = new HashMap<String,AltosUIMapStore>();
+
+ public static AltosUIMapStore get(String url, File file) {
+ AltosUIMapStore store;
+ synchronized(stores) {
+ if (stores.containsKey(url)) {
+ store = stores.get(url);
+ } else {
+ store = new AltosUIMapStore(url, file);
+ stores.put(url, store);
+ }
+ }
+ return store;
+ }
+
+}
diff --git a/altosuilib/AltosUIMapStoreListener.java b/altosuilib/AltosUIMapStoreListener.java
new file mode 100644
index 00000000..91aff00c
--- /dev/null
+++ b/altosuilib/AltosUIMapStoreListener.java
@@ -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_2;
+
+public interface AltosUIMapStoreListener {
+ abstract void notify_store(AltosUIMapStore store, int status);
+}
diff --git a/altosuilib/AltosUIMapTile.java b/altosuilib/AltosUIMapTile.java
new file mode 100644
index 00000000..7c823183
--- /dev/null
+++ b/altosuilib/AltosUIMapTile.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright © 2010 Anthony Towns <aj@erisian.com.au>
+ *
+ * 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 java.awt.*;
+import java.awt.image.*;
+import javax.swing.*;
+import javax.imageio.*;
+import java.awt.geom.*;
+import java.io.*;
+import java.util.*;
+import java.awt.RenderingHints.*;
+import org.altusmetrum.altoslib_4.*;
+
+public class AltosUIMapTile {
+ AltosUIMapTileListener listener;
+ AltosUILatLon upper_left, center;
+ int px_size;
+ int zoom;
+ int maptype;
+ AltosUIMapStore store;
+ AltosUIMapCache cache;
+ int status;
+
+ private File map_file() {
+ double lat = center.lat;
+ double lon = center.lon;
+ char chlat = lat < 0 ? 'S' : 'N';
+ char chlon = lon < 0 ? 'W' : 'E';
+
+ if (lat < 0) lat = -lat;
+ if (lon < 0) lon = -lon;
+ String maptype_string = String.format("%s-", AltosUIMap.maptype_names[maptype]);
+ String format_string;
+ if (maptype == AltosUIMap.maptype_hybrid || maptype == AltosUIMap.maptype_satellite || maptype == AltosUIMap.maptype_terrain)
+ format_string = "jpg";
+ else
+ format_string = "png";
+ return new File(AltosUIPreferences.mapdir(),
+ String.format("map-%c%.6f,%c%.6f-%s%d.%s",
+ chlat, lat, chlon, lon, maptype_string, zoom, format_string));
+ }
+
+ private String map_url() {
+ String format_string;
+ if (maptype == AltosUIMap.maptype_hybrid || maptype == AltosUIMap.maptype_satellite || maptype == AltosUIMap.maptype_terrain)
+ format_string = "jpg";
+ else
+ format_string = "png32";
+
+ if (AltosUIVersion.has_google_maps_api_key())
+ return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=%s&format=%s&key=%s",
+ center.lat, center.lon, zoom, px_size, px_size, AltosUIMap.maptype_names[maptype], format_string, AltosUIVersion.google_maps_api_key);
+ else
+ return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=%s&format=%s",
+ center.lat, center.lon, zoom, px_size, px_size, AltosUIMap.maptype_names[maptype], format_string);
+ }
+ private Font font = null;
+
+ public void set_font(Font font) {
+ this.font = font;
+ }
+
+ int painting_serial;
+ int painted_serial;
+
+ Image image;
+
+ public void paint_graphics(Graphics2D g2d, AltosUIMapTransform t, int serial) {
+ if (serial < painted_serial)
+ return;
+
+ Point2D.Double point_double = t.screen(upper_left);
+ Point point = new Point((int) (point_double.x + 0.5),
+ (int) (point_double.y + 0.5));
+
+ painted_serial = serial;
+
+ if (!g2d.hitClip(point.x, point.y, px_size, px_size))
+ return;
+
+ if (image != null) {
+ g2d.drawImage(image, point.x, point.y, null);
+ image = null;
+ } else {
+ g2d.setColor(Color.GRAY);
+ g2d.fillRect(point.x, point.y, px_size, px_size);
+
+ if (t.has_location()) {
+ String message = null;
+ switch (status) {
+ case AltosUIMapCache.loading:
+ message = "Loading...";
+ break;
+ case AltosUIMapCache.bad_request:
+ message = "Internal error";
+ break;
+ case AltosUIMapCache.failed:
+ message = "Network error, check connection";
+ break;
+ case AltosUIMapCache.forbidden:
+ message = "Too many requests, try later";
+ break;
+ }
+ if (message != null && font != null) {
+ g2d.setFont(font);
+ g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+ Rectangle2D bounds = font.getStringBounds(message, g2d.getFontRenderContext());
+
+ float x = px_size / 2.0f;
+ float y = px_size / 2.0f;
+ x = x - (float) bounds.getWidth() / 2.0f;
+ y = y + (float) bounds.getHeight() / 2.0f;
+ g2d.setColor(Color.BLACK);
+ g2d.drawString(message, (float) point_double.x + x, (float) point_double.y + y);
+ }
+ }
+ }
+ }
+
+ public void set_status(int status) {
+ this.status = status;
+ listener.notify_tile(this, status);
+ }
+
+ public void notify_image(Image image) {
+ listener.notify_tile(this, status);
+ }
+
+ public void paint(Graphics g, AltosUIMapTransform t) {
+ Graphics2D g2d = (Graphics2D) g;
+ boolean queued = false;
+
+ Point2D.Double point = t.screen(upper_left);
+
+ if (!g.hitClip((int) (point.x + 0.5), (int) (point.y + 0.5), px_size, px_size))
+ return;
+
+ ++painting_serial;
+
+ if (image == null && t.has_location())
+ image = cache.get(this, store, px_size, px_size);
+
+ paint_graphics(g2d, t, painting_serial);
+ }
+
+ public int store_status() {
+ return store.status();
+ }
+
+ public void add_store_listener(AltosUIMapStoreListener listener) {
+ store.add_listener(listener);
+ }
+
+ public void remove_store_listener(AltosUIMapStoreListener listener) {
+ store.remove_listener(listener);
+ }
+
+ public AltosUIMapTile(AltosUIMapTileListener listener, AltosUILatLon upper_left, AltosUILatLon center, int zoom, int maptype, int px_size, Font font) {
+ this.listener = listener;
+ this.upper_left = upper_left;
+ cache = listener.cache();
+
+ while (center.lon < -180.0)
+ center.lon += 360.0;
+ while (center.lon > 180.0)
+ center.lon -= 360.0;
+
+ this.center = center;
+ this.zoom = zoom;
+ this.maptype = maptype;
+ this.px_size = px_size;
+ this.font = font;
+ status = AltosUIMapCache.loading;
+ store = AltosUIMapStore.get(map_url(), map_file());
+ }
+}
diff --git a/altosuilib/AltosUIMapTileListener.java b/altosuilib/AltosUIMapTileListener.java
new file mode 100644
index 00000000..4ca13539
--- /dev/null
+++ b/altosuilib/AltosUIMapTileListener.java
@@ -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.
+ */
+
+package org.altusmetrum.altosuilib_2;
+
+public interface AltosUIMapTileListener {
+ abstract public void notify_tile(AltosUIMapTile tile, int status);
+
+ abstract public AltosUIMapCache cache();
+}
diff --git a/altosuilib/AltosUIMapTransform.java b/altosuilib/AltosUIMapTransform.java
new file mode 100644
index 00000000..e6f1ffe3
--- /dev/null
+++ b/altosuilib/AltosUIMapTransform.java
@@ -0,0 +1,106 @@
+/*
+ * 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_2;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import java.io.*;
+import java.lang.Math;
+import java.awt.geom.*;
+import java.util.*;
+import java.util.concurrent.*;
+import org.altusmetrum.altoslib_4.*;
+
+public class AltosUIMapTransform {
+
+ double scale_x, scale_y;
+
+ double offset_x, offset_y;
+
+ public AltosUILatLon lat_lon (Point2D.Double point) {
+ double lat, lon;
+ double rads;
+
+ lon = point.x/scale_x;
+ rads = 2 * Math.atan(Math.exp(-point.y/scale_y));
+ lat = Math.toDegrees(rads - Math.PI/2);
+
+ return new AltosUILatLon(lat,lon);
+ }
+
+ public Point2D.Double screen_point(Point screen) {
+ return new Point2D.Double(screen.x + offset_x, screen.y + offset_y);
+ }
+
+ public AltosUILatLon screen_lat_lon(Point screen) {
+ return lat_lon(screen_point(screen));
+ }
+
+ public Point2D.Double point(AltosUILatLon lat_lon) {
+ double x, y;
+ double e;
+
+ x = lat_lon.lon * scale_x;
+
+ e = Math.sin(Math.toRadians(lat_lon.lat));
+ e = Math.max(e,-(1-1.0E-15));
+ e = Math.min(e, 1-1.0E-15 );
+
+ y = 0.5*Math.log((1+e)/(1-e))*-scale_y;
+
+ return new Point2D.Double(x, y);
+ }
+
+ public Point2D.Double screen(Point2D.Double point) {
+ return new Point2D.Double(point.x - offset_x, point.y - offset_y);
+ }
+
+ public Point screen(Point point) {
+ return new Point((int) (point.x - offset_x + 0.5),
+ (int) (point.y - offset_y + 0.5));
+ }
+
+ public Rectangle screen(AltosUIMapRectangle map_rect) {
+ Point2D.Double ul = screen(map_rect.ul);
+ Point2D.Double lr = screen(map_rect.lr);
+
+ return new Rectangle((int) ul.x, (int) ul.y, (int) (lr.x - ul.x), (int) (lr.y - ul.y));
+ }
+
+ public Point2D.Double screen(AltosUILatLon lat_lon) {
+ return screen(point(lat_lon));
+ }
+
+ private boolean has_location;
+
+ public boolean has_location() {
+ return has_location;
+ }
+
+ public AltosUIMapTransform(int width, int height, int zoom, AltosUILatLon centre_lat_lon) {
+ scale_x = 256/360.0 * Math.pow(2, zoom);
+ scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom);
+
+ Point2D.Double centre_pt = point(centre_lat_lon);
+
+ has_location = (centre_lat_lon.lat != 0 || centre_lat_lon.lon != 0);
+ offset_x = centre_pt.x - width / 2.0;
+ offset_y = centre_pt.y - height / 2.0;
+ }
+}
diff --git a/altosuilib/AltosUIMapView.java b/altosuilib/AltosUIMapView.java
new file mode 100644
index 00000000..a14fde65
--- /dev/null
+++ b/altosuilib/AltosUIMapView.java
@@ -0,0 +1,472 @@
+/*
+ * 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_2;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.image.*;
+import javax.swing.*;
+import java.io.*;
+import java.lang.*;
+import java.awt.geom.*;
+import java.util.*;
+import java.util.concurrent.*;
+import org.altusmetrum.altoslib_4.*;
+
+public class AltosUIMapView extends Component implements MouseMotionListener, MouseListener, MouseWheelListener, ComponentListener, AltosUIMapTileListener, AltosUIMapStoreListener {
+
+ AltosUIMapPath path = new AltosUIMapPath();
+
+ AltosUIMapLine line = new AltosUIMapLine();
+
+ AltosUIMapCache cache = new AltosUIMapCache();
+
+ LinkedList<AltosUIMapMark> marks = new LinkedList<AltosUIMapMark>();
+
+ LinkedList<AltosUIMapZoomListener> zoom_listeners = new LinkedList<AltosUIMapZoomListener>();
+
+ boolean have_boost = false;
+ boolean have_landed = false;
+
+ ConcurrentHashMap<Point,AltosUIMapTile> tiles = new ConcurrentHashMap<Point,AltosUIMapTile>();
+
+ static final int default_zoom = 15;
+ static final int min_zoom = 3;
+ static final int max_zoom = 21;
+ static final int px_size = 512;
+
+ int load_radius;
+ AltosUILatLon load_centre = null;
+ AltosUIMapTileListener load_listener;
+
+ int zoom = default_zoom;
+ int maptype = AltosUIMap.maptype_default;
+
+ long user_input_time;
+
+ /* Milliseconds to wait after user action before auto-scrolling
+ */
+ static final long auto_scroll_delay = 20 * 1000;
+
+ AltosUIMapTransform transform;
+ AltosUILatLon centre;
+
+ public void set_font() {
+ line.set_font(AltosUILib.value_font);
+ for (AltosUIMapTile tile : tiles.values())
+ tile.set_font(AltosUILib.value_font);
+ repaint();
+ }
+
+ public void set_units() {
+ repaint();
+ }
+
+ private boolean is_drag_event(MouseEvent e) {
+ return e.getModifiers() == InputEvent.BUTTON1_MASK;
+ }
+
+ Point drag_start;
+
+ private void drag(MouseEvent e) {
+ if (drag_start == null)
+ return;
+
+ int dx = e.getPoint().x - drag_start.x;
+ int dy = e.getPoint().y - drag_start.y;
+
+ AltosUILatLon new_centre = transform.screen_lat_lon(new Point(getWidth() / 2 - dx, getHeight() / 2 - dy));
+ centre (new_centre.lat, new_centre.lon);
+ drag_start = e.getPoint();
+ }
+
+ private void drag_start(MouseEvent e) {
+ drag_start = e.getPoint();
+ }
+
+ private void notice_user_input() {
+ user_input_time = System.currentTimeMillis();
+ }
+
+ private boolean recent_user_input() {
+ return (System.currentTimeMillis() - user_input_time) < auto_scroll_delay;
+ }
+
+ /* MouseMotionListener methods */
+
+ public void mouseDragged(MouseEvent e) {
+ notice_user_input();
+ if (is_drag_event(e))
+ drag(e);
+ else {
+ line.dragged(e, transform);
+ repaint();
+ }
+ }
+
+ public void mouseMoved(MouseEvent e) {
+ }
+
+ /* MouseListener methods */
+ public void mouseClicked(MouseEvent e) {
+ }
+
+ public void mouseEntered(MouseEvent e) {
+ }
+
+ public void mouseExited(MouseEvent e) {
+ }
+
+ public void mousePressed(MouseEvent e) {
+ notice_user_input();
+ if (is_drag_event(e))
+ drag_start(e);
+ else {
+ line.pressed(e, transform);
+ repaint();
+ }
+ }
+
+ public void mouseReleased(MouseEvent e) {
+ }
+
+ /* MouseWheelListener methods */
+
+ public void mouseWheelMoved(MouseWheelEvent e) {
+ int zoom_change = e.getWheelRotation();
+
+ notice_user_input();
+ AltosUILatLon mouse_lat_lon = transform.screen_lat_lon(e.getPoint());
+ set_zoom(zoom() - zoom_change);
+
+ Point2D.Double new_mouse = transform.screen(mouse_lat_lon);
+
+ int dx = getWidth()/2 - e.getPoint().x;
+ int dy = getHeight()/2 - e.getPoint().y;
+
+ AltosUILatLon new_centre = transform.screen_lat_lon(new Point((int) new_mouse.x + dx, (int) new_mouse.y + dy));
+
+ centre(new_centre.lat, new_centre.lon);
+ }
+
+ /* ComponentListener methods */
+
+ public void componentHidden(ComponentEvent e) {
+ }
+
+ public void componentMoved(ComponentEvent e) {
+ }
+
+ public void componentResized(ComponentEvent e) {
+ set_transform();
+ }
+
+ public void componentShown(ComponentEvent e) {
+ set_transform();
+ }
+
+ public void repaint(Rectangle r, int pad) {
+ repaint(r.x - pad, r.y - pad, r.width + pad*2, r.height + pad*2);
+ }
+
+ public void repaint(AltosUIMapRectangle rect, int pad) {
+ repaint (transform.screen(rect), pad);
+ }
+
+ private boolean far_from_centre(AltosUILatLon lat_lon) {
+
+ if (centre == null || transform == null)
+ return true;
+
+ Point2D.Double screen = transform.screen(lat_lon);
+
+ int width = getWidth();
+ int dx = Math.abs ((int) screen.x - width/2);
+
+ if (dx > width / 4)
+ return true;
+
+ int height = getHeight();
+ int dy = Math.abs ((int) screen.y - height/2);
+
+ if (dy > height / 4)
+ return true;
+
+ return false;
+ }
+
+ public void show(AltosState state, AltosListenerState listener_state) {
+
+ /* If insufficient gps data, nothing to update
+ */
+ AltosGPS gps = state.gps;
+
+ if (gps == null)
+ return;
+
+ if (!gps.locked && gps.nsat < 4)
+ return;
+
+ AltosUIMapRectangle damage = path.add(gps.lat, gps.lon, state.state);
+
+ switch (state.state) {
+ case AltosLib.ao_flight_boost:
+ if (!have_boost) {
+ add_mark(gps.lat, gps.lon, state.state);
+ have_boost = true;
+ }
+ break;
+ case AltosLib.ao_flight_landed:
+ if (!have_landed) {
+ add_mark(gps.lat, gps.lon, state.state);
+ have_landed = true;
+ }
+ break;
+ }
+
+ if (damage != null)
+ repaint(damage, AltosUIMapPath.stroke_width);
+ maybe_centre(gps.lat, gps.lon);
+ }
+
+ private void set_transform() {
+ Rectangle bounds = getBounds();
+
+ transform = new AltosUIMapTransform(bounds.width, bounds.height, zoom, centre);
+ repaint();
+ }
+
+ public boolean set_zoom(int zoom) {
+ if (min_zoom <= zoom && zoom <= max_zoom && zoom != this.zoom) {
+ this.zoom = zoom;
+ tiles.clear();
+ set_transform();
+
+ for (AltosUIMapZoomListener listener : zoom_listeners)
+ listener.zoom_changed(this.zoom);
+
+ return true;
+ }
+ return false;
+ }
+
+ public void add_zoom_listener(AltosUIMapZoomListener listener) {
+ if (!zoom_listeners.contains(listener))
+ zoom_listeners.add(listener);
+ }
+
+ public void remove_zoom_listener(AltosUIMapZoomListener listener) {
+ zoom_listeners.remove(listener);
+ }
+
+ public void set_load_params(double lat, double lon, int radius, AltosUIMapTileListener listener) {
+ load_centre = new AltosUILatLon(lat, lon);
+ load_radius = radius;
+ load_listener = listener;
+ centre(lat, lon);
+ make_tiles();
+ for (AltosUIMapTile tile : tiles.values()) {
+ tile.add_store_listener(this);
+ if (tile.store_status() != AltosUIMapStore.loading)
+ listener.notify_tile(tile, tile.store_status());
+ }
+ repaint();
+ }
+
+ public boolean all_fetched() {
+ for (AltosUIMapTile tile : tiles.values()) {
+ if (tile.store_status() == AltosUIMapStore.loading)
+ return false;
+ }
+ return true;
+ }
+
+ public boolean set_maptype(int maptype) {
+ if (maptype != this.maptype) {
+ this.maptype = maptype;
+ tiles.clear();
+ repaint();
+ return true;
+ }
+ return false;
+ }
+
+ public int get_maptype() {
+ return maptype;
+ }
+
+ public int zoom() {
+ return zoom;
+ }
+
+ public void centre(AltosUILatLon lat_lon) {
+ centre = lat_lon;
+ set_transform();
+ }
+
+ public void centre(double lat, double lon) {
+ centre(new AltosUILatLon(lat, lon));
+ }
+
+ public void maybe_centre(double lat, double lon) {
+ AltosUILatLon lat_lon = new AltosUILatLon(lat, lon);
+ if (centre == null || (!recent_user_input() && far_from_centre(lat_lon)))
+ centre(lat_lon);
+ }
+
+ private VolatileImage create_back_buffer() {
+ return getGraphicsConfiguration().createCompatibleVolatileImage(getWidth(), getHeight());
+ }
+
+ private Point floor(Point2D.Double point) {
+ return new Point ((int) Math.floor(point.x / px_size) * px_size,
+ (int) Math.floor(point.y / px_size) * px_size);
+ }
+
+ private Point ceil(Point2D.Double point) {
+ return new Point ((int) Math.ceil(point.x / px_size) * px_size,
+ (int) Math.ceil(point.y / px_size) * px_size);
+ }
+
+ private void make_tiles() {
+ Point upper_left;
+ Point lower_right;
+
+ if (load_centre != null) {
+ Point centre = floor(transform.point(load_centre));
+
+ upper_left = new Point(centre.x - load_radius * px_size,
+ centre.y - load_radius * px_size);
+ lower_right = new Point(centre.x + load_radius * px_size,
+ centre.y + load_radius * px_size);
+ } else {
+ upper_left = floor(transform.screen_point(new Point(0, 0)));
+ lower_right = floor(transform.screen_point(new Point(getWidth(), getHeight())));
+ }
+ LinkedList<Point> to_remove = new LinkedList<Point>();
+
+ for (Point point : tiles.keySet()) {
+ if (point.x < upper_left.x || lower_right.x < point.x ||
+ point.y < upper_left.y || lower_right.y < point.y) {
+ to_remove.add(point);
+ }
+ }
+
+ 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));
+ 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);
+
+ if (!tiles.containsKey(point)) {
+ AltosUILatLon ul = transform.lat_lon(new Point2D.Double(x, y));
+ AltosUILatLon center = transform.lat_lon(new Point2D.Double(x + px_size/2, y + px_size/2));
+ AltosUIMapTile tile = new AltosUIMapTile(this, ul, center, zoom, maptype,
+ px_size, AltosUILib.value_font);
+ tiles.put(point, tile);
+ }
+ }
+ }
+ }
+
+ /* AltosUIMapTileListener methods */
+ public synchronized void notify_tile(AltosUIMapTile tile, int status) {
+ for (Point point : tiles.keySet()) {
+ if (tile == tiles.get(point)) {
+ Point screen = transform.screen(point);
+ repaint(screen.x, screen.y, px_size, px_size);
+ }
+ }
+ }
+
+ public AltosUIMapCache cache() { return cache; }
+
+ /* AltosUIMapStoreListener methods */
+ public synchronized void notify_store(AltosUIMapStore store, int status) {
+ if (load_listener != null) {
+ for (AltosUIMapTile tile : tiles.values())
+ if (store.equals(tile.store))
+ load_listener.notify_tile(tile, status);
+ }
+ }
+
+ private void do_paint(Graphics g) {
+ Graphics2D g2d = (Graphics2D) g;
+
+ make_tiles();
+
+ for (AltosUIMapTile tile : tiles.values())
+ tile.paint(g2d, transform);
+
+ synchronized(marks) {
+ for (AltosUIMapMark mark : marks)
+ mark.paint(g2d, transform);
+ }
+
+ path.paint(g2d, transform);
+
+ line.paint(g2d, transform);
+ }
+
+ public void paint(Graphics g) {
+ VolatileImage back_buffer = create_back_buffer();
+ do {
+ GraphicsConfiguration gc = getGraphicsConfiguration();
+ int code = back_buffer.validate(gc);
+ if (code == VolatileImage.IMAGE_INCOMPATIBLE)
+ back_buffer = create_back_buffer();
+
+ Graphics g_back = back_buffer.getGraphics();
+ g_back.setClip(g.getClip());
+ do_paint(g_back);
+ g_back.dispose();
+
+ g.drawImage(back_buffer, 0, 0, this);
+ } while (back_buffer.contentsLost());
+ back_buffer.flush();
+ }
+
+ public void update(Graphics g) {
+ paint(g);
+ }
+
+ public void add_mark(double lat, double lon, int state) {
+ synchronized(marks) {
+ marks.add(new AltosUIMapMark(lat, lon, state));
+ }
+ repaint();
+ }
+
+ public void clear_marks() {
+ synchronized(marks) {
+ marks.clear();
+ }
+ }
+
+ public AltosUIMapView() {
+ centre(0, 0);
+
+ addComponentListener(this);
+ addMouseMotionListener(this);
+ addMouseListener(this);
+ addMouseWheelListener(this);
+ set_font();
+ }
+}
diff --git a/altosuilib/AltosUIMapZoomListener.java b/altosuilib/AltosUIMapZoomListener.java
new file mode 100644
index 00000000..02e8bb51
--- /dev/null
+++ b/altosuilib/AltosUIMapZoomListener.java
@@ -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_2;
+
+public interface AltosUIMapZoomListener {
+ abstract public void zoom_changed(int zoom);
+}
diff --git a/altosuilib/AltosUIMarker.java b/altosuilib/AltosUIMarker.java
index ae8eb034..cd6fa589 100644
--- a/altosuilib/AltosUIMarker.java
+++ b/altosuilib/AltosUIMarker.java
@@ -15,14 +15,14 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_1;
+package org.altusmetrum.altosuilib_2;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
@@ -41,7 +41,7 @@ public class AltosUIMarker implements AltosUIGrapher {
boolean enabled;
int fetch;
Color color;
-
+
private void remove_markers() {
for (ValueMarker marker : markers)
plot.removeDomainMarker(marker);
diff --git a/altosuilib/AltosUIPreferences.java b/altosuilib/AltosUIPreferences.java
index 4c995f80..7a582a7d 100644
--- a/altosuilib/AltosUIPreferences.java
+++ b/altosuilib/AltosUIPreferences.java
@@ -15,13 +15,13 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_1;
+package org.altusmetrum.altosuilib_2;
import java.io.*;
import java.util.*;
import java.awt.Component;
import javax.swing.*;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
public class AltosUIPreferences extends AltosPreferences {
diff --git a/altosuilib/AltosUIPreferencesBackend.java b/altosuilib/AltosUIPreferencesBackend.java
index 64d3e3df..da29253d 100644
--- a/altosuilib/AltosUIPreferencesBackend.java
+++ b/altosuilib/AltosUIPreferencesBackend.java
@@ -15,17 +15,17 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_1;
+package org.altusmetrum.altosuilib_2;
import java.io.File;
import java.util.prefs.*;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
import javax.swing.filechooser.FileSystemView;
public class AltosUIPreferencesBackend implements AltosPreferencesBackend {
private Preferences _preferences = null;
-
+
public AltosUIPreferencesBackend() {
_preferences = Preferences.userRoot().node("/org/altusmetrum/altosui");
}
diff --git a/altosuilib/AltosUISeries.java b/altosuilib/AltosUISeries.java
index 1f2a1c3f..b0632d18 100644
--- a/altosuilib/AltosUISeries.java
+++ b/altosuilib/AltosUISeries.java
@@ -15,14 +15,14 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_1;
+package org.altusmetrum.altosuilib_2;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_3.*;
+import org.altusmetrum.altoslib_4.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
@@ -38,7 +38,7 @@ class AltosUITime extends AltosUnits {
public double value(double v, boolean imperial_units) { return v; }
public double inverse(double v, boolean imperial_unis) { return v; }
-
+
public String show_units(boolean imperial_units) { return "s"; }
public String say_units(boolean imperial_units) { return "seconds"; }
@@ -60,7 +60,7 @@ public class AltosUISeries extends XYSeries implements AltosUIGrapher {
XYItemRenderer renderer;
int fetch;
boolean enable;
-
+
public void set_units() {
axis.set_units();
StandardXYToolTipGenerator ttg;
@@ -104,6 +104,7 @@ public class AltosUISeries extends XYSeries implements AltosUIGrapher {
renderer = new XYLineAndShapeRenderer(true, false);
renderer.setSeriesPaint(0, color);
+ renderer.setSeriesStroke(0, new BasicStroke(2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
renderer.setSeriesVisible(0, enable);
set_units();
}
diff --git a/altosuilib/AltosUIUnitsIndicator.java b/altosuilib/AltosUIUnitsIndicator.java
new file mode 100644
index 00000000..2285b6fc
--- /dev/null
+++ b/altosuilib/AltosUIUnitsIndicator.java
@@ -0,0 +1,122 @@
+/*
+ * 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_2;
+
+import java.awt.*;
+import javax.swing.*;
+import org.altusmetrum.altoslib_4.*;
+
+public abstract class AltosUIUnitsIndicator extends AltosUIIndicator {
+
+ AltosUnits units;
+
+ abstract public double value(AltosState state, int i);
+ public double good() { return 0; }
+ public boolean good(double value) { return value != AltosLib.MISSING && value >= good(); }
+ public boolean hide(double value) { return false; }
+
+ public boolean hide(AltosState state, int i) {
+ if (state == null)
+ return hide(AltosLib.MISSING);
+ return hide(value(state, i));
+ }
+
+ public double value (AltosState state, AltosListenerState listener_state, int i) {
+ return value(state, i);
+ }
+
+ public double[] last_values;
+
+ public void show(double... v) {
+ show();
+ for (int i = 0; i < values.length; i++) {
+ if (v[i] != last_values[i]) {
+ String value_text;
+ boolean good = false;
+
+ if (v[i] == AltosLib.MISSING) {
+ value_text = "Missing";
+ } else {
+ value_text = units.show(8, v[i]);
+ if (i == 0)
+ good = good(v[i]);
+ }
+ last_values[i] = v[i];
+ if (i == 0 && lights != null)
+ set_lights(good);
+ values[i].setText(value_text);
+ }
+ }
+ }
+
+ public void units_changed(boolean imperial_units) {
+ show(last_values);
+ }
+
+ public void show (AltosState state, AltosListenerState listener_state) {
+ double[] v = new double[values.length];
+ boolean hide = false;
+
+ for (int i = 0; i < values.length; i++) {
+ if (state != null)
+ v[i] = value(state, listener_state, i);
+ else
+ v[i] = AltosLib.MISSING;
+ if (hide(state, i))
+ hide = true;
+ }
+
+ if (hide)
+ hide();
+ else
+ show(v);
+ }
+
+ public void reset() {
+ for (int i = 0; i < last_values.length; i++)
+ last_values[i] = AltosLib.MISSING - 1;
+ }
+
+ public AltosUIUnitsIndicator (Container container, int x, int y, int label_width, AltosUnits units, String name, int number_values, boolean has_lights, int width) {
+ super(container, x, y, label_width, name, number_values, has_lights, width);
+ this.units = units;
+ last_values = new double[values.length];
+ for (int i = 0; i < last_values.length; i++)
+ last_values[i] = AltosLib.MISSING - 1;
+ }
+
+ public AltosUIUnitsIndicator (Container container, int x, int y, AltosUnits units, String name, int number_values, boolean has_lights, int width) {
+ this(container, x, y, 1, units, name, number_values, has_lights, width);
+ }
+
+ public AltosUIUnitsIndicator (Container container, int y, AltosUnits units, String name, int number_values, boolean has_lights, int width) {
+ this(container, 0, y, units, name, number_values, has_lights, width);
+ }
+
+ public AltosUIUnitsIndicator (Container container, int y, AltosUnits units, String name, int width) {
+ this(container, 0, y, units, name, 1, false, width);
+ }
+
+ public AltosUIUnitsIndicator (Container container, int y, AltosUnits units, String name) {
+ this(container, 0, y, units, name, 1, false, 1);
+ }
+
+ public AltosUIUnitsIndicator (Container container, int x,int y, AltosUnits units, String name) {
+ this(container, x, y, units, name, 1, false, 1);
+ }
+}
diff --git a/altosuilib/AltosUIVersion.java.in b/altosuilib/AltosUIVersion.java.in
index 169cca1b..0edb5c04 100644
--- a/altosuilib/AltosUIVersion.java.in
+++ b/altosuilib/AltosUIVersion.java.in
@@ -15,8 +15,14 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_1;
+package org.altusmetrum.altosuilib_2;
public class AltosUIVersion {
public final static String version = "@VERSION@";
+
+ public final static String google_maps_api_key = @GOOGLEKEY@;
+
+ static boolean has_google_maps_api_key() {
+ return google_maps_api_key != null && google_maps_api_key.length() > 1;
+ }
}
diff --git a/altosuilib/AltosUIVoltageIndicator.java b/altosuilib/AltosUIVoltageIndicator.java
new file mode 100644
index 00000000..3ff17213
--- /dev/null
+++ b/altosuilib/AltosUIVoltageIndicator.java
@@ -0,0 +1,42 @@
+/*
+ * 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_2;
+
+import java.awt.*;
+import javax.swing.*;
+import org.altusmetrum.altoslib_4.*;
+
+public abstract class AltosUIVoltageIndicator extends AltosUIUnitsIndicator {
+
+ abstract public double voltage(AltosState state);
+ abstract public double good();
+
+ public double value(AltosState state, int i) {
+ return voltage(state);
+ }
+
+ double last_voltage = -1;
+
+ public AltosUIVoltageIndicator (Container container, int x, int y, String name, int width) {
+ super(container, x, y, AltosConvert.voltage, name, 1, true, width);
+ }
+
+ public AltosUIVoltageIndicator (Container container, int y, String name, int width) {
+ this(container, 0, y, name, width);
+ }
+}
diff --git a/altosuilib/AltosUSBDevice.java b/altosuilib/AltosUSBDevice.java
index 4f329840..b70b5e83 100644
--- a/altosuilib/AltosUSBDevice.java
+++ b/altosuilib/AltosUSBDevice.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_1;
+package org.altusmetrum.altosuilib_2;
import java.util.*;
import libaltosJNI.*;
diff --git a/altosui/AltosVoice.java b/altosuilib/AltosVoice.java
index 2ed6a8c2..a3995f68 100644
--- a/altosui/AltosVoice.java
+++ b/altosuilib/AltosVoice.java
@@ -15,12 +15,11 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altosuilib_2;
import com.sun.speech.freetts.Voice;
import com.sun.speech.freetts.VoiceManager;
import java.util.concurrent.LinkedBlockingQueue;
-import org.altusmetrum.altosuilib_1.*;
public class AltosVoice implements Runnable {
VoiceManager voice_manager;
diff --git a/altosui/GrabNDrag.java b/altosuilib/GrabNDrag.java
index 2fd6c4da..4426f7a3 100644
--- a/altosui/GrabNDrag.java
+++ b/altosuilib/GrabNDrag.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.altosuilib_2;
import java.awt.*;
import java.awt.event.*;
@@ -33,16 +33,23 @@ class GrabNDrag extends MouseInputAdapter {
scroll.setAutoscrolls(true);
}
+ public static boolean grab_n_drag(MouseEvent e) {
+ return e.getModifiers() == InputEvent.BUTTON1_MASK;
+ }
+
public void mousePressed(MouseEvent e) {
- startPt.setLocation(e.getPoint());
+ if (grab_n_drag(e))
+ startPt.setLocation(e.getPoint());
}
public void mouseDragged(MouseEvent e) {
- int xd = e.getX() - startPt.x;
- int yd = e.getY() - startPt.y;
+ if (grab_n_drag(e)) {
+ int xd = e.getX() - startPt.x;
+ int yd = e.getY() - startPt.y;
- Rectangle r = scroll.getVisibleRect();
- r.x -= xd;
- r.y -= yd;
- scroll.scrollRectToVisible(r);
+ Rectangle r = scroll.getVisibleRect();
+ r.x -= xd;
+ r.y -= yd;
+ scroll.scrollRectToVisible(r);
+ }
}
}
diff --git a/altosuilib/Makefile.am b/altosuilib/Makefile.am
index 4b22af1f..e08fbe74 100644
--- a/altosuilib/Makefile.am
+++ b/altosuilib/Makefile.am
@@ -1,4 +1,4 @@
-AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -source 6
+AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked -source 6
JAVAROOT=bin
@@ -9,8 +9,10 @@ SRC=.
altosuilibdir = $(datadir)/java
altosuilib_JAVA = \
+ GrabNDrag.java \
AltosDevice.java \
AltosDeviceDialog.java \
+ AltosFlightDisplay.java \
AltosFontListener.java \
AltosPositionListener.java \
AltosUIConfigure.java \
@@ -30,10 +32,70 @@ altosuilib_JAVA = \
AltosUIPreferences.java \
AltosUISeries.java \
AltosUIVersion.java \
- AltosUSBDevice.java
+ AltosUSBDevice.java \
+ AltosVoice.java \
+ AltosDisplayThread.java \
+ AltosDeviceUIDialog.java \
+ AltosFreqList.java \
+ AltosSerial.java \
+ AltosSerialInUseException.java \
+ AltosConfigFreqUI.java \
+ AltosScanUI.java \
+ AltosEepromDelete.java \
+ AltosEepromManage.java \
+ AltosEepromMonitorUI.java \
+ AltosEepromSelect.java \
+ AltosCSVUI.java \
+ AltosDataChooser.java \
+ AltosLights.java \
+ AltosLed.java \
+ AltosFlashUI.java \
+ AltosRomconfigUI.java \
+ AltosInfoTable.java \
+ AltosFlightInfoTableModel.java \
+ AltosFlightStatsTable.java \
+ AltosGraph.java \
+ AltosGraphDataPoint.java \
+ AltosGraphDataSet.java \
+ AltosBTDevice.java \
+ AltosBTDeviceIterator.java \
+ AltosBTManage.java \
+ AltosBTKnown.java \
+ AltosUIMap.java \
+ AltosUIMapView.java \
+ AltosUIMapLine.java \
+ AltosUIMapMark.java \
+ AltosUIMapPath.java \
+ AltosUIMapTile.java \
+ AltosUIMapCache.java \
+ AltosUIMapImage.java \
+ AltosUIMapTransform.java \
+ AltosUIMapRectangle.java \
+ AltosUIMapZoomListener.java \
+ AltosUIMapTileListener.java \
+ AltosUIMapPreload.java \
+ AltosUIMapStore.java \
+ AltosUIMapStoreListener.java \
+ AltosUILatLon.java \
+ AltosUIFlightTab.java \
+ AltosUIIndicator.java \
+ AltosUIUnitsIndicator.java \
+ AltosUIVoltageIndicator.java
JAR=altosuilib_$(ALTOSUILIB_VERSION).jar
+# Icons
+ICONDIR=$(top_srcdir)/icon
+
+ICONS= $(ICONDIR)/redled.png $(ICONDIR)/redoff.png \
+ $(ICONDIR)/greenled.png $(ICONDIR)/greenoff.png \
+ $(ICONDIR)/grayon.png $(ICONDIR)/grayled.png
+
+# icon base names for jar
+ICONJAR= -C $(ICONDIR) redled.png -C $(ICONDIR) redoff.png \
+ -C $(ICONDIR) greenled.png -C $(ICONDIR) greenoff.png \
+ -C $(ICONDIR) grayon.png -C $(ICONDIR) grayled.png
+
all-local: $(JAR)
clean-local:
@@ -48,5 +110,5 @@ install-altosuilibJAVA: $(JAR)
$(JAVAROOT):
mkdir -p $(JAVAROOT)
-$(JAR): classaltosuilib.stamp
- jar cf $@ -C $(JAVAROOT) .
+$(JAR): classaltosuilib.stamp $(ICONS)
+ jar cf $@ $(ICONJAR) -C $(JAVAROOT) .
diff --git a/altusmetrum.cat b/altusmetrum.cat
new file mode 100644
index 00000000..2d7e8b26
--- /dev/null
+++ b/altusmetrum.cat
Binary files differ
diff --git a/telemetrum.inf b/altusmetrum.inf
index 220069b3..45905cc8 100755
--- a/telemetrum.inf
+++ b/altusmetrum.inf
@@ -6,9 +6,10 @@ Signature = "$Windows NT$"
Class = Modem
ClassGUID = {4D36E96D-E325-11CE-BFC1-08002BE10318}
Provider = %Mfg%
-DriverVer = 08/05/2010,7.1.1.0
+DriverVer = 06/15/2014,7.1.1.0
PnpLockDown = 0
DriverPackageDisplayName = %DriverName%
+CatalogFile = altusmetrum.cat
[DestinationDirs]
FakeModemCopyFileSection = 12
diff --git a/ao-bringup/cal-freq b/ao-bringup/cal-freq
index dc2f2212..68a8ebf2 100755
--- a/ao-bringup/cal-freq
+++ b/ao-bringup/cal-freq
@@ -21,6 +21,7 @@ while true; do
case "$FREQ" in
"")
+ echo $SERIAL","$CAL_VALUE >> cal_values
exit 0
;;
*)
@@ -44,3 +45,4 @@ EOF
;;
esac
done
+
diff --git a/ao-bringup/test-baro b/ao-bringup/test-baro
new file mode 100755
index 00000000..ce5b7f80
--- /dev/null
+++ b/ao-bringup/test-baro
@@ -0,0 +1,99 @@
+#!/usr/bin/nickle
+
+import File;
+
+string timed_read(file f, int timeout) {
+ thread reader = fork func() {
+ try {
+ return fgets(f);
+ } catch Thread::signal(int i) {
+ return "";
+ }
+ }();
+
+ thread killer = fork func() {
+ try {
+ sleep (timeout);
+ Thread::send_signal(reader, 1);
+ } catch Thread::signal(int i) {
+ return;
+ }
+ }();
+
+ poly v = Thread::join(reader);
+ Thread::send_signal(killer, 1);
+ Thread::join(killer);
+ if (is_string(v))
+ return v;
+ return "";
+}
+
+void flush_input(file f) {
+ for (;;) {
+ string s = timed_read(f, 200);
+ if (s == "")
+ break;
+ }
+}
+
+string[*] baro(file f) {
+ string[...] x = {};
+
+ flush_input(f);
+ fprintf (f, "B\n");
+ flush(f);
+ for (;;) {
+ string l = timed_read(f, 1000);
+ if (l == "") {
+ File::fprintf(stderr, "read timedout\n");
+ exit(1);
+ }
+ x[dim(x)] = l;
+ if (String::index(l, "Altitude:") == 0)
+ break;
+ }
+ return x;
+}
+
+string[*] find_baro(string[*] s, string match) {
+ for (int i = 0; i < dim(s); i++)
+ if (String::index(s[i], match) >= 0)
+ return String::wordsplit(s[i], " ");
+ return (string[*]) {};
+}
+
+bool
+do_baro(file f) {
+ string[*] i = baro(f);
+ string[*] temp = find_baro(i, "Temperature");
+ string[*] alt = find_baro(i, "Altitude");
+
+ real temperature = string_to_integer(temp[2]) / 100.0;
+ real altitude = string_to_integer(alt[1]);
+
+ if (altitude < -50 || 3000 < altitude) {
+ printf ("weird altitude %f\n", altitude);
+ return false;
+ }
+
+ if (temperature < 20 || 30 < temperature) {
+ printf ("weird temperature %f\n", temperature);
+ return false;
+ }
+
+ printf ("altitude %f temperature %f\n", altitude, temperature);
+
+ return true;
+}
+
+void main () {
+ string name = argv[1];
+ file f = open(name, "r+");
+ bool ret = true;
+
+ if (!do_baro(f))
+ ret = false;
+ exit (ret? 0 : 1);
+}
+
+main();
diff --git a/ao-bringup/test-easymini b/ao-bringup/test-easymini
new file mode 100755
index 00000000..29139385
--- /dev/null
+++ b/ao-bringup/test-easymini
@@ -0,0 +1,63 @@
+#!/bin/sh
+
+VERSION=1.0
+PRODUCT=EasyMini
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+
+echo "$PRODUCT-v$VERSION Test Program"
+echo "Copyright 2014 by Keith Packard. Released under GPL v2"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo
+
+ret=1
+ao-list | while read product serial dev; do
+ case "$product" in
+ "$PRODUCT-v$VERSION")
+
+ echo "Testing $product $serial $dev"
+
+ echo "Testing igniters. Both should flash"
+ ./test-igniter "$dev" drogue main
+
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "failed"
+ exit 1
+ esac
+
+ echo "Testing baro sensor"
+ ./test-baro "$dev"
+
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "failed"
+ exit 1
+ esac
+
+ FLASHSIZE=1048576
+
+ echo "Testing flash"
+ ./test-flash "$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
diff --git a/ao-bringup/test-flash b/ao-bringup/test-flash
new file mode 100755
index 00000000..d79de320
--- /dev/null
+++ b/ao-bringup/test-flash
@@ -0,0 +1,101 @@
+#!/usr/bin/nickle
+
+import File;
+
+string timed_read(file f, int timeout) {
+ thread reader = fork func() {
+ try {
+ return fgets(f);
+ } catch Thread::signal(int i) {
+ return "";
+ }
+ }();
+
+ thread killer = fork func() {
+ try {
+ sleep (timeout);
+ Thread::send_signal(reader, 1);
+ } catch Thread::signal(int i) {
+ return;
+ }
+ }();
+
+ poly v = Thread::join(reader);
+ Thread::send_signal(killer, 1);
+ Thread::join(killer);
+ if (is_string(v))
+ return v;
+ return "";
+}
+
+void flush_input(file f) {
+ for (;;) {
+ string s = timed_read(f, 200);
+ if (s == "")
+ break;
+ }
+}
+
+string[*] flash(file f) {
+ string[...] x = {};
+
+ flush_input(f);
+ fprintf (f, "f\nv\n");
+ flush(f);
+ for (;;) {
+ string l = timed_read(f, 1000);
+ if (l == "") {
+ File::fprintf(stderr, "Read timedout\n");
+ exit(1);
+ }
+ x[dim(x)] = l;
+ if (String::index(l, "software-version") == 0)
+ break;
+ }
+ return x;
+}
+
+string[*] find_flash(string[*] s, string match) {
+ for (int i = 0; i < dim(s); i++)
+ if (String::index(s[i], match) >= 0)
+ return String::wordsplit(s[i], " ");
+ return (string[*]) {};
+}
+
+bool
+do_flash(file f, int expected_size) {
+ string[*] i = flash(f);
+ string[*] size = find_flash(i, "Storage size:");
+ string[*] erase = find_flash(i, "Storage erase unit:");
+
+ int actual_size = string_to_integer(size[2]);
+
+ if (actual_size != expected_size) {
+ printf ("weird flash size %d != %d\n", actual_size, expected_size);
+ return false;
+ }
+
+ int actual_erase = string_to_integer(erase[3]);
+
+ if (actual_erase != 65536) {
+ printf ("weird erase size %d\n", actual_erase);
+ return false;
+ }
+
+ printf ("flash size %d erase block %d\n", actual_size, actual_erase);
+
+ return true;
+}
+
+void main () {
+ string name = argv[1];
+ string size = argv[2];
+ file f = open(name, "r+");
+ bool ret = true;
+
+ if (!do_flash(f, string_to_integer(size)))
+ ret = false;
+ exit (ret? 0 : 1);
+}
+
+main();
diff --git a/ao-bringup/test-gps b/ao-bringup/test-gps
new file mode 100755
index 00000000..a1e21626
--- /dev/null
+++ b/ao-bringup/test-gps
@@ -0,0 +1,102 @@
+#!/usr/bin/nickle
+
+import File;
+
+string timed_read(file f, int timeout) {
+ thread reader = fork func() {
+ try {
+ return fgets(f);
+ } catch Thread::signal(int i) {
+ return "";
+ }
+ }();
+
+ thread killer = fork func() {
+ try {
+ sleep (timeout);
+ Thread::send_signal(reader, 1);
+ } catch Thread::signal(int i) {
+ return;
+ }
+ }();
+
+ poly v = Thread::join(reader);
+ Thread::send_signal(killer, 1);
+ Thread::join(killer);
+ if (is_string(v))
+ return v;
+ return "";
+}
+
+void flush_input(file f) {
+ for (;;) {
+ string s = timed_read(f, 200);
+ if (s == "")
+ break;
+ }
+}
+
+string[*] gps(file f) {
+ string[...] x = {};
+
+ flush_input(f);
+ fprintf (f, "g\nv\n");
+ flush(f);
+ for (;;) {
+ string l = timed_read(f, 1000);
+ if (l == "") {
+ File::fprintf(stderr, "Read timedout\n");
+ exit(1);
+ }
+ x[dim(x)] = l;
+ if (String::index(l, "software-version") == 0)
+ break;
+ }
+ return x;
+}
+
+string[*] find_gps(string[*] s, string match) {
+ for (int i = 0; i < dim(s); i++)
+ if (String::index(s[i], match) >= 0)
+ return String::wordsplit(s[i], " ");
+ return (string[*]) {};
+}
+
+bool
+do_gps(file f) {
+
+ string[*] i = gps(f);
+ string[*] flags = find_gps(i, "Flags:");
+ string[*] sats = find_gps(i, "Sats:");
+
+ int actual_flags = string_to_integer(flags[1]);
+
+ while ((actual_flags & (1 << 4)) == 0) {
+ printf("Flags: %s\n", flags[1]);
+ printf("Sats: %s\n", sats[1]);
+
+ sleep(1000);
+ i = gps(f);
+ flags = find_gps(i, "Flags:");
+ sats = find_gps(i, "Sats:");
+
+ actual_flags = string_to_integer(flags[1]);
+ }
+
+ printf("Flags: %s\n", flags[1]);
+ printf("Sats: %s\n", sats[1]);
+ printf("GPS locked\n");
+ return true;
+}
+
+void main () {
+ string name = argv[1];
+ file f = open(name, "r+");
+ bool ret = true;
+
+ if (!do_gps(f))
+ ret = false;
+ exit (ret? 0 : 1);
+}
+
+main();
diff --git a/ao-bringup/test-igniter b/ao-bringup/test-igniter
new file mode 100755
index 00000000..454f6328
--- /dev/null
+++ b/ao-bringup/test-igniter
@@ -0,0 +1,136 @@
+#!/usr/bin/nickle
+
+import File;
+
+string timed_read(file f, int timeout) {
+ thread reader = fork func() {
+ try {
+ return fgets(f);
+ } catch Thread::signal(int i) {
+ return "";
+ }
+ }();
+
+ thread killer = fork func() {
+ try {
+ sleep (timeout);
+ Thread::send_signal(reader, 1);
+ } catch Thread::signal(int i) {
+ return;
+ }
+ }();
+
+ poly v = Thread::join(reader);
+ Thread::send_signal(killer, 1);
+ Thread::join(killer);
+ if (is_string(v))
+ return v;
+ return "";
+}
+
+void flush_input(file f) {
+ for (;;) {
+ string s = timed_read(f, 200);
+ if (s == "")
+ break;
+ }
+}
+
+string[*] settings(file f) {
+ string[...] x = {};
+
+ flush_input(f);
+ fprintf (f, "c s\nv\n");
+ flush(f);
+ for (;;) {
+ string l = File::fgets(f);
+ x[dim(x)] = l;
+ if (String::index(l, "software-version") == 0)
+ break;
+ }
+ return x;
+}
+
+string[*] find_setting(string[*] s, string match) {
+ for (int i = 0; i < dim(s); i++)
+ if (String::index(s[i], match) == 0)
+ return String::wordsplit(s[i], " ");
+ return (string[*]) {};
+}
+
+string[*] igniters(file f) {
+ string[...] x = {};
+
+ flush_input(f);
+ fprintf (f, "t\nv\n");
+ flush(f);
+ for (;;) {
+ string l = File::fgets(f);
+ x[dim(x)] = l;
+ if (String::index(l, "software-version") == 0)
+ break;
+ }
+ return x;
+}
+
+string[*] find_igniter(string[*] s, string match) {
+ for (int i = 0; i < dim(s); i++)
+ if (String::index(s[i], match) >= 0)
+ return String::wordsplit(s[i], " ");
+ return (string[*]) {};
+}
+
+bool
+do_igniter(file f, string igniter) {
+ string[*] i = igniters(f);
+ string[*] status = find_igniter(i, igniter);
+ if (dim(status) < 4) {
+ printf ("no igniter %s found in %v\n", igniter, i);
+ return false;
+ }
+ if (String::index(status[3], "ready") < 0) {
+ printf("igniter %s status is \"%s\"\n", igniter, status[3]);
+ return false;
+ }
+ fprintf(f, "i DoIt %s\n", igniter);
+ flush(f);
+ flush_input(f);
+ return true;
+}
+
+file
+open_tty(string name)
+{
+ int i = 0;
+ for (;;) {
+ try {
+ return open (name, "r+");
+ } catch open_error(string error, File::error_type error, string name) {
+ if (error == File::error_type.BUSY) {
+ if (i < 30) {
+ printf ("waiting for %s to be usable\n", name);
+ sleep(2000);
+ continue;
+ }
+ } else {
+ printf ("%s: %s\n", name, error);
+ exit(1);
+ }
+ }
+ }
+}
+
+void main () {
+ string name = argv[1];
+ string[dim(argv)-2] igniters = { [i] = argv[i+2] };
+ file f = open_tty(name);
+ bool ret = true;
+
+ for (int i = 0; i < dim(igniters); i++) {
+ if (!do_igniter(f, igniters[i]))
+ ret = false;
+ }
+ exit (ret? 0 : 1);
+}
+
+main();
diff --git a/ao-bringup/test-telegps b/ao-bringup/test-telegps
new file mode 100755
index 00000000..f3174485
--- /dev/null
+++ b/ao-bringup/test-telegps
@@ -0,0 +1,52 @@
+#!/bin/sh
+
+VERSION=1.0
+PRODUCT=TeleGPS
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+
+echo "$PRODUCT-v$VERSION Test Program"
+echo "Copyright 2014 by Bdale Garbee. Released under GPL v2"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo
+
+ret=1
+ao-list | while read product serial dev; do
+ case "$product" in
+ "$PRODUCT-v$VERSION")
+
+ echo "Testing $product $serial $dev"
+
+ FLASHSIZE=2097152
+
+ echo "Testing flash"
+ ./test-flash "$dev" "$FLASHSIZE"
+
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "failed"
+ exit 1
+ esac
+
+ echo "Testing GPS"
+ ./test-gps "$dev"
+
+ 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
diff --git a/ao-bringup/turnon_easymini b/ao-bringup/turnon_easymini
new file mode 100755
index 00000000..0b915c5e
--- /dev/null
+++ b/ao-bringup/turnon_easymini
@@ -0,0 +1,72 @@
+#!/bin/sh
+
+if [ -x ../ao-tools/ao-flash/ao-flash-lpc ]; then
+ FLASH_LPC=../ao-tools/ao-flash/ao-flash-lpc
+elif [ -x /usr/bin/ao-flash-lpc ]; then
+ FLASH_LPC=/usr/bin/ao-flash-lpc
+else
+ echo "Can't find ao-flash-lpc! Aborting."
+ exit 1
+fi
+
+if [ -x ../ao-tools/ao-usbload/ao-usbload ]; then
+ USBLOAD=../ao-tools/ao-usbload/ao-usbload
+elif [ -x /usr/bin/ao-usbload ]; then
+ USBLOAD=/usr/bin/ao-usbload
+else
+ echo "Can't find ao-usbload! Aborting."
+ exit 1
+fi
+
+VERSION=1.0
+PRODUCT=EasyMini
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+echo $FILE
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2010 by Bdale Garbee. Released under GPL v2"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo "\t\twith ST-Link-V2 cabled to debug header"
+echo
+
+case $# in
+ 1)
+ SERIAL="$1"
+ echo "$PRODUCT-$VERSION serial number: $SERIAL"
+ ;;
+ 0)
+ echo -n "$PRODUCT-$VERSION serial number: "
+ read SERIAL
+ ;;
+ *)
+ echo "Usage: $0 <serial-number>" 1>&2
+ exit 1;
+ ;;
+esac
+
+#
+# Use released versions of everything
+#
+FLASH_FILE=~/altusmetrumllc/Binaries/loaders/easymini-v1.0-altos-flash-*.elf
+ALTOS_FILE=~/altusmetrumllc/Binaries/easymini-v1.0-*.elf
+
+#FLASH_FILE=../src/$BASE-v$VERSION/flash-loader/$BASE-v$VERSION-altos-flash-*.elf
+#ALTOS_FILE=../src/$BASE-v$VERSION/*.ihx
+
+echo $FLASH_LPC $FLASH_FILE
+
+$FLASH_LPC $FLASH_FILE || exit 1
+
+sleep 1
+
+echo $USBLOAD $ALTOS_FILE
+
+$USBLOAD --serial=$SERIAL $ALTOS_FILE || exit 1
+
+sleep 2
+
+./test-easymini
+
+exit $?
diff --git a/ao-bringup/turnon_telebt b/ao-bringup/turnon_telebt
index ef20e915..c4902f31 100755
--- a/ao-bringup/turnon_telebt
+++ b/ao-bringup/turnon_telebt
@@ -45,7 +45,8 @@ read FREQ
CAL_VALUE=`nickle -e "floor(434.55 / $FREQ * 1186611 + 0.5)"`
echo "Programming flash with cal value " $CAL_VALUE
-$AOLOAD -D $DONGLE --cal $CAL_VALUE /usr/share/altos/stable/telebt-v1.0*.ihx $SERIAL
+$AOLOAD -D $DONGLE --cal $CAL_VALUE /usr/share/altos/telebt-v1.0*.ihx $SERIAL
echo "Serial number "$SERIAL" programmed with RF cal value "$CAL_VALUE
+echo $SERIAL","$CAL_VALUE >> cal_values
echo "Unplug debug cable, power cycle, cu to the board, confirm freq and record power"
diff --git a/ao-bringup/turnon_teledongle b/ao-bringup/turnon_teledongle
index a11683db..ddee5ee8 100755
--- a/ao-bringup/turnon_teledongle
+++ b/ao-bringup/turnon_teledongle
@@ -45,4 +45,5 @@ echo "Programming flash with cal value " $CAL_VALUE
$AOLOAD -D 100 --cal $CAL_VALUE /usr/share/altos/teledongle-v0.2*.ihx $SERIAL
echo "Serial number "$SERIAL" programmed with RF cal value "$CAL_VALUE
+echo $SERIAL","$CAL_VALUE >> cal_values
echo "Unplug and replug USB, cu to the board, confirm freq and record power"
diff --git a/ao-bringup/turnon_telegps b/ao-bringup/turnon_telegps
new file mode 100755
index 00000000..123f0b54
--- /dev/null
+++ b/ao-bringup/turnon_telegps
@@ -0,0 +1,81 @@
+#!/bin/sh
+
+if [ -x /usr/bin/ao-flash-lpc ]; then
+ FLASH_LPC=/usr/bin/ao-flash-lpc
+else
+ echo "Can't find ao-flash-lpc! Aborting."
+ exit 1
+fi
+
+if [ -x /usr/bin/ao-usbload ]; then
+ USBLOAD=/usr/bin/ao-usbload
+else
+ echo "Can't find ao-usbload! Aborting."
+ exit 1
+fi
+
+VERSION=1.0
+PRODUCT=TeleGPS
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+echo $FILE
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2014 by Bdale Garbee. Released under GPL v2"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo "\t\twith ST-Link-V2 cabled to debug header"
+echo
+
+case $# in
+ 1)
+ SERIAL="$1"
+ echo "$PRODUCT-$VERSION serial number: $SERIAL"
+ ;;
+ 0)
+ echo -n "$PRODUCT-$VERSION serial number: "
+ read SERIAL
+ ;;
+ *)
+ echo "Usage: $0 <serial-number>" 1>&2
+ exit 1;
+ ;;
+esac
+
+#
+# Use released versions of everything
+#
+FLASH_FILE=~/altusmetrumllc/Binaries/loaders/telegps-v1.0-altos-flash-*.elf
+ALTOS_FILE=~/altusmetrumllc/Binaries/telegps-v1.0-*.elf
+
+echo $FLASH_LPC $FLASH_FILE
+
+$FLASH_LPC $FLASH_FILE || exit 1
+
+sleep 2
+
+echo $USBLOAD $ALTOS_FILE
+
+$USBLOAD --serial=$SERIAL $ALTOS_FILE || exit 1
+
+sleep 2
+
+dev=`ao-list | awk '/TeleGPS-v'"$VERSION"'/ { print $3; exit(0); }'`
+
+case "$dev" in
+/dev/tty*)
+ echo "TeleGPS found on $dev"
+ ;;
+*)
+ echo 'No TeleGPS-v'"$VERSION"' found'
+ exit 1
+ ;;
+esac
+
+echo 'E 0' > $dev
+
+./test-telegps
+
+SERIAL=$SERIAL ./cal-freq $dev
+
+exit $?
diff --git a/ao-bringup/turnon_telemega b/ao-bringup/turnon_telemega
index 3880b197..39a63642 100755
--- a/ao-bringup/turnon_telemega
+++ b/ao-bringup/turnon_telemega
@@ -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
+ STMLOAD=/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."
@@ -19,10 +15,10 @@ else
fi
VERSION=1.0
-#VERSION=0.1
+REPO=~/altusmetrumllc/Binaries
echo "TeleMega v$VERSION Turn-On and Calibration Program"
-echo "Copyright 2010 by Bdale Garbee. Released under GPL v2"
+echo "Copyright 2014 by Bdale Garbee. Released under GPL v2"
echo
echo "Expectations:"
echo "\tTeleMega v$VERSIOn powered from USB"
@@ -34,12 +30,11 @@ read SERIAL
echo $STMLOAD
-$STMLOAD --raw ../src/telemega-v$VERSION/flash-loader/*.elf || exit 1
+$STMLOAD $REPO/loaders/telemega-v$VERSION*.elf || exit 1
sleep 2
-#$USBLOAD --serial=$SERIAL ../src/telemega-v$VERSION/*.ihx || exit 1
-$USBLOAD --serial=$SERIAL /usr/share/altos/telemega-v$VERSION*.ihx || exit 1
+$USBLOAD --serial=$SERIAL $REPO/telemega-v$VERSION*.elf || exit 1
sleep 2
diff --git a/ao-bringup/turnon_telemetrum b/ao-bringup/turnon_telemetrum
index bcf6239f..80193c4c 100755
--- a/ao-bringup/turnon_telemetrum
+++ b/ao-bringup/turnon_telemetrum
@@ -39,7 +39,7 @@ sleep 2
$USBLOAD --serial=$SERIAL /usr/share/altos/telemetrum-v$VERSION*.ihx || exit 1
-sleep 2
+sleep 5
dev=`ao-list | awk '/TeleMetrum-v'"$VERSION"'/ { print $3; exit(0); }'`
diff --git a/ao-tools/ao-flash/ao-flash-lpc b/ao-tools/ao-flash/ao-flash-lpc
index 57f632b4..7ac5b523 100644..100755
--- a/ao-tools/ao-flash/ao-flash-lpc
+++ b/ao-tools/ao-flash/ao-flash-lpc
@@ -7,15 +7,10 @@ case "$#" in
esac
cmds=/tmp/flash$$
trap "rm $cmds" 0 1 15
-for file in "$@"; do
- echo "flash write_image $file"
-done > $cmds
+file="$1"
+echo "program $file verify reset" > $cmds
openocd \
-f interface/stlink-v2.cfg \
-f target/lpc11u14.cfg \
- -c init \
- -c 'reset halt' \
-f $cmds \
- -c 'reset init' \
- -c 'reset run' \
-c shutdown
diff --git a/ao-tools/ao-load/ao-load.c b/ao-tools/ao-load/ao-load.c
index c1f55149..0cf03772 100644
--- a/ao-tools/ao-load/ao-load.c
+++ b/ao-tools/ao-load/ao-load.c
@@ -26,7 +26,7 @@
#define AO_USB_DESC_STRING 3
-struct sym {
+static struct sym {
unsigned addr;
char *name;
int required;
diff --git a/ao-tools/ao-telem/ao-telem.c b/ao-tools/ao-telem/ao-telem.c
index f1755b82..da873838 100644
--- a/ao-tools/ao-telem/ao-telem.c
+++ b/ao-tools/ao-telem/ao-telem.c
@@ -158,7 +158,8 @@ main (int argc, char **argv)
printf ("\n");
break;
case AO_TELEMETRY_MEGA_SENSOR:
- printf ("accel %5d pres %9d temp %5d accel_x %5d accel_y %5d accel_z %5d gyro_x %5d gyro_y %5d gyro_z %5d mag_x %5d mag_y %5d mag_z %5d\n",
+ printf ("orient %3d accel %5d pres %9d temp %5d accel_x %5d accel_y %5d accel_z %5d gyro_x %5d gyro_y %5d gyro_z %5d mag_x %5d mag_y %5d mag_z %5d\n",
+ telem.mega_sensor.orient,
telem.mega_sensor.accel,
telem.mega_sensor.pres,
telem.mega_sensor.temp,
diff --git a/ao-tools/ao-usbload/ao-usbload.c b/ao-tools/ao-usbload/ao-usbload.c
index 0c8a23df..fd34fbdc 100644
--- a/ao-tools/ao-usbload/ao-usbload.c
+++ b/ao-tools/ao-usbload/ao-usbload.c
@@ -142,6 +142,8 @@ main (int argc, char **argv)
int verbose = 0;
struct ao_sym *file_symbols;
int num_file_symbols;
+ uint32_t flash_base, flash_bound;
+ int has_flash_size = 0;
while ((c = getopt_long(argc, argv, "rT:D:c:s:v:", options, NULL)) != -1) {
switch (c) {
@@ -222,6 +224,14 @@ main (int argc, char **argv)
cc_usb_getline(cc, line, sizeof(line));
if (!strncmp(line, "altos-loader", 12))
is_loader = 1;
+ if (!strncmp(line, "flash-range", 11)) {
+ int i;
+ for (i = 11; i < strlen(line); i++)
+ if (line[i] != ' ')
+ break;
+ if (sscanf(line + i, "%x %x", &flash_base, &flash_bound) == 2)
+ has_flash_size = 1;
+ }
if (!strncmp(line, "software-version", 16))
break;
}
@@ -262,6 +272,22 @@ main (int argc, char **argv)
#endif
}
+ /* If the device can tell us the size of flash, make sure
+ * the image fits in that
+ */
+ if (has_flash_size) {
+ if (load->address < flash_base ||
+ load->address + load->length > flash_bound)
+ {
+ fprintf(stderr, "Image does not fit on device.\n");
+ fprintf(stderr, " Image base: %08x bounds %08x\n",
+ load->address, load->address + load->length);
+ fprintf(stderr, " Device base: %08x bounds %08x\n",
+ flash_base, flash_bound);
+ done(cc, 1);
+ }
+ }
+
if (!raw) {
/* Go fetch existing config values
* if available
@@ -295,7 +321,7 @@ main (int argc, char **argv)
/* And flash the resulting image to the device
*/
success = ao_self_write(cc, load);
-
+
if (!success) {
fprintf (stderr, "\"%s\": Write failed\n", filename);
done(cc, 1);
diff --git a/ao-tools/lib/ao-editaltos.c b/ao-tools/lib/ao-editaltos.c
index a8b64098..7547c82c 100644
--- a/ao-tools/lib/ao-editaltos.c
+++ b/ao-tools/lib/ao-editaltos.c
@@ -20,12 +20,26 @@
#include "ao-editaltos.h"
struct ao_sym ao_symbols[] = {
-
- { 0, 0, "ao_romconfig_version", 1 },
- { 0, 0, "ao_romconfig_check", 1 },
- { 0, 0, "ao_serial_number", 1 },
- { 0, 0, "ao_radio_cal", 0 },
- { 0, 0, "ao_usb_descriptors", 0 },
+ {
+ .name = "ao_romconfig_version",
+ .required = 1
+ },
+ {
+ .name = "ao_romconfig_check",
+ .required = 1
+ },
+ {
+ .name = "ao_serial_number",
+ .required = 1
+ },
+ {
+ .name = "ao_radio_cal",
+ .required = 0
+ },
+ {
+ .name = "ao_usb_descriptors",
+ .required = 0
+ },
};
#define NUM_SYMBOLS 5
diff --git a/ao-tools/lib/ao-hex.h b/ao-tools/lib/ao-hex.h
index 98497460..eb510ba2 100644
--- a/ao-tools/lib/ao-hex.h
+++ b/ao-tools/lib/ao-hex.h
@@ -51,7 +51,6 @@ struct ao_hex_image {
struct ao_sym {
unsigned addr;
- unsigned default_addr;
char *name;
bool required;
bool found;
diff --git a/ao-tools/lib/cc-telemetry.h b/ao-tools/lib/cc-telemetry.h
index c28aceb8..d64c4b30 100644
--- a/ao-tools/lib/cc-telemetry.h
+++ b/ao-tools/lib/cc-telemetry.h
@@ -157,7 +157,7 @@ struct ao_telemetry_mega_sensor {
uint16_t tick; /* 2 */
uint8_t type; /* 4 */
- uint8_t pad5; /* 5 */
+ uint8_t orient; /* 5 angle from vertical */
int16_t accel; /* 6 Z axis */
int32_t pres; /* 8 Pa * 10 */
diff --git a/ao-tools/lib/cc-usb.c b/ao-tools/lib/cc-usb.c
index d7ac138c..38dfff04 100644
--- a/ao-tools/lib/cc-usb.c
+++ b/ao-tools/lib/cc-usb.c
@@ -53,6 +53,7 @@ struct cc_usb {
struct cc_hex_read hex_buf[CC_NUM_HEX_READ];
int hex_count;
+ int show_input;
int remote;
};
@@ -156,7 +157,7 @@ cc_usb_dbg(int indent, uint8_t *bytes, int len)
*/
static int
-_cc_usb_sync(struct cc_usb *cc, int wait_for_input)
+_cc_usb_sync(struct cc_usb *cc, int wait_for_input, int write_timeout)
{
int ret;
struct pollfd fds;
@@ -165,7 +166,7 @@ _cc_usb_sync(struct cc_usb *cc, int wait_for_input)
fds.fd = cc->fd;
for (;;) {
if (cc->hex_count || cc->out_count)
- timeout = 5000;
+ timeout = write_timeout;
else if (wait_for_input && cc->in_pos == cc->in_count)
timeout = wait_for_input;
else
@@ -200,6 +201,10 @@ _cc_usb_sync(struct cc_usb *cc, int wait_for_input)
cc->in_count += ret;
if (cc->hex_count)
cc_handle_hex_read(cc);
+ if (cc->show_input && cc->in_count) {
+ write(2, cc->in_buf, cc->in_count);
+ cc->in_count = 0;
+ }
} else if (ret < 0)
perror("read");
}
@@ -222,7 +227,7 @@ _cc_usb_sync(struct cc_usb *cc, int wait_for_input)
void
cc_usb_sync(struct cc_usb *cc)
{
- if (_cc_usb_sync(cc, 0) < 0) {
+ if (_cc_usb_sync(cc, 0, 5000) < 0) {
fprintf(stderr, "USB link timeout\n");
exit(1);
}
@@ -263,7 +268,7 @@ int
cc_usb_getchar_timeout(struct cc_usb *cc, int timeout)
{
while (cc->in_pos == cc->in_count) {
- if (_cc_usb_sync(cc, timeout) < 0) {
+ if (_cc_usb_sync(cc, timeout, 5000) < 0) {
fprintf(stderr, "USB link timeout\n");
exit(1);
}
@@ -395,7 +400,7 @@ cc_usb_open_remote(struct cc_usb *cc, int freq, char *call)
cc_usb_printf(cc, "\nc F %d\nc c %s\np\nE 0\n", freq, call);
do {
cc->in_count = cc->in_pos = 0;
- _cc_usb_sync(cc, 100);
+ _cc_usb_sync(cc, 100, 5000);
} while (cc->in_count > 0);
cc->remote = 1;
}
@@ -412,19 +417,35 @@ cc_usb_close_remote(struct cc_usb *cc)
static struct termios save_termios;
+#include <errno.h>
+
struct cc_usb *
cc_usb_open(char *tty)
{
struct cc_usb *cc;
struct termios termios;
+ int i;
if (!tty)
tty = DEFAULT_TTY;
cc = calloc (sizeof (struct cc_usb), 1);
if (!cc)
return NULL;
- cc->fd = open(tty, O_RDWR | O_NONBLOCK);
- if (cc->fd < 0) {
+ i = 0;
+ for (;;) {
+ cc->fd = open(tty, O_RDWR | O_NONBLOCK);
+ if (cc->fd >= 0)
+ break;
+ i++;
+ if (errno == EBUSY || errno == EPERM || errno == EACCES) {
+ fprintf(stderr, "open failed, pausing");
+ perror(tty);
+ if (i < 20) {
+ sleep(3);
+ continue;
+ }
+ }
+
perror(tty);
free (cc);
return NULL;
@@ -438,7 +459,7 @@ cc_usb_open(char *tty)
cc_usb_printf(cc, "\nE 0\nm 0\n");
do {
cc->in_count = cc->in_pos = 0;
- _cc_usb_sync(cc, 100);
+ _cc_usb_sync(cc, 100, 5000);
} while (cc->in_count > 0);
return cc;
}
@@ -452,3 +473,26 @@ cc_usb_close(struct cc_usb *cc)
close (cc->fd);
free (cc);
}
+
+int
+cc_usb_write(struct cc_usb *cc, void *buf, int c)
+{
+ uint8_t *b;
+ int this_time;
+
+ b = buf;
+ cc->show_input = 1;
+ while (c > 0) {
+ this_time = c;
+ if (this_time > CC_OUT_BUF - cc->out_count)
+ this_time = CC_OUT_BUF - cc->out_count;
+ memcpy(cc->out_buf + cc->out_count, b, this_time);
+ cc->out_count += this_time;
+ c -= this_time;
+ b += this_time;
+ while (cc->out_count >= CC_OUT_BUF) {
+ _cc_usb_sync(cc, 0, -1);
+ }
+ }
+ return 1;
+}
diff --git a/ao-tools/lib/cc-usb.h b/ao-tools/lib/cc-usb.h
index f1193456..e08a956b 100644
--- a/ao-tools/lib/cc-usb.h
+++ b/ao-tools/lib/cc-usb.h
@@ -65,6 +65,9 @@ cc_usb_getline(struct cc_usb *cc, char *line, int max);
void
cc_usb_printf(struct cc_usb *cc, char *format, ...);
+int
+cc_usb_write(struct cc_usb *cc, void *buf, int c);
+
void
cc_usb_open_remote(struct cc_usb *cc, int freq, char *call);
diff --git a/configure.ac b/configure.ac
index 6be99d1f..23dc9d82 100644
--- a/configure.ac
+++ b/configure.ac
@@ -18,8 +18,8 @@ dnl
dnl Process this file with autoconf to create configure.
AC_PREREQ(2.57)
-AC_INIT([altos], 1.3.2)
-AC_CONFIG_SRCDIR([src/core/ao.h])
+AC_INIT([altos], 1.4)
+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=1
-ALTOSLIB_VERSION=3
+ALTOSUILIB_VERSION=2
+ALTOSLIB_VERSION=4
AC_SUBST(ALTOSLIB_VERSION)
AC_DEFINE(ALTOSLIB_VERSION,$ALTOSLIB_VERSION,[Version of the AltosLib package])
@@ -162,6 +162,20 @@ AM_CONDITIONAL(FATINSTALL, [test "x$FATDIR" != "xnone"])
AC_SUBST(FATDIR)
+AC_ARG_WITH(google-key, AS_HELP_STRING([--with-google-key=PATH],
+ [Set the file to read the google maps API key from (defaults to ~/altusmetrumllc/google-maps-api-key)]),
+ [GOOGLEKEYFILE=$withval], [GOOGLEKEYFILE=$HOME/altusmetrumllc/google-maps-api-key])
+
+if test -r "$GOOGLEKEYFILE" -a -s "$GOOGLEKEYFILE"; then
+ GOOGLEKEY='"'`cat "$GOOGLEKEYFILE"`'"'
+ HAVE_GOOGLE_KEY="yes"
+else
+ GOOGLEKEY='null'
+ HAVE_GOOGLE_KEY="no"
+fi
+
+AC_SUBST(GOOGLEKEY)
+
AC_PROG_CC
AC_PROG_INSTALL
AC_PROG_LN_S
@@ -487,6 +501,7 @@ AC_OUTPUT([
Makefile
src/Makedefs
altoslib/Makefile
+icon/Makefile
altosuilib/Makefile
altosuilib/AltosUIVersion.java
altosui/Makefile
@@ -496,6 +511,9 @@ libaltos/Makefile
micropeak/Makefile
micropeak/Info.plist
micropeak/micropeak-windows.nsi
+telegps/Makefile
+telegps/Info.plist
+telegps/telegps-windows.nsi
altosdroid/Makefile
altosdroid/local.properties
ao-tools/Makefile
@@ -536,11 +554,12 @@ echo " STlink support..............: ${HAVE_STLINK}"
echo " Local pdclib................: ${HAVE_PDCLIB}"
echo " i386 and amd64 libaltos.....: ${MULTI_ARCH}"
echo ""
-echo " Java paths"
+echo " Java"
echo " freetts.....................: ${FREETTS}"
echo " jfreechart..................: ${JFREECHART}"
echo " jcommon.....................: ${JCOMMON}"
echo " JVM include.................: ${JVM_INCLUDE}"
+echo " Google maps API key.........: ${HAVE_GOOGLE_KEY}"
if test x${ANDROID_SDK} != "xno"; then
echo ""
echo " Android path"
diff --git a/debian/altos.install b/debian/altos.install
index 05f0eec5..50f21eb1 100644
--- a/debian/altos.install
+++ b/debian/altos.install
@@ -1,4 +1,3 @@
-debian/altos.desktop usr/share/applications
debian/altusmetrum.xpm usr/share/pixmaps
src/*/*.ihx usr/share/altos
src/*/*.map usr/share/altos
diff --git a/debian/control b/debian/control
index f23a841a..3c9e8999 100644
--- a/debian/control
+++ b/debian/control
@@ -3,7 +3,7 @@ Section: electronics
Priority: optional
Maintainer: Bdale Garbee <bdale@gag.com>
Uploaders: Keith Packard <keithp@keithp.com>
-Build-Depends: debhelper (>= 7), autoconf, automake, gawk, libreadline-dev, libusb-1.0-0-dev, nickle, cc1111, xsltproc, fop, xmlto, docbook-xml, docbook-xsl, swig, default-jdk, freetts, libtool, libjfreechart-java, libbluetooth-dev, pkg-config, libelf-dev, libbluetooth-dev, libssl-dev, gcc-arm-none-eabi
+Build-Depends: debhelper (>= 7), autoconf, automake, gawk, libreadline-dev, libusb-1.0-0-dev, nickle, cc1111, xsltproc, fop, xmlto, docbook-xml, docbook-xsl, swig, default-jdk, freetts, libtool, libjfreechart-java, libbluetooth-dev, pkg-config, libelf-dev, libbluetooth-dev, libssl-dev, gcc-arm-none-eabi, icoutils, librsvg2-bin, icnsutils, graphicsmagick | imagemagick
Standards-Version: 3.9.5
Homepage: http://altusmetrum.org/AltOS
Vcs-Git: git://git.gag.com/fw/altos
diff --git a/doc/Makefile b/doc/Makefile
index 83731fbe..254e63c4 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -14,7 +14,8 @@ RELNOTES=\
release-notes-1.2.1.html \
release-notes-1.3.html \
release-notes-1.3.1.html \
- release-notes-1.3.2.html
+ release-notes-1.3.2.html \
+ release-notes-1.4.html
PICTURES=\
altosui.png \
@@ -34,6 +35,19 @@ PICTURES=\
landed.png \
launch-pad.png \
load-maps.png \
+ micropeak-app.png \
+ micropeak-back.jpg \
+ micropeak-device-dialog.png \
+ micropeak-dime.jpg \
+ micropeak-download.png \
+ micropeak-graph-configure.png \
+ micropeak-graph.png \
+ micropeak-preferences.png \
+ micropeak-raw-data.png \
+ micropeak-save-dialog.png \
+ micropeak-statistics.png \
+ MicroPeakUSB-2.0-inuse.jpg \
+ MicroPeakUSB-2.0.jpg \
scan-channels.png \
site-map.png \
table.png \
@@ -41,21 +55,23 @@ PICTURES=\
telemetrum-v1.1-thside.jpg \
telemini-v1-top.jpg \
telemini-v2-top.jpg
+
SVG=\
- easymini-outline.svg \
- telemega-outline.svg \
+ easymini.svg \
+ telemega.svg \
telemetrum.svg \
telemini.svg
RELNOTES_XSL=$(RELNOTES:.html=.xsl)
-HTML=altusmetrum.html altos.html telemetry.html companion.html micropeak.html $(RELNOTES)
-PDF=altusmetrum.pdf altos.pdf telemetry.pdf companion.pdf micropeak.pdf
+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
HTMLSTYLE=/usr/share/xml/docbook/stylesheet/docbook-xsl/html/docbook.xsl
FOSTYLE=xorg-fo.xsl
TEMPLATES=titlepage.templates.xsl
PDFSTYLE=
IMAGES=$(PICTURES) $(SVG)
-DOC=$(HTML) $(PDF) $(PICTURES)
+DOC=$(HTML) $(PDF) $(IMAGES)
.SUFFIXES: .xml .xsl .html .pdf
diff --git a/doc/altos.xsl b/doc/altos.xsl
index 5b9e12e8..6092dfcb 100644
--- a/doc/altos.xsl
+++ b/doc/altos.xsl
@@ -413,7 +413,7 @@
<title>__sfr, __sfr16, __sfr32, __sbit</title>
<para>
Access to physical registers in the device use this mode
- which declares the variable name, it's type and the
+ which declares the variable name, its type and the
address it lives at. No memory is allocated for these
variables.
</para>
@@ -809,7 +809,7 @@
ao_dma_abort(uint8_t id)
</programlisting>
<para>
- Terminate any in-progress DMA transation, marking its
+ Terminate any in-progress DMA transaction, marking its
'done' variable with the AO_DMA_ABORTED bit.
</para>
</section>
@@ -894,7 +894,7 @@
ao_dma_abort(uint8_t id)
</programlisting>
<para>
- Terminate any in-progress DMA transation, marking its
+ Terminate any in-progress DMA transaction, marking its
'done' variable with the AO_DMA_ABORTED bit.
</para>
</section>
@@ -904,7 +904,7 @@
<title>Stdio interface</title>
<para>
AltOS offers a stdio interface over USB, serial and the RF
- packet link. This provides for control of the device localy or
+ packet link. This provides for control of the device locally or
remotely. This is hooked up to the stdio functions by providing
the standard putchar/getchar/flush functions. These
automatically multiplex the available communication channels;
@@ -944,7 +944,7 @@
<para>
Flushes the current console device output buffer. Any
pending characters will be delivered to the target device.
- xo </para>
+ </para>
</section>
<section>
<title>ao_add_stdio</title>
diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl
index fb08f5c6..5ccbee9f 100644
--- a/doc/altusmetrum.xsl
+++ b/doc/altusmetrum.xsl
@@ -41,6 +41,13 @@
</legalnotice>
<revhistory>
<revision>
+ <revnumber>1.4</revnumber>
+ <date>15 June 2014</date>
+ <revremark>
+ Major release adding TeleGPS support.
+ </revremark>
+ </revision>
+ <revision>
<revnumber>1.3.2</revnumber>
<date>24 January 2014</date>
<revremark>
@@ -1539,10 +1546,13 @@ NAR #88757, TRA #12200
first five seconds of operation.
</para>
<para>
- At power on, you will hear three beeps or see three flashes
- (“S” in Morse code for start up) and then a pause while
- the altimeter completes initialization and self test, and decides
- which mode to enter next.
+ At power on, the altimeter will beep out the battery voltage
+ to the nearest tenth of a volt. Each digit is represented by
+ a sequence of short “dit” beeps, with a pause between
+ digits. A zero digit is represented with one long “dah”
+ beep. Then there will be a short pause while the altimeter
+ completes initialization and self test, and decides which mode
+ to enter next.
</para>
<para>
Here's a short summary of all of the modes and the beeping (or
@@ -1570,7 +1580,7 @@ NAR #88757, TRA #12200
<row>
<entry>Startup</entry>
<entry>S</entry>
- <entry>dit dit dit</entry>
+ <entry>battery voltage in decivolts</entry>
<entry>
<para>
Calibrating sensors, detecting orientation.
@@ -2181,6 +2191,20 @@ NAR #88757, TRA #12200
</para>
</section>
<section>
+ <title>Apogee Lockout</title>
+ <para>
+ Apogee lockout is the number of seconds after boost where
+ the flight computer will not fire the apogee charge, even if
+ the rocket appears to be at apogee. This is often called
+ 'Mach Delay', as it is intended to prevent a flight computer
+ from unintentionally firing apogee charges due to the pressure
+ spike that occurrs across a mach transition. Altus Metrum
+ flight computers include a Kalman filter which is not fooled
+ by this sharp pressure increase, and so this setting should
+ be left at the default value of zero to disable it.
+ </para>
+ </section>
+ <section>
<title>Main Deployment Altitude</title>
<para>
By default, the altimeter will fire the main deployment charge at an
@@ -2755,10 +2779,19 @@ NAR #88757, TRA #12200
dark blue for main, and black for landed.
</para>
<para>
- The map's scale is approximately 3m (10ft) per pixel. The map
+ The map's default scale is approximately 3m (10ft) per pixel. The map
can be dragged using the left mouse button. The map will attempt
to keep the rocket roughly centered while data is being received.
</para>
+ <para>
+ You can adjust the style of map and the zoom level with
+ buttons on the right side of the map window. You can draw a
+ line on the map by moving the mouse over the map with a
+ button other than the left one pressed, or by pressing the
+ left button while also holding down the shift key. The
+ length of the line in real-world units will be shown at the
+ start of the line.
+ </para>
<para>
Images are fetched automatically via the Google Maps Static API,
and cached on disk for reuse. If map images cannot be downloaded,
@@ -2770,6 +2803,24 @@ NAR #88757, TRA #12200
before you leave home; check out the 'Preload Maps' section below.
</para>
</section>
+ <section>
+ <title>Ignitor</title>
+ <informalfigure>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="ignitor.png" width="5.5in"/>
+ </imageobject>
+ </mediaobject>
+ </informalfigure>
+ <para>
+ TeleMega includes four additional programmable pyro
+ channels. The Ignitor tab shows whether each of them has
+ continuity. If an ignitor has a low resistance, then the
+ voltage measured here will be close to the pyro battery
+ voltage. A value greater than 3.2V is required for a 'GO'
+ status.
+ </para>
+ </section>
</section>
<section>
<title>Save Flight Data</title>
@@ -3036,7 +3087,21 @@ NAR #88757, TRA #12200
</para>
</section>
<section>
- <title>Radio Frequency</title>
+ <title>Apogee Lockoug</title>
+ <para>
+ Apogee lockout is the number of seconds after boost where
+ the flight computer will not fire the apogee charge, even if
+ the rocket appears to be at apogee. This is often called
+ 'Mach Delay', as it is intended to prevent a flight computer
+ from unintentionally firing apogee charges due to the pressure
+ spike that occurrs across a mach transition. Altus Metrum
+ flight computers include a Kalman filter which is not fooled
+ by this sharp pressure increase, and so this setting should
+ be left at the default value of zero to disable it.
+ </para>
+ </section>
+ <section>
+ <title>Frequency</title>
<para>
This configures which of the frequencies to use for both
telemetry and packet command mode. Note that if you set this
@@ -3094,12 +3159,11 @@ NAR #88757, TRA #12200
</para>
</section>
<section>
- <title>Ignite Mode</title>
+ <title>Ignitor Firing Mode</title>
<para>
- TeleMetrum and TeleMini provide two igniter channels as they
- were originally designed as dual-deploy flight
- computers. This configuration parameter allows the two
- channels to be used in different configurations.
+ This configuration parameter allows the two standard ignitor
+ channels (Apogee and Main) to be used in different
+ configurations.
</para>
<variablelist>
<varlistentry>
@@ -3170,6 +3234,16 @@ NAR #88757, TRA #12200
</variablelist>
</section>
<section>
+ <title>Beeper Frequency</title>
+ <para>
+ The beeper on all Altus Metrum flight computers works best
+ at 4000Hz, however if you have more than one flight computer
+ in a single airframe, having all of them sound at the same
+ frequency can be confusing. This parameter lets you adjust
+ the base beeper frequency value.
+ </para>
+ </section>
+ <section>
<title>Configure Pyro Channels</title>
<informalfigure>
<mediaobject>
@@ -3195,6 +3269,11 @@ NAR #88757, TRA #12200
the same condition with different channels.
</para>
<para>
+ At the bottom of the window, the 'Pyro Firing Time'
+ configuration sets the length of time (in seconds) which
+ each of these pyro channels will fire for.
+ </para>
+ <para>
Once you have selected the appropriate configuration for all
of the necessary pyro channels, you can save the pyro
configuration along with the rest of the flight computer
@@ -3481,9 +3560,62 @@ NAR #88757, TRA #12200
and name of the site. The contents of this list are actually
downloaded from our server at run-time, so as new sites are sent
in, they'll get automatically added to this list.
+ If the launch site isn't in the list, you can manually enter the lat/lon values
</para>
<para>
- If the launch site isn't in the list, you can manually enter the lat/lon values
+ There are four different kinds of maps you can view; you can
+ select which to download by selecting as many as you like from
+ the available types:
+ <variablelist>
+ <varlistentry>
+ <term>Hybrid</term>
+ <listitem>
+ <para>
+ A combination of satellite imagery and road data. This
+ is the default view.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Satellite</term>
+ <listitem>
+ <para>
+ Just the satellite imagery without any annotation.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Roadmap</term>
+ <listitem>
+ <para>
+ Roads, political boundaries and a few geographic features.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Terrain</term>
+ <listitem>
+ <para>
+ Contour intervals and shading that show hills and
+ valleys.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+ <para>
+ You can specify the range of zoom levels to download; smaller
+ numbers show more area with less resolution. The default
+ level, 0, shows about 3m/pixel. One zoom level change
+ doubles or halves that number.
+ </para>
+ <para>
+ The Tile Radius value sets how large an area around the center
+ point to download. Each tile is 512x512 pixels, and the
+ 'radius' value specifies how many tiles away from the center
+ will be downloaded. Specify a radius of 0 and you get only the
+ center tile. A radius of 1 loads a 3x3 grid, centered on the
+ specified location.
</para>
<para>
Clicking the 'Load Map' button will fetch images from Google
@@ -5127,7 +5259,8 @@ NAR #88757, TRA #12200
<informalfigure>
<mediaobject id="TeleMegaTemplate">
<imageobject>
- <imagedata format="SVG" fileref="telemega-outline.svg"/>
+ <imagedata format="SVG" fileref="telemega.svg"
+ scalefit="0" scale="100" align="center" />
</imageobject>
</mediaobject>
</informalfigure>
@@ -5141,7 +5274,8 @@ NAR #88757, TRA #12200
<informalfigure>
<mediaobject id="TeleMetrumTemplate">
<imageobject>
- <imagedata format="SVG" fileref="telemetrum.svg"/>
+ <imagedata format="SVG" fileref="telemetrum.svg"
+ scalefit="0" scale="100" align="center" />
</imageobject>
</mediaobject>
</informalfigure>
@@ -5155,7 +5289,8 @@ NAR #88757, TRA #12200
<informalfigure>
<mediaobject id="MiniTemplate">
<imageobject>
- <imagedata format="SVG" fileref="easymini-outline.svg"/>
+ <imagedata format="SVG" fileref="easymini.svg"
+ scalefit="0" scale="100" align="center" />
</imageobject>
</mediaobject>
</informalfigure>
@@ -5169,7 +5304,8 @@ NAR #88757, TRA #12200
<informalfigure>
<mediaobject id="TeleMiniTemplate">
<imageobject>
- <imagedata format="SVG" fileref="telemini.svg"/>
+ <imagedata format="SVG" fileref="telemini.svg"
+ scalefit="0" scale="100" align="center" />
</imageobject>
</mediaobject>
</informalfigure>
@@ -5278,6 +5414,13 @@ NAR #88757, TRA #12200
<appendix>
<title>Release Notes</title>
<simplesect>
+ <title>Version 1.4</title>
+ <xi:include
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="release-notes-1.4.xsl"
+ xpointer="xpointer(/article/*)"/>
+ </simplesect>
+ <simplesect>
<title>Version 1.3.2</title>
<xi:include
xmlns:xi="http://www.w3.org/2001/XInclude"
diff --git a/doc/ascent.png b/doc/ascent.png
index d486d19c..2d62f06e 100644
--- a/doc/ascent.png
+++ b/doc/ascent.png
Binary files differ
diff --git a/doc/configure-altimeter.png b/doc/configure-altimeter.png
index afb19325..514db3ed 100644
--- a/doc/configure-altimeter.png
+++ b/doc/configure-altimeter.png
Binary files differ
diff --git a/doc/configure-pyro.png b/doc/configure-pyro.png
index 1c6ae066..599d45b5 100644
--- a/doc/configure-pyro.png
+++ b/doc/configure-pyro.png
Binary files differ
diff --git a/doc/descent.png b/doc/descent.png
index 4ac4b962..5a7baadd 100644
--- a/doc/descent.png
+++ b/doc/descent.png
Binary files differ
diff --git a/doc/easymini-outline.pdf b/doc/easymini-outline.pdf
deleted file mode 100644
index a1a0b19d..00000000
--- a/doc/easymini-outline.pdf
+++ /dev/null
Binary files differ
diff --git a/doc/easymini-outline.svg b/doc/easymini-outline.svg
deleted file mode 100644
index 40faddb3..00000000
--- a/doc/easymini-outline.svg
+++ /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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="427.5"
- height="270"
- id="svg2"
- version="1.1"
- inkscape:version="0.48.4 r9939"
- sodipodi:docname="easymini-outline.svg">
- <defs
- id="defs4">
- <marker
- inkscape:stockid="Arrow2Lend"
- orient="auto"
- refY="0.0"
- refX="0.0"
- id="Arrow2Lend"
- style="overflow:visible;">
- <path
- id="path3866"
- style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
- d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
- transform="scale(1.1) rotate(180) translate(1,0)" />
- </marker>
- <inkscape:perspective
- sodipodi:type="inkscape:persp3d"
- inkscape:vp_x="0 : 526.18109 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_z="744.09448 : 526.18109 : 1"
- inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
- id="perspective10" />
- </defs>
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="6.4827171"
- inkscape:cx="163.56238"
- inkscape:cy="128.7277"
- inkscape:document-units="px"
- inkscape:current-layer="layer1"
- showgrid="false"
- inkscape:window-width="1146"
- inkscape:window-height="846"
- inkscape:window-x="0"
- inkscape:window-y="26"
- inkscape:window-maximized="0"
- units="in">
- <inkscape:grid
- type="xygrid"
- id="grid3005" />
- </sodipodi:namedview>
- <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(0,-782.35975)">
- <rect
- style="fill:none;stroke:#000000;stroke-width:0.29770368;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- id="rect2816"
- width="135.0623"
- height="72.062294"
- x="89.986351"
- y="890.31354" />
- <g
- inkscape:tile-y0="681.11218"
- inkscape:tile-x0="90"
- id="use3601"
- transform="translate(5.5965353,264.43715)">
- <path
- sodipodi:type="arc"
- style="fill:none;stroke:#000000;stroke-width:1.41507304;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- id="path3611"
- sodipodi:cx="116"
- sodipodi:cy="739.36218"
- sodipodi:rx="17"
- sodipodi:ry="18"
- d="m 133,739.36218 c 0,9.94113 -7.61116,18 -17,18 -9.38884,0 -17,-8.05887 -17,-18 0,-9.94112 7.61116,-18 17,-18 9.38884,0 17,8.05888 17,18 z"
- transform="matrix(0.32722728,0,0,0.3090422,57.632964,458.24316)" />
- <path
- style="color:#000000;fill:#67615b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.10785132;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 95.625,692.36218 0,-11.25"
- id="path3613"
- sodipodi:nodetypes="cc"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="cc"
- id="path3615"
- d="m 90,686.73718 11.25,0"
- style="color:#000000;fill:#67615b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.09;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:connector-curvature="0" />
- </g>
- <g
- inkscape:tile-y0="681.11218"
- inkscape:tile-x0="90"
- id="use3603"
- transform="translate(118.09654,214.93471)">
- <path
- sodipodi:type="arc"
- style="fill:none;stroke:#000000;stroke-width:1.41507304;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- id="path3619"
- sodipodi:cx="116"
- sodipodi:cy="739.36218"
- sodipodi:rx="17"
- sodipodi:ry="18"
- d="m 133,739.36218 c 0,9.94113 -7.61116,18 -17,18 -9.38884,0 -17,-8.05887 -17,-18 0,-9.94112 7.61116,-18 17,-18 9.38884,0 17,8.05888 17,18 z"
- transform="matrix(0.32722728,0,0,0.3090422,57.632964,458.24316)" />
- <path
- style="color:#000000;fill:#67615b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.10785132;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 95.625,692.36218 0,-11.25"
- id="path3621"
- sodipodi:nodetypes="cc"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="cc"
- id="path3623"
- d="m 90,686.73718 11.25,0"
- style="color:#000000;fill:#67615b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.09;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:connector-curvature="0" />
- </g>
- <g
- inkscape:tile-y0="681.11218"
- inkscape:tile-x0="90"
- id="use3605"
- transform="translate(118.09654,264.39215)">
- <path
- sodipodi:type="arc"
- style="fill:none;stroke:#000000;stroke-width:1.41507304;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- id="path3627"
- sodipodi:cx="116"
- sodipodi:cy="739.36218"
- sodipodi:rx="17"
- sodipodi:ry="18"
- d="m 133,739.36218 c 0,9.94113 -7.61116,18 -17,18 -9.38884,0 -17,-8.05887 -17,-18 0,-9.94112 7.61116,-18 17,-18 9.38884,0 17,8.05888 17,18 z"
- transform="matrix(0.32722728,0,0,0.3090422,57.632964,458.24316)" />
- <path
- style="color:#000000;fill:#67615b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.10785132;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 95.625,692.36218 0,-11.25"
- id="path3629"
- sodipodi:nodetypes="cc"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="cc"
- id="path3631"
- d="m 90,686.73718 11.25,0"
- style="color:#000000;fill:#67615b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.09;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:connector-curvature="0" />
- </g>
- <g
- inkscape:tile-y0="681.11218"
- inkscape:tile-x0="90"
- id="use3607"
- transform="translate(5.5965353,214.93471)">
- <path
- sodipodi:type="arc"
- style="fill:none;stroke:#000000;stroke-width:1.41507304;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- id="path3635"
- sodipodi:cx="116"
- sodipodi:cy="739.36218"
- sodipodi:rx="17"
- sodipodi:ry="18"
- d="m 133,739.36218 c 0,9.94113 -7.61116,18 -17,18 -9.38884,0 -17,-8.05887 -17,-18 0,-9.94112 7.61116,-18 17,-18 9.38884,0 17,8.05888 17,18 z"
- transform="matrix(0.32722728,0,0,0.3090422,57.632964,458.24316)" />
- <path
- style="color:#000000;fill:#67615b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.10785132;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 95.625,692.36218 0,-11.25"
- id="path3637"
- sodipodi:nodetypes="cc"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="cc"
- id="path3639"
- d="m 90,686.73718 11.25,0"
- style="color:#000000;fill:#67615b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.09;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:connector-curvature="0" />
- </g>
- <path
- style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.18224967;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;marker-end:url(#Arrow2Lend);visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 116.64314,926.46226 64.93789,0"
- id="path2829"
- sodipodi:nodetypes="cc"
- inkscape:connector-curvature="0" />
- <text
- xml:space="preserve"
- style="font-size:22px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Minion Pro;-inkscape-font-specification:Minion Pro"
- x="912.26929"
- y="-186.53189"
- id="text4236"
- sodipodi:linespacing="125%"
- transform="matrix(0,1,-1,0,0,0)"><tspan
- sodipodi:role="line"
- x="912.26929"
- y="-186.53189"
- id="tspan4242">UP</tspan></text>
- </g>
-</svg>
diff --git a/doc/easymini-outline.xsl b/doc/easymini-outline.xsl
new file mode 100644
index 00000000..88125322
--- /dev/null
+++ b/doc/easymini-outline.xsl
@@ -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>EasyMini Outline and Hole Pattern</title>
+ <para>
+ This image, when printed, provides a precise template for the
+ mounting holes in EasyMini. EasyMini has overall dimensions
+ of 0.800 x 1.500 inches, and the mounting holes are sized for
+ use with 4-40 or M3 screws.
+ </para>
+ <informalfigure>
+ <mediaobject id="EasyMiniTemplate">
+ <imageobject>
+ <imagedata format="SVG" fileref="easymini.svg"
+ scalefit="0" scale="100" align="center" />
+ </imageobject>
+ </mediaobject>
+ </informalfigure>
+</article>
+
+<!-- LocalWords: Altusmetrum
+-->
diff --git a/doc/easymini.svg b/doc/easymini.svg
new file mode 100644
index 00000000..8a9cba02
--- /dev/null
+++ b/doc/easymini.svg
@@ -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="1.75in"
+ height="1.05in"
+ viewBox="0 0 175 105"
+ 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:20">
+ <!-- outline -->
+ <rect width="150" height="80" 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="M137.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,67.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="M137.5,67.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="M25,40 l100,0"/>
+ <path style="fill:#000000;stroke:none" d="M125,35 l10,5 l-10,5 z"/>
+ <!-- label -->
+ <text x="75" y="35" style="fill:#000000;stroke:none" text-anchor="middle">EasyMini</text>
+ <g transform="rotate(90)">
+ <text x="40" y="-133" style="fill:#000000;stroke:none" text-anchor="middle">UP</text>
+ </g>
+ </g>
+</svg> \ No newline at end of file
diff --git a/doc/graph-configure.png b/doc/graph-configure.png
index d3374ba8..ed0d5112 100644
--- a/doc/graph-configure.png
+++ b/doc/graph-configure.png
Binary files differ
diff --git a/doc/graph-map.png b/doc/graph-map.png
index fd0fb134..bcea5ff8 100644
--- a/doc/graph-map.png
+++ b/doc/graph-map.png
Binary files differ
diff --git a/doc/ignitor.png b/doc/ignitor.png
new file mode 100644
index 00000000..d1f5aebe
--- /dev/null
+++ b/doc/ignitor.png
Binary files differ
diff --git a/doc/landed.png b/doc/landed.png
index 777d2445..a58cfbf4 100644
--- a/doc/landed.png
+++ b/doc/landed.png
Binary files differ
diff --git a/doc/launch-pad.png b/doc/launch-pad.png
index a7a05c08..f2c41e6b 100644
--- a/doc/launch-pad.png
+++ b/doc/launch-pad.png
Binary files differ
diff --git a/doc/load-maps.png b/doc/load-maps.png
index dc7ea64c..ae98c9a5 100644
--- a/doc/load-maps.png
+++ b/doc/load-maps.png
Binary files differ
diff --git a/doc/micropeak.xsl b/doc/micropeak.xsl
index 66b04072..dafe3682 100644
--- a/doc/micropeak.xsl
+++ b/doc/micropeak.xsl
@@ -10,7 +10,7 @@
<surname>Packard</surname>
</author>
<copyright>
- <year>2012</year>
+ <year>2014</year>
<holder>Bdale Garbee and Keith Packard</holder>
</copyright>
<mediaobject>
diff --git a/doc/release-notes-1.4.xsl b/doc/release-notes-1.4.xsl
new file mode 100644
index 00000000..2893f1aa
--- /dev/null
+++ b/doc/release-notes-1.4.xsl
@@ -0,0 +1,204 @@
+<?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.4 is a major release. It includes support for our new
+ TeleGPS 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 TeleGPS boards.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Replace the 'dit dit dit' tones at startup with the current
+ battery voltage, measured in tenths of a volt. This lets you
+ check the battery voltage without needing telemetry, which
+ is especially useful on EasyMini.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Change state beeping to "Farnsworth spacing", which means
+ they're quite a bit faster than before, and so they take
+ less time to send.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Make the beeper tone configurable, making it possible to
+ distinguish between two Altus Metrum products in the same ebay.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Make the firing time for extra pyro channels configurable,
+ allowing longer (or shorter) than the default 50ms. Only relevant
+ for TeleMega at this time.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ AltOS Fixes
+ <itemizedlist>
+ <listitem>
+ <para>
+ Fix bug preventing the selection of the 'Flight State After'
+ mode in pyro configuration.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Fix bug where erasing flights would reset the flight number
+ to 2 on TeleMega and TeleMetrum v2.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Fix u-Blox GPS driver to mark course and speed data as being
+ present.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ AltosUI New Features
+ <itemizedlist>
+ <listitem>
+ <para>
+ Add zooming and new content types (terrain and road maps) to
+ map view. Change map storage format from PNG to Jpeg, which
+ saves a huge amount of disk space. You will need to
+ re-download all of your pre-loaded map images.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Add a distance measuring device to the maps view. Select
+ this by using any button other than the left one, or by
+ pressing shift or control on the keyboard while using the
+ left button.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Add new 'Ignitor' tab to the flight monitor display for
+ TeleMega's extra ignitors.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Increase the width of data lines in the graphs to make them
+ easier to read.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Add additional ignitor firing marks and voltages to the
+ graph so you can see when the ignitors fired, along with
+ the ignitor voltages.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Add GPS course, ground speed and climb rate as optional
+ graph elements.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ AltosUI Fixes
+ <itemizedlist>
+ <listitem>
+ <para>
+ When flashing new firmware, re-try opening the device as
+ sometimes it takes a while for the underlying operating
+ system to recognize that the device has rebooted in
+ preparation for the flashing operation.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Hide Tilt Angle in ascent tab for devices that don't have a gyro.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Filter out speed and acceleration spikes caused by ejection
+ charge firing when computing the maximum values. This
+ provides a more accurate reading of those maximums.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Fix EasyMini voltage displays. Early EasyMini prototypes
+ used a 3.0V regulator, and AltosUI still used that value as
+ the basis of the computation. Production EasyMini boards
+ have always shipped with a 3.3V regulator. Also, purple
+ EasyMini boards sensed the battery voltage past the blocking
+ diode, resulting in a drop of about 150mV from the true
+ battery voltage. Compensate for that when displaying the
+ value.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Display error message when trying to configure maximum
+ flight log size while the flight computer still has flight
+ data stored.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Handle TeleMetrum and TeleMini eeprom files generated with
+ pre-1.0 firmware. Those ancient versions didn't report the
+ log format, so just use the product name instead.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ TeleGPS Application
+ <itemizedlist>
+ <listitem>
+ <para>
+ New application designed for use with TeleGPS boards.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Shares code with AltosUI, mostly just trimmed down to focus
+ on TeleGPS-related functions.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ Documentation changes
+ <itemizedlist>
+ <listitem>
+ <para>
+ Re-create the drill template images; they should print
+ correctly from Firefox at least. Ship these as individual
+ PDF files so they're easy to print.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Add a description of the 'Apogee Lockout' setting, which
+ prevents the apogee charge from firing for a configurable
+ amount of time after boost.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+</article>
diff --git a/doc/site-map.png b/doc/site-map.png
index 755e7361..ebac1dfb 100644
--- a/doc/site-map.png
+++ b/doc/site-map.png
Binary files differ
diff --git a/doc/telegps-configure.png b/doc/telegps-configure.png
new file mode 100644
index 00000000..56cb2031
--- /dev/null
+++ b/doc/telegps-configure.png
Binary files differ
diff --git a/doc/telegps-graph-configure.png b/doc/telegps-graph-configure.png
new file mode 100644
index 00000000..67eb5d91
--- /dev/null
+++ b/doc/telegps-graph-configure.png
Binary files differ
diff --git a/doc/telegps-graph-graph.png b/doc/telegps-graph-graph.png
new file mode 100644
index 00000000..443ada07
--- /dev/null
+++ b/doc/telegps-graph-graph.png
Binary files differ
diff --git a/doc/telegps-graph-map.png b/doc/telegps-graph-map.png
new file mode 100644
index 00000000..dddea22a
--- /dev/null
+++ b/doc/telegps-graph-map.png
Binary files differ
diff --git a/doc/telegps-graph-stats.png b/doc/telegps-graph-stats.png
new file mode 100644
index 00000000..d181ce55
--- /dev/null
+++ b/doc/telegps-graph-stats.png
Binary files differ
diff --git a/doc/telegps-info.png b/doc/telegps-info.png
new file mode 100644
index 00000000..cc279b8f
--- /dev/null
+++ b/doc/telegps-info.png
Binary files differ
diff --git a/doc/telegps-location.png b/doc/telegps-location.png
new file mode 100644
index 00000000..e32b14cd
--- /dev/null
+++ b/doc/telegps-location.png
Binary files differ
diff --git a/doc/telegps-map.png b/doc/telegps-map.png
new file mode 100644
index 00000000..f5557ded
--- /dev/null
+++ b/doc/telegps-map.png
Binary files differ
diff --git a/doc/telegps-preferences.png b/doc/telegps-preferences.png
new file mode 100644
index 00000000..ad14fd8d
--- /dev/null
+++ b/doc/telegps-preferences.png
Binary files differ
diff --git a/doc/telegps-scan.png b/doc/telegps-scan.png
new file mode 100644
index 00000000..9b19e685
--- /dev/null
+++ b/doc/telegps-scan.png
Binary files differ
diff --git a/doc/telegps-status.png b/doc/telegps-status.png
new file mode 100644
index 00000000..dc338f07
--- /dev/null
+++ b/doc/telegps-status.png
Binary files differ
diff --git a/doc/telegps-table.png b/doc/telegps-table.png
new file mode 100644
index 00000000..b3c82e8d
--- /dev/null
+++ b/doc/telegps-table.png
Binary files differ
diff --git a/doc/telegps-v1.0-top.jpg b/doc/telegps-v1.0-top.jpg
new file mode 100644
index 00000000..ac122f26
--- /dev/null
+++ b/doc/telegps-v1.0-top.jpg
Binary files differ
diff --git a/doc/telegps.xsl b/doc/telegps.xsl
new file mode 100644
index 00000000..836c3d9a
--- /dev/null
+++ b/doc/telegps.xsl
@@ -0,0 +1,1300 @@
+<?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">
+<book>
+ <title>TeleGPS Owner's Manual</title>
+ <subtitle>A recording GPS tracker</subtitle>
+ <bookinfo>
+ <author>
+ <firstname>Keith</firstname>
+ <surname>Packard</surname>
+ </author>
+ <copyright>
+ <year>2014</year>
+ <holder>Bdale Garbee and Keith Packard</holder>
+ </copyright>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="telegps-v1.0-top.jpg" width="4in"/>
+ </imageobject>
+ </mediaobject>
+ <legalnotice>
+ <para>
+ This document is released under the terms of the
+ <ulink url="http://creativecommons.org/licenses/by-sa/3.0/">
+ Creative Commons ShareAlike 3.0
+ </ulink>
+ license.
+ </para>
+ </legalnotice>
+ <revhistory>
+ <revision>
+ <revnumber>1.4</revnumber>
+ <date>13 June 2014</date>
+ <revremark>
+ Initial release
+ </revremark>
+ </revision>
+ </revhistory>
+ </bookinfo>
+ <dedication>
+ <title>Acknowledgements</title>
+ <para>
+ Have fun using these products, and we hope to meet all of you
+ out on the rocket flight line somewhere.
+ <literallayout>
+Bdale Garbee, KB0G
+NAR #87103, TRA #12201
+
+Keith Packard, KD7SQG
+NAR #88757, TRA #12200
+ </literallayout>
+ </para>
+ </dedication>
+ <chapter>
+ <title>Quick Start Guide</title>
+ <para>
+ TeleGPS is designed to be easy to use. Requiring no external
+ components, flying takes just a few steps.
+ </para>
+ <para>
+ First, download and install the software from <ulink
+ url="http://altusmetrum.org/AltOS"/>. This will make sure that
+ you have the right device drivers installed.
+ </para>
+ <para>
+ Next, plug in the battery and USB cable and connect TeleGPS to
+ your computer. This will charge the battery and allow you to
+ configure the device.
+ </para>
+ <para>
+ Start the TeleGPS application and set the callsign and frequency
+ on your TeleGPS device; refer to the Configure TeleGPS section
+ in the TeleGPS Application chapter for instructions.
+ </para>
+ <para>
+ Unplug TeleGPS when the battery charger light goes green. This
+ will enable the radio and logging portions of the TeleGPS
+ firmware.
+ </para>
+ <para>
+ Connect TeleDongle to your computer and start TeleGPS or start
+ AltosDroid on your android device and connect to TeleBT. Set the
+ frequency to match the TeleGPS and you should be receiving telemetry.
+ </para>
+ </chapter>
+ <chapter>
+ <title>Handling Precautions</title>
+ <para>
+ All Altus Metrum products are sophisticated electronic devices.
+ When handled gently and properly installed in an air-frame, they
+ will deliver impressive results. However, as with all electronic
+ devices, there are some precautions you must take.
+ </para>
+ <para>
+ The Lithium polymer batteries have an
+ extraordinary power density. This is great because we can fly with
+ much less battery mass... but if they are punctured
+ or their contacts are allowed to short, they can and will release their
+ energy very rapidly!
+ Thus we recommend that you take some care when handling TeleGPS
+ to keep conductive material from coming in contact with the exposed metal elements.
+ </para>
+ <para>
+ As with all other rocketry electronics, Altus Metrum devices must
+ be protected from exposure to corrosive motor exhaust and ejection
+ charge gasses.
+ </para>
+ </chapter>
+ <chapter>
+ <title>TeleGPS Hardware</title>
+ <section>
+ <title>Hooking Up Lithium Polymer Batteries</title>
+ <para>
+ TeleGPS has a two pin JST PH series connector to connect up
+ a single-cell Lithium Polymer cell (3.7V nominal). You can
+ purchase matching batteries from the Altus Metrum store, or
+ other vendors, or you can make your own. Pin 1 of the
+ connector is positive, pin 2 is negative. Spark Fun sells a
+ cable with the connector attached, which they call a <ulink
+ url="https://www.sparkfun.com/products/9914">JST Jumper 2
+ Wire Assembly</ulink>.
+ </para>
+ <para>
+ Many RC vendors also sell lithium polymer batteries with
+ this same connector. All that we have found use the opposite
+ polarity, and if you use them that way, you will damage or
+ destroy TeleGPS.
+ </para>
+ </section>
+ <section>
+ <title>On-board Data Recording</title>
+ <para>
+ TeleGPS logs GPS data at a user-configurable rate. Data are
+ logged to a 2MB on-board flash memory part, which can be
+ partitioned into several equal-sized blocks, one for each
+ flight. 64kB of this storage are reserved to hold
+ configuration data, leaving 1984kB for flight data.
+ </para>
+ <para>
+ The on-board flash is partitioned into separate flight logs,
+ each of a fixed maximum size. Increase the maximum size of
+ each log and you reduce the number of flights that can be
+ stored. Decrease the size and you can store more flights.
+ </para>
+ <para>
+ To compute the amount of space needed for a single log, you
+ can divide the expected time (in seconds) by the sample period
+ (by default, 1 second per sample) and then multiply the result
+ by 32 bytes per sample. For instance, a sample period of 1
+ second and a flight lasting one hour will take 32 * 3600 =
+ 115200 bytes. TeleGPS does try to reduce log space used by not
+ recording position information when it isn't moving, so actual
+ space consumed may be less than this.
+ </para>
+ <para>
+ The default size allows for four flights of 496kB each, which
+ provides over four hours of logging at 1 sample per second.
+ </para>
+ <para>
+ TeleGPS will not overwrite existing flight data, so be sure to
+ download flight data and erase it from the onboard flash
+ before it fills up. TeleGPS will still report telemetry even
+ if memory is full, so the only thing you will lose is the
+ on-board data log.
+ </para>
+ </section>
+ <section>
+ <title>Installation</title>
+ <para>
+ The battery connectors are a standard 2-pin JST connector and
+ match batteries sold by Spark Fun. These batteries are
+ single-cell Lithium Polymer batteries that nominally provide 3.7
+ volts. Other vendors sell similar batteries for RC aircraft
+ using mating connectors, however the polarity for those is
+ generally reversed from the batteries used by Altus Metrum
+ products. In particular, the Tenergy batteries supplied for use
+ in Featherweight flight computers are not compatible with Altus
+ Metrum flight computers or battery chargers. <emphasis>Check
+ polarity and voltage before connecting any battery not purchased
+ from Altus Metrum or Spark Fun.</emphasis>
+ </para>
+ <para>
+ TeleGPS uses an integrate GPS patch antenna and won't
+ receive GPS signals if installed inside a metal or carbon
+ fiber compartment. Test GPS reception and telemetry
+ transmission with the system installed and all other
+ electronics powered up to verify signal reception and make
+ sure there isn't any interference from other systems.
+ </para>
+ </section>
+ </chapter>
+ <chapter>
+ <title>System Operation</title>
+ <section>
+ <title>GFSK Telemetry</title>
+ <para>
+ TeleGPS's native telemetry system doesn't use a 'normal packet
+ radio' mode like APRS because it's not very efficient. The
+ GFSK modulation we use is FSK with the base-band pulses passed
+ through a Gaussian filter before they go into the modulator to
+ limit the transmitted bandwidth. When combined with forward
+ error correction and interleaving, this allows us to have a
+ very robust 19.2 kilobit data link with only 10-40 milliwatts
+ of transmit power, a whip antenna in the rocket, and a
+ hand-held Yagi on the ground. We've had flights to above 21k
+ feet AGL with great reception, and calculations suggest we
+ should be good to well over 40k feet AGL with a 5-element yagi
+ on the ground with our 10mW units and over 100k feet AGL with
+ the 40mW devices.
+ </para>
+ </section>
+ <section>
+ <title>APRS</title>
+ <para>
+ TeleGPS can send APRS if desired, and the
+ interval between APRS packets can be configured. As each APRS
+ packet takes a full second to transmit, we recommend an
+ interval of at least 5 seconds to avoid consuming too much
+ battery power or radio channel bandwidth. You can configure
+ the APRS interval using AltosUI; that process is described in
+ the Configure Altimeter section of the AltosUI chapter.
+ </para>
+ <para>
+ AltOS uses the APRS compressed position report data format,
+ which provides for higher position precision and shorter
+ packets than the original APRS format. It also includes
+ altitude data, which is invaluable when tracking rockets. We
+ haven't found a receiver which doesn't handle compressed
+ positions, but it's just possible that you have one, so if you
+ have an older device that can receive the raw packets but
+ isn't displaying position information, it's possible that this
+ is the cause.
+ </para>
+ <para>
+ The APRS packet format includes a comment field that can have
+ arbitrary text in it. AltOS uses this to send status
+ information about the flight computer. It sends four fields as
+ shown in the following table.
+ </para>
+ <table frame='all'>
+ <title>Altus Metrum APRS Comments</title>
+ <?dbfo keep-together="always"?>
+ <tgroup cols='3' align='center' colsep='1' rowsep='1'>
+ <colspec align='center' colwidth='*' colname='Field'/>
+ <colspec align='center' colwidth='*' colname='Example'/>
+ <colspec align='center' colwidth='4*' colname='Description'/>
+ <thead>
+ <row>
+ <entry align='center'>Field</entry>
+ <entry align='center'>Example</entry>
+ <entry align='center'>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>1</entry>
+ <entry>L</entry>
+ <entry>GPS Status U for unlocked, L for locked</entry>
+ </row>
+ <row>
+ <entry>2</entry>
+ <entry>6</entry>
+ <entry>Number of Satellites in View</entry>
+ </row>
+ <row>
+ <entry>3</entry>
+ <entry>B4.0</entry>
+ <entry>Battery Voltage</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>
+ Here's an example of an APRS comment showing GPS lock with 6
+ satellites in view and a battery at 4.0V.
+ <screen>
+ L6 B4.0
+ </screen>
+ </para>
+ <para>
+ Make sure your primary battery is above 3.8V and GPS is locked
+ with at least 5 or 6 satellites in view before starting. If GPS
+ is switching between L and U regularly, then it doesn't have a
+ good lock and you should wait until it becomes stable.
+ </para>
+ <para>
+ If the GPS receiver loses lock, the APRS data transmitted will
+ contain the last position for which GPS lock was
+ available. You can tell that this has happened by noticing
+ that the GPS status character switches from 'L' to 'U'. Before
+ GPS has locked, APRS will transmit zero for latitude,
+ longitude and altitude.
+ </para>
+ </section>
+ <section>
+ <title>Configurable Parameters</title>
+ <para>
+ Configuring TeleGPS is very
+ simple; the few configurable parameters can all be set
+ using the TeleGPS application over USB. Read
+ the Configure TeleGPS section in the TeleGPS Software chapter below
+ for more information.
+ </para>
+ <section>
+ <title>Radio Frequency</title>
+ <para>
+ Altus Metrum boards support radio frequencies in the 70cm
+ band. By default, the configuration interface provides a
+ list of 10 “standard” frequencies in 100kHz channels starting at
+ 434.550MHz. However, the firmware supports use of
+ any 50kHz multiple within the 70cm band. At any given
+ launch, we highly recommend coordinating when and by whom each
+ frequency will be used to avoid interference. And of course, both
+ TeleGPS and the receiver must be configured to the same
+ frequency to successfully communicate with each other.
+ </para>
+ </section>
+ <section>
+ <title>Callsign</title>
+ <para>
+ This sets the callsign used for telemetry and APRS to
+ identify the device.
+ </para>
+ </section>
+ <section>
+ <title>Telemetry/RDF/APRS Enable</title>
+ <para>
+ You can completely disable the radio, if necessary, leaving
+ TeleGPS only logging data to internal memory.
+ </para>
+ </section>
+ <section>
+ <title>APRS Interval</title>
+ <para>
+ This selects how often APRS packets are transmitted. Set
+ this to zero to disable APRS without also disabling the
+ regular telemetry and RDF transmissions. As APRS takes a
+ full second to transmit a single position report, we
+ recommend sending packets no more than once every 5 seconds.
+ </para>
+ </section>
+ <section>
+ <title>Maximum Flight Log</title>
+ <para>
+ Changing this value will set the maximum amount of flight
+ log storage that an individual flight will use. The
+ available storage is divided into as many flights of the
+ specified size as can fit in the available space. You can
+ download and erase individual flight logs. If you fill up
+ the available storage, future flights will not get logged
+ until you erase some of the stored ones.
+ </para>
+ </section>
+ <section>
+ <title>Logging Trigger Motion</title>
+ <para>
+ If TeleGPS moves less than this distance over a long period
+ of time, it will not log that location, saving storage space.
+ </para>
+ </section>
+ <section>
+ <title>Position Reporting Interval</title>
+ <para>
+ This sets how often TeleGPS reports position information via
+ telemetry and to the on-board log. Reducing this value will
+ save power and logging memory consumption.
+ </para>
+ </section>
+ </section>
+ </chapter>
+ <chapter>
+ <title>TeleGPS Application</title>
+ <para>
+ The TeleGPS application provides a graphical user interface for
+ interacting with the Altus Metrum product family. TeleGPS can
+ monitor telemetry data, configure devices and many other
+ tasks. The primary interface window is for displaying data
+ received over the telemetry link. There are additional
+ tasks available from the main window menu bar. This chapter
+ is split into sections, each of which documents one of the tasks
+ provided from the top-level toolbar.
+ </para>
+ <section>
+ <title>Telemetry Monitoring</title>
+ <para>
+ This is the window brought up when you start the
+ application. If you have a TeleDongle device connected to the
+ computer, it will automatically be selected for telemetry monitoring
+ </para>
+ <para>
+ All telemetry data received are automatically recorded in
+ suitable log files. The name of the files includes the current
+ date and TeleGPS serial and flight numbers.
+ </para>
+ <para>
+ The radio frequency being monitored by the TeleDongle device
+ is displayed at the top of the window. You can configure the
+ frequency by clicking on the frequency box and selecting the
+ desired frequency. The TeleGPS application remembers the last
+ frequency selected for each TeleDongle and selects that
+ automatically the next time you use that device.
+ </para>
+ <para>
+ Below the TeleDongle frequency selector, the window contains a few
+ significant pieces of information about the altimeter providing
+ the telemetry data stream:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>The configured call-sign</para>
+ </listitem>
+ <listitem>
+ <para>The device serial number</para>
+ </listitem>
+ <listitem>
+ <para>The flight number. TeleGPS remembers how many
+ times it has flown.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The Received Signal Strength Indicator value. This lets
+ you know how strong a signal TeleDongle is receiving. The
+ radio inside TeleDongle operates down to about -100dBm;
+ weaker signals may not be receivable. The packet link uses
+ error detection and correction techniques which prevent
+ incorrect data from being reported.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The age of the displayed data, in seconds since the last
+ successfully received telemetry packet. In normal operation
+ this will stay in the low single digits. If the number starts
+ counting up, then you are no longer receiving data over the radio
+ link from the flight computer.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Finally, the largest portion of the window contains a set of
+ tabs, each of which contain some information about the TeleGPS
+ board. The final 'table' tab displays many of the raw telemetry
+ values in one place in a spreadsheet-like format.
+ </para>
+ <section>
+ <title>Map</title>
+ <para>
+ The Map tab shows the TeleGPS track over time on top of map
+ data making it easy to locate the device.
+ </para>
+ <informalfigure>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="telegps-map.png" width="5.5in"/>
+ </imageobject>
+ </mediaobject>
+ </informalfigure>
+ <para>
+ The map's default scale is approximately 3m (10ft) per pixel. The map
+ can be dragged using the left mouse button. The map will attempt
+ to keep the rocket roughly centered while data is being received.
+ </para>
+ <para>
+ You can adjust the style of map and the zoom level with
+ buttons on the right side of the map window. You can draw a
+ line on the map by moving the mouse over the map with a
+ button other than the left one pressed, or by pressing the
+ left button while also holding down the shift key. The
+ length of the line in real-world units will be shown at the
+ start of the line.
+ </para>
+ <para>
+ Images are fetched automatically via the Google Maps Static API,
+ and cached on disk for reuse. If map images cannot be downloaded,
+ the rocket's path will be traced on a dark gray background
+ instead.
+ </para>
+ <para>
+ You can pre-load images for your favorite launch sites
+ before you leave home; check out the 'Preload Maps' section below.
+ </para>
+ </section>
+ <section>
+ <title>Location</title>
+ <para>
+ The Location tab shows the raw GPS data received from TeleGPS.
+ </para>
+ <informalfigure>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="telegps-location.png" width="5.5in"/>
+ </imageobject>
+ </mediaobject>
+ </informalfigure>
+ </section>
+ <section>
+ <title>Status</title>
+ <para>
+ The Status tab shows data relative to the location of
+ TeleGPS when the application first received telemetry from
+ it.
+ </para>
+ <informalfigure>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="telegps-status.png" width="5.5in"/>
+ </imageobject>
+ </mediaobject>
+ </informalfigure>
+ </section>
+ <section>
+ <title>Table</title>
+ <para>
+ The Table tab shows detailed information about the GPS
+ receiver
+ </para>
+ <informalfigure>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="telegps-table.png" width="5.5in"/>
+ </imageobject>
+ </mediaobject>
+ </informalfigure>
+ </section>
+ </section>
+ <!--
+ <variablelist>
+ <varlistentry>
+ <term></term>
+ <listitem>
+ <para>
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ -->
+ <section>
+ <title>TeleGPS Menus</title>
+ <para>
+ TeleGPS has three or four menus at the top of the window:
+ <variablelist>
+ <varlistentry>
+ <term>File</term>
+ <listitem>
+ <para>
+ New Window, Graph Data, Export Data, Load Maps, Preferences, Close and Exit
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Monitor</term>
+ <listitem>
+ <para>
+ Connect Device, Disconnect and Scan Channels
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Device</term>
+ <listitem>
+ <para>
+ Download Data, Configure Device and Flash Device
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Frequency</term>
+ <listitem>
+ <para>
+ This shows the current monitoring frequency with a
+ drop-down menu listing other configured
+ frequencies. You can change the set of frequencies
+ shown here from the Preferences dialog. This menu is
+ only shown when the TeleGPS application is connected
+ to a TeleDongle or TeleBT device.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+ <section>
+ <title>New Window</title>
+ <para>
+ This creates another telemetry monitoring window, in case
+ you have multiple TeleDongle devices connected to the
+ computer.
+ </para>
+ </section>
+ <section>
+ <title>Graph Data</title>
+ <para>
+ This brings up a file dialog to load a saved log, either
+ a .telem file of recorded telemetry or .eeprom of saved
+ data from on-board memory. It looks a bit like the flight
+ monitoring window, using a selection of tabs to show
+ different views of the saved data.
+ </para>
+ <section>
+ <title>Graph</title>
+ <para>
+ The Graph tab shows a plot of the the GPS data
+ collected. The X axis is time in seconds; there are a
+ variety of Y axes available for different kinds of data.
+ </para>
+ <informalfigure>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="telegps-graph-graph.png" width="6in" scalefit="1"/>
+ </imageobject>
+ </mediaobject>
+ </informalfigure>
+ </section>
+ <section>
+ <title>Configure Graph</title>
+ <informalfigure>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="telegps-graph-configure.png" width="6in" scalefit="1"/>
+ </imageobject>
+ </mediaobject>
+ </informalfigure>
+ <para>
+ This selects which graph elements to show, and, at the
+ bottom, lets you switch between metric and imperial units
+ </para>
+ </section>
+ <section>
+ <title>Statistics</title>
+ <informalfigure>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="telegps-graph-stats.png" width="6in" scalefit="1"/>
+ </imageobject>
+ </mediaobject>
+ </informalfigure>
+ <para>
+ Shows overall data computed from the flight.
+ </para>
+ </section>
+ <section>
+ <title>Map</title>
+ <informalfigure>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="telegps-graph-map.png" width="6in" scalefit="1"/>
+ </imageobject>
+ </mediaobject>
+ </informalfigure>
+ <para>
+ Shows a map of the area overlaid with the GPS track. As with
+ the telemetry monitoring window, you can select the style
+ of map and zoom level using buttons along the side;
+ you can scroll the map by dragging within the map pressing
+ the left button and you can draw a line to measure
+ distances using either the left button with the shift key,
+ or any other button.
+ </para>
+ </section>
+ </section>
+ <section>
+ <title>Export Data</title>
+ <para>
+ This tool takes the raw data files and makes them available for
+ external analysis. When you select this button, you are prompted to
+ select a data file, which can be either a .eeprom or .telem.
+ The .eeprom files contain higher resolution and more continuous data,
+ while .telem files contain receiver signal strength information.
+ Next, a second dialog appears which is used to select
+ where to write the resulting file. It has a selector to choose
+ between CSV and KML file formats.
+ </para>
+ <section>
+ <title>Comma Separated Value Format</title>
+ <para>
+ This is a text file containing the data in a form suitable for
+ import into a spreadsheet or other external data analysis
+ tool. The first few lines of the file contain the version and
+ configuration information from TeleGPS, then
+ there is a single header line which labels all of the
+ fields. All of these lines start with a '#' character which
+ many tools can be configured to skip over.
+ </para>
+ <para>
+ The remaining lines of the file contain the data, with each
+ field separated by a comma and at least one space. All of
+ the sensor values are converted to standard units, with the
+ barometric data reported in both pressure, altitude and
+ height above pad units.
+ </para>
+ </section>
+ <section>
+ <title>Keyhole Markup Language (for Google Earth)</title>
+ <para>
+ This is the format used by Google Earth to provide an overlay
+ within that application. With this, you can use Google Earth to
+ see the whole flight path in 3D.
+ </para>
+ </section>
+ </section>
+ <section>
+ <title>Load Maps</title>
+ <informalfigure>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="load-maps.png" width="5.2in" scalefit="1"/>
+ </imageobject>
+ </mediaobject>
+ </informalfigure>
+ <para>
+ Before using TeleGPS, you can use Load Maps to load map data
+ in case you don't have access to the internet while
+ receiving telemetry.
+ </para>
+ <para>
+ There's a drop-down menu of rocket launch sites we know
+ about; if your favorites aren't there, please let us know
+ the lat/lon and name of the site. The contents of this list
+ are actually downloaded from our server at run-time, so as
+ new sites are sent in, they'll get automatically added to
+ this list. If the launch site isn't in the list, you can
+ manually enter the lat/lon values
+ </para>
+ <para>
+ There are four different kinds of maps you can view; you can
+ select which to download by selecting as many as you like from
+ the available types:
+ <variablelist>
+ <varlistentry>
+ <term>Hybrid</term>
+ <listitem>
+ <para>
+ A combination of satellite imagery and road data. This
+ is the default view.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Satellite</term>
+ <listitem>
+ <para>
+ Just the satellite imagery without any annotation.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Roadmap</term>
+ <listitem>
+ <para>
+ Roads, political boundaries and a few geographic features.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Terrain</term>
+ <listitem>
+ <para>
+ Contour intervals and shading that show hills and
+ valleys.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+ <para>
+ You can specify the range of zoom levels to download; smaller
+ numbers show more area with less resolution. The default
+ level, 0, shows about 3m/pixel. One zoom level change
+ doubles or halves that number.
+ </para>
+ <para>
+ The Tile Radius value sets how large an area around the center
+ point to download. Each tile is 512x512 pixels, and the
+ 'radius' value specifies how many tiles away from the center
+ will be downloaded. Specify a radius of 0 and you get only the
+ center tile. A radius of 1 loads a 3x3 grid, centered on the
+ specified location.
+ </para>
+ <para>
+ Clicking the 'Load Map' button will fetch images from Google
+ Maps; note that Google limits how many images you can fetch at
+ once, so if you load more than one launch site, you may get
+ some gray areas in the map which indicate that Google is tired
+ of sending data to you. Try again later.
+ </para>
+ </section>
+ <section>
+ <title>Preferences</title>
+ <informalfigure>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="telegps-preferences.png" width="2.4in" scalefit="1"/>
+ </imageobject>
+ </mediaobject>
+ </informalfigure>
+ <section>
+ <title>Voice Settings</title>
+ <para>
+ AltosUI provides voice announcements during flight so that you
+ can keep your eyes on the sky and still get information about
+ the current flight status. However, sometimes you don't want
+ to hear them.
+ </para>
+ <variablelist>
+ <varlistentry>
+ <term>Enable</term>
+ <listitem>
+ <para>Turns all voice announcements on and off</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Test Voice</term>
+ <listitem>
+ <para>
+ Plays a short message allowing you to verify
+ that the audio system is working and the volume settings
+ are reasonable
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section>
+ <title>Log Directory</title>
+ <para>
+ AltosUI logs all telemetry data and saves all TeleMetrum flash
+ data to this directory. This directory is also used as the
+ staring point when selecting data files for display or export.
+ </para>
+ <para>
+ Click on the directory name to bring up a directory choosing
+ dialog, select a new directory and click 'Select Directory' to
+ change where AltosUI reads and writes data files.
+ </para>
+ </section>
+ <section>
+ <title>Callsign</title>
+ <para>
+ This value is transmitted in each command packet sent from
+ TeleDongle and received from an altimeter. It is not used in
+ telemetry mode, as the callsign configured in the altimeter board
+ is included in all telemetry packets. Configure this
+ with the AltosUI operators call sign as needed to comply with
+ your local radio regulations.
+ </para>
+ <para>
+ Note that to successfully command a flight computer over the radio
+ (to configure the altimeter, monitor idle, or fire pyro charges),
+ the callsign configured here must exactly match the callsign
+ configured in the flight computer. This matching is case
+ sensitive.
+ </para>
+ </section>
+ <section>
+ <title>Imperial Units</title>
+ <para>
+ This switches between metric units (meters) and imperial
+ units (feet and miles). This affects the display of values
+ use during flight monitoring, configuration, data graphing
+ and all of the voice announcements. It does not change the
+ units used when exporting to CSV files, those are always
+ produced in metric units.
+ </para>
+ </section>
+ <section>
+ <title>Serial Debug</title>
+ <para>
+ This causes all communication with a connected device to be
+ dumped to the console from which AltosUI was started. If
+ you've started it from an icon or menu entry, the output
+ will simply be discarded. This mode can be useful to debug
+ various serial communication issues.
+ </para>
+ </section>
+ <section>
+ <title>Font Size</title>
+ <para>
+ Selects the set of fonts used in the flight monitor
+ window. Choose between the small, medium and large sets.
+ </para>
+ </section>
+ <section>
+ <title>Look &amp; Feel</title>
+ <para>
+ Adjust the style of the windows. By default, the TeleGPS
+ application attempts to blend in with the native style.
+ </para>
+ </section>
+ <section>
+ <title>Manage Frequencies</title>
+ <para>
+ This brings up a dialog where you can configure the set of
+ frequencies shown in the various frequency menus. You can
+ add as many as you like, or even reconfigure the default
+ set. Changing this list does not affect the frequency
+ settings of any devices, it only changes the set of
+ frequencies shown in the menus.
+ </para>
+ </section>
+ </section>
+ <section>
+ <title>Close</title>
+ <para>
+ This closes the current window, leaving any other windows
+ open and the application running.
+ </para>
+ </section>
+ <section>
+ <title>Exit</title>
+ <para>
+ This closes all TeleGPS windows and terminates the application.
+ </para>
+ </section>
+ <section>
+ <title>Connect Device</title>
+ <para>
+ Selecting this item brings up a dialog box listing all of
+ the connected TeleDongle devices. When you choose one of
+ these, AltosUI will display telemetry data as received by
+ the selected TeleDongle device.
+ </para>
+ <informalfigure>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="device-selection.png" width="3.1in"/>
+ </imageobject>
+ </mediaobject>
+ </informalfigure>
+ </section>
+ <section>
+ <title>Disconnect</title>
+ <para>
+ Disconnects the currently connected TeleDongle or TeleBT
+ </para>
+ </section>
+ <section>
+ <title>Scan Channels</title>
+ <para>
+ Scans the configured set of frequencies looking for
+ telemetry signals. A list of all of the discovered signals
+ is show; selecting one of those and clicking on 'Monitor'
+ will select that frequency in the associated TeleGPS
+ application window.
+ </para>
+ <informalfigure>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="telegps-scan.png" width="3.1in"/>
+ </imageobject>
+ </mediaobject>
+ </informalfigure>
+ </section>
+ <section>
+ <title>Download Data</title>
+ <para>
+ TeleGPS records data to its internal flash memory.
+ On-board data is recorded at the same rate as telemetry
+ but is not subject to radio drop-outs. As
+ such, it generally provides a more complete and precise record.
+ The 'Download Data' menu entry allows you to read the
+ flash memory and write it to disk.
+ </para>
+ <para>
+ Select the 'Download Data' menu entry to bring up a list of
+ connected TeleGPS devices. After the device has been
+ selected, a dialog showing the data stored in the
+ device will be shown allowing you to select which entries to
+ download and which to delete. You must erase flights in order for the space they
+ consume to be reused by another track. This prevents
+ accidentally losing data if you neglect to download
+ data before starting TeleGPS again. Note that if there is no more
+ space available in the device, then no data will be recorded.
+ </para>
+ <para>
+ The file name for each data log is computed automatically
+ from the recorded date, altimeter serial number and flight
+ number information.
+ </para>
+ </section>
+ <section>
+ <title>Configure Device</title>
+ <informalfigure>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="telegps-configure.png" width="3.6in" scalefit="1"/>
+ </imageobject>
+ </mediaobject>
+ </informalfigure>
+ <para>
+ Select this button and then select any connected TeleGPS
+ device from the list provided.
+ </para>
+ <para>
+ The first few lines of the dialog provide information about the
+ connected device, including the product name,
+ software version and hardware serial number. Below that are the
+ individual configuration entries.
+ </para>
+ <para>
+ At the bottom of the dialog, there are four buttons:
+ </para>
+ <variablelist>
+ <varlistentry>
+ <term>Save</term>
+ <listitem>
+ <para>
+ This writes any changes to the
+ configuration parameter block in flash memory. If you don't
+ press this button, any changes you make will be lost.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Reset</term>
+ <listitem>
+ <para>
+ This resets the dialog to the most recently saved values,
+ erasing any changes you have made.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Reboot</term>
+ <listitem>
+ <para>
+ This reboots the device. This will restart logging for
+ a new flight number, if any log information has been
+ saved for the current flight.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Close</term>
+ <listitem>
+ <para>
+ This closes the dialog. Any unsaved changes will be
+ lost.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ <para>
+ The rest of the dialog contains the parameters to be configured.
+ </para>
+ <section>
+ <title>Frequency</title>
+ <para>
+ This configures which of the frequencies to use for both
+ telemetry and packet command mode. Note that if you set this
+ value via packet command mode, the TeleDongle frequency will
+ also be automatically reconfigured to match so that
+ communication will continue afterwards.
+ </para>
+ </section>
+ <section>
+ <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. If you need to you can adjust the calibration
+ by changing this value. Do not do this without understanding what
+ the value means, read the appendix on calibration and/or the source
+ code for more information. To change a TeleDongle's calibration,
+ you must reprogram the unit completely.
+ </para>
+ </section>
+ <section>
+ <title>Telemetry/RDF/APRS Enable</title>
+ <para>
+ Enables the radio for transmission during flight. When
+ disabled, the radio will not transmit anything during flight
+ at all.
+ </para>
+ </section>
+ <section>
+ <title>APRS Interval</title>
+ <para>
+ How often to transmit GPS information via APRS (in
+ seconds). When set to zero, APRS transmission is
+ disabled. This option is available on TeleMetrum v2 and
+ TeleMega boards. TeleMetrum v1 boards cannot transmit APRS
+ packets. Note that a single APRS packet takes nearly a full
+ second to transmit, so enabling this option will prevent
+ sending any other telemetry during that time.
+ </para>
+ </section>
+ <section>
+ <title>Callsign</title>
+ <para>
+ This sets the call sign included in each telemetry packet. Set this
+ as needed to conform to your local radio regulations.
+ </para>
+ </section>
+ <section>
+ <title>Maximum Log Size</title>
+ <para>
+ This sets the space (in kilobytes) allocated for each data
+ log. The available space will be divided into chunks of this
+ size. A smaller value will allow more logs to be stored,
+ a larger value will record data for longer times.
+ </para>
+ </section>
+ <section>
+ <title>Logging Trigger Motion</title>
+ <para>
+ If TeleGPS moves less than this distance over a long period
+ of time, it will not log that location, saving storage space.
+ </para>
+ </section>
+ <section>
+ <title>Position Reporting Interval</title>
+ <para>
+ This sets how often TeleGPS reports position information via
+ telemetry and to the on-board log. Reducing this value will
+ save power and logging memory consumption.
+ </para>
+ </section>
+ </section>
+ <section>
+ <title>Flash Device</title>
+ <para>
+ This reprograms TeleGPS devices with new firmware. Please
+ read the directions for flashing devices in the Updating
+ Device Firmware chapter below.
+ </para>
+ </section>
+ </section>
+ </chapter>
+ <chapter>
+ <title>Updating Device Firmware</title>
+ <para>
+ TeleGPS is programmed directly over its USB connectors.
+ </para>
+ <para>
+ You may wish to begin by ensuring you have current firmware images.
+ These are distributed as part of the TeleGPS software bundle that
+ also includes the TeleGPS ground station program. Newer ground
+ station versions typically work fine with older firmware versions,
+ so you don't need to update your devices just to try out new
+ software features. You can always download the most recent
+ version from <ulink url="http://www.altusmetrum.org/AltOS/"/>.
+ </para>
+ <section>
+ <title>
+ Updating TeleGPS Firmware
+ </title>
+ <orderedlist inheritnum='inherit' numeration='arabic'>
+ <listitem>
+ <para>
+ Attach a battery and power switch to the target
+ device. Power up the device.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Using a Micro USB cable, connect the target device to your
+ computer's USB socket.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Run TeleGPS, and select 'Flash Device' from the Device menu.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Select the target device in the Device Selection dialog.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Select the image you want to flash to the device, which
+ should have a name in the form
+ &lt;product&gt;-v&lt;product-version&gt;-&lt;software-version&gt;.ihx, such
+ as TeleGPS-v1.0-1.4.0.ihx.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Make sure the configuration parameters are reasonable
+ looking. If the serial number and/or RF configuration
+ values aren't right, you'll need to change them.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Hit the 'OK' button and the software should proceed to flash
+ the device with new firmware, showing a progress bar.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Verify that the device is working by using the 'Configure
+ Altimeter' item to check over the configuration.
+ </para>
+ </listitem>
+ </orderedlist>
+<!--
+ <section>
+ <title>Recovering From Self-Flashing Failure</title>
+ <para>
+ If the firmware loading fails, it can leave the device
+ unable to boot. Not to worry, you can force the device to
+ start the boot loader instead, which will let you try to
+ flash the device again.
+ </para>
+ <para>
+ On each device, connecting two pins from one of the exposed
+ connectors will force the boot loader to start, even if the
+ regular operating system has been corrupted in some way.
+ </para>
+ <variablelist>
+ <varlistentry>
+ <term>TeleMega</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>
+ <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>EasyMini</term>
+ <listitem>
+ <para>
+ Connect pin 6 and pin 1 of the debug connector, which is
+ the six holes next to the beeper. Pin 1 can be identified
+ by the square pad around it, and then the pins could
+ sequentially across the board, making Pin 6 the one on the
+ other end of the row.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ -->
+ </section>
+ </chapter>
+ <chapter>
+ <title>Technical Information</title>
+ <section>
+ <title>GPS Receiver</title>
+ <para>
+ TeleGPS uses the u-Blox Max-7Q GPS receiver.
+ </para>
+ </section>
+ <section>
+ <title>Micro-controller</title>
+ <para>
+ TeleGPS uses an NXP LPC11U14 micro-controller. This tiny
+ CPU contains 32kB of flash for the application and 4kB of RAM for
+ temporary data storage.
+ </para>
+ </section>
+ <section>
+ <title>Lithium Polymer Battery</title>
+ <para>
+ Shipping restrictions may prevent us from including a battery
+ battery with TeleGPS.
+ </para>
+ </section>
+ <section>
+ <title>Mechanical Considerations</title>
+ <para>
+ TeleGPS is designed to be rugged enough for typical rocketry
+ applications. The 4 mounting holes on the board are sized for
+ use with 4-40 or M3 screws.
+ </para>
+ </section>
+ <section>
+ <title>On-board data storage</title>
+ <para>
+ TeleGPS has 2MB of non-volatile storage, separate from the
+ code storage memory. The TeleGPS firmware uses this to log
+ information during flight.
+ </para>
+ </section>
+ </chapter>
+</book>
+<!-- LocalWords: Altusmetrum TeleGPS
+-->
diff --git a/doc/telemega-outline.pdf b/doc/telemega-outline.pdf
deleted file mode 100644
index f8fc26e2..00000000
--- a/doc/telemega-outline.pdf
+++ /dev/null
Binary files differ
diff --git a/doc/telemega-outline.svg b/doc/telemega-outline.svg
deleted file mode 100644
index e8d74d38..00000000
--- a/doc/telemega-outline.svg
+++ /dev/null
@@ -1,244 +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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="427.5"
- height="270"
- id="svg2"
- version="1.1"
- inkscape:version="0.48.3.1 r9886"
- sodipodi:docname="megametrum-outline.svg">
- <defs
- id="defs4">
- <marker
- inkscape:stockid="Arrow2Lend"
- orient="auto"
- refY="0.0"
- refX="0.0"
- id="Arrow2Lend"
- style="overflow:visible;">
- <path
- id="path3866"
- style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
- d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
- transform="scale(1.1) rotate(180) translate(1,0)" />
- </marker>
- <inkscape:perspective
- sodipodi:type="inkscape:persp3d"
- inkscape:vp_x="0 : 526.18109 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_z="744.09448 : 526.18109 : 1"
- inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
- id="perspective10" />
- </defs>
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="2.1783851"
- inkscape:cx="315.40175"
- inkscape:cy="122.33575"
- inkscape:document-units="in"
- inkscape:current-layer="layer1"
- showgrid="true"
- inkscape:window-width="1527"
- inkscape:window-height="1313"
- inkscape:window-x="813"
- inkscape:window-y="166"
- inkscape:window-maximized="0"
- units="in"
- showguides="true"
- inkscape:guide-bbox="true">
- <sodipodi:guide
- position="0,0"
- orientation="0,427.5"
- id="guide3005" />
- <sodipodi:guide
- position="427.5,0"
- orientation="-270,0"
- id="guide3007" />
- <sodipodi:guide
- position="427.5,270"
- orientation="0,-427.5"
- id="guide3009" />
- <sodipodi:guide
- position="0,270"
- orientation="270,0"
- id="guide3011" />
- <inkscape:grid
- type="xygrid"
- id="grid3013"
- empspacing="4"
- visible="true"
- enabled="true"
- snapvisiblegridlinesonly="true"
- units="in"
- spacingx="0.025in"
- spacingy="0.025in" />
- </sodipodi:namedview>
- <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(0,-782.35975)">
- <rect
- style="fill:none;stroke:#000000;stroke-width:0.54555845;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- id="rect2816"
- width="291.95444"
- height="111.95444"
- x="90.272781"
- y="850.13251" />
- <g
- inkscape:tile-y0="681.11218"
- inkscape:tile-x0="90"
- id="use3601"
- transform="matrix(0.97131843,0,0,0.97528987,8.397686,191.32255)">
- <path
- sodipodi:type="arc"
- style="fill:none;stroke:#000000;stroke-width:1.41507304;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- id="path3611"
- sodipodi:cx="116"
- sodipodi:cy="739.36218"
- sodipodi:rx="17"
- sodipodi:ry="18"
- d="m 133,739.36218 c 0,9.94113 -7.61116,18 -17,18 -9.38884,0 -17,-8.05887 -17,-18 0,-9.94112 7.61116,-18 17,-18 9.38884,0 17,8.05888 17,18 z"
- transform="matrix(0.32722728,0,0,0.3090422,57.632964,458.24316)" />
- <path
- style="color:#000000;fill:#67615b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.10785132;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 95.625,692.36218 0,-11.25"
- id="path3613"
- sodipodi:nodetypes="cc"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="cc"
- id="path3615"
- d="m 90,686.73718 11.25,0"
- style="color:#000000;fill:#67615b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.09;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:connector-curvature="0" />
- </g>
- <g
- inkscape:tile-y0="681.11218"
- inkscape:tile-x0="90"
- id="use3603"
- transform="matrix(0.97186116,0,0,0.97241431,278.34851,193.3134)">
- <path
- sodipodi:type="arc"
- style="fill:none;stroke:#000000;stroke-width:1.41507304;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- id="path3619"
- sodipodi:cx="116"
- sodipodi:cy="739.36218"
- sodipodi:rx="17"
- sodipodi:ry="18"
- d="m 133,739.36218 c 0,9.94113 -7.61116,18 -17,18 -9.38884,0 -17,-8.05887 -17,-18 0,-9.94112 7.61116,-18 17,-18 9.38884,0 17,8.05888 17,18 z"
- transform="matrix(0.32722728,0,0,0.3090422,57.632964,458.24316)" />
- <path
- style="color:#000000;fill:#67615b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.10785132;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 95.625,692.36218 0,-11.25"
- id="path3621"
- sodipodi:nodetypes="cc"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="cc"
- id="path3623"
- d="m 90,686.73718 11.25,0"
- style="color:#000000;fill:#67615b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.09;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:connector-curvature="0" />
- </g>
- <g
- inkscape:tile-y0="681.11218"
- inkscape:tile-x0="90"
- id="use3605"
- transform="matrix(0.97475506,0,0,0.97241431,278.08835,283.31323)">
- <path
- sodipodi:type="arc"
- style="fill:none;stroke:#000000;stroke-width:1.41507304;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- id="path3627"
- sodipodi:cx="116"
- sodipodi:cy="739.36218"
- sodipodi:rx="17"
- sodipodi:ry="18"
- d="m 133,739.36218 c 0,9.94113 -7.61116,18 -17,18 -9.38884,0 -17,-8.05887 -17,-18 0,-9.94112 7.61116,-18 17,-18 9.38884,0 17,8.05888 17,18 z"
- transform="matrix(0.32722728,0,0,0.3090422,57.632964,458.24316)" />
- <path
- style="color:#000000;fill:#67615b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.10785132;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 95.625,692.36218 0,-11.25"
- id="path3629"
- sodipodi:nodetypes="cc"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="cc"
- id="path3631"
- d="m 90,686.73718 11.25,0"
- style="color:#000000;fill:#67615b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.09;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:connector-curvature="0" />
- </g>
- <g
- inkscape:tile-y0="681.11218"
- inkscape:tile-x0="90"
- id="use3607"
- transform="matrix(0.97186116,0,0,0.97241431,8.3485628,283.31356)">
- <path
- sodipodi:type="arc"
- style="fill:none;stroke:#000000;stroke-width:1.41507304;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- id="path3635"
- sodipodi:cx="116"
- sodipodi:cy="739.36218"
- sodipodi:rx="17"
- sodipodi:ry="18"
- d="m 133,739.36218 c 0,9.94113 -7.61116,18 -17,18 -9.38884,0 -17,-8.05887 -17,-18 0,-9.94112 7.61116,-18 17,-18 9.38884,0 17,8.05888 17,18 z"
- transform="matrix(0.32722728,0,0,0.3090422,57.632964,458.24316)" />
- <path
- style="color:#000000;fill:#67615b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.10785132;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 95.625,692.36218 0,-11.25"
- id="path3637"
- sodipodi:nodetypes="cc"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="cc"
- id="path3639"
- d="m 90,686.73718 11.25,0"
- style="color:#000000;fill:#67615b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.09;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:connector-curvature="0" />
- </g>
- <path
- style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.79999995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;marker-end:url(#Arrow2Lend);visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 135,903.85975 157.5,0"
- id="path2829"
- sodipodi:nodetypes="cc"
- inkscape:connector-curvature="0" />
- <text
- xml:space="preserve"
- style="font-size:22px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Minion Pro;-inkscape-font-specification:Minion Pro"
- x="888.10974"
- y="-303.75"
- id="text4236"
- sodipodi:linespacing="125%"
- transform="matrix(0,1,-1,0,0,0)"><tspan
- sodipodi:role="line"
- x="888.10974"
- y="-303.75"
- id="tspan4242">UP</tspan></text>
- </g>
-</svg>
diff --git a/doc/telemega-outline.xsl b/doc/telemega-outline.xsl
new file mode 100644
index 00000000..5d3411e9
--- /dev/null
+++ b/doc/telemega-outline.xsl
@@ -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>TeleMega Outline and Hole Pattern</title>
+ <para>
+ This image, when printed, provides a precise template for the
+ mounting holes in TeleMega. TeleMega has overall dimensions
+ of 1.250 x 3.250 inches, and the mounting holes are sized for
+ use with 4-40 or M3 screws.
+ </para>
+ <informalfigure>
+ <mediaobject id="TeleMegaTemplate">
+ <imageobject>
+ <imagedata format="SVG" fileref="telemega.svg"
+ scalefit="0" scale="100" align="center" />
+ </imageobject>
+ </mediaobject>
+ </informalfigure>
+</article>
+
+<!-- LocalWords: Altusmetrum
+-->
diff --git a/doc/telemega.svg b/doc/telemega.svg
new file mode 100644
index 00000000..40edf696
--- /dev/null
+++ b/doc/telemega.svg
@@ -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="3.5in"
+ height="1.5in"
+ viewBox="0 0 350 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="325" 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="M312.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="M312.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 l225,0"/>
+ <path style="fill:#000000;stroke:none" d="M275,57.5 l10,5 l-10,5 z"/>
+ <!-- label -->
+ <text x="162.5" y="57.5" style="fill:#000000;stroke:none" text-anchor="middle">TeleMega</text>
+ <g transform="rotate(90)">
+ <text x="62.5" y="-290" style="fill:#000000;stroke:none" text-anchor="middle">UP</text>
+ </g>
+ </g>
+</svg> \ No newline at end of file
diff --git a/doc/telemetrum-outline.pdf b/doc/telemetrum-outline.pdf
deleted file mode 100644
index 09ce5577..00000000
--- a/doc/telemetrum-outline.pdf
+++ /dev/null
Binary files differ
diff --git a/doc/telemetrum-outline.svg b/doc/telemetrum-outline.svg
deleted file mode 100644
index aee63ed2..00000000
--- a/doc/telemetrum-outline.svg
+++ /dev/null
@@ -1,207 +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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="427.5"
- height="270"
- id="svg2"
- version="1.1"
- inkscape:version="0.47 r22583"
- sodipodi:docname="telemetrum-outline.svg">
- <defs
- id="defs4">
- <marker
- inkscape:stockid="Arrow2Lend"
- orient="auto"
- refY="0.0"
- refX="0.0"
- id="Arrow2Lend"
- style="overflow:visible;">
- <path
- id="path3866"
- style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
- d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
- transform="scale(1.1) rotate(180) translate(1,0)" />
- </marker>
- <inkscape:perspective
- sodipodi:type="inkscape:persp3d"
- inkscape:vp_x="0 : 526.18109 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_z="744.09448 : 526.18109 : 1"
- inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
- id="perspective10" />
- </defs>
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="1.1459933"
- inkscape:cx="182.36411"
- inkscape:cy="261.60668"
- inkscape:document-units="px"
- inkscape:current-layer="layer1"
- showgrid="false"
- inkscape:window-width="1146"
- inkscape:window-height="846"
- inkscape:window-x="0"
- inkscape:window-y="20"
- inkscape:window-maximized="0"
- units="in" />
- <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></dc:title>
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Layer 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(0,-782.35975)">
- <rect
- style="fill:none;stroke:#000000;stroke-width:0.44999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- id="rect2816"
- width="247.38385"
- height="89.893326"
- x="90.0625"
- y="872.40637" />
- <g
- inkscape:tile-y0="681.11218"
- inkscape:tile-x0="90"
- id="use3601"
- transform="translate(28.141535,264.43715)">
- <path
- sodipodi:type="arc"
- style="fill:none;stroke:#000000;stroke-width:1.41507304;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- id="path3611"
- sodipodi:cx="116"
- sodipodi:cy="739.36218"
- sodipodi:rx="17"
- sodipodi:ry="18"
- d="m 133,739.36218 c 0,9.94113 -7.61116,18 -17,18 -9.38884,0 -17,-8.05887 -17,-18 0,-9.94112 7.61116,-18 17,-18 9.38884,0 17,8.05888 17,18 z"
- transform="matrix(0.32722728,0,0,0.3090422,57.632964,458.24316)" />
- <path
- style="color:#000000;fill:#67615b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.10785132;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 95.625,692.36218 0,-11.25"
- id="path3613"
- sodipodi:nodetypes="cc" />
- <path
- sodipodi:nodetypes="cc"
- id="path3615"
- d="m 90,686.73718 11.25,0"
- style="color:#000000;fill:#67615b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.09;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- </g>
- <g
- inkscape:tile-y0="681.11218"
- inkscape:tile-x0="90"
- id="use3603"
- transform="translate(230.64154,196.89215)">
- <path
- sodipodi:type="arc"
- style="fill:none;stroke:#000000;stroke-width:1.41507304;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- id="path3619"
- sodipodi:cx="116"
- sodipodi:cy="739.36218"
- sodipodi:rx="17"
- sodipodi:ry="18"
- d="m 133,739.36218 c 0,9.94113 -7.61116,18 -17,18 -9.38884,0 -17,-8.05887 -17,-18 0,-9.94112 7.61116,-18 17,-18 9.38884,0 17,8.05888 17,18 z"
- transform="matrix(0.32722728,0,0,0.3090422,57.632964,458.24316)" />
- <path
- style="color:#000000;fill:#67615b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.10785132;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 95.625,692.36218 0,-11.25"
- id="path3621"
- sodipodi:nodetypes="cc" />
- <path
- sodipodi:nodetypes="cc"
- id="path3623"
- d="m 90,686.73718 11.25,0"
- style="color:#000000;fill:#67615b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.09;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- </g>
- <g
- inkscape:tile-y0="681.11218"
- inkscape:tile-x0="90"
- id="use3605"
- transform="translate(230.64154,264.39215)">
- <path
- sodipodi:type="arc"
- style="fill:none;stroke:#000000;stroke-width:1.41507304;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- id="path3627"
- sodipodi:cx="116"
- sodipodi:cy="739.36218"
- sodipodi:rx="17"
- sodipodi:ry="18"
- d="m 133,739.36218 c 0,9.94113 -7.61116,18 -17,18 -9.38884,0 -17,-8.05887 -17,-18 0,-9.94112 7.61116,-18 17,-18 9.38884,0 17,8.05888 17,18 z"
- transform="matrix(0.32722728,0,0,0.3090422,57.632964,458.24316)" />
- <path
- style="color:#000000;fill:#67615b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.10785132;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 95.625,692.36218 0,-11.25"
- id="path3629"
- sodipodi:nodetypes="cc" />
- <path
- sodipodi:nodetypes="cc"
- id="path3631"
- d="m 90,686.73718 11.25,0"
- style="color:#000000;fill:#67615b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.09;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- </g>
- <g
- inkscape:tile-y0="681.11218"
- inkscape:tile-x0="90"
- id="use3607"
- transform="translate(28.141535,196.89215)">
- <path
- sodipodi:type="arc"
- style="fill:none;stroke:#000000;stroke-width:1.41507304;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- id="path3635"
- sodipodi:cx="116"
- sodipodi:cy="739.36218"
- sodipodi:rx="17"
- sodipodi:ry="18"
- d="m 133,739.36218 c 0,9.94113 -7.61116,18 -17,18 -9.38884,0 -17,-8.05887 -17,-18 0,-9.94112 7.61116,-18 17,-18 9.38884,0 17,8.05888 17,18 z"
- transform="matrix(0.32722728,0,0,0.3090422,57.632964,458.24316)" />
- <path
- style="color:#000000;fill:#67615b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.10785132;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 95.625,692.36218 0,-11.25"
- id="path3637"
- sodipodi:nodetypes="cc" />
- <path
- sodipodi:nodetypes="cc"
- id="path3639"
- d="m 90,686.73718 11.25,0"
- style="color:#000000;fill:#67615b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.09;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- </g>
- <path
- style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.80000000000000004;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;marker-end:url(#Arrow2Lend)"
- d="m 135,135 157.5,0"
- id="path2829"
- transform="translate(0,782.35975)"
- sodipodi:nodetypes="cc" />
- <text
- xml:space="preserve"
- style="font-size:22px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Minion Pro;-inkscape-font-specification:Minion Pro"
- x="903.51935"
- y="-305.87912"
- id="text4236"
- sodipodi:linespacing="125%"
- transform="matrix(0,1,-1,0,0,0)"><tspan
- sodipodi:role="line"
- x="903.51935"
- y="-305.87912"
- id="tspan4242">UP</tspan></text>
- </g>
-</svg>
diff --git a/doc/telemetrum-outline.xsl b/doc/telemetrum-outline.xsl
new file mode 100644
index 00000000..4a0ade47
--- /dev/null
+++ b/doc/telemetrum-outline.xsl
@@ -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>TeleMetrum Outline and Hole Pattern</title>
+ <para>
+ This image, when printed, provides a precise template for the
+ mounting holes in TeleMetrum. TeleMetrum has overall dimensions
+ of 1.000 x 2.750 inches, and the mounting holes are sized for
+ use with 4-40 or M3 screws.
+ </para>
+ <informalfigure>
+ <mediaobject id="TeleMetrumTemplate">
+ <imageobject>
+ <imagedata format="SVG" fileref="telemetrum.svg"
+ scalefit="0" scale="100" align="center" />
+ </imageobject>
+ </mediaobject>
+ </informalfigure>
+</article>
+
+<!-- LocalWords: Altusmetrum
+-->
diff --git a/doc/telemetrum.svg b/doc/telemetrum.svg
index 97c4e4a8..80ee182d 100644
--- a/doc/telemetrum.svg
+++ b/doc/telemetrum.svg
@@ -6,14 +6,14 @@
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="5in"
- height="2.5in"
- viewBox="0 0 500 250"
+ width="3in"
+ height="1.25in"
+ viewBox="0 0 300 125"
preserveaspectratio="none"
id="svg2"
version="1.1">
- <g transform="translate(112.5,75)"
- style="fill:none;stroke:#000000;stroke-width:1;stroke-linejoin:miter;font-family:Frutiger LT Std">
+ <g transform="translate(12.5,12.5)"
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-linejoin:miter;font-size:24">
<!-- outline -->
<rect width="275" height="100" x="0" y="0"/>
<!-- holes -->
diff --git a/doc/telemini.svg b/doc/telemini.svg
index d07b4971..b2e21e3d 100644
--- a/doc/telemini.svg
+++ b/doc/telemini.svg
@@ -6,26 +6,26 @@
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="5in"
- height="2in"
- viewBox="0 0 500 200"
+ width="1.75in"
+ height=".75in"
+ viewBox="0 0 175 75"
preserveaspectratio="none"
id="svg2"
version="1.1">
- <g transform="translate(175,75)"
- style="fill:none;stroke:#000000;stroke-width:1;stroke-linejoin:miter;font-family:Frutiger LT Std">
+ <g transform="translate(12.5,12.5)"
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-linejoin:miter;font-size:20">
<!-- outline -->
<rect width="150" height="50" x="0" y="0"/>
<!-- holes -->
- <path d="M135,10 A5,5,0,1,0,145,10 A5,5,0,1,0,135,10 M135,10 l10,0 M140,5 l0,10"/>
- <path d="M135,40 A5,5,0,1,0,145,40 A5,5,0,1,0,135,40 M135,40 l10,0 M140,35 l0,10"/>
+ <path d="M140,10 m-5,0 a5,5,0,1,0,10,0 a5,5,0,1,0,-10,0 l10,0 m-5,-5 l0,10"/>
+ <path d="M140,40 m-5,0 a5,5,0,1,0,10,0 a5,5,0,1,0,-10,0 l10,0 m-5,-5 l0,10"/>
<!-- arrow -->
- <path d="M25,25 l90,0"/>
- <path style="fill:#000000;stroke:none" d="M115,20 l10,5 l-10,5 z"/>
+ <path d="M25,25 l100,0"/>
+ <path style="fill:#000000;stroke:none" d="M125,20 l10,5 l-10,5 z"/>
<!-- label -->
<text x="75" y="20" style="fill:#000000;stroke:none" text-anchor="middle">TeleMini</text>
- <g transform="rotate(90)">
- <text x="25" y="-130" style="fill:#000000;stroke:none" text-anchor="middle">UP</text>
+ <g transform="rotate(90)" style="font-size:14">
+ <text x="25" y="-133" style="fill:#000000;stroke:none" text-anchor="middle">UP</text>
</g>
</g>
</svg> \ No newline at end of file
diff --git a/icon/.gitignore b/icon/.gitignore
new file mode 100644
index 00000000..e89555de
--- /dev/null
+++ b/icon/.gitignore
@@ -0,0 +1,6 @@
+altus-metrum-*.png
+micropeak-*.png
+telegps-*.png
+*.ico
+*.icns
+*.build
diff --git a/icon/Makefile.am b/icon/Makefile.am
new file mode 100644
index 00000000..b1c00f4b
--- /dev/null
+++ b/icon/Makefile.am
@@ -0,0 +1,73 @@
+JAVA_RES=16 32 48 64 128 256
+MAC_RES=16 32 128 256 512
+WIN_RES=16 24 32 48 64 72 96 128 180 256
+RES=$(shell echo $(JAVA_RES) $(MAC_RES) $(WIN_RES) | awk '{ for (i = 1; i <= NF; i++) printf("%s\n", $$i); }' | sort -n -u)
+
+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)
+
+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)
+
+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)
+
+ICO_FILES=altus-metrum.ico micro-peak.ico telegps.ico
+ICNS_FILES=AltosUIIcon.icns TeleGPS.icns MicroPeak.icns
+
+icondir = $(datadir)/icons/hicolor/scalable/apps
+
+AM_ICON = altusmetrum.svg
+MP_ICON = micropeak.svg
+TG_ICON = telegps.svg
+
+icon_DATA = $(AM_ICON) $(MP_ICON) $(TG_ICON)
+
+EXTRA_DIST = $(icon_DATA) $(AM_FILES) $(MP_FILES) $(TG_FILES)
+
+res:
+ echo $(RES)
+
+all-local: $(ICO_FILES) $(ICNS_FILES)
+
+clean-local:
+ $(RM) altus-metrum-*.png telegps-*.png micropeak-*.png *.build *.ico *.icns
+
+$(AM_FILES): altusmetrum.build
+
+altusmetrum.build: altusmetrum.svg
+ for i in $(RES); do rsvg-convert -w $$i -h $$i -o altus-metrum-$$i.png altusmetrum.svg; done && touch $@
+
+$(TG_FILES): telegps.build
+
+telegps.build: telegps.svg
+ for i in $(RES); do rsvg-convert -w $$i -h $$i -o telegps-$$i.png telegps.svg; done && touch $@
+
+$(MP_FILES): micropeak.build
+
+micropeak.build: micropeak.svg
+ for i in $(RES); do rsvg-convert -w $$i -h $$i -o micropeak-$$i.png micropeak.svg; done && touch $@
+
+#clean-local:
+# $(RM) -f $(ICO_FILES)
+
+altus-metrum.ico: $(WIN_AM_FILES)
+ icotool -c -o $@ $(WIN_AM_FILES)
+
+micro-peak.ico: $(WIN_MP_FILES)
+ icotool -c -o $@ $(WIN_MP_FILES)
+
+telegps.ico: $(WIN_TG_FILES)
+ icotool -c -o $@ $(WIN_TG_FILES)
+
+AltosUIIcon.icns: $(MAC_AM_FILES)
+ png2icns $@ $(MAC_AM_FILES)
+
+TeleGPS.icns: $(MAC_TG_FILES)
+ png2icns $@ $(MAC_TG_FILES)
+
+MicroPeak.icns: $(MAC_MP_FILES)
+ png2icns $@ $(MAC_MP_FILES)
diff --git a/icon/altus-metrum-128.png b/icon/altus-metrum-128.png
deleted file mode 100644
index f1343d9e..00000000
--- a/icon/altus-metrum-128.png
+++ /dev/null
Binary files differ
diff --git a/icon/altus-metrum-16.png b/icon/altus-metrum-16.png
deleted file mode 100644
index 5bd45999..00000000
--- a/icon/altus-metrum-16.png
+++ /dev/null
Binary files differ
diff --git a/icon/altus-metrum-256.png b/icon/altus-metrum-256.png
deleted file mode 100644
index 46e1670a..00000000
--- a/icon/altus-metrum-256.png
+++ /dev/null
Binary files differ
diff --git a/icon/altus-metrum-32.png b/icon/altus-metrum-32.png
deleted file mode 100644
index c8588899..00000000
--- a/icon/altus-metrum-32.png
+++ /dev/null
Binary files differ
diff --git a/icon/altus-metrum-48.png b/icon/altus-metrum-48.png
deleted file mode 100644
index 3bee98e6..00000000
--- a/icon/altus-metrum-48.png
+++ /dev/null
Binary files differ
diff --git a/icon/altus-metrum-512.png b/icon/altus-metrum-512.png
deleted file mode 100644
index 47c47003..00000000
--- a/icon/altus-metrum-512.png
+++ /dev/null
Binary files differ
diff --git a/icon/altus-metrum-64.png b/icon/altus-metrum-64.png
deleted file mode 100644
index 0ee086a6..00000000
--- a/icon/altus-metrum-64.png
+++ /dev/null
Binary files differ
diff --git a/icon/altus-metrum.ico b/icon/altus-metrum.ico
deleted file mode 100644
index bedf04ef..00000000
--- a/icon/altus-metrum.ico
+++ /dev/null
Binary files differ
diff --git a/icon/altusmetrum.svg b/icon/altusmetrum.svg
new file mode 100644
index 00000000..e8935a65
--- /dev/null
+++ b/icon/altusmetrum.svg
@@ -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/micro-peak.ico b/icon/micro-peak.ico
deleted file mode 100644
index b672aa04..00000000
--- a/icon/micro-peak.ico
+++ /dev/null
Binary files differ
diff --git a/icon/micropeak-128.png b/icon/micropeak-128.png
deleted file mode 100644
index f045dc6a..00000000
--- a/icon/micropeak-128.png
+++ /dev/null
Binary files differ
diff --git a/icon/micropeak-16.png b/icon/micropeak-16.png
deleted file mode 100644
index d8140802..00000000
--- a/icon/micropeak-16.png
+++ /dev/null
Binary files differ
diff --git a/icon/micropeak-256.png b/icon/micropeak-256.png
deleted file mode 100644
index b96d4706..00000000
--- a/icon/micropeak-256.png
+++ /dev/null
Binary files differ
diff --git a/icon/micropeak-32.png b/icon/micropeak-32.png
deleted file mode 100644
index d34c5c12..00000000
--- a/icon/micropeak-32.png
+++ /dev/null
Binary files differ
diff --git a/icon/micropeak-48.png b/icon/micropeak-48.png
deleted file mode 100644
index 86dc4f7f..00000000
--- a/icon/micropeak-48.png
+++ /dev/null
Binary files differ
diff --git a/icon/micropeak-64.png b/icon/micropeak-64.png
deleted file mode 100644
index 6ca7c2eb..00000000
--- a/icon/micropeak-64.png
+++ /dev/null
Binary files differ
diff --git a/icon/micropeak.svg b/icon/micropeak.svg
new file mode 100644
index 00000000..d37130f5
--- /dev/null
+++ b/icon/micropeak.svg
@@ -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/telegps.svg b/icon/telegps.svg
new file mode 100644
index 00000000..1e390f3b
--- /dev/null
+++ b/icon/telegps.svg
@@ -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/jenkins.sh b/jenkins.sh
new file mode 100755
index 00000000..e6cc7da4
--- /dev/null
+++ b/jenkins.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+# jenkins.sh
+# This script is used by Jenkins to perform a complete rebuild of Altos
+
+
+prefix="--prefix=/usr/local"
+ANDROID_SDK="${ANDROID_SDK:-$HOME/android-sdk-linux}"
+android="--with-android=$ANDROID_SDK"
+# use time if we have it
+time=`which time`
+if [ -n "$time" ]; then
+ time="$time -v"
+fi
+# NOTE: the build process may fail on multi-cpu systems. If it fails try setting cpus=1
+# cpus=$(nproc)
+cpus=1
+
+echo "=== starting altos build at $(date) ==="
+env
+echo "======================================="
+set -x
+
+./autogen.sh $prefix $android
+make -j $cpus clean
+$time make -j $cpus all fat
diff --git a/libaltos/Makefile.am b/libaltos/Makefile.am
index 969aa8ad..d2531133 100644
--- a/libaltos/Makefile.am
+++ b/libaltos/Makefile.am
@@ -5,7 +5,7 @@ AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -source 6
altoslibdir=$(libdir)/altos
altoslib_LTLIBRARIES=libaltos.la
-libaltos_la_LDFLAGS=-version-info 1:0:1
+libaltos_la_LDFLAGS=-version-info 1:0:1 -Wl,-znoexecstack
libaltos_la_SOURCES=\
libaltos.c \
diff --git a/libaltos/libaltos.c b/libaltos/libaltos.c
index a623d5ae..b7ec98fc 100644
--- a/libaltos/libaltos.c
+++ b/libaltos/libaltos.c
@@ -817,7 +817,7 @@ get_string(io_object_t object, CFStringRef entry, char *result, int result_len)
got_string = CFStringGetCString(entry_as_string,
result, result_len,
kCFStringEncodingASCII);
-
+
CFRelease(entry_as_string);
if (got_string)
return 1;
@@ -830,7 +830,7 @@ get_number(io_object_t object, CFStringRef entry, int *result)
{
CFTypeRef entry_as_number;
Boolean got_number;
-
+
entry_as_number = IORegistryEntrySearchCFProperty (object,
kIOServicePlane,
entry,
@@ -885,7 +885,7 @@ altos_list_next(struct altos_list *list, struct altos_device *device)
object = IOIteratorNext(list->iterator);
if (!object)
return 0;
-
+
if (!get_number (object, CFSTR(kUSBVendorID), &device->vendor) ||
!get_number (object, CFSTR(kUSBProductID), &device->product))
continue;
@@ -989,7 +989,7 @@ log_message(char *fmt, ...)
if (log) {
SYSTEMTIME time;
GetLocalTime(&time);
- fprintf (log, "%4d-%02d-%02d %2d:%02d:%02d. ",
+ fprintf (log, "%4d-%02d-%02d %2d:%02d:%02d. ",
time.wYear, time.wMonth, time.wDay,
time.wHour, time.wMinute, time.wSecond);
va_start(a, fmt);
@@ -1340,7 +1340,7 @@ altos_open(struct altos_device *device)
altos_set_last_windows_error();
Sleep(100);
}
-
+
if (file->handle == INVALID_HANDLE_VALUE) {
free(file);
return NULL;
diff --git a/micropeak/.gitignore b/micropeak/.gitignore
index 6a6475f0..f9a61359 100644
--- a/micropeak/.gitignore
+++ b/micropeak/.gitignore
@@ -11,6 +11,7 @@ micropeak-windows.nsi
MicroPeak-Linux-*
MicroPeak-Mac-*
MicroPeak-Windows-*
+micropeak.desktop
*.dll
*.dylib
*.so
diff --git a/micropeak/Makefile.am b/micropeak/Makefile.am
index 1a614cbd..216874df 100644
--- a/micropeak/Makefile.am
+++ b/micropeak/Makefile.am
@@ -1,5 +1,5 @@
JAVAROOT=classes
-AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -source 6
+AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked -source 6
man_MANS=micropeak.1
@@ -72,6 +72,11 @@ ICONJAR= -C $(ICONDIR) micropeak-16.png \
-C $(ICONDIR) micropeak-256.png
WINDOWS_ICON=$(ICONDIR)/micro-peak.ico
+MACOSX_ICON=$(ICONDIR)/MicroPeak.icns
+
+desktopdir = $(datadir)/applications
+desktop_file = micropeak.desktop
+desktop_SCRIPTS = $(desktop_file)
all-local: micropeak-test micropeak-jdb $(JAR)
@@ -84,7 +89,14 @@ clean-local:
micropeak micropeak-test micropeak-jdb macosx linux windows micropeak-windows.log \
micropeak-windows.nsi
+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 > $@
+ chmod +x $@
+
LINUX_DIST=MicroPeak-Linux-$(VERSION).tar.bz2
+LINUX_SH=MicroPeak-Linux-$(VERSION).sh
MACOSX_DIST=MicroPeak-Mac-$(VERSION).dmg
WINDOWS_DIST=MicroPeak-Windows-$(VERSION_DASH).exe
@@ -94,14 +106,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)
-LINUX_EXTRA=micropeak-fat
+LINUX_FILES=$(FAT_FILES) libaltos.so $(FIRMWARE) $(DOC) micropeak.desktop.in ../icon/micropeak.svg
+LINUX_EXTRA=micropeak-fat micropeak.desktop.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_FILES=$(FAT_FILES) libaltos.dylib $(MACOSX_INFO_PLIST) $(MACOSX_DRIVER) $(MACOSX_README) $(DOC) $(MACOSX_ICON)
$(MACOSX_DRIVER):
wget $(MACOSX_DRIVER_URL)
@@ -119,15 +131,20 @@ if FATINSTALL
FATTARGET=$(FATDIR)/$(VERSION)
LINUX_DIST_TARGET=$(FATTARGET)/$(LINUX_DIST)
+LINUX_SH_TARGET=$(FATTARGET)/$(LINUX_SH)
MACOSX_DIST_TARGET=$(FATTARGET)/$(MACOSX_DIST)
WINDOWS_DIST_TARGET=$(FATTARGET)/$(WINDOWS_DIST)
-fat: $(LINUX_DIST_TARGET) $(MACOSX_DIST_TARGET) $(WINDOWS_DIST_TARGET)
+fat: $(LINUX_DIST_TARGET) $(LINUX_SH_TARGET) $(MACOSX_DIST_TARGET) $(WINDOWS_DIST_TARGET)
$(LINUX_DIST_TARGET): $(LINUX_DIST)
mkdir -p $(FATTARGET)
cp -p $< $@
+$(LINUX_SH_TARGET): $(LINUX_SH)
+ mkdir -p $(FATTARGET)
+ cp -p $< $@
+
$(MACOSX_DIST_TARGET): $(MACOSX_DIST)
mkdir -p $(FATTARGET)
cp -p $< $@
@@ -137,7 +154,7 @@ $(WINDOWS_DIST_TARGET): $(WINDOWS_DIST)
cp -p $< $@
else
-fat: $(LINUX_DIST) $(MACOSX_DIST) $(WINDOWS_DIST)
+fat: $(LINUX_DIST) $(LINUX_SH) $(MACOSX_DIST) $(WINDOWS_DIST)
endif
micropeak: Makefile
@@ -230,6 +247,10 @@ $(LINUX_DIST): $(LINUX_FILES) $(LINUX_EXTRA)
chmod +x linux/MicroPeak/micropeak
tar cjf $@ -C linux MicroPeak
+$(LINUX_SH): $(LINUX_DIST) $(srcdir)/../altosui/linux-install.sh
+ sed 's/AltOS/MicroPeak/g' $(srcdir)/../altosui/linux-install.sh | cat - $(LINUX_DIST) > $@
+ chmod +x $@
+
$(MACOSX_DIST): $(MACOSX_FILES)
-rm -f $@
-rm -rf macosx
@@ -240,6 +261,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 $(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
diff --git a/micropeak/MicroData.java b/micropeak/MicroData.java
index e786ff1e..ca211f16 100644
--- a/micropeak/MicroData.java
+++ b/micropeak/MicroData.java
@@ -20,8 +20,8 @@ package org.altusmetrum.micropeak;
import java.lang.*;
import java.io.*;
import java.util.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
class MicroIterator implements Iterator<MicroDataPoint> {
int i;
diff --git a/micropeak/MicroDataPoint.java b/micropeak/MicroDataPoint.java
index 61faf794..5a5e8c37 100644
--- a/micropeak/MicroDataPoint.java
+++ b/micropeak/MicroDataPoint.java
@@ -17,7 +17,7 @@
package org.altusmetrum.micropeak;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altosuilib_2.*;
public class MicroDataPoint implements AltosUIDataPoint {
public double time;
diff --git a/micropeak/MicroDeviceDialog.java b/micropeak/MicroDeviceDialog.java
index 533605d6..305421a7 100644
--- a/micropeak/MicroDeviceDialog.java
+++ b/micropeak/MicroDeviceDialog.java
@@ -21,7 +21,7 @@ import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altosuilib_2.*;
public class MicroDeviceDialog extends AltosDeviceDialog {
diff --git a/micropeak/MicroDownload.java b/micropeak/MicroDownload.java
index 7d2e9eb4..1c70e1d1 100644
--- a/micropeak/MicroDownload.java
+++ b/micropeak/MicroDownload.java
@@ -23,8 +23,8 @@ import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
public class MicroDownload extends AltosUIDialog implements Runnable, ActionListener, MicroSerialLog, WindowListener {
MicroPeak owner;
diff --git a/micropeak/MicroExport.java b/micropeak/MicroExport.java
index c170f544..87d5499b 100644
--- a/micropeak/MicroExport.java
+++ b/micropeak/MicroExport.java
@@ -23,8 +23,8 @@ import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
public class MicroExport extends JFileChooser {
diff --git a/micropeak/MicroFile.java b/micropeak/MicroFile.java
index b6a9d401..019346ae 100644
--- a/micropeak/MicroFile.java
+++ b/micropeak/MicroFile.java
@@ -19,8 +19,8 @@ package org.altusmetrum.micropeak;
import java.io.*;
import java.util.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
public class MicroFile {
diff --git a/micropeak/MicroFileChooser.java b/micropeak/MicroFileChooser.java
index 595d1ff7..00b6690a 100644
--- a/micropeak/MicroFileChooser.java
+++ b/micropeak/MicroFileChooser.java
@@ -20,8 +20,8 @@ package org.altusmetrum.micropeak;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.io.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
public class MicroFileChooser extends JFileChooser {
JFrame frame;
diff --git a/micropeak/MicroFrame.java b/micropeak/MicroFrame.java
index ef8b24cc..5bfe5bf7 100644
--- a/micropeak/MicroFrame.java
+++ b/micropeak/MicroFrame.java
@@ -21,7 +21,7 @@ import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altosuilib_2.*;
public class MicroFrame extends AltosUIFrame {
static String[] micro_icon_names = {
diff --git a/micropeak/MicroGraph.java b/micropeak/MicroGraph.java
index 5960fe4d..f9968919 100644
--- a/micropeak/MicroGraph.java
+++ b/micropeak/MicroGraph.java
@@ -22,8 +22,8 @@ import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
diff --git a/micropeak/MicroPeak.java b/micropeak/MicroPeak.java
index 78bc857e..19e91660 100644
--- a/micropeak/MicroPeak.java
+++ b/micropeak/MicroPeak.java
@@ -23,8 +23,8 @@ import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
public class MicroPeak extends MicroFrame implements ActionListener, ItemListener {
diff --git a/micropeak/MicroRaw.java b/micropeak/MicroRaw.java
index d64da387..26d62012 100644
--- a/micropeak/MicroRaw.java
+++ b/micropeak/MicroRaw.java
@@ -20,8 +20,8 @@ package org.altusmetrum.micropeak;
import java.awt.*;
import java.io.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
public class MicroRaw extends JTextArea {
diff --git a/micropeak/MicroSave.java b/micropeak/MicroSave.java
index 0addfa88..7c5d6abe 100644
--- a/micropeak/MicroSave.java
+++ b/micropeak/MicroSave.java
@@ -24,8 +24,8 @@ import javax.swing.filechooser.FileNameExtensionFilter;
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
public class MicroSave extends JFileChooser {
diff --git a/micropeak/MicroSerial.java b/micropeak/MicroSerial.java
index 39f421ec..37b68636 100644
--- a/micropeak/MicroSerial.java
+++ b/micropeak/MicroSerial.java
@@ -20,7 +20,7 @@ package org.altusmetrum.micropeak;
import java.util.*;
import java.io.*;
import libaltosJNI.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altosuilib_2.*;
public class MicroSerial extends InputStream {
SWIGTYPE_p_altos_file file;
diff --git a/micropeak/MicroSerialLog.java b/micropeak/MicroSerialLog.java
index 0a5a0b91..7300f06d 100644
--- a/micropeak/MicroSerialLog.java
+++ b/micropeak/MicroSerialLog.java
@@ -20,7 +20,7 @@ package org.altusmetrum.micropeak;
import java.util.*;
import java.io.*;
import libaltosJNI.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altosuilib_2.*;
public interface MicroSerialLog {
diff --git a/micropeak/MicroStats.java b/micropeak/MicroStats.java
index 765525b0..45c9f225 100644
--- a/micropeak/MicroStats.java
+++ b/micropeak/MicroStats.java
@@ -18,8 +18,8 @@
package org.altusmetrum.micropeak;
import java.io.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
public class MicroStats {
double coast_height;
diff --git a/micropeak/MicroStatsTable.java b/micropeak/MicroStatsTable.java
index ea1609ac..3b17e731 100644
--- a/micropeak/MicroStatsTable.java
+++ b/micropeak/MicroStatsTable.java
@@ -19,8 +19,8 @@ package org.altusmetrum.micropeak;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_3.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
public class MicroStatsTable extends JComponent implements AltosFontListener {
GridBagLayout layout;
@@ -59,6 +59,7 @@ public class MicroStatsTable extends JComponent implements AltosFontListener {
texts = new JTextField[values.length];
for (int j = 0; j < values.length; j++) {
JTextField value = new JTextField(values[j]);
+ value.setEditable(false);
value.setFont(AltosUILib.value_font);
value.setHorizontalAlignment(SwingConstants.RIGHT);
texts[j] = value;
@@ -160,4 +161,4 @@ public class MicroStatsTable extends JComponent implements AltosFontListener {
this(new MicroStats());
}
-} \ No newline at end of file
+}
diff --git a/micropeak/MicroUSB.java b/micropeak/MicroUSB.java
index 3bd61470..437fa0bc 100644
--- a/micropeak/MicroUSB.java
+++ b/micropeak/MicroUSB.java
@@ -19,7 +19,7 @@ package org.altusmetrum.micropeak;
import java.util.*;
import libaltosJNI.*;
-import org.altusmetrum.altosuilib_1.*;
+import org.altusmetrum.altosuilib_2.*;
public class MicroUSB extends altos_device implements AltosDevice {
diff --git a/micropeak/micropeak-windows.nsi.in b/micropeak/micropeak-windows.nsi.in
index 656f8af3..6dc9d8c1 100644
--- a/micropeak/micropeak-windows.nsi.in
+++ b/micropeak/micropeak-windows.nsi.in
@@ -1,8 +1,10 @@
!addplugindir Instdrv/NSIS/Plugins
-; Definitions for Java 1.6 Detection
-!define JRE_VERSION "1.6"
-!define JRE_ALTERNATE "1.7"
-!define JRE_URL "http://javadl.sun.com/webapps/download/AutoDL?BundleId=52247&/jre-6u27-windows-i586-p.exe"
+!include x64.nsh
+; Definitions for Java 1.7 Detection
+!define JRE_VERSION "1.7"
+!define JRE_ALTERNATE "1.6"
+!define JRE32_URL "http://javadl.sun.com/webapps/download/AutoDL?BundleId=83383&/jre-7u51-windows-i586.exe"
+!define JRE64_URL "http://javadl.sun.com/webapps/download/AutoDL?BundleId=83385&/jre-7u51-windows-x64.exe"
!define PRODUCT_NAME "Altus Metrum Windows Software"
Name "Altus Metrum MicroPeak Installer"
@@ -23,12 +25,34 @@ ShowInstDetails Show
ComponentText "Altus Metrum MicroPeak Software Installer"
+Function .onInit
+ DetailPrint "Checking host operating system"
+ ${If} ${RunningX64}
+ DetailPrint "Installer running on 64-bit host"
+ SetRegView 64
+ StrCpy $INSTDIR "$PROGRAMFILES64\AltusMetrum"
+ ${DisableX64FSRedirection}
+ ${EndIf}
+FunctionEnd
+
+Var JavaDownload
+Var JavaBits
+
Function GetJRE
- MessageBox MB_OK "${PRODUCT_NAME} uses Java ${JRE_VERSION} 32-bit, it will now \
- be downloaded and installed"
+ ${If} ${RunningX64}
+ StrCpy $JavaDownload ${JRE64_URL}
+ StrCpy $JavaBits "64"
+ ${Else}
+ StrCpy $JavaDownload ${JRE32_URL}
+ StrCpy $JavaBits "32"
+ ${EndIf}
+
+ MessageBox MB_OK "${PRODUCT_NAME} uses Java ${JRE_VERSION}, \
+ $JavaBits bits, it will now \
+ be downloaded and installed"
StrCpy $2 "$TEMP\Java Runtime Environment.exe"
- nsisdl::download /TIMEOUT=30000 ${JRE_URL} $2
+ nsisdl::download /TIMEOUT=30000 $JavaDownload $2
Pop $R0 ;Get the return value
StrCmp $R0 "success" +3
MessageBox MB_OK "Download failed: $R0"
@@ -37,7 +61,6 @@ Function GetJRE
Delete $2
FunctionEnd
-
Function DetectJRE
ReadRegStr $2 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment" \
"CurrentVersion"
diff --git a/micropeak/micropeak.desktop.in b/micropeak/micropeak.desktop.in
new file mode 100644
index 00000000..abdf286f
--- /dev/null
+++ b/micropeak/micropeak.desktop.in
@@ -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%/micropeak.svg
+Exec=%bindir%/micropeak %f
+Terminal=false
+MimeType=text/plain;
+Categories=Education;Electronics;Science;
diff --git a/signing-driver b/signing-driver
new file mode 100644
index 00000000..177c5079
--- /dev/null
+++ b/signing-driver
@@ -0,0 +1,20 @@
+Notes on getting a signing key for driver signing
+
+http://technet.microsoft.com/en-us/library/dd919238%28v=ws.10%29.aspx
+
+# use MMC to add the certificates snap-in for ComputerAccount on Local computer
+
+Run console as Administrator:
+
+makecert -r -n "CN=AltusMetrum" -ss AltusMetrumCertStore -sr LocalMachine
+
+# <path> contains the altusmetrum.inf file we ship. Make sure <path>
+# is otherwise empty or inf2cat will get confused
+
+inf2cat /driver:<path> /os:7_X86,7_X64,8_X86,8_X64
+
+signtool sign /s AltusMetrumCertStore /n “AltusMetrum"
+ /t http://timestamp.verisign.com/scripts/timestamp.dll
+ altusmetrum.cat
+
+pnputil -i -a altusmetrum.inf
diff --git a/src/Makefile b/src/Makefile
index 392262d4..4e8b3c20 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -19,11 +19,10 @@ include Makedefs
SDCCDIRS=\
telemetrum-v1.2 telemetrum-v1.1 telemetrum-v1.0 \
teledongle-v0.2 \
- telemini-v1.0 \
+ telemini-v1.0 telemini-v2.0 \
telebt-v1.0 \
teleterra-v0.2 teleshield-v0.1 \
- telefire-v0.1 telefire-v0.2 \
- telemini-v2.0
+ telefire-v0.1 telefire-v0.2
ARMM3DIRS=\
telemega-v0.1 telemega-v0.1/flash-loader \
@@ -31,8 +30,10 @@ ARMM3DIRS=\
telemetrum-v2.0 telemetrum-v2.0/flash-loader \
megadongle-v0.1 megadongle-v0.1/flash-loader \
telegps-v0.3 telegps-v0.3/flash-loader \
+ telegps-v1.0 telegps-v1.0/flash-loader \
telelco-v0.2 telelco-v0.2/flash-loader \
- telescience-v0.2 telescience-v0.2/flash-loader
+ telescience-v0.2 telescience-v0.2/flash-loader \
+ teleballoon-v2.0
ARMM0DIRS=\
easymini-v1.0 easymini-v1.0/flash-loader
diff --git a/src/attiny/ao_async.c b/src/attiny/ao_async.c
index 3556f54c..f64f7bde 100644
--- a/src/attiny/ao_async.c
+++ b/src/attiny/ao_async.c
@@ -40,11 +40,98 @@ ao_async_byte(uint8_t byte)
{
uint8_t b;
uint16_t w;
+ uint8_t v;
+ uint8_t bit;
+ uint8_t w_hi, w_lo;
/* start data stop */
w = (0x000 << 0) | (byte << 1) | (0x001 << 9);
+ w_hi = w >> 8;
+ w_lo = w;
+
ao_arch_block_interrupts();
+
+ /* Ok, this is a bit painful.
+ * We need this loop to be precisely timed, which
+ * means knowing exactly how many instructions will
+ * be executed for each bit. It's easy to do that by
+ * compiling the C code and looking at the output,
+ * but we need this code to work even if the compiler
+ * changes. So, just hand-code the whole thing
+ */
+
+ asm volatile (
+ " ldi %[b], 10\n" // loop value
+ "loop:\n"
+ " in %[v], %[port]\n" // read current value
+ " andi %[v], %[led_mask]\n" // mask to clear LED bit
+ " mov %[bit], %[w_lo]\n" // get current data byte
+ " andi %[bit], 0x01\n" // get current data bit
+#if AO_LED_SERIAL >= 1
+ " add %[bit],%[bit]\n" // shift by one
+#else
+ " nop\n"
+#endif
+#if AO_LED_SERIAL >= 2
+ " add %[bit],%[bit]\n" // shift by one
+#else
+ " nop\n"
+#endif
+#if AO_LED_SERIAL >= 3
+ " add %[bit],%[bit]\n" // shift by one
+#else
+ " nop\n"
+#endif
+#if AO_LED_SERIAL >= 4
+ " add %[bit],%[bit]\n" // shift by one
+#else
+ " nop\n"
+#endif
+#if AO_LED_SERIAL >= 5
+ " add %[bit],%[bit]\n" // shift by one
+#else
+ " nop\n"
+#endif
+#if AO_LED_SERIAL >= 6
+ " add %[bit],%[bit]\n" // shift by one
+#else
+ " nop\n"
+#endif
+#if AO_LED_SERIAL >= 7
+ " add %[bit],%[bit]\n" // shift by one
+#else
+ " nop\n"
+#endif
+ " or %[v], %[bit]\n" // add to register
+ " out %[port], %[v]\n" // write current value
+ " lsr %[w_hi]\n" // shift data
+ " ror %[w_lo]\n" // ...
+ " nop\n"
+ " nop\n"
+ " nop\n"
+ " nop\n"
+ " nop\n"
+
+ " nop\n"
+ " nop\n"
+ " nop\n"
+ " subi %[b], 1\n" // decrement bit count
+ " brne loop\n" // jump back to top
+ : [v] "=&r" (v),
+ [bit] "=&r" (bit),
+ [b] "=&r" (b),
+ [w_lo] "+r" (w_lo),
+ [w_hi] "+r" (w_hi)
+ : [port] "I" (_SFR_IO_ADDR(LED_PORT)),
+ [led_mask] "M" ((~(1 << AO_LED_SERIAL)) & 0xff)
+ );
+
+#if 0
+ /*
+ * Here's the equivalent C code to document
+ * what the above assembly code does
+ */
for (b = 0; b < 10; b++) {
uint8_t v = LED_PORT & ~(1 << AO_LED_SERIAL);
v |= (w & 1) << AO_LED_SERIAL;
@@ -54,6 +141,7 @@ ao_async_byte(uint8_t byte)
/* Carefully timed to hit around 9600 baud */
asm volatile ("nop");
asm volatile ("nop");
+ asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
@@ -67,5 +155,6 @@ ao_async_byte(uint8_t byte)
asm volatile ("nop");
asm volatile ("nop");
}
+#endif
ao_arch_release_interrupts();
}
diff --git a/src/avr-demo/Makefile b/src/avr-demo/Makefile
index 6d9bfea2..e21ad047 100644
--- a/src/avr-demo/Makefile
+++ b/src/avr-demo/Makefile
@@ -2,7 +2,7 @@
# AltOS build
#
#
-vpath % ..:../core:../product:../drivers:../avr
+vpath % ..:../kernel:../product:../drivers:../avr
vpath make-altitude ..
vpath make-kalman ..
vpath kalman.5c ../kalman
@@ -46,7 +46,7 @@ PRODUCT=AvrDemo-v0.0
MCU=atmega32u4
PRODUCT_DEF=-DAVR_DEMO
IDPRODUCT=0x000a
-CFLAGS = $(PRODUCT_DEF) -I. -I../avr -I../core -I..
+CFLAGS = $(PRODUCT_DEF) -I. -I../avr -I../kernel -I..
CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -Os -mcall-prologues
NICKLE=nickle
diff --git a/src/avr/ao_usb_avr.c b/src/avr/ao_usb_avr.c
index bd75b17d..cb0455c2 100644
--- a/src/avr/ao_usb_avr.c
+++ b/src/avr/ao_usb_avr.c
@@ -46,7 +46,7 @@ static __xdata uint8_t ao_usb_ep0_out_len;
static __xdata uint8_t *__xdata ao_usb_ep0_out_data;
static __xdata uint8_t ao_usb_in_flushed;
-static __xdata uint8_t ao_usb_running;
+__xdata uint8_t ao_usb_running;
static __xdata uint8_t ao_usb_configuration;
static __xdata uint8_t ueienx_0;
diff --git a/src/cc1111/Makefile.cc1111 b/src/cc1111/Makefile.cc1111
index 78b653b3..0ea30e1d 100644
--- a/src/cc1111/Makefile.cc1111
+++ b/src/cc1111/Makefile.cc1111
@@ -3,7 +3,7 @@ CC=$(SDCC)
CFLAGS=--model-small --debug --opt-code-speed -DCODESIZE=$(CODESIZE)
-CFLAGS += $(PRODUCT_DEF) -I. -I.. -I../core -I../cc1111 -I../drivers -I../product
+CFLAGS += $(PRODUCT_DEF) -I. -I.. -I../kernel -I../cc1111 -I../drivers -I../product
CODESIZE ?= 0x8000
diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h
index 34235b08..fcac331b 100644
--- a/src/cc1111/ao_arch.h
+++ b/src/cc1111/ao_arch.h
@@ -326,4 +326,6 @@ void
ao_p0_isr(void) __interrupt(13);
#endif
+#define AO_ADC_MAX 32767
+
#endif /* _AO_ARCH_H_ */
diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h
index 2f0e2884..2b19f1f6 100644
--- a/src/cc1111/ao_pins.h
+++ b/src/cc1111/ao_pins.h
@@ -18,12 +18,16 @@
#ifndef _AO_PINS_H_
#define _AO_PINS_H_
-#define HAS_RADIO 1
+#define HAS_RADIO 1
+#define DISABLE_LOG_SPACE 1
#if defined(TELEMETRUM_V_1_0)
+ /* Discontinued and was never built with CC1111 chips needing this */
+ #define NEEDS_CC1111_CLOCK_HACK 0
#define HAS_FLIGHT 1
#define HAS_USB 1
#define HAS_BEEP 1
+ #define HAS_BEEP_CONFIG 0
#define HAS_GPS 1
#define HAS_SERIAL_1 1
#define HAS_ADC 1
@@ -55,9 +59,13 @@
#endif
#if defined(TELEMETRUM_V_1_1)
+ /* Discontinued and was never built with CC1111 chips needing this */
+ #define NEEDS_CC1111_CLOCK_HACK 0
#define HAS_FLIGHT 1
#define HAS_USB 1
#define HAS_BEEP 1
+ #define HAS_BEEP_CONFIG 0
+ #define HAS_BATTERY_REPORT 1
#define HAS_GPS 1
#define HAS_SERIAL_1 1
#define HAS_ADC 1
@@ -91,9 +99,13 @@
#endif
#if defined(TELEMETRUM_V_1_2)
+ /* Discontinued and was never built with CC1111 chips needing this */
+ #define NEEDS_CC1111_CLOCK_HACK 0
#define HAS_FLIGHT 1
#define HAS_USB 1
#define HAS_BEEP 1
+ #define HAS_BEEP_CONFIG 0
+ #define HAS_BATTERY_REPORT 1
#define HAS_GPS 1
#define HAS_SERIAL_1 1
#define HAS_ADC 1
@@ -155,6 +167,8 @@
#endif
#if defined(TELEMINI_V_1_0)
+ /* Discontinued and was never built with CC1111 chips needing this */
+ #define NEEDS_CC1111_CLOCK_HACK 0
#define HAS_FLIGHT 1
#define HAS_USB 0
#define HAS_BEEP 0
@@ -182,6 +196,8 @@
#endif
#if defined(TELENANO_V_0_1)
+ /* Discontinued and was never built with CC1111 chips needing this */
+ #define NEEDS_CC1111_CLOCK_HACK 0
#define HAS_FLIGHT 1
#define HAS_USB 0
#define HAS_BEEP 0
@@ -207,9 +223,12 @@
#endif
#if defined(TELEMETRUM_V_0_1)
+ /* Discontinued and was never built with CC1111 chips needing this */
+ #define NEEDS_CC1111_CLOCK_HACK 0
#define HAS_FLIGHT 1
#define HAS_USB 1
#define HAS_BEEP 1
+ #define HAS_BEEP_CONFIG 0
#define HAS_GPS 1
#define HAS_SERIAL_1 1
#define HAS_ADC 1
@@ -237,6 +256,8 @@
#endif
#if defined(TELEDONGLE_V_0_1)
+ /* Discontinued and was never built with CC1111 chips needing this */
+ #define NEEDS_CC1111_CLOCK_HACK 0
#define HAS_FLIGHT 0
#define HAS_USB 1
#define HAS_BEEP 0
@@ -265,6 +286,8 @@
#endif
#if defined(TIDONGLE)
+ /* Discontinued and was never built with CC1111 chips needing this */
+ #define NEEDS_CC1111_CLOCK_HACK 0
#define HAS_FLIGHT 0
#define HAS_USB 1
#define HAS_BEEP 0
@@ -292,6 +315,8 @@
#endif
#if defined(TELEBT_V_0_0)
+ /* Discontinued and was never built with CC1111 chips needing this */
+ #define NEEDS_CC1111_CLOCK_HACK 0
#define HAS_FLIGHT 0
#define HAS_USB 1
#define HAS_BEEP 0
@@ -328,9 +353,12 @@
#endif
#if defined(TELEBT_V_0_1)
+ /* Discontinued and was never built with CC1111 chips needing this */
+ #define NEEDS_CC1111_CLOCK_HACK 0
#define HAS_FLIGHT 0
#define HAS_USB 1
#define HAS_BEEP 1
+ #define HAS_BEEP_CONFIG 0
#define HAS_SERIAL_1 1
#define HAS_SERIAL_1_ALT_1 1
#define HAS_SERIAL_1_ALT_2 0
@@ -371,6 +399,8 @@
#endif
#if defined(TELELAUNCH_V_0_1)
+ /* Discontinued and was never built with CC1111 chips needing this */
+ #define NEEDS_CC1111_CLOCK_HACK 0
#define HAS_FLIGHT 0
#define HAS_USB 1
#define HAS_BEEP 1
@@ -572,4 +602,21 @@ struct ao_adc {
#endif
};
+/*
+ * Voltage divider on ADC battery sampler
+ */
+#define AO_BATTERY_DIV_PLUS 5 /* 5k */
+#define AO_BATTERY_DIV_MINUS 10 /* 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
+
#endif /* _AO_PINS_H_ */
diff --git a/src/cc1111/ao_timer.c b/src/cc1111/ao_timer.c
index 75cc4ce8..2fbc6621 100644
--- a/src/cc1111/ao_timer.c
+++ b/src/cc1111/ao_timer.c
@@ -83,25 +83,57 @@ ao_timer_init(void)
T1CTL = T1CTL_MODE_MODULO | T1CTL_DIV_8;
}
+#ifndef NEEDS_CC1111_CLOCK_HACK
+#define NEEDS_CC1111_CLOCK_HACK 1
+#endif
+
+#if NEEDS_CC1111_CLOCK_HACK
+static void
+ao_clock_delay(void)
+{
+ uint16_t i = 0;
+
+ while (--i)
+ ao_arch_nop();
+}
+#endif
+
/*
* AltOS always cranks the clock to the max frequency
*/
void
ao_clock_init(void)
{
+#if NEEDS_CC1111_CLOCK_HACK
+ /* Power up both oscillators */
+ SLEEP &= ~(SLEEP_OSC_PD);
+
+ /* Switch to the HFRC oscillator */
+ CLKCON = (CLKCON & ~CLKCON_OSC_MASK) | (CLKCON_OSC_RC);
+
+ /* Wait for the HFRC oscillator to be stable */
+ while (!(SLEEP & SLEEP_HFRC_STB))
+ ;
+
+ /* Delay for 'a while' waiting for the crystal to
+ * stabilize -- the XOSC_STB bit isn't reliable
+ *
+ * http://www.ti.com/lit/er/swrz022c/swrz022c.pdf
+ */
+
+ ao_clock_delay();
+#endif
+
/* Switch system clock to crystal oscilator */
CLKCON = (CLKCON & ~CLKCON_OSC_MASK) | (CLKCON_OSC_XTAL);
+ /* Wait for the HFRC oscillator to be stable */
while (!(SLEEP & SLEEP_XOSC_STB))
;
/* Power down the unused HFRC oscillator */
SLEEP |= SLEEP_OSC_PD;
- /* Wait for HFRC to power down */
- while ((SLEEP & SLEEP_HFRC_STB) != 0)
- ;
-
/* Crank up the timer tick and system clock speed */
CLKCON = ((CLKCON & ~(CLKCON_TICKSPD_MASK | CLKCON_CLKSPD_MASK)) |
(CLKCON_TICKSPD_1 | CLKCON_CLKSPD_1));
diff --git a/src/cc1111/ao_usb.c b/src/cc1111/ao_usb.c
index b0ab409d..d9d255f8 100644
--- a/src/cc1111/ao_usb.c
+++ b/src/cc1111/ao_usb.c
@@ -24,7 +24,7 @@ static __xdata uint16_t ao_usb_in_bytes;
static __pdata uint16_t ao_usb_in_bytes_last;
static __xdata uint16_t ao_usb_out_bytes;
static __pdata uint8_t ao_usb_iif;
-static __pdata uint8_t ao_usb_running;
+__pdata uint8_t ao_usb_running;
static void
ao_usb_set_interrupts(void)
@@ -274,7 +274,7 @@ ao_usb_ep0_setup(void)
ao_usb_ep0_in_len = ao_usb_setup.length;
ao_usb_ep0_flush();
} else if (ao_usb_ep0_out_len) {
-
+
/* Receiving data from the host
*/
ao_usb_ep0_state = AO_USB_EP0_DATA_OUT;
@@ -448,6 +448,9 @@ ao_usb_enable(void)
USBCIF = 0;
USBOIF = 0;
USBIIF = 0;
+#if HAS_USB_PULLUP
+ ao_gpio_set(AO_USB_PULLUP_PORT, AO_USB_PULLUP_PIN, AO_USB_PULLUP, 0);
+#endif
}
void
@@ -459,6 +462,10 @@ ao_usb_disable(void)
USBCIE = 0;
IEN2 &= ~IEN2_USBIE;
+#if HAS_USB_PULLUP
+ ao_gpio_set(AO_USB_PULLUP_PORT, AO_USB_PULLUP_PIN, AO_USB_PULLUP, 0);
+#endif
+
/* Clear any pending interrupts */
USBCIF = 0;
USBOIF = 0;
@@ -471,6 +478,9 @@ ao_usb_disable(void)
void
ao_usb_init(void)
{
+#if HAS_USB_PULLUP
+ ao_enable_output(AO_USB_PULLUP_PORT, AO_USB_PULLUP_PIN, AO_USB_PULLUP, 0);
+#endif
ao_usb_enable();
ao_add_task(&ao_usb_task, ao_usb_ep0, "usb");
diff --git a/src/core/ao_config.h b/src/core/ao_config.h
deleted file mode 100644
index e101af8e..00000000
--- a/src/core/ao_config.h
+++ /dev/null
@@ -1,53 +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_CONFIG_H_
-#define _AO_CONFIG_H_
-
-#ifndef USE_STORAGE_CONFIG
-#define USE_STORAGE_CONFIG 1
-#endif
-
-#ifndef USE_EEPROM_CONFIG
-#define USE_EEPROM_CONFIG 0
-#endif
-
-#if USE_STORAGE_CONFIG
-
-#include <ao_storage.h>
-
-#define ao_config_setup() ao_storage_setup()
-#define ao_config_erase() ao_storage_erase(ao_storage_config)
-#define ao_config_write(pos,bytes, len) ao_storage_write(ao_storage_config+(pos), bytes, len)
-#define ao_config_read(pos,bytes, len) ao_storage_read(ao_storage_config+(pos), bytes, len)
-#define ao_config_flush() ao_storage_flush()
-
-#endif
-
-#if USE_EEPROM_CONFIG
-
-#include <ao_eeprom.h>
-
-#define ao_config_setup()
-#define ao_config_erase()
-#define ao_config_write(pos,bytes, len) ao_eeprom_write(pos, bytes, len)
-#define ao_config_read(pos,bytes, len) ao_eeprom_read(pos, bytes, len)
-#define ao_config_flush()
-
-#endif
-
-#endif /* _AO_CONFIG_H_ */
diff --git a/src/drivers/ao_aprs.c b/src/drivers/ao_aprs.c
index 0a6c72ce..8a1b6a4d 100644
--- a/src/drivers/ao_aprs.c
+++ b/src/drivers/ao_aprs.c
@@ -144,7 +144,6 @@
#endif
#include <ao_aprs.h>
-#include <math.h>
// Public methods, constants, and data structures for each class.
@@ -512,23 +511,38 @@ static int tncComment(uint8_t *buf)
{
#if HAS_ADC
struct ao_data packet;
-
+
ao_arch_critical(ao_data_get(&packet););
int16_t battery = ao_battery_decivolt(packet.adc.v_batt);
+#ifdef AO_SENSE_DROGUE
int16_t apogee = ao_ignite_decivolt(AO_SENSE_DROGUE(&packet));
+#endif
+#ifdef AO_SENSE_MAIN
int16_t main = ao_ignite_decivolt(AO_SENSE_MAIN(&packet));
+#endif
return sprintf((char *) buf,
- "%c%d B%d.%d A%d.%d M%d.%d",
- ao_gps_locked(),
+ "%c%d B%d.%d"
+#ifdef AO_SENSE_DROGUE
+ " A%d.%d"
+#endif
+#ifdef AO_SENSE_MAIN
+ " M%d.%d"
+#endif
+ , ao_gps_locked(),
ao_num_sats(),
battery/10,
- battery % 10,
- apogee/10,
- apogee%10,
- main/10,
- main%10);
+ battery % 10
+#ifdef AO_SENSE_DROGUE
+ , apogee/10,
+ apogee%10
+#endif
+#ifdef AO_SENSE_MAIN
+ , main/10,
+ main%10
+#endif
+ );
#else
return sprintf((char *) buf,
"%c%d",
@@ -537,6 +551,144 @@ static int tncComment(uint8_t *buf)
#endif
}
+/*
+ * APRS use a log encoding of altitude with a base of 1.002, such that
+ *
+ * feet = 1.002 ** encoded_altitude
+ *
+ * meters = (1.002 ** encoded_altitude) * 0.3048
+ *
+ * log2(meters) = log2(1.002 ** encoded_altitude) + log2(0.3048)
+ *
+ * log2(meters) = encoded_altitude * log2(1.002) + log2(0.3048)
+ *
+ * encoded_altitude = (log2(meters) - log2(0.3048)) / log2(1.002)
+ *
+ * encoded_altitude = (log2(meters) + log2(1/0.3048)) * (1/log2(1.002))
+ *
+ * We need 9 bits of mantissa to hold 1/log2(1.002) (~ 347), which leaves us
+ * 23 bits of fraction. That turns out to be *just* enough to avoid any
+ * errors in the result (cool, huh?).
+ */
+
+#define fixed23_int(x) ((uint32_t) ((x) << 23))
+#define fixed23_one fixed23_int(1)
+#define fixed23_two fixed23_int(2)
+#define fixed23_half (fixed23_one >> 1)
+#define fixed23_floor(x) ((x) >> 23)
+#define fixed23_real(x) ((uint32_t) ((x) * fixed23_one + 0.5))
+
+static inline uint64_t
+fixed23_mul(uint32_t x, uint32_t y)
+{
+ return ((uint64_t) x * y + fixed23_half) >> 23;
+}
+
+/*
+ * Use 30 fraction bits for the altitude. We need two bits at the
+ * top as we need to handle x, where 0 <= x < 4. We don't
+ * need 30 bits, but it's actually easier this way as we normalize
+ * the incoming value to 1 <= x < 2, and having the integer portion
+ * way up high means we don't have to deal with shifting in both
+ * directions to cover from 0 to 2**30-1.
+ */
+
+#define fixed30_int(x) ((uint32_t) ((x) << 30))
+#define fixed30_one fixed30_int(1)
+#define fixed30_half (fixed30_one >> 1)
+#define fixed30_two fixed30_int(2)
+
+static inline uint32_t
+fixed30_mul(uint32_t x, uint32_t y)
+{
+ return ((uint64_t) x * y + fixed30_half) >> 30;
+}
+
+/*
+ * Fixed point log2. Takes integer argument, returns
+ * fixed point result with 23 bits of fraction
+ */
+
+static uint32_t
+ao_fixed_log2(uint32_t x)
+{
+ uint32_t result;
+ uint32_t frac = fixed23_one;
+
+ /* Bounds check for sanity */
+ if (x <= 0)
+ return 0;
+
+ if (x >= fixed30_one)
+ return 0xffffffff;
+
+ /*
+ * Normalize and compute integer log portion
+ *
+ * This makes 1 <= x < 2, and computes result to be
+ * the integer portion of the log2 of x
+ */
+
+ for (result = fixed23_int(30); x < fixed30_one; result -= fixed23_one, x <<= 1)
+ ;
+
+ /*
+ * Given x, find y and n such that:
+ *
+ * x = y * 2**n 1 <= y < 2
+ *
+ * That means:
+ *
+ * lb(x) = n + lb(y)
+ *
+ * Now, repeatedly square y to find find z and m such that:
+ *
+ * z = y ** (2**m) 2 <= z < 4
+ *
+ * This is possible because 1 <= y < 2
+ *
+ * lb(y) = lb(z) / 2**m
+ *
+ * (1 + lb(z/2))
+ * = -------------
+ * 2**m
+ *
+ * = 2**-m + 2**-m * lb(z/2)
+ *
+ * Note that if 2 <= z < 4, then 1 <= (z/2) < 2, so we can
+ * iterate to find lb(z/2)
+ *
+ * In this implementation, we don't care about the 'm' value,
+ * instead we only care about 2**-m, which we store in 'frac'
+ */
+
+ while (frac != 0 && x != fixed30_one) {
+ /* Repeatedly square x until 2 <= x < 4 */
+ while (x < fixed30_two) {
+ x = fixed30_mul(x, x);
+
+ /* Divide the fractional result bit by 2 */
+ frac >>= 1;
+ }
+
+ /* Add in this result bit */
+ result |= frac;
+
+ /* Make 1 <= x < 2 again and iterate */
+ x >>= 1;
+ }
+ return result;
+}
+
+#define APRS_LOG_CONVERT fixed23_real(1.714065192056127)
+#define APRS_LOG_BASE fixed23_real(346.920048461100941)
+
+static int
+ao_aprs_encode_altitude(int meters)
+{
+ return fixed23_floor(fixed23_mul(ao_fixed_log2(meters) + APRS_LOG_CONVERT, APRS_LOG_BASE) + fixed23_half);
+}
+
/**
* Generate the plain text position packet.
*/
@@ -565,10 +717,7 @@ static int tncPositionPacket(void)
lat = ((uint64_t) 380926 * (900000000 - latitude)) / 10000000;
lon = ((uint64_t) 190463 * (1800000000 + longitude)) / 10000000;
-#define ALTITUDE_LOG_BASE 0.001998002662673f /* log(1.002) */
-
- alt = (altitude * (int32_t) 10000 + (3048/2)) / (int32_t) 3048;
- alt = logf((float) altitude) * (1/ALTITUDE_LOG_BASE);
+ alt = ao_aprs_encode_altitude(altitude);
tncCompressInt(buf, lat, 4);
buf += 4;
diff --git a/src/drivers/ao_cc115l.c b/src/drivers/ao_cc115l.c
index f0f72d4d..f250e714 100644
--- a/src/drivers/ao_cc115l.c
+++ b/src/drivers/ao_cc115l.c
@@ -52,8 +52,8 @@ struct ao_cc115l_reg {
#if CC115L_TRACE
-const static struct ao_cc115l_reg ao_cc115l_reg[];
-const static char *cc115l_state_name[];
+static const struct ao_cc115l_reg ao_cc115l_reg[];
+static const char *cc115l_state_name[];
enum ao_cc115l_trace_type {
trace_strobe,
@@ -88,6 +88,8 @@ static void trace_add(enum ao_cc115l_trace_type type, int16_t addr, int16_t valu
case trace_strobe:
comment = cc115l_state_name[(value >> 4) & 0x7];
break;
+ default:
+ break;
}
trace[trace_i].type = type;
trace[trace_i].addr = addr;
@@ -197,24 +199,22 @@ ao_radio_tx_fifo_space(void)
return CC115L_FIFO_SIZE - (ao_radio_reg_read(CC115L_TXBYTES) & CC115L_TXBYTES_NUM_TX_BYTES_MASK);
}
-#if UNUSED
+#if CC115L_DEBUG
static uint8_t
ao_radio_status(void)
{
return ao_radio_strobe (CC115L_SNOP);
}
-#endif
-#define ao_radio_rdf_value 0x55
-
-#if UNUSED
static uint8_t
ao_radio_get_marcstate(void)
{
return ao_radio_reg_read(CC115L_MARCSTATE) & CC115L_MARCSTATE_MASK;
}
#endif
-
+
+#define ao_radio_rdf_value 0x55
+
static void
ao_radio_done_isr(void)
{
@@ -612,6 +612,12 @@ ao_radio_rdf_abort(void)
#define POWER_STEP 0x08
+#if HAS_RADIO_POWER
+#define RADIO_POWER ao_config.radio_power
+#else
+#define RADIO_POWER 0xc0
+#endif
+
static void
ao_radio_stx(void)
{
@@ -619,9 +625,10 @@ ao_radio_stx(void)
ao_radio_pa_on();
ao_radio_reg_write(CC115L_PA, 0);
ao_radio_strobe(CC115L_STX);
- for (power = POWER_STEP; power < ao_config.radio_power; power += POWER_STEP)
+ for (power = POWER_STEP; power < RADIO_POWER; power += POWER_STEP)
ao_radio_reg_write(CC115L_PA, power);
- ao_radio_reg_write(CC115L_PA, ao_config.radio_power);
+ if (power != RADIO_POWER)
+ ao_radio_reg_write(CC115L_PA, RADIO_POWER);
}
static void
@@ -668,8 +675,8 @@ ao_radio_test_cmd(void)
static inline int16_t
ao_radio_gpio_bits(void)
{
- return AO_CC115L_DONE_INT_PORT->idr & ((1 << AO_CC115L_FIFO_INT_PIN) |
- (1 << AO_CC115L_DONE_INT_PIN));
+ return ((ao_gpio_get(AO_CC115L_DONE_INT_PORT, AO_CC115L_DONE_INT_PIN, AO_CC115L_DONE_INT) << 1) |
+ ao_gpio_get(AO_CC115L_FIFO_INT_PORT, AO_CC115L_FIFO_INT_PIN, AO_CC115L_FIFO_INT));
}
#endif
@@ -819,7 +826,7 @@ ao_radio_send_aprs(ao_radio_fill_func fill)
}
#if CC115L_DEBUG
-const static char *cc115l_state_name[] = {
+static const char *cc115l_state_name[] = {
[CC115L_STATUS_STATE_IDLE] = "IDLE",
[CC115L_STATUS_STATE_TX] = "TX",
[CC115L_STATUS_STATE_FSTXON] = "FSTXON",
@@ -828,7 +835,7 @@ const static char *cc115l_state_name[] = {
[CC115L_STATUS_STATE_TX_FIFO_UNDERFLOW] = "TX_FIFO_UNDERFLOW",
};
-const static struct ao_cc115l_reg ao_cc115l_reg[] = {
+static const struct ao_cc115l_reg ao_cc115l_reg[] = {
{ .addr = CC115L_IOCFG2, .name = "IOCFG2" },
{ .addr = CC115L_IOCFG1, .name = "IOCFG1" },
{ .addr = CC115L_IOCFG0, .name = "IOCFG0" },
@@ -874,7 +881,7 @@ const static struct ao_cc115l_reg ao_cc115l_reg[] = {
static void ao_radio_show(void) {
uint8_t status = ao_radio_status();
- int i;
+ unsigned int i;
ao_radio_get();
status = ao_radio_status();
diff --git a/src/drivers/ao_gps_ublox.c b/src/drivers/ao_gps_ublox.c
index 01169522..077698a9 100644
--- a/src/drivers/ao_gps_ublox.c
+++ b/src/drivers/ao_gps_ublox.c
@@ -601,6 +601,14 @@ static const uint8_t ublox_enable_nav[] = {
};
void
+ao_gps_set_rate(uint8_t rate)
+{
+ uint8_t i;
+ for (i = 0; i < sizeof (ublox_enable_nav); i++)
+ ao_ublox_set_message_rate(UBLOX_NAV, ublox_enable_nav[i], rate);
+}
+
+void
ao_gps(void) __reentrant
{
uint8_t class, id;
@@ -616,8 +624,7 @@ ao_gps(void) __reentrant
ao_ublox_set_message_rate(UBLOX_NAV, ublox_disable_nav[i], 0);
/* Enable all of the messages we want */
- for (i = 0; i < sizeof (ublox_enable_nav); i++)
- ao_ublox_set_message_rate(UBLOX_NAV, ublox_enable_nav[i], 1);
+ ao_gps_set_rate(1);
ao_ublox_set_navigation_settings((1 << UBLOX_CFG_NAV5_MASK_DYN) | (1 << UBLOX_CFG_NAV5_MASK_FIXMODE),
UBLOX_CFG_NAV5_DYNMODEL_AIRBORNE_4G,
@@ -713,7 +720,7 @@ ao_gps(void) __reentrant
ao_gps_data.flags |= AO_GPS_RUNNING;
if (nav_sol.gps_fix & (1 << NAV_SOL_FLAGS_GPSFIXOK)) {
uint8_t nsat = nav_sol.nsat;
- ao_gps_data.flags |= AO_GPS_VALID;
+ ao_gps_data.flags |= AO_GPS_VALID | AO_GPS_COURSE_VALID;
if (nsat > 15)
nsat = 15;
ao_gps_data.flags |= nsat;
diff --git a/src/drivers/ao_lco_func.c b/src/drivers/ao_lco_func.c
index a5d28e61..9e642836 100644
--- a/src/drivers/ao_lco_func.c
+++ b/src/drivers/ao_lco_func.c
@@ -36,7 +36,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(20));
+ r = ao_radio_cmac_recv(query, sizeof (*query), AO_MS_TO_TICKS(10));
if (r == AO_RADIO_CMAC_OK)
*tick_offset = sent_time - query->tick;
ao_mutex_put(&ao_lco_mutex);
diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c
index 58ab9197..6098699e 100644
--- a/src/drivers/ao_ms5607.c
+++ b/src/drivers/ao_ms5607.c
@@ -21,8 +21,8 @@
#if HAS_MS5607 || HAS_MS5611
-static __xdata struct ao_ms5607_prom ms5607_prom;
-static __xdata uint8_t ms5607_configured;
+__xdata struct ao_ms5607_prom ao_ms5607_prom;
+static __xdata uint8_t ms5607_configured;
static void
ao_ms5607_start(void) {
@@ -111,7 +111,7 @@ ao_ms5607_setup(void)
return;
ms5607_configured = 1;
ao_ms5607_reset();
- ao_ms5607_prom_read(&ms5607_prom);
+ ao_ms5607_prom_read(&ao_ms5607_prom);
}
static __xdata volatile uint8_t ao_ms5607_done;
@@ -208,14 +208,14 @@ __xdata struct ao_task ao_ms5607_task;
void
ao_ms5607_info(void)
{
- printf ("ms5607 reserved: %u\n", ms5607_prom.reserved);
- printf ("ms5607 sens: %u\n", ms5607_prom.sens);
- printf ("ms5607 off: %u\n", ms5607_prom.off);
- printf ("ms5607 tcs: %u\n", ms5607_prom.tcs);
- printf ("ms5607 tco: %u\n", ms5607_prom.tco);
- printf ("ms5607 tref: %u\n", ms5607_prom.tref);
- printf ("ms5607 tempsens: %u\n", ms5607_prom.tempsens);
- printf ("ms5607 crc: %u\n", ms5607_prom.crc);
+ printf ("ms5607 reserved: %u\n", ao_ms5607_prom.reserved);
+ printf ("ms5607 sens: %u\n", ao_ms5607_prom.sens);
+ printf ("ms5607 off: %u\n", ao_ms5607_prom.off);
+ printf ("ms5607 tcs: %u\n", ao_ms5607_prom.tcs);
+ printf ("ms5607 tco: %u\n", ao_ms5607_prom.tco);
+ printf ("ms5607 tref: %u\n", ao_ms5607_prom.tref);
+ printf ("ms5607 tempsens: %u\n", ao_ms5607_prom.tempsens);
+ printf ("ms5607 crc: %u\n", ao_ms5607_prom.crc);
}
static void
diff --git a/src/drivers/ao_ms5607.h b/src/drivers/ao_ms5607.h
index 206efd64..b58178fd 100644
--- a/src/drivers/ao_ms5607.h
+++ b/src/drivers/ao_ms5607.h
@@ -57,6 +57,7 @@ struct ao_ms5607_value {
};
extern __xdata struct ao_ms5607_sample ao_ms5607_current;
+extern __xdata struct ao_ms5607_prom ao_ms5607_prom;
void
ao_ms5607_setup(void);
@@ -74,7 +75,4 @@ void
ao_ms5607_convert(__xdata struct ao_ms5607_sample *sample,
__xdata struct ao_ms5607_value *value);
-void
-ao_ms5607_get_prom(__data struct ao_ms5607_prom *prom);
-
#endif /* _AO_MS5607_H_ */
diff --git a/src/drivers/ao_ms5607_convert.c b/src/drivers/ao_ms5607_convert.c
index bfb952a4..4d412cbe 100644
--- a/src/drivers/ao_ms5607_convert.c
+++ b/src/drivers/ao_ms5607_convert.c
@@ -25,16 +25,16 @@ ao_ms5607_convert(struct ao_ms5607_sample *sample, struct ao_ms5607_value *value
int64_t OFF;
int64_t SENS;
- dT = sample->temp - ((int32_t) ms5607_prom.tref << 8);
+ dT = sample->temp - ((int32_t) ao_ms5607_prom.tref << 8);
- TEMP = 2000 + (((int64_t) dT * ms5607_prom.tempsens) >> 23);
+ TEMP = 2000 + (((int64_t) dT * ao_ms5607_prom.tempsens) >> 23);
#if HAS_MS5611
- OFF = ((int64_t) ms5607_prom.off << 16) + (((int64_t) ms5607_prom.tco * dT) >> 7);
- SENS = ((int64_t) ms5607_prom.sens << 15) + (((int64_t) ms5607_prom.tcs * dT) >> 8);
+ OFF = ((int64_t) ao_ms5607_prom.off << 16) + (((int64_t) ao_ms5607_prom.tco * dT) >> 7);
+ SENS = ((int64_t) ao_ms5607_prom.sens << 15) + (((int64_t) ao_ms5607_prom.tcs * dT) >> 8);
#else
- OFF = ((int64_t) ms5607_prom.off << 17) + (((int64_t) ms5607_prom.tco * dT) >> 6);
- SENS = ((int64_t) ms5607_prom.sens << 16) + (((int64_t) ms5607_prom.tcs * dT) >> 7);
+ OFF = ((int64_t) ao_ms5607_prom.off << 17) + (((int64_t) ao_ms5607_prom.tco * dT) >> 6);
+ SENS = ((int64_t) ao_ms5607_prom.sens << 16) + (((int64_t) ao_ms5607_prom.tcs * dT) >> 7);
#endif
if (TEMP < 2000) {
diff --git a/src/drivers/ao_ms5607_convert_8051.c b/src/drivers/ao_ms5607_convert_8051.c
index f3a48c46..a74086d9 100644
--- a/src/drivers/ao_ms5607_convert_8051.c
+++ b/src/drivers/ao_ms5607_convert_8051.c
@@ -40,30 +40,30 @@ ao_ms5607_convert(__xdata struct ao_ms5607_sample *sample,
__LOCAL ao_int64_t SENS;
__LOCAL ao_int64_t a;
- dT = sample->temp - ((int32_t) ms5607_prom.tref << 8);
+ dT = sample->temp - ((int32_t) ao_ms5607_prom.tref << 8);
- /* TEMP = 2000 + (((int64_t) dT * ms5607_prom.tempsens) >> 23); */
- ao_mul64_32_32(&a, dT, ms5607_prom.tempsens);
+ /* TEMP = 2000 + (((int64_t) dT * ao_ms5607_prom.tempsens) >> 23); */
+ ao_mul64_32_32(&a, dT, ao_ms5607_prom.tempsens);
ao_rshift64(&a, &a, 23);
TEMP = 2000 + a.low;
/* */
- /* OFF = ((int64_t) ms5607_prom.off << SHIFT_OFF) + (((int64_t) ms5607_prom.tco * dT) >> SHIFT_TCO);*/
+ /* OFF = ((int64_t) ao_ms5607_prom.off << SHIFT_OFF) + (((int64_t) ao_ms5607_prom.tco * dT) >> SHIFT_TCO);*/
#if SHIFT_OFF > 16
- OFF.high = ms5607_prom.off >> (32 - SHIFT_OFF);
+ OFF.high = ao_ms5607_prom.off >> (32 - SHIFT_OFF);
#else
OFF.high = 0;
#endif
- OFF.low = (uint32_t) ms5607_prom.off << SHIFT_OFF;
- ao_mul64_32_32(&a, ms5607_prom.tco, dT);
+ OFF.low = (uint32_t) ao_ms5607_prom.off << SHIFT_OFF;
+ ao_mul64_32_32(&a, ao_ms5607_prom.tco, dT);
ao_rshift64(&a, &a, SHIFT_TCO);
ao_plus64(&OFF, &OFF, &a);
/**/
- /* SENS = ((int64_t) ms5607_prom.sens << SHIFT_SENS) + (((int64_t) ms5607_prom.tcs * dT) >> SHIFT_TCS); */
+ /* SENS = ((int64_t) ao_ms5607_prom.sens << SHIFT_SENS) + (((int64_t) ao_ms5607_prom.tcs * dT) >> SHIFT_TCS); */
SENS.high = 0;
- SENS.low = (uint32_t) ms5607_prom.sens << SHIFT_SENS;
- ao_mul64_32_32(&a, ms5607_prom.tcs, dT);
+ SENS.low = (uint32_t) ao_ms5607_prom.sens << SHIFT_SENS;
+ ao_mul64_32_32(&a, ao_ms5607_prom.tcs, dT);
ao_rshift64(&a, &a, SHIFT_TCS);
ao_plus64(&SENS, &SENS, &a);
/**/
diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c
index 62ae68e9..144cbd70 100644
--- a/src/drivers/ao_pad.c
+++ b/src/drivers/ao_pad.c
@@ -153,11 +153,11 @@ ao_pad_monitor(void)
*
* v_pyro \
* 100k igniter
- * output /
+ * output /
* 100k \
* sense relay
- * 27k /
- * gnd ---
+ * 27k /
+ * gnd ---
*
* If the relay is closed, then sense will be 0
* If no igniter is present, then sense will be v_pyro * 27k/227k = pyro * 127 / 227 ~= pyro/2
diff --git a/src/drivers/ao_pca9922.c b/src/drivers/ao_pca9922.c
index d376b968..6d1b5fae 100644
--- a/src/drivers/ao_pca9922.c
+++ b/src/drivers/ao_pca9922.c
@@ -66,6 +66,24 @@ ao_led_set_mask(uint8_t colors, uint8_t mask)
ao_led_apply();
}
+#define LED_TEST 1
+#if LED_TEST
+static void
+ao_led_test(void)
+{
+ ao_cmd_hexbyte();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ ao_led_set(ao_cmd_lex_i);
+ printf("LEDs set to %02x\n", ao_cmd_lex_i);
+}
+
+static const struct ao_cmds ao_led_cmds[] = {
+ { ao_led_test, "l <value>\0Set LEDs to <value>" },
+ { 0, NULL }
+};
+#endif
+
void
ao_led_toggle(uint8_t colors)
{
@@ -86,4 +104,7 @@ ao_led_init(uint8_t enable)
{
(void) enable;
ao_enable_output(AO_PCA9922_CS_PORT, AO_PCA9922_CS_PIN, AO_PCA9922_CS, 1);
+#if LED_TEST
+ ao_cmd_register(&ao_led_cmds[0]);
+#endif
}
diff --git a/src/drivers/ao_quadrature.c b/src/drivers/ao_quadrature.c
index d07488d0..0cdcc9fb 100644
--- a/src/drivers/ao_quadrature.c
+++ b/src/drivers/ao_quadrature.c
@@ -22,11 +22,14 @@
#include <ao_event.h>
__xdata int32_t ao_quadrature_count[AO_QUADRATURE_COUNT];
-static uint8_t ao_quadrature_state[AO_QUADRATURE_COUNT];
-static int8_t ao_quadrature_raw[AO_QUADRATURE_COUNT];
+static uint8_t ao_quadrature_state[AO_QUADRATURE_COUNT];
-#define BIT(a,b) ((a) | ((b) << 1))
-#define STATE(old_a, old_b, new_a, new_b) (((BIT(old_a, old_b) << 2) | BIT(new_a, new_b)))
+struct ao_debounce {
+ uint8_t state;
+ uint8_t count;
+};
+
+static struct ao_debounce ao_debounce_state[AO_QUADRATURE_COUNT][2];
#define port(q) AO_QUADRATURE_ ## q ## _PORT
#define bita(q) AO_QUADRATURE_ ## q ## _A
@@ -35,14 +38,35 @@ static int8_t ao_quadrature_raw[AO_QUADRATURE_COUNT];
#define pinb(q) AO_QUADRATURE_ ## q ## _B ## _PIN
#define isr(q) ao_quadrature_isr_ ## q
-static inline uint16_t
-ao_quadrature_read(struct stm_gpio *gpio, uint8_t pin_a, uint8_t pin_b) {
- uint16_t v = stm_gpio_get_all(gpio);
+#define DEBOUNCE 10
- return ~((((v >> pin_a) & 1) | (((v >> pin_b) & 1) << 1))) & 3;
+static uint8_t
+ao_debounce(uint8_t cur, struct ao_debounce *debounce)
+{
+ if (cur == debounce->state)
+ debounce->count = 0;
+ else {
+ if (++debounce->count == DEBOUNCE) {
+ debounce->state = cur;
+ debounce->count = 0;
+ }
+ }
+ return debounce->state;
}
-#define _ao_quadrature_get(q) ao_quadrature_read(port(q), bita(q), bitb(q))
+static uint16_t
+ao_quadrature_read(struct stm_gpio *gpio, uint8_t pin_a, uint8_t pin_b, struct ao_debounce debounce_state[2]) {
+ uint16_t v = ~stm_gpio_get_all(gpio);
+ uint8_t a = (v >> pin_a) & 1;
+ uint8_t b = (v >> pin_b) & 1;
+
+ a = ao_debounce(a, &debounce_state[0]);
+ b = ao_debounce(b, &debounce_state[1]);
+
+ return a | (b << 1);
+}
+
+#define _ao_quadrature_get(q) ao_quadrature_read(port(q), bita(q), bitb(q), ao_debounce_state[q])
static void
_ao_quadrature_queue(uint8_t q, int8_t step)
@@ -54,51 +78,28 @@ _ao_quadrature_queue(uint8_t q, int8_t step)
ao_wakeup(&ao_quadrature_count[q]);
}
-static const int8_t step[16] = {
- [STATE(0,0,0,0)] = 0,
- [STATE(0,0,0,1)] = -1,
- [STATE(0,0,1,0)] = 1,
- [STATE(0,0,1,1)] = 0,
- [STATE(0,1,0,0)] = 1,
- [STATE(0,1,1,0)] = 0,
- [STATE(0,1,1,1)] = -1,
- [STATE(1,0,0,0)] = -1,
- [STATE(1,0,0,1)] = 0,
- [STATE(1,0,1,0)] = 0,
- [STATE(1,0,1,1)] = 1,
- [STATE(1,1,0,0)] = 0,
- [STATE(1,1,0,1)] = 1,
- [STATE(1,1,1,0)] = -1,
- [STATE(1,1,1,1)] = 0
-};
-
static void
-_ao_quadrature_set(uint8_t q, uint8_t value) {
- uint8_t v;
-
- v = ao_quadrature_state[q] & 3;
- value = value & 3;
-
- if (v == value)
- return;
-
- ao_quadrature_state[q] = (v << 2) | value;
+_ao_quadrature_set(uint8_t q, uint8_t new) {
+ uint8_t old = ao_quadrature_state[q];
- ao_quadrature_raw[q] += step[ao_quadrature_state[q]];
- if (value == 0) {
- if (ao_quadrature_raw[q] == 4)
+ if (old != new && new == 0) {
+ if (old & 2)
_ao_quadrature_queue(q, 1);
- else if (ao_quadrature_raw[q] == -4)
+ else if (old & 1)
_ao_quadrature_queue(q, -1);
- ao_quadrature_raw[q] = 0;
}
+ ao_quadrature_state[q] = new;
}
static void
ao_quadrature_isr(void)
{
+#if AO_QUADRATURE_COUNT > 0
_ao_quadrature_set(0, _ao_quadrature_get(0));
+#endif
+#if AO_QUADRATURE_COUNT > 1
_ao_quadrature_set(1, _ao_quadrature_get(1));
+#endif
}
int32_t
@@ -120,6 +121,8 @@ static void
ao_quadrature_test(void)
{
uint8_t q;
+ int32_t c;
+ uint8_t s;
ao_cmd_decimal();
q = ao_cmd_lex_i;
@@ -127,10 +130,18 @@ ao_quadrature_test(void)
ao_cmd_status = ao_cmd_syntax_error;
return;
}
- printf ("count %d state %x raw %d\n",
- ao_quadrature_count[q],
- ao_quadrature_state[q],
- ao_quadrature_raw[q]);
+
+ c = -10000;
+ s = 0;
+ while (ao_quadrature_count[q] != 10) {
+ if (ao_quadrature_count[q] != c ||
+ ao_quadrature_state[q] != s) {
+ c = ao_quadrature_count[q];
+ s = ao_quadrature_state[q];
+ printf ("count %3d state %2x\n", c, s);
+ flush();
+ }
+ }
#if 0
for (;;) {
int32_t c;
diff --git a/src/easymega-v0.1/.gitignore b/src/easymega-v0.1/.gitignore
new file mode 100644
index 00000000..410943d5
--- /dev/null
+++ b/src/easymega-v0.1/.gitignore
@@ -0,0 +1,2 @@
+ao_product.h
+easymega-*.elf
diff --git a/src/easymega-v0.1/Makefile b/src/easymega-v0.1/Makefile
new file mode 100644
index 00000000..66619852
--- /dev/null
+++ b/src/easymega-v0.1/Makefile
@@ -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-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
new file mode 100644
index 00000000..e217c33c
--- /dev/null
+++ b/src/easymega-v0.1/ao_easymega.c
@@ -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-v0.1/ao_pins.h b/src/easymega-v0.1/ao_pins.h
new file mode 100644
index 00000000..cb6e3980
--- /dev/null
+++ b/src/easymega-v0.1/ao_pins.h
@@ -0,0 +1,352 @@
+/*
+ * 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
new file mode 100644
index 00000000..35312fd6
--- /dev/null
+++ b/src/easymega-v0.1/flash-loader/Makefile
@@ -0,0 +1,8 @@
+#
+# 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
new file mode 100644
index 00000000..445289bf
--- /dev/null
+++ b/src/easymega-v0.1/flash-loader/ao_pins.h
@@ -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_ */
diff --git a/src/easymini-v1.0/Makefile b/src/easymini-v1.0/Makefile
index 7dae2692..654be22b 100644
--- a/src/easymini-v1.0/Makefile
+++ b/src/easymini-v1.0/Makefile
@@ -32,6 +32,7 @@ ALTOS_SRC = \
ao_sample.c \
ao_data.c \
ao_convert_pa.c \
+ ao_convert_volt.c \
ao_task.c \
ao_log.c \
ao_log_mini.c \
diff --git a/src/easymini-v1.0/ao_pins.h b/src/easymini-v1.0/ao_pins.h
index e721030d..0edde5a2 100644
--- a/src/easymini-v1.0/ao_pins.h
+++ b/src/easymini-v1.0/ao_pins.h
@@ -15,8 +15,8 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#define HAS_BEEP 1
-#define HAS_LED 0
+#define HAS_BEEP 1
+#define HAS_BATTERY_REPORT 1
#define AO_STACK_SIZE 384
@@ -134,3 +134,20 @@ struct ao_adc {
#define AO_ADC_DUMP(p) \
printf("tick: %5u apogee: %5d main: %5d batt: %5d\n", \
(p)->tick, (p)->adc.sense_a, (p)->adc.sense_m, (p)->adc.v_batt)
+
+/*
+ * Voltage divider on ADC battery sampler
+ */
+#define AO_BATTERY_DIV_PLUS 100 /* 100k */
+#define AO_BATTERY_DIV_MINUS 27 /* 27k */
+
+/*
+ * 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
diff --git a/src/core/altitude.h b/src/kernel/altitude.h
index a278bbc6..a278bbc6 100644
--- a/src/core/altitude.h
+++ b/src/kernel/altitude.h
diff --git a/src/core/ao.h b/src/kernel/ao.h
index 29ad2603..5ff9b518 100644
--- a/src/core/ao.h
+++ b/src/kernel/ao.h
@@ -394,6 +394,9 @@ struct ao_gps_tracking_orig {
};
void
+ao_gps_set_rate(uint8_t rate);
+
+void
ao_gps(void);
void
@@ -737,6 +740,7 @@ ao_igniter_init(void);
/*
* ao_config.c
*/
+#include <ao_config.h>
#if AO_PYRO_NUM
#include <ao_pyro.h>
@@ -749,81 +753,6 @@ ao_igniter_init(void);
extern __xdata uint8_t ao_force_freq;
#endif
-#define AO_CONFIG_MAJOR 1
-#define AO_CONFIG_MINOR 15
-
-#define AO_AES_LEN 16
-
-extern __xdata uint8_t ao_config_aes_seq;
-
-struct ao_config {
- uint8_t major;
- uint8_t minor;
- uint16_t main_deploy;
- int16_t accel_plus_g; /* changed for minor version 2 */
- uint8_t _legacy_radio_channel;
- char callsign[AO_MAX_CALLSIGN + 1];
- uint8_t apogee_delay; /* minor version 1 */
- int16_t accel_minus_g; /* minor version 2 */
- uint32_t radio_cal; /* minor version 3 */
- uint32_t flight_log_max; /* minor version 4 */
- uint8_t ignite_mode; /* minor version 5 */
- uint8_t pad_orientation; /* minor version 6 */
- uint32_t radio_setting; /* minor version 7 */
- uint8_t radio_enable; /* minor version 8 */
- uint8_t aes_key[AO_AES_LEN]; /* minor version 9 */
- uint32_t frequency; /* minor version 10 */
- uint16_t apogee_lockout; /* minor version 11 */
-#if AO_PYRO_NUM
- struct ao_pyro pyro[AO_PYRO_NUM]; /* minor version 12 */
-#endif
- uint16_t aprs_interval; /* minor version 13 */
-#if HAS_RADIO_POWER
- uint8_t radio_power; /* minor version 14 */
-#endif
-#if HAS_RADIO_AMP
- uint8_t radio_amp; /* minor version 14 */
-#endif
-#if HAS_GYRO
- int16_t accel_zero_along; /* minor version 15 */
- int16_t accel_zero_across; /* minor version 15 */
- int16_t accel_zero_through; /* minor version 15 */
-#endif
-};
-
-#define AO_IGNITE_MODE_DUAL 0
-#define AO_IGNITE_MODE_APOGEE 1
-#define AO_IGNITE_MODE_MAIN 2
-
-#define AO_RADIO_ENABLE_CORE 1
-#define AO_RADIO_DISABLE_TELEMETRY 2
-#define AO_RADIO_DISABLE_RDF 4
-
-#define AO_PAD_ORIENTATION_ANTENNA_UP 0
-#define AO_PAD_ORIENTATION_ANTENNA_DOWN 1
-
-extern __xdata struct ao_config ao_config;
-
-#define AO_CONFIG_MAX_SIZE 128
-
-void
-_ao_config_edit_start(void);
-
-void
-_ao_config_edit_finish(void);
-
-void
-ao_config_get(void);
-
-void
-ao_config_put(void);
-
-void
-ao_config_set_radio(void);
-
-void
-ao_config_init(void);
-
/*
* ao_rssi.c
*/
diff --git a/src/core/ao_adc.h b/src/kernel/ao_adc.h
index 373db1c4..373db1c4 100644
--- a/src/core/ao_adc.h
+++ b/src/kernel/ao_adc.h
diff --git a/src/core/ao_aes.h b/src/kernel/ao_aes.h
index c47bc2db..c47bc2db 100644
--- a/src/core/ao_aes.h
+++ b/src/kernel/ao_aes.h
diff --git a/src/teleballoon-v1.1/ao_balloon.c b/src/kernel/ao_balloon.c
index 12752d1f..904a9c08 100644
--- a/src/teleballoon-v1.1/ao_balloon.c
+++ b/src/kernel/ao_balloon.c
@@ -31,6 +31,13 @@
#error Please define HAS_USB
#endif
+#if HAS_SENSOR_ERRORS
+/* Any sensor can set this to mark the flight computer as 'broken' */
+__xdata uint8_t ao_sensor_errors;
+#endif
+
+__pdata uint16_t ao_motor_number; /* number of motors burned so far */
+
/* Main flight thread. */
__pdata enum ao_flight_state ao_flight_state; /* current flight state */
@@ -67,7 +74,8 @@ ao_flight(void)
/* Disable the USB controller in flight mode
* to save power
*/
- ao_usb_disable();
+ if (!ao_usb_running)
+ ao_usb_disable();
#endif
/* Disable packet mode in pad state */
@@ -112,9 +120,8 @@ ao_flight(void)
ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
}
break;
- case ao_flight_drogue:
+ default:
break;
-
}
}
}
diff --git a/src/core/ao_beep.h b/src/kernel/ao_beep.h
index 55f61171..9d6ecf27 100644
--- a/src/core/ao_beep.h
+++ b/src/kernel/ao_beep.h
@@ -18,6 +18,12 @@
#ifndef _AO_BEEP_H_
#define _AO_BEEP_H_
+#ifndef HAS_BEEP_CONFIG
+#if defined(USE_EEPROM_CONFIG) && USE_EEPROM_CONFIG || HAS_EEPROM
+#define HAS_BEEP_CONFIG 1
+#endif
+#endif
+
/*
* ao_beep.c
*/
@@ -28,9 +34,16 @@
* frequency = 1/2 (24e6/32) / beep
*/
-#define AO_BEEP_LOW 150 /* 2500Hz */
-#define AO_BEEP_MID 94 /* 3989Hz */
-#define AO_BEEP_HIGH 75 /* 5000Hz */
+#define AO_BEEP_MID_DEFAULT 94 /* 3989Hz */
+
+#if HAS_BEEP_CONFIG
+#define AO_BEEP_MID ao_config.mid_beep
+#else
+#define AO_BEEP_MID AO_BEEP_MID_DEFAULT
+#endif
+#define AO_BEEP_LOW AO_BEEP_MID * 150 / 94 /* 2500Hz */
+#define AO_BEEP_HIGH AO_BEEP_MID * 75 / 94 /* 5000Hz */
+
#define AO_BEEP_OFF 0 /* off */
#define AO_BEEP_g 240 /* 1562.5Hz */
diff --git a/src/stm/ao_boot.h b/src/kernel/ao_boot.h
index e0ed4de7..62392d25 100644
--- a/src/stm/ao_boot.h
+++ b/src/kernel/ao_boot.h
@@ -31,9 +31,11 @@ ao_boot_check_chain(void);
void
ao_boot_reboot(uint32_t *base);
+#define AO_BOOT_FORCE_LOADER ((uint32_t *) 0)
+
static inline void
ao_boot_loader(void) {
- ao_boot_reboot(AO_BOOT_LOADER_BASE);
+ ao_boot_reboot(AO_BOOT_FORCE_LOADER);
}
#endif /* _AO_BOOT_H_ */
diff --git a/src/core/ao_btm.h b/src/kernel/ao_btm.h
index 484e5d7f..484e5d7f 100644
--- a/src/core/ao_btm.h
+++ b/src/kernel/ao_btm.h
diff --git a/src/core/ao_cmd.c b/src/kernel/ao_cmd.c
index 4ebaa607..0052bdce 100644
--- a/src/core/ao_cmd.c
+++ b/src/kernel/ao_cmd.c
@@ -23,7 +23,11 @@ __pdata uint32_t ao_cmd_lex_u32;
__pdata char ao_cmd_lex_c;
__pdata enum ao_cmd_status ao_cmd_status;
+#if AO_PYRO_NUM
+#define CMD_LEN 128
+#else
#define CMD_LEN 48
+#endif
static __xdata char cmd_line[CMD_LEN];
static __pdata uint8_t cmd_len;
@@ -274,20 +278,32 @@ version(void)
printf("manufacturer %s\n"
"product %s\n"
"serial-number %u\n"
-#if HAS_FLIGHT
+#if HAS_FLIGHT || HAS_TRACKER
"current-flight %u\n"
#endif
#if HAS_LOG
"log-format %u\n"
+#if !DISABLE_LOG_SPACE
+ "log-space %lu\n"
+#endif
+#endif
+#if defined(AO_BOOT_APPLICATION_BASE) && defined(AO_BOOT_APPLICATION_BOUND)
+ "program-space %u\n"
#endif
, ao_manufacturer
, ao_product
, ao_serial_number
-#if HAS_FLIGHT
+#if HAS_FLIGHT || HAS_TRACKER
, ao_flight_number
#endif
#if HAS_LOG
, ao_log_format
+#if !DISABLE_LOG_SPACE
+ , (unsigned long) ao_storage_log_max
+#endif
+#endif
+#if defined(AO_BOOT_APPLICATION_BASE) && defined(AO_BOOT_APPLICATION_BOUND)
+ , (uint32_t) AO_BOOT_APPLICATION_BOUND - (uint32_t) AO_BOOT_APPLICATION_BASE
#endif
);
printf("software-version %s\n", ao_version);
diff --git a/src/core/ao_companion.h b/src/kernel/ao_companion.h
index 035325a3..035325a3 100644
--- a/src/core/ao_companion.h
+++ b/src/kernel/ao_companion.h
diff --git a/src/core/ao_config.c b/src/kernel/ao_config.c
index 4482f673..71445335 100644
--- a/src/core/ao_config.c
+++ b/src/kernel/ao_config.c
@@ -22,6 +22,12 @@
#include <ao_sample.h>
#include <ao_data.h>
#endif
+#if HAS_BEEP
+#include <ao_beep.h>
+#endif
+#if HAS_TRACKER
+#include <ao_tracker.h>
+#endif
__xdata struct ao_config ao_config;
__pdata uint8_t ao_config_loaded;
@@ -38,6 +44,7 @@ __xdata uint8_t ao_config_mutex;
#define AO_CONFIG_DEFAULT_APOGEE_DELAY 0
#define AO_CONFIG_DEFAULT_IGNITE_MODE AO_IGNITE_MODE_DUAL
#define AO_CONFIG_DEFAULT_PAD_ORIENTATION AO_PAD_ORIENTATION_ANTENNA_UP
+#define AO_CONFIG_DEFAULT_PYRO_TIME AO_MS_TO_TICKS(50)
#if HAS_EEPROM
#ifndef USE_INTERNAL_FLASH
#error Please define USE_INTERNAL_FLASH
@@ -127,7 +134,7 @@ _ao_config_get(void)
ao_config.radio_cal = ao_radio_cal;
#endif
/* Fixups for minor version 4 */
-#if HAS_FLIGHT
+#if HAS_LOG
if (minor < 4)
ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX;
#endif
@@ -171,6 +178,20 @@ _ao_config_get(void)
ao_config.accel_minus_g = 0;
}
#endif
+#if HAS_BEEP_CONFIG
+ if (minor < 16)
+ ao_config.mid_beep = AO_BEEP_MID_DEFAULT;
+#endif
+#if HAS_TRACKER
+ if (minor < 17) {
+ ao_config.tracker_motion = AO_TRACKER_MOTION_DEFAULT;
+ ao_config.tracker_interval = AO_TRACKER_INTERVAL_DEFAULT;
+ }
+#endif
+#if AO_PYRO_NUM
+ if (minor < 18)
+ ao_config.pyro_time = AO_CONFIG_DEFAULT_PYRO_TIME;
+#endif
ao_config.minor = AO_CONFIG_MINOR;
ao_config_dirty = 1;
}
@@ -357,7 +378,7 @@ ao_config_accel_calibrate_set(void) __reentrant
int16_t accel_across_up = 0, accel_across_down = 0;
int16_t accel_through_up = 0, accel_through_down = 0;
#endif
-
+
ao_cmd_decimal();
if (ao_cmd_status != ao_cmd_success)
return;
@@ -555,7 +576,7 @@ ao_config_radio_enable_set(void) __reentrant
_ao_config_edit_finish();
}
#endif /* HAS_RADIO */
-
+
#if HAS_AES
__xdata uint8_t ao_config_aes_seq = 1;
@@ -650,6 +671,72 @@ ao_config_radio_power_set(void)
#endif
+#if HAS_BEEP_CONFIG
+void
+ao_config_beep_show(void)
+{
+ printf ("Beeper setting: %d\n", ao_config.mid_beep);
+}
+
+void
+ao_config_beep_set(void)
+{
+ ao_cmd_decimal();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ _ao_config_edit_start();
+ ao_config.mid_beep = ao_cmd_lex_i;
+ _ao_config_edit_finish();
+}
+#endif
+
+#if HAS_TRACKER
+void
+ao_config_tracker_show(void)
+{
+ printf ("Tracker setting: %d %d\n",
+ ao_config.tracker_motion,
+ ao_config.tracker_interval);
+}
+
+void
+ao_config_tracker_set(void)
+{
+ uint16_t m, i;
+ ao_cmd_decimal();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ m = ao_cmd_lex_i;
+ ao_cmd_decimal();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ i = ao_cmd_lex_i;
+ _ao_config_edit_start();
+ ao_config.tracker_motion = m;
+ ao_config.tracker_interval = i;
+ _ao_config_edit_finish();
+}
+#endif /* HAS_TRACKER */
+
+#if AO_PYRO_NUM
+void
+ao_config_pyro_time_show(void)
+{
+ printf ("Pyro time: %d\n", ao_config.pyro_time);
+}
+
+void
+ao_config_pyro_time_set(void)
+{
+ ao_cmd_decimal();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ _ao_config_edit_start();
+ ao_config.pyro_time = ao_cmd_lex_i;
+ _ao_config_edit_finish();
+}
+#endif
+
struct ao_config_var {
__code char *str;
void (*set)(void) __reentrant;
@@ -697,7 +784,7 @@ __code struct ao_config_var ao_config_vars[] = {
#if HAS_ACCEL
{ "a <+g> <-g>\0Accel calib (0 for auto)",
ao_config_accel_calibrate_set,ao_config_accel_calibrate_show },
- { "o <0 antenna up, 1 antenna down>\0Set pad orientation",
+ { "o <0 antenna up, 1 antenna down>\0Pad orientation",
ao_config_pad_orientation_set,ao_config_pad_orientation_show },
#endif /* HAS_ACCEL */
#if HAS_LOG
@@ -705,21 +792,31 @@ __code struct ao_config_var ao_config_vars[] = {
ao_config_log_set, ao_config_log_show },
#endif
#if HAS_IGNITE
- { "i <0 dual, 1 apogee, 2 main>\0Set igniter mode",
+ { "i <0 dual, 1 apogee, 2 main>\0Igniter mode",
ao_config_ignite_mode_set, ao_config_ignite_mode_show },
#endif
#if HAS_AES
- { "k <32 hex digits>\0Set AES encryption key",
+ { "k <32 hex digits>\0AES encryption key",
ao_config_key_set, ao_config_key_show },
#endif
#if AO_PYRO_NUM
- { "P <n,?>\0Configure pyro channels",
+ { "P <n,?>\0Pyro channels",
ao_pyro_set, ao_pyro_show },
+ { "I <ticks>\0Pyro firing time",
+ ao_config_pyro_time_set, ao_config_pyro_time_show },
#endif
#if HAS_APRS
{ "A <secs>\0APRS packet interval (0 disable)",
ao_config_aprs_set, ao_config_aprs_show },
#endif
+#if HAS_BEEP_CONFIG
+ { "b <val>\0Beeper tone (freq = 1/2 (24e6/32) / beep",
+ ao_config_beep_set, ao_config_beep_show },
+#endif
+#if HAS_TRACKER
+ { "t <motion> <interval>\0Tracker configuration",
+ ao_config_tracker_set, ao_config_tracker_show },
+#endif
{ "s\0Show",
ao_config_show, 0 },
#if HAS_EEPROM
diff --git a/src/kernel/ao_config.h b/src/kernel/ao_config.h
new file mode 100644
index 00000000..2b5cd352
--- /dev/null
+++ b/src/kernel/ao_config.h
@@ -0,0 +1,146 @@
+/*
+ * 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_CONFIG_H_
+#define _AO_CONFIG_H_
+
+#include <ao_pyro.h>
+
+#ifndef USE_STORAGE_CONFIG
+#define USE_STORAGE_CONFIG 1
+#endif
+
+#ifndef USE_EEPROM_CONFIG
+#define USE_EEPROM_CONFIG 0
+#endif
+
+#if USE_STORAGE_CONFIG
+
+#include <ao_storage.h>
+
+#define ao_config_setup() ao_storage_setup()
+#define ao_config_erase() ao_storage_erase(ao_storage_config)
+#define ao_config_write(pos,bytes, len) ao_storage_write(ao_storage_config+(pos), bytes, len)
+#define ao_config_read(pos,bytes, len) ao_storage_read(ao_storage_config+(pos), bytes, len)
+#define ao_config_flush() ao_storage_flush()
+
+#endif
+
+#if USE_EEPROM_CONFIG
+
+#include <ao_eeprom.h>
+
+#define ao_config_setup()
+#define ao_config_erase()
+#define ao_config_write(pos,bytes, len) ao_eeprom_write(pos, bytes, len)
+#define ao_config_read(pos,bytes, len) ao_eeprom_read(pos, bytes, len)
+#define ao_config_flush()
+
+#endif
+
+#define AO_CONFIG_MAJOR 1
+#define AO_CONFIG_MINOR 18
+
+#define AO_AES_LEN 16
+
+extern __xdata uint8_t ao_config_aes_seq;
+
+struct ao_config {
+ uint8_t major;
+ uint8_t minor;
+ uint16_t main_deploy;
+ int16_t accel_plus_g; /* changed for minor version 2 */
+ uint8_t _legacy_radio_channel;
+ char callsign[AO_MAX_CALLSIGN + 1];
+ uint8_t apogee_delay; /* minor version 1 */
+ int16_t accel_minus_g; /* minor version 2 */
+ uint32_t radio_cal; /* minor version 3 */
+ uint32_t flight_log_max; /* minor version 4 */
+ uint8_t ignite_mode; /* minor version 5 */
+ uint8_t pad_orientation; /* minor version 6 */
+ uint32_t radio_setting; /* minor version 7 */
+ uint8_t radio_enable; /* minor version 8 */
+ uint8_t aes_key[AO_AES_LEN]; /* minor version 9 */
+ uint32_t frequency; /* minor version 10 */
+ uint16_t apogee_lockout; /* minor version 11 */
+#if AO_PYRO_NUM
+ struct ao_pyro pyro[AO_PYRO_NUM]; /* minor version 12 */
+#endif
+ uint16_t aprs_interval; /* minor version 13 */
+#if HAS_RADIO_POWER
+ uint8_t radio_power; /* minor version 14 */
+#endif
+#if HAS_RADIO_AMP
+ uint8_t radio_amp; /* minor version 14 */
+#endif
+#if HAS_GYRO
+ int16_t accel_zero_along; /* minor version 15 */
+ int16_t accel_zero_across; /* minor version 15 */
+ int16_t accel_zero_through; /* minor version 15 */
+#endif
+#if HAS_BEEP
+ uint8_t mid_beep; /* minor version 16 */
+#endif
+#if HAS_TRACKER
+ uint16_t tracker_motion; /* minor version 17 */
+ uint8_t tracker_interval; /* minor version 17 */
+#endif
+#if AO_PYRO_NUM
+ uint16_t pyro_time; /* minor version 18 */
+#endif
+};
+
+#define AO_IGNITE_MODE_DUAL 0
+#define AO_IGNITE_MODE_APOGEE 1
+#define AO_IGNITE_MODE_MAIN 2
+
+#define AO_RADIO_ENABLE_CORE 1
+#define AO_RADIO_DISABLE_TELEMETRY 2
+#define AO_RADIO_DISABLE_RDF 4
+
+#define AO_PAD_ORIENTATION_ANTENNA_UP 0
+#define AO_PAD_ORIENTATION_ANTENNA_DOWN 1
+
+#ifndef AO_CONFIG_MAX_SIZE
+#define AO_CONFIG_MAX_SIZE 128
+#endif
+
+/* Make sure AO_CONFIG_MAX_SIZE is big enough */
+typedef uint8_t config_check_space[(int) (AO_CONFIG_MAX_SIZE - sizeof (struct ao_config))];
+
+extern __xdata struct ao_config ao_config;
+extern __pdata uint8_t ao_config_loaded;
+
+void
+_ao_config_edit_start(void);
+
+void
+_ao_config_edit_finish(void);
+
+void
+ao_config_get(void);
+
+void
+ao_config_put(void);
+
+void
+ao_config_set_radio(void);
+
+void
+ao_config_init(void);
+
+#endif /* _AO_CONFIG_H_ */
diff --git a/src/core/ao_convert.c b/src/kernel/ao_convert.c
index aa9b5f48..aa9b5f48 100644
--- a/src/core/ao_convert.c
+++ b/src/kernel/ao_convert.c
diff --git a/src/core/ao_convert_pa.c b/src/kernel/ao_convert_pa.c
index fe6e0ef6..fe6e0ef6 100644
--- a/src/core/ao_convert_pa.c
+++ b/src/kernel/ao_convert_pa.c
diff --git a/src/core/ao_convert_pa_test.c b/src/kernel/ao_convert_pa_test.c
index 7d5b1922..7d5b1922 100644
--- a/src/core/ao_convert_pa_test.c
+++ b/src/kernel/ao_convert_pa_test.c
diff --git a/src/core/ao_convert_test.c b/src/kernel/ao_convert_test.c
index 87e76841..87e76841 100644
--- a/src/core/ao_convert_test.c
+++ b/src/kernel/ao_convert_test.c
diff --git a/src/core/ao_convert_volt.c b/src/kernel/ao_convert_volt.c
index 8556d423..f697e748 100644
--- a/src/core/ao_convert_volt.c
+++ b/src/kernel/ao_convert_volt.c
@@ -17,17 +17,23 @@
#include "ao.h"
-#define scale(v,p,m) ((int32_t) (v) * (AO_ADC_REFERENCE_DV * ((p) + (m))) / (AO_ADC_MAX * (m)))
+#define MUL(p,m) ((int32_t) AO_ADC_REFERENCE_DV * ((p) + (m)))
+#define ADD(p,m) (MUL(p,m)/2)
+#define DIV(p,m) ((int32_t) AO_ADC_MAX * (m))
+#define scale(v,p,m) (((int32_t) (v) * MUL(p,m) + ADD(p,m)) / DIV(p,m))
+#if HAS_APRS || HAS_BATTERY_REPORT
int16_t
ao_battery_decivolt(int16_t adc)
{
return scale(adc, AO_BATTERY_DIV_PLUS, AO_BATTERY_DIV_MINUS);
}
+#endif
+#if HAS_APRS && defined(AO_IGNITE_DIV_PLUS)
int16_t
ao_ignite_decivolt(int16_t adc)
{
return scale(adc, AO_IGNITE_DIV_PLUS, AO_IGNITE_DIV_MINUS);
}
-
+#endif
diff --git a/src/core/ao_data.c b/src/kernel/ao_data.c
index 6a3d02a1..6a3d02a1 100644
--- a/src/core/ao_data.c
+++ b/src/kernel/ao_data.c
diff --git a/src/core/ao_data.h b/src/kernel/ao_data.h
index c4b062fd..c4b062fd 100644
--- a/src/core/ao_data.h
+++ b/src/kernel/ao_data.h
diff --git a/src/core/ao_dbg.h b/src/kernel/ao_dbg.h
index 181e6ec2..181e6ec2 100644
--- a/src/core/ao_dbg.h
+++ b/src/kernel/ao_dbg.h
diff --git a/src/core/ao_debounce.c b/src/kernel/ao_debounce.c
index b9d67729..b9d67729 100644
--- a/src/core/ao_debounce.c
+++ b/src/kernel/ao_debounce.c
diff --git a/src/core/ao_debounce.h b/src/kernel/ao_debounce.h
index 19c620f5..19c620f5 100644
--- a/src/core/ao_debounce.h
+++ b/src/kernel/ao_debounce.h
diff --git a/src/kernel/ao_distance.c b/src/kernel/ao_distance.c
new file mode 100644
index 00000000..5654182a
--- /dev/null
+++ b/src/kernel/ao_distance.c
@@ -0,0 +1,123 @@
+/*
+ * 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_distance.h>
+
+static uint32_t
+ao_dist(int32_t a, int32_t b)
+{
+ int32_t d = a - b;
+ if (d < 0)
+ d = -d;
+
+ return (uint32_t) ((int64_t) d * 111198 / 10000000);
+}
+
+static uint32_t
+ao_lat_dist(int32_t lat_a, int32_t lat_b)
+{
+ return ao_dist(lat_a, lat_b);
+}
+
+static const uint8_t cos_table[] = {
+ 0, /* 0 */
+ 0, /* 1 */
+ 0, /* 2 */
+ 255, /* 3 */
+ 254, /* 4 */
+ 253, /* 5 */
+ 252, /* 6 */
+ 251, /* 7 */
+ 249, /* 8 */
+ 247, /* 9 */
+ 245, /* 10 */
+ 243, /* 11 */
+ 240, /* 12 */
+ 238, /* 13 */
+ 235, /* 14 */
+ 232, /* 15 */
+ 228, /* 16 */
+ 225, /* 17 */
+ 221, /* 18 */
+ 217, /* 19 */
+ 213, /* 20 */
+ 209, /* 21 */
+ 205, /* 22 */
+ 200, /* 23 */
+ 195, /* 24 */
+ 190, /* 25 */
+ 185, /* 26 */
+ 180, /* 27 */
+ 175, /* 28 */
+ 169, /* 29 */
+ 163, /* 30 */
+ 158, /* 31 */
+ 152, /* 32 */
+ 145, /* 33 */
+ 139, /* 34 */
+ 133, /* 35 */
+ 126, /* 36 */
+ 120, /* 37 */
+ 113, /* 38 */
+ 106, /* 39 */
+ 100, /* 40 */
+ 93, /* 41 */
+ 86, /* 42 */
+ 79, /* 43 */
+ 71, /* 44 */
+ 64, /* 45 */
+ 57, /* 46 */
+ 49, /* 47 */
+ 42, /* 48 */
+ 35, /* 49 */
+ 27, /* 50 */
+ 20, /* 51 */
+ 12, /* 52 */
+ 5, /* 53 */
+ 1, /* 54 */
+};
+
+static uint32_t
+ao_lon_dist(int32_t lon_a, int32_t lon_b)
+{
+ uint8_t c = cos_table[lon_a >> 24];
+ uint32_t lon_dist;
+
+ /* check if it's shorter to go the other way around */
+ if ((lon_a >> 1) < (lon_b >> 1) - (1800000000 >> 1))
+ lon_a += 3600000000;
+ lon_dist = ao_dist(lon_a, lon_b);
+ if (c) {
+ if (lon_dist & 0x7f800000)
+ lon_dist = (lon_dist >> 8) * c;
+ else
+ lon_dist = (lon_dist * (int16_t) c) >> 8;
+ }
+ return lon_dist;
+}
+
+static uint32_t sqr(uint32_t x) { return x * x; }
+
+uint32_t
+ao_distance(int32_t lat_a, int32_t lon_a, int32_t lat_b, int32_t lon_b)
+{
+ uint32_t lat_dist = ao_lat_dist(lat_a, lat_b);
+ uint32_t lon_dist = ao_lon_dist(lon_a, lon_b);
+
+ return ao_sqrt (sqr(lat_dist) + sqr(lon_dist));
+}
diff --git a/src/kernel/ao_distance.h b/src/kernel/ao_distance.h
new file mode 100644
index 00000000..6762434e
--- /dev/null
+++ b/src/kernel/ao_distance.h
@@ -0,0 +1,25 @@
+/*
+ * 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_DISTANCE_H_
+#define _AO_DISTANCE_H_
+#include <stdint.h>
+
+uint32_t
+ao_distance(int32_t lat_a, int32_t lon_a, int32_t lat_b, int32_t lon_b);
+
+#endif /* _AO_DISTANCE_H_ */
diff --git a/src/core/ao_ee_fake.c b/src/kernel/ao_ee_fake.c
index 7fcfcab0..7fcfcab0 100644
--- a/src/core/ao_ee_fake.c
+++ b/src/kernel/ao_ee_fake.c
diff --git a/src/core/ao_eeprom.h b/src/kernel/ao_eeprom.h
index 915522bf..915522bf 100644
--- a/src/core/ao_eeprom.h
+++ b/src/kernel/ao_eeprom.h
diff --git a/src/kernel/ao_fake_flight.c b/src/kernel/ao_fake_flight.c
new file mode 100644
index 00000000..11329bb9
--- /dev/null
+++ b/src/kernel/ao_fake_flight.c
@@ -0,0 +1,219 @@
+/*
+ * 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_fake_flight.h>
+#if HAS_MS5607 || HAS_MS5611
+#include <ao_ms5607.h>
+#endif
+
+uint8_t ao_fake_flight_active;
+
+static uint8_t ao_fake_has_cur;
+static volatile uint8_t ao_fake_has_next;
+static uint8_t ao_fake_has_offset;
+static uint16_t ao_fake_tick_offset;
+static struct ao_data ao_fake_cur, ao_fake_next;
+
+void
+ao_fake_flight_poll(void)
+{
+ if (ao_fake_has_next && (ao_tick_count - ao_fake_next.tick) >= 0) {
+ ao_fake_cur = ao_fake_next;
+ ao_fake_has_next = 0;
+ ao_wakeup((void *) &ao_fake_has_next);
+ ao_fake_has_cur = 1;
+ }
+ if (!ao_fake_has_cur)
+ return;
+ ao_data_ring[ao_data_head] = ao_fake_cur;
+ ao_data_ring[ao_data_head].tick = ao_tick_count;
+ ao_data_head = ao_data_ring_next(ao_data_head);
+ ao_wakeup((void *) &ao_data_head);
+}
+
+static uint8_t
+ao_fake_data_read(void)
+{
+ uint8_t i;
+ uint8_t *d = (void *) &ao_fake_next;
+
+ if (getchar() == 0)
+ return FALSE;
+ for (i = 0; i < sizeof (struct ao_data); i++)
+ *d++ = getchar();
+ if (!ao_fake_has_offset) {
+ ao_fake_tick_offset = (ao_tick_count + 1000) - ao_fake_next.tick;
+ ao_fake_next.tick = ao_tick_count;
+ ao_fake_has_offset = 1;
+ } else
+ ao_fake_next.tick += ao_fake_tick_offset;
+ ao_fake_has_next = 1;
+ return TRUE;
+}
+
+static void
+ao_fake_calib_get(struct ao_fake_calib *calib)
+{
+#if HAS_ACCEL
+ calib->accel_plus_g = ao_config.accel_plus_g;
+ calib->accel_minus_g = ao_config.accel_minus_g;
+#endif
+#if HAS_GYRO
+ calib->accel_zero_along = ao_config.accel_zero_along;
+ calib->accel_zero_across = ao_config.accel_zero_across;
+ calib->accel_zero_through = ao_config.accel_zero_through;
+#endif
+#if HAS_MS5607 || HAS_MS5611
+ calib->ms5607_prom = ao_ms5607_prom;
+#endif
+}
+
+static void
+ao_fake_calib_set(struct ao_fake_calib *calib)
+{
+#if HAS_ACCEL
+ ao_config.accel_plus_g = calib->accel_plus_g;
+ ao_config.accel_minus_g = calib->accel_minus_g;
+#endif
+#if HAS_GYRO
+ ao_config.accel_zero_along = calib->accel_zero_along;
+ ao_config.accel_zero_across = calib->accel_zero_across;
+ ao_config.accel_zero_through = calib->accel_zero_through;
+#endif
+#if HAS_MS5607 || HAS_MS5611
+ ao_ms5607_prom = calib->ms5607_prom;
+#endif
+}
+
+static uint8_t
+ao_fake_calib_read(void)
+{
+ struct ao_fake_calib ao_calib;
+ uint8_t *d = (void *) &ao_calib;
+ uint16_t i;
+
+ /* Read calibration data */
+ for (i = 0; i < sizeof (struct ao_fake_calib); i++)
+ *d++ = getchar();
+ if (ao_calib.major != AO_FAKE_CALIB_MAJOR
+#if AO_FAKE_CALIB_MINOR != 0
+ || ao_calib.minor < AO_FAKE_CALIB_MINOR
+#endif
+ ) {
+ printf ("Calibration data major version mismatch %d.%d <= %d.%d\n",
+ ao_calib.major, ao_calib.minor, AO_FAKE_CALIB_MAJOR, AO_FAKE_CALIB_MINOR);
+ return FALSE;
+ }
+ ao_fake_calib_set(&ao_calib);
+ return TRUE;
+}
+
+static void
+ao_fake_flight(void)
+{
+ int16_t calib_size, data_size;
+ struct ao_fake_calib save_calib;
+ uint16_t my_pyro_fired = 0;
+ enum ao_flight_state my_state = ao_flight_invalid;
+ int i;
+
+ ao_cmd_hex();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ calib_size = ao_cmd_lex_i;
+ ao_cmd_hex();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ data_size = ao_cmd_lex_i;
+ if ((unsigned) calib_size != sizeof (struct ao_fake_calib)) {
+ printf ("calib size %d larger than actual size %d\n",
+ calib_size, sizeof (struct ao_fake_calib));
+ ao_cmd_status = ao_cmd_syntax_error;
+ return;
+ }
+ if (data_size != sizeof (struct ao_data)) {
+ printf ("data size %d doesn't match actual size %d\n",
+ data_size, sizeof (struct ao_data));
+ ao_cmd_status = ao_cmd_syntax_error;
+ return;
+ }
+ ao_fake_calib_get(&save_calib);
+ if (!ao_fake_calib_read())
+ return;
+
+ ao_fake_has_next = 0;
+ ao_fake_has_cur = 0;
+ ao_fake_flight_active = 1;
+ ao_sample_init();
+#if PACKET_HAS_SLAVE
+ ao_packet_slave_stop();
+#endif
+#if AO_LED_RED
+ /* Turn on the LED to indicate startup */
+ ao_led_on(AO_LED_RED);
+#endif
+ ao_flight_state = ao_flight_startup;
+ for (;;) {
+ if (my_state != ao_flight_state) {
+ printf("state %d\n", ao_flight_state);
+ my_state = ao_flight_state;
+ flush();
+ }
+ if (my_pyro_fired != ao_pyro_fired) {
+ int pyro;
+
+ for (pyro = 0; pyro < AO_PYRO_NUM; pyro++) {
+ uint16_t bit = (1 << pyro);
+ if (!(my_pyro_fired & bit) && (ao_pyro_fired & bit))
+ printf ("fire %d\n", pyro);
+ }
+ my_pyro_fired = ao_pyro_fired;
+ }
+ while (ao_fake_has_next)
+ ao_sleep((void *) &ao_fake_has_next);
+ if (!ao_fake_data_read())
+ break;
+ }
+
+ /* Wait 20 seconds to see if we enter landed state */
+ for (i = 0; i < 200; i++)
+ {
+ if (ao_flight_state == ao_flight_landed)
+ break;
+ ao_delay(AO_MS_TO_TICKS(100));
+ }
+#if AO_LED_RED
+ /* Turn on the LED to indicate startup */
+ ao_led_on(AO_LED_RED);
+#endif
+ ao_fake_flight_active = 0;
+ ao_flight_state = ao_flight_startup;
+ ao_sample_init();
+ ao_fake_calib_set(&save_calib);
+}
+
+static const struct ao_cmds ao_fake_flight_cmds[] = {
+ { ao_fake_flight, "F <calib-size> <data-size>\0Start fake flight" },
+ { 0, NULL }
+};
+
+void
+ao_fake_flight_init(void)
+{
+ ao_cmd_register(&ao_fake_flight_cmds[0]);
+}
diff --git a/src/kernel/ao_fake_flight.h b/src/kernel/ao_fake_flight.h
new file mode 100644
index 00000000..172fc589
--- /dev/null
+++ b/src/kernel/ao_fake_flight.h
@@ -0,0 +1,53 @@
+/*
+ * 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_FAKE_FLIGHT_H_
+#define _AO_FAKE_FLIGHT_H_
+#if HAS_MS5607 || HAS_MS5611
+#include <ao_ms5607.h>
+#endif
+
+extern uint8_t ao_fake_flight_active;
+
+#define AO_FAKE_CALIB_MAJOR 1
+#define AO_FAKE_CALIB_MINOR 0
+
+struct ao_fake_calib {
+ uint16_t major;
+ uint16_t minor;
+#if HAS_ACCEL
+ int16_t accel_plus_g;
+ int16_t accel_minus_g;
+#endif
+#if HAS_GYRO
+ int16_t accel_zero_along;
+ int16_t accel_zero_across;
+ int16_t accel_zero_through;
+ uint16_t pad30;
+#endif
+#if HAS_MS5607 || HAS_MS5611
+ struct ao_ms5607_prom ms5607_prom;
+#endif
+};
+
+void
+ao_fake_flight_poll(void);
+
+void
+ao_fake_flight_init(void);
+
+#endif /* _AO_FAKE_FLIGHT_H_ */
diff --git a/src/core/ao_fec.h b/src/kernel/ao_fec.h
index 618756c1..618756c1 100644
--- a/src/core/ao_fec.h
+++ b/src/kernel/ao_fec.h
diff --git a/src/core/ao_fec_rx.c b/src/kernel/ao_fec_rx.c
index c4f5559a..c4f5559a 100644
--- a/src/core/ao_fec_rx.c
+++ b/src/kernel/ao_fec_rx.c
diff --git a/src/core/ao_fec_tx.c b/src/kernel/ao_fec_tx.c
index 4941d745..4941d745 100644
--- a/src/core/ao_fec_tx.c
+++ b/src/kernel/ao_fec_tx.c
diff --git a/src/core/ao_flight.c b/src/kernel/ao_flight.c
index 702c3403..2b433ee9 100644
--- a/src/core/ao_flight.c
+++ b/src/kernel/ao_flight.c
@@ -36,6 +36,10 @@
#error Please define HAS_USB
#endif
+#if HAS_FAKE_FLIGHT
+#include <ao_fake_flight.h>
+#endif
+
#ifndef HAS_TELEMETRY
#define HAS_TELEMETRY HAS_RADIO
#endif
@@ -130,7 +134,10 @@ ao_flight(void)
/* Disable the USB controller in flight mode
* to save power
*/
- ao_usb_disable();
+#if HAS_FAKE_FLIGHT
+ if (!ao_fake_flight_active)
+#endif
+ ao_usb_disable();
#endif
#if !HAS_ACCEL && PACKET_HAS_SLAVE
@@ -143,7 +150,7 @@ ao_flight(void)
ao_rdf_set(1);
ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD);
#endif
-#if HAS_LED
+#if AO_LED_RED
/* signal successful initialization by turning off the LED */
ao_led_off(AO_LED_RED);
#endif
@@ -160,7 +167,7 @@ ao_flight(void)
ao_packet_slave_start();
#endif
-#if HAS_LED
+#if AO_LED_RED
/* signal successful initialization by turning off the LED */
ao_led_off(AO_LED_RED);
#endif
@@ -170,7 +177,6 @@ ao_flight(void)
break;
case ao_flight_pad:
-
/* pad to boost:
*
* barometer: > 20m vertical motion
diff --git a/src/core/ao_flight.h b/src/kernel/ao_flight.h
index 01d21c11..01d21c11 100644
--- a/src/core/ao_flight.h
+++ b/src/kernel/ao_flight.h
diff --git a/src/core/ao_flight_nano.c b/src/kernel/ao_flight_nano.c
index 406d81ad..406d81ad 100644
--- a/src/core/ao_flight_nano.c
+++ b/src/kernel/ao_flight_nano.c
diff --git a/src/core/ao_freq.c b/src/kernel/ao_freq.c
index 12496f6f..12496f6f 100644
--- a/src/core/ao_freq.c
+++ b/src/kernel/ao_freq.c
diff --git a/src/core/ao_gps_print.c b/src/kernel/ao_gps_print.c
index 47c945d7..47c945d7 100644
--- a/src/core/ao_gps_print.c
+++ b/src/kernel/ao_gps_print.c
diff --git a/src/core/ao_gps_report.c b/src/kernel/ao_gps_report.c
index 07201ac2..07201ac2 100644
--- a/src/core/ao_gps_report.c
+++ b/src/kernel/ao_gps_report.c
diff --git a/src/core/ao_gps_report_mega.c b/src/kernel/ao_gps_report_mega.c
index 5e3c71bf..cb0c0fd9 100644
--- a/src/core/ao_gps_report_mega.c
+++ b/src/kernel/ao_gps_report_mega.c
@@ -18,6 +18,43 @@
#include "ao.h"
#include "ao_log.h"
+#ifndef GPS_SPARSE_LOG
+#define GPS_SPARSE_LOG 0
+#endif
+
+#if GPS_SPARSE_LOG
+static int32_t prev_lat, prev_lon, int16_t prev_alt;
+static uint8_t has_prev, unmoving;
+
+#define GPS_SPARSE_UNMOVING_REPORTS 10
+#define GPS_SPARSE_UNMOVING_GROUND 10
+#define GPS_SPARSE_UNMOVING_AIR 10
+
+static uint8_t
+ao_gps_sparse_should_log(int32_t lat, int32_t lon, int16_t alt)
+{
+ uint8_t ret = 1;
+
+ if (has_prev && ao_log_running) {
+ uint32_t h = ao_distance(prev_lat, prev_lon, lat, lon);
+ uint16_t v = alt > prev_alt ? (alt - prev_alt) : (prev_alt - alt);
+
+ if (h < GPS_SPARSE_UNMOVING_GROUND && v < GPS_SPARSE_UNMOVING_AIR) {
+ if (unmoving < GPS_SPARSE_UNMOVING_REPORTS)
+ ++unmoving;
+ } else
+ unmoving = 0;
+ } else
+ unmoving = 0;
+
+ prev_lat = lat;
+ prev_lon = lon;
+ prev_alt = alt;
+ has_prev = 1;
+ return unmoving >= GPS_SPARSE_UNMOVING_REPORTS;
+}
+#endif
+
void
ao_gps_report_mega(void)
{
@@ -38,7 +75,14 @@ ao_gps_report_mega(void)
ao_gps_new = 0;
ao_mutex_put(&ao_gps_mutex);
+#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))
+ continue;
+#endif
if ((new & AO_GPS_NEW_DATA) && (gps_data.flags & AO_GPS_VALID)) {
+
gps_log.tick = ao_gps_tick;
gps_log.type = AO_LOG_GPS_TIME;
gps_log.u.gps.latitude = gps_data.latitude;
diff --git a/src/core/ao_gps_report_metrum.c b/src/kernel/ao_gps_report_metrum.c
index 696a833b..696a833b 100644
--- a/src/core/ao_gps_report_metrum.c
+++ b/src/kernel/ao_gps_report_metrum.c
diff --git a/src/core/ao_gps_show.c b/src/kernel/ao_gps_show.c
index 3a05e35a..3a05e35a 100644
--- a/src/core/ao_gps_show.c
+++ b/src/kernel/ao_gps_show.c
diff --git a/src/core/ao_host.h b/src/kernel/ao_host.h
index 6eb752c9..6eb752c9 100644
--- a/src/core/ao_host.h
+++ b/src/kernel/ao_host.h
diff --git a/src/core/ao_ignite.c b/src/kernel/ao_ignite.c
index 823d003c..823d003c 100644
--- a/src/core/ao_ignite.c
+++ b/src/kernel/ao_ignite.c
diff --git a/src/core/ao_int64.c b/src/kernel/ao_int64.c
index aa23dbe0..ca75751b 100644
--- a/src/core/ao_int64.c
+++ b/src/kernel/ao_int64.c
@@ -17,8 +17,6 @@
#include <ao_int64.h>
-__pdata ao_int64_t *__data ao_64r, *__data ao_64a, *__data ao_64b;
-
void ao_plus64(__pdata ao_int64_t *r, __pdata ao_int64_t *a, __pdata ao_int64_t *b) __FATTR {
__LOCAL uint32_t t;
@@ -151,8 +149,8 @@ void ao_mul64_64_16(__ARG ao_int64_t *r, __ARG ao_int64_t *a, __ARG uint16_t b)
ao_neg64(&ap, a);
a = &ap;
negative++;
- } else
- ao_umul64_64_16(r, a, b);
+ }
+ ao_umul64_64_16(r, a, b);
if (negative)
ao_neg64(r, r);
}
diff --git a/src/core/ao_int64.h b/src/kernel/ao_int64.h
index b16db58c..b16db58c 100644
--- a/src/core/ao_int64.h
+++ b/src/kernel/ao_int64.h
diff --git a/src/core/ao_kalman.c b/src/kernel/ao_kalman.c
index 9aea1f14..9aea1f14 100644
--- a/src/core/ao_kalman.c
+++ b/src/kernel/ao_kalman.c
diff --git a/src/core/ao_lcd.h b/src/kernel/ao_lcd.h
index f7e1391a..f7e1391a 100644
--- a/src/core/ao_lcd.h
+++ b/src/kernel/ao_lcd.h
diff --git a/src/core/ao_led.h b/src/kernel/ao_led.h
index d9a0914a..d9a0914a 100644
--- a/src/core/ao_led.h
+++ b/src/kernel/ao_led.h
diff --git a/src/core/ao_list.h b/src/kernel/ao_list.h
index 8a6fa4d9..8a6fa4d9 100644
--- a/src/core/ao_list.h
+++ b/src/kernel/ao_list.h
diff --git a/src/core/ao_log.c b/src/kernel/ao_log.c
index 20febefe..91617d93 100644
--- a/src/core/ao_log.c
+++ b/src/kernel/ao_log.c
@@ -18,7 +18,11 @@
#include "ao.h"
#include <ao_log.h>
#include <ao_config.h>
+#if HAS_TRACKER
+#include <ao_tracker.h>
+#endif
+__xdata uint8_t ao_log_mutex;
__pdata uint32_t ao_log_current_pos;
__pdata uint32_t ao_log_end_pos;
__pdata uint32_t ao_log_start_pos;
@@ -38,13 +42,22 @@ ao_log_flush(void)
*/
struct ao_log_erase {
- uint8_t unused;
+ uint8_t mark;
uint16_t flight;
};
static __xdata struct ao_log_erase erase;
+#ifndef LOG_MAX_ERASE
#define LOG_MAX_ERASE 16
+#endif
+
+#ifndef LOG_ERASE_MARK
+#if USE_EEPROM_CONFIG
+#error "Must define LOG_ERASE_MARK with USE_EEPROM_CONFIG"
+#endif
+#define LOG_ERASE_MARK 0x00
+#endif
static uint32_t
ao_log_erase_pos(uint8_t i)
@@ -55,9 +68,21 @@ ao_log_erase_pos(uint8_t i)
void
ao_log_write_erase(uint8_t pos)
{
- erase.unused = 0x00;
+ erase.mark = LOG_ERASE_MARK;
erase.flight = ao_flight_number;
ao_config_write(ao_log_erase_pos(pos), &erase, sizeof (erase));
+
+#if USE_EEPROM_CONFIG
+ if (pos == 0) {
+ uint8_t i;
+ for (i = 1; i < LOG_MAX_ERASE; i++) {
+ erase.mark = ~LOG_ERASE_MARK;
+ erase.flight = 0;
+ ao_config_write(ao_log_erase_pos(i), &erase, sizeof (erase));
+ }
+ }
+#endif
+
ao_config_flush();
}
@@ -75,9 +100,9 @@ ao_log_erase_mark(void)
for (i = 0; i < LOG_MAX_ERASE; i++) {
ao_log_read_erase(i);
- if (erase.unused == 0 && erase.flight == ao_flight_number)
+ if (erase.mark == LOG_ERASE_MARK && erase.flight == ao_flight_number)
return;
- if (erase.unused == 0xff) {
+ if (erase.mark != LOG_ERASE_MARK) {
ao_log_write_erase(i);
return;
}
@@ -136,7 +161,7 @@ ao_log_scan(void) __reentrant
*/
for (log_slot = LOG_MAX_ERASE; log_slot-- > 0;) {
ao_log_read_erase(log_slot);
- if (erase.unused == 0) {
+ if (erase.mark == LOG_ERASE_MARK) {
if (ao_flight_number == 0 ||
(int16_t) (erase.flight - ao_flight_number) > 0)
ao_flight_number = erase.flight;
@@ -196,7 +221,11 @@ ao_log_full(void)
return ao_log_current_pos == ao_log_end_pos;
}
-#if HAS_ADC
+#ifndef LOG_ADC
+#define LOG_ADC HAS_ADC
+#endif
+
+#if LOG_ADC
static __xdata struct ao_task ao_log_task;
#endif
@@ -225,6 +254,7 @@ 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)
@@ -235,10 +265,13 @@ ao_log_delete(void) __reentrant
if (ao_cmd_lex_i) {
for (slot = 0; slot < slots; slot++) {
if (ao_log_flight(slot) == ao_cmd_lex_i) {
+#if HAS_TRACKER
+ ao_tracker_erase_start(ao_cmd_lex_i);
+#endif
ao_log_erase_mark();
- ao_log_current_pos = ao_log_pos(slot);
- ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max;
- while (ao_log_current_pos < ao_log_end_pos) {
+ 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;
@@ -248,15 +281,18 @@ ao_log_delete(void) __reentrant
* memory over and over again
*/
for (i = 0; i < 16; i++) {
- if (ao_storage_read(ao_log_current_pos + i, &b, 1))
+ if (ao_storage_read(log_current_pos + i, &b, 1))
if (b != 0xff)
break;
}
if (i == 16)
break;
- ao_storage_erase(ao_log_current_pos);
- ao_log_current_pos += ao_storage_block;
+ ao_storage_erase(log_current_pos);
+ log_current_pos += ao_storage_block;
}
+#if HAS_TRACKER
+ ao_tracker_erase_end();
+#endif
puts("Erased");
return;
}
@@ -284,7 +320,7 @@ ao_log_init(void)
#ifndef HAS_ADC
#error Define HAS_ADC for ao_log.c
#endif
-#if HAS_ADC
+#if LOG_ADC
/* Create a task to log events to eeprom */
ao_add_task(&ao_log_task, ao_log, "log");
#endif
diff --git a/src/core/ao_log.h b/src/kernel/ao_log.h
index 09f31188..33cda3eb 100644
--- a/src/core/ao_log.h
+++ b/src/kernel/ao_log.h
@@ -29,7 +29,7 @@
* by sleeping on this variable.
*/
extern __xdata uint16_t ao_flight_number;
-
+extern __xdata uint8_t ao_log_mutex;
extern __pdata uint32_t ao_log_current_pos;
extern __pdata uint32_t ao_log_end_pos;
extern __pdata uint32_t ao_log_start_pos;
@@ -47,6 +47,7 @@ extern __pdata enum ao_flight_state ao_log_state;
#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 */
extern __code uint8_t ao_log_format;
@@ -206,9 +207,9 @@ struct ao_log_mega {
uint16_t flight; /* 4 */
int16_t ground_accel; /* 6 */
uint32_t ground_pres; /* 8 */
- int16_t ground_accel_along; /* 16 */
- int16_t ground_accel_across; /* 12 */
- int16_t ground_accel_through; /* 14 */
+ int16_t ground_accel_along; /* 12 */
+ int16_t ground_accel_across; /* 14 */
+ int16_t ground_accel_through; /* 16 */
int16_t ground_roll; /* 18 */
int16_t ground_pitch; /* 20 */
int16_t ground_yaw; /* 22 */
@@ -364,6 +365,50 @@ struct ao_log_mini {
(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 */
+ int16_t altitude; /* 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 */
+ uint8_t state; /* 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;
+};
+
/* Write a record to the eeprom log */
uint8_t
ao_log_data(__xdata struct ao_log_record *log) __reentrant;
@@ -377,6 +422,9 @@ ao_log_metrum(__xdata struct ao_log_metrum *log) __reentrant;
uint8_t
ao_log_mini(__xdata struct ao_log_mini *log) __reentrant;
+uint8_t
+ao_log_gps(__xdata struct ao_log_gps *log) __reentrant;
+
void
ao_log_flush(void);
diff --git a/src/core/ao_log_big.c b/src/kernel/ao_log_big.c
index db01f46c..8f57bf75 100644
--- a/src/core/ao_log_big.c
+++ b/src/kernel/ao_log_big.c
@@ -17,7 +17,6 @@
#include "ao.h"
-static __xdata uint8_t ao_log_mutex;
static __xdata struct ao_log_record log;
__code uint8_t ao_log_format = AO_LOG_FORMAT_FULL;
diff --git a/src/kernel/ao_log_gps.c b/src/kernel/ao_log_gps.c
new file mode 100644
index 00000000..3b728c25
--- /dev/null
+++ b/src/kernel/ao_log_gps.c
@@ -0,0 +1,137 @@
+/*
+ * 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_log.h>
+#include <ao_log_gps.h>
+#include <ao_data.h>
+#include <ao_flight.h>
+#include <ao_distance.h>
+#include <ao_tracker.h>
+
+static __xdata struct ao_log_gps log;
+
+__code uint8_t ao_log_format = AO_LOG_FORMAT_TELEGPS;
+
+static uint8_t
+ao_log_csum(__xdata uint8_t *b) __reentrant
+{
+ uint8_t sum = 0x5a;
+ uint8_t i;
+
+ for (i = 0; i < sizeof (struct ao_log_gps); i++)
+ sum += *b++;
+ return -sum;
+}
+
+uint8_t
+ao_log_gps(__xdata struct ao_log_gps *log) __reentrant
+{
+ uint8_t wrote = 0;
+ /* set checksum */
+ log->csum = 0;
+ log->csum = ao_log_csum((__xdata uint8_t *) log);
+ ao_mutex_get(&ao_log_mutex); {
+ if (ao_log_current_pos >= ao_log_end_pos && ao_log_running)
+ ao_log_stop();
+ if (ao_log_running) {
+ wrote = 1;
+ ao_storage_write(ao_log_current_pos,
+ log,
+ sizeof (struct ao_log_gps));
+ ao_log_current_pos += sizeof (struct ao_log_gps);
+ }
+ } ao_mutex_put(&ao_log_mutex);
+ return wrote;
+}
+
+void
+ao_log_gps_flight(void)
+{
+ log.type = AO_LOG_FLIGHT;
+ log.tick = ao_time();
+ log.u.flight.flight = ao_flight_number;
+ ao_log_gps(&log);
+}
+
+void
+ao_log_gps_data(uint16_t tick, struct ao_telemetry_location *gps_data)
+{
+ log.tick = tick;
+ 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.hour = gps_data->hour;
+ log.u.gps.minute = gps_data->minute;
+ log.u.gps.second = gps_data->second;
+ log.u.gps.flags = gps_data->flags;
+ log.u.gps.year = gps_data->year;
+ log.u.gps.month = gps_data->month;
+ log.u.gps.day = gps_data->day;
+ log.u.gps.course = gps_data->course;
+ log.u.gps.ground_speed = gps_data->ground_speed;
+ log.u.gps.climb_rate = gps_data->climb_rate;
+ log.u.gps.pdop = gps_data->pdop;
+ log.u.gps.hdop = gps_data->hdop;
+ log.u.gps.vdop = gps_data->vdop;
+ log.u.gps.mode = gps_data->mode;
+ ao_log_gps(&log);
+}
+
+void
+ao_log_gps_tracking(uint16_t tick, struct ao_telemetry_satellite *gps_tracking_data)
+{
+ uint8_t c, n, i;
+
+ log.tick = tick;
+ log.type = AO_LOG_GPS_SAT;
+ i = 0;
+ n = gps_tracking_data->channels;
+ for (c = 0; c < n; c++)
+ if ((log.u.gps_sat.sats[i].svid = gps_tracking_data->sats[c].svid))
+ {
+ log.u.gps_sat.sats[i].c_n = gps_tracking_data->sats[c].c_n_1;
+ i++;
+ if (i >= 12)
+ break;
+ }
+ log.u.gps_sat.channels = i;
+ ao_log_gps(&log);
+}
+
+static uint8_t
+ao_log_dump_check_data(void)
+{
+ if (ao_log_csum((uint8_t *) &log) != 0)
+ return 0;
+ return 1;
+}
+
+uint16_t
+ao_log_flight(uint8_t slot)
+{
+ if (!ao_storage_read(ao_log_pos(slot),
+ &log,
+ sizeof (struct ao_log_gps)))
+ return 0;
+
+ if (ao_log_dump_check_data() && log.type == AO_LOG_FLIGHT)
+ return log.u.flight.flight;
+ return 0;
+}
diff --git a/src/kernel/ao_log_gps.h b/src/kernel/ao_log_gps.h
new file mode 100644
index 00000000..5851f4d1
--- /dev/null
+++ b/src/kernel/ao_log_gps.h
@@ -0,0 +1,33 @@
+/*
+ * 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_telemetry.h"
+
+#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);
+
+void
+ao_log_gps_data(uint16_t tick, struct ao_telemetry_location *gps_data);
+
+#endif /* _AO_LOG_GPS_H_ */
diff --git a/src/core/ao_log_mega.c b/src/kernel/ao_log_mega.c
index 768947d5..cb83be4b 100644
--- a/src/core/ao_log_mega.c
+++ b/src/kernel/ao_log_mega.c
@@ -20,7 +20,6 @@
#include <ao_data.h>
#include <ao_flight.h>
-static __xdata uint8_t ao_log_mutex;
static __xdata struct ao_log_mega log;
__code uint8_t ao_log_format = AO_LOG_FORMAT_TELEMEGA;
@@ -65,7 +64,7 @@ ao_log_dump_check_data(void)
return 1;
}
-#if HAS_ADC
+#if HAS_FLIGHT
static __data uint8_t ao_log_data_pos;
/* a hack to make sure that ao_log_megas fill the eeprom block in even units */
@@ -100,9 +99,9 @@ ao_log(void)
log.u.flight.ground_accel_along = ao_ground_accel_along;
log.u.flight.ground_accel_across = ao_ground_accel_across;
log.u.flight.ground_accel_through = ao_ground_accel_through;
+ log.u.flight.ground_roll = ao_ground_roll;
log.u.flight.ground_pitch = ao_ground_pitch;
log.u.flight.ground_yaw = ao_ground_yaw;
- log.u.flight.ground_roll = ao_ground_roll;
#endif
log.u.flight.ground_pres = ao_ground_pres;
log.u.flight.flight = ao_flight_number;
@@ -183,7 +182,7 @@ ao_log(void)
ao_sleep(&ao_log_running);
}
}
-#endif
+#endif /* HAS_FLIGHT */
uint16_t
ao_log_flight(uint8_t slot)
diff --git a/src/core/ao_log_metrum.c b/src/kernel/ao_log_metrum.c
index 91624d98..08e7b8c4 100644
--- a/src/core/ao_log_metrum.c
+++ b/src/kernel/ao_log_metrum.c
@@ -20,7 +20,6 @@
#include <ao_data.h>
#include <ao_flight.h>
-static __xdata uint8_t ao_log_mutex;
static __xdata struct ao_log_metrum log;
__code uint8_t ao_log_format = AO_LOG_FORMAT_TELEMETRUM;
@@ -116,7 +115,9 @@ ao_log(void)
log.u.sensor.pres = ao_data_ring[ao_log_data_pos].ms5607_raw.pres;
log.u.sensor.temp = ao_data_ring[ao_log_data_pos].ms5607_raw.temp;
#endif
+#if HAS_ACCEL
log.u.sensor.accel = ao_data_accel(&ao_data_ring[ao_log_data_pos]);
+#endif
ao_log_metrum(&log);
if (ao_log_state <= ao_flight_coast)
next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT;
diff --git a/src/core/ao_log_micro.c b/src/kernel/ao_log_micro.c
index d665efb5..d665efb5 100644
--- a/src/core/ao_log_micro.c
+++ b/src/kernel/ao_log_micro.c
diff --git a/src/core/ao_log_micro.h b/src/kernel/ao_log_micro.h
index 976852ee..976852ee 100644
--- a/src/core/ao_log_micro.h
+++ b/src/kernel/ao_log_micro.h
diff --git a/src/core/ao_log_mini.c b/src/kernel/ao_log_mini.c
index 29e3bd9f..0ca3ed06 100644
--- a/src/core/ao_log_mini.c
+++ b/src/kernel/ao_log_mini.c
@@ -20,7 +20,6 @@
#include <ao_data.h>
#include <ao_flight.h>
-static __xdata uint8_t ao_log_mutex;
static __xdata struct ao_log_mini log;
__code uint8_t ao_log_format = AO_LOG_FORMAT;
diff --git a/src/core/ao_log_single.c b/src/kernel/ao_log_single.c
index 3f6235a6..3f6235a6 100644
--- a/src/core/ao_log_single.c
+++ b/src/kernel/ao_log_single.c
diff --git a/src/core/ao_log_telem.c b/src/kernel/ao_log_telem.c
index 095aca37..095aca37 100644
--- a/src/core/ao_log_telem.c
+++ b/src/kernel/ao_log_telem.c
diff --git a/src/core/ao_log_telescience.c b/src/kernel/ao_log_telescience.c
index 002a10bd..002a10bd 100644
--- a/src/core/ao_log_telescience.c
+++ b/src/kernel/ao_log_telescience.c
diff --git a/src/core/ao_log_tiny.c b/src/kernel/ao_log_tiny.c
index 67767dc9..67767dc9 100644
--- a/src/core/ao_log_tiny.c
+++ b/src/kernel/ao_log_tiny.c
diff --git a/src/core/ao_microflight.c b/src/kernel/ao_microflight.c
index f680e400..f680e400 100644
--- a/src/core/ao_microflight.c
+++ b/src/kernel/ao_microflight.c
diff --git a/src/core/ao_microkalman.c b/src/kernel/ao_microkalman.c
index 0684ea2b..0684ea2b 100644
--- a/src/core/ao_microkalman.c
+++ b/src/kernel/ao_microkalman.c
diff --git a/src/core/ao_monitor.c b/src/kernel/ao_monitor.c
index 18f170b4..18f170b4 100644
--- a/src/core/ao_monitor.c
+++ b/src/kernel/ao_monitor.c
diff --git a/src/core/ao_mutex.c b/src/kernel/ao_mutex.c
index 952ff462..952ff462 100644
--- a/src/core/ao_mutex.c
+++ b/src/kernel/ao_mutex.c
diff --git a/src/core/ao_notask.c b/src/kernel/ao_notask.c
index 6f967e6d..6f967e6d 100644
--- a/src/core/ao_notask.c
+++ b/src/kernel/ao_notask.c
diff --git a/src/core/ao_notask.h b/src/kernel/ao_notask.h
index 6b6b5bb8..6b6b5bb8 100644
--- a/src/core/ao_notask.h
+++ b/src/kernel/ao_notask.h
diff --git a/src/core/ao_packet.h b/src/kernel/ao_packet.h
index b8426cf9..b8426cf9 100644
--- a/src/core/ao_packet.h
+++ b/src/kernel/ao_packet.h
diff --git a/src/core/ao_panic.c b/src/kernel/ao_panic.c
index c29cd8fe..c29cd8fe 100644
--- a/src/core/ao_panic.c
+++ b/src/kernel/ao_panic.c
diff --git a/src/core/ao_product.c b/src/kernel/ao_product.c
index b9327bac..b9327bac 100644
--- a/src/core/ao_product.c
+++ b/src/kernel/ao_product.c
diff --git a/src/core/ao_pyro.c b/src/kernel/ao_pyro.c
index e59f5bc4..85d88d98 100644
--- a/src/core/ao_pyro.c
+++ b/src/kernel/ao_pyro.c
@@ -213,7 +213,7 @@ ao_pyro_pins_fire(uint16_t fire)
if (fire & (1 << p))
ao_pyro_pin_set(p, 1);
}
- ao_delay(AO_MS_TO_TICKS(50));
+ ao_delay(ao_config.pyro_time);
for (p = 0; p < AO_PYRO_NUM; p++) {
if (fire & (1 << p)) {
ao_pyro_pin_set(p, 0);
@@ -281,7 +281,7 @@ ao_pyro_check(void)
#define NO_VALUE 0xff
-#define AO_PYRO_NAME_LEN 3
+#define AO_PYRO_NAME_LEN 4
#if !DISABLE_HELP
#define ENABLE_HELP 1
@@ -403,7 +403,10 @@ ao_pyro_show(void)
if (ao_pyro_values[v].offset != NO_VALUE) {
int16_t value;
- value = *((int16_t *) ((char *) pyro + ao_pyro_values[v].offset));
+ if (ao_pyro_values[v].flag & AO_PYRO_8_BIT_VALUE)
+ value = *((uint8_t *) ((char *) pyro + ao_pyro_values[v].offset));
+ else
+ value = *((int16_t *) ((char *) pyro + ao_pyro_values[v].offset));
printf ("%6d ", value);
} else {
printf (" ");
@@ -467,7 +470,10 @@ ao_pyro_set(void)
ao_cmd_decimal();
if (ao_cmd_status != ao_cmd_success)
return;
- *((int16_t *) ((char *) &pyro_tmp + ao_pyro_values[v].offset)) = ao_cmd_lex_i;
+ if (ao_pyro_values[v].flag & AO_PYRO_8_BIT_VALUE)
+ *((uint8_t *) ((char *) &pyro_tmp + ao_pyro_values[v].offset)) = ao_cmd_lex_i;
+ else
+ *((int16_t *) ((char *) &pyro_tmp + ao_pyro_values[v].offset)) = ao_cmd_lex_i;
}
}
_ao_config_edit_start();
diff --git a/src/core/ao_pyro.h b/src/kernel/ao_pyro.h
index 0c5642d6..b37aaeb1 100644
--- a/src/core/ao_pyro.h
+++ b/src/kernel/ao_pyro.h
@@ -45,7 +45,11 @@ enum ao_pyro_flag {
ao_pyro_state_less = 0x00004000,
ao_pyro_state_greater_or_equal = 0x00008000,
-};
+}
+#ifdef __GNUC__
+ __attribute__ ((packed))
+#endif
+ ;
struct ao_pyro {
enum ao_pyro_flag flags;
@@ -61,6 +65,8 @@ struct ao_pyro {
uint8_t fired;
};
+#define AO_PYRO_8_BIT_VALUE (ao_pyro_state_less|ao_pyro_state_greater_or_equal)
+
extern uint8_t ao_pyro_wakeup;
extern uint16_t ao_pyro_fired;
diff --git a/src/core/ao_quaternion.h b/src/kernel/ao_quaternion.h
index 044f1607..044f1607 100644
--- a/src/core/ao_quaternion.h
+++ b/src/kernel/ao_quaternion.h
diff --git a/src/core/ao_radio_cmac.c b/src/kernel/ao_radio_cmac.c
index bff848f6..bff848f6 100644
--- a/src/core/ao_radio_cmac.c
+++ b/src/kernel/ao_radio_cmac.c
diff --git a/src/core/ao_radio_cmac.h b/src/kernel/ao_radio_cmac.h
index e86f31e9..e86f31e9 100644
--- a/src/core/ao_radio_cmac.h
+++ b/src/kernel/ao_radio_cmac.h
diff --git a/src/core/ao_radio_cmac_cmd.c b/src/kernel/ao_radio_cmac_cmd.c
index 64410921..64410921 100644
--- a/src/core/ao_radio_cmac_cmd.c
+++ b/src/kernel/ao_radio_cmac_cmd.c
diff --git a/src/core/ao_radio_cmac_cmd.h b/src/kernel/ao_radio_cmac_cmd.h
index 6b8782de..6b8782de 100644
--- a/src/core/ao_radio_cmac_cmd.h
+++ b/src/kernel/ao_radio_cmac_cmd.h
diff --git a/src/core/ao_report.c b/src/kernel/ao_report.c
index 1104cd82..f2263154 100644
--- a/src/core/ao_report.c
+++ b/src/kernel/ao_report.c
@@ -52,6 +52,60 @@ static const uint8_t flight_reports[] = {
static __pdata enum ao_flight_state ao_report_state;
+/*
+ * Farnsworth spacing
+ *
+ * From: http://www.arrl.org/files/file/Technology/x9004008.pdf
+ *
+ * c: character rate in wpm
+ * s: overall rate in wpm
+ * u: unit rate (dit speed)
+ *
+ * dit: u
+ * dah: 3u
+ * intra-character-time: u
+ *
+ * u = 1.2/c
+ *
+ * Because our clock runs at 10ms, we'll round up to 70ms for u, which
+ * is about 17wpm
+ *
+ * Farnsworth adds space between characters and
+ * words:
+ * 60 c - 37.2 s
+ * Ta = -------------
+ * sc
+ *
+ * 3 Ta
+ * Tc = ----
+ * 19
+ *
+ * 7 Ta
+ * Tw = ----
+ * 19
+ *
+ * Ta = total delay to add to the characters (31 units)
+ * of a standard 50-unit "word", in seconds
+ *
+ * Tc = period between characters, in seconds
+ *
+ * Tw = period between words, in seconds
+ *
+ * We'll use Farnsworth spacing with c=18 and s=12:
+ *
+ * u = 1.2/18 = 0.0667
+ *
+ * Ta = (60 * 17 - 37.2 * 12) / (17 * 12) = 2.812
+ *
+ * Tc = 3 * Ta / 19 = .444
+ *
+ * Tw = 1.036
+ *
+ * Note that the values below are all reduced by 10ms; that's because
+ * the timer always adds a tick to make sure the task actually sleeps
+ * at least as long as the argument.
+ */
+
static void
ao_report_beep(void) __reentrant
{
@@ -62,13 +116,13 @@ ao_report_beep(void) __reentrant
return;
while (l--) {
if (r & 8)
- mid(AO_MS_TO_TICKS(600));
- else
mid(AO_MS_TO_TICKS(200));
- pause(AO_MS_TO_TICKS(200));
+ else
+ mid(AO_MS_TO_TICKS(60));
+ pause(AO_MS_TO_TICKS(60));
r >>= 1;
}
- pause(AO_MS_TO_TICKS(400));
+ pause(AO_MS_TO_TICKS(360));
}
static void
@@ -87,19 +141,18 @@ ao_report_digit(uint8_t digit) __reentrant
}
static void
-ao_report_altitude(void)
+ao_report_number(int16_t n)
{
- __pdata int16_t agl = ao_max_height;
__xdata uint8_t digits[10];
__pdata uint8_t ndigits, i;
- if (agl < 0)
- agl = 0;
+ if (n < 0)
+ n = 0;
ndigits = 0;
do {
- digits[ndigits++] = agl % 10;
- agl /= 10;
- } while (agl);
+ digits[ndigits++] = n % 10;
+ n /= 10;
+ } while (n);
i = ndigits;
do
@@ -107,6 +160,27 @@ ao_report_altitude(void)
while (i != 0);
}
+static void
+ao_report_altitude(void)
+{
+ ao_report_number(ao_max_height);
+}
+
+#if HAS_BATTERY_REPORT
+static void
+ao_report_battery(void)
+{
+ __xdata struct ao_data packet;
+ for (;;) {
+ ao_data_get(&packet);
+ if (packet.adc.v_batt != 0)
+ break;
+ ao_sleep(DATA_TO_XDATA(&ao_sample_data));
+ }
+ ao_report_number(ao_battery_decivolt(packet.adc.v_batt));
+}
+#endif
+
#if HAS_IGNITE_REPORT
static uint8_t
ao_report_igniter_ready(enum ao_igniter igniter)
@@ -163,7 +237,12 @@ ao_report(void)
{
ao_report_state = ao_flight_state;
for(;;) {
- ao_report_beep();
+#if HAS_BATTERY_REPORT
+ if (ao_flight_state == ao_flight_startup)
+ ao_report_battery();
+ else
+#endif
+ ao_report_beep();
if (ao_flight_state == ao_flight_landed) {
ao_report_altitude();
#if HAS_FLIGHT
diff --git a/src/core/ao_report_micro.c b/src/kernel/ao_report_micro.c
index 0e8e287f..0e8e287f 100644
--- a/src/core/ao_report_micro.c
+++ b/src/kernel/ao_report_micro.c
diff --git a/src/core/ao_rssi.c b/src/kernel/ao_rssi.c
index 244a84fe..244a84fe 100644
--- a/src/core/ao_rssi.c
+++ b/src/kernel/ao_rssi.c
diff --git a/src/core/ao_sample.c b/src/kernel/ao_sample.c
index 34658951..34658951 100644
--- a/src/core/ao_sample.c
+++ b/src/kernel/ao_sample.c
diff --git a/src/core/ao_sample.h b/src/kernel/ao_sample.h
index 16d4c507..16d4c507 100644
--- a/src/core/ao_sample.h
+++ b/src/kernel/ao_sample.h
diff --git a/src/core/ao_sample_profile.c b/src/kernel/ao_sample_profile.c
index d3743d12..d3743d12 100644
--- a/src/core/ao_sample_profile.c
+++ b/src/kernel/ao_sample_profile.c
diff --git a/src/core/ao_sample_profile.h b/src/kernel/ao_sample_profile.h
index dbc29d3d..dbc29d3d 100644
--- a/src/core/ao_sample_profile.h
+++ b/src/kernel/ao_sample_profile.h
diff --git a/src/core/ao_send_packet.c b/src/kernel/ao_send_packet.c
index 66315d22..66315d22 100644
--- a/src/core/ao_send_packet.c
+++ b/src/kernel/ao_send_packet.c
diff --git a/src/core/ao_send_packet.h b/src/kernel/ao_send_packet.h
index 526f7b55..526f7b55 100644
--- a/src/core/ao_send_packet.h
+++ b/src/kernel/ao_send_packet.h
diff --git a/src/core/ao_serial.h b/src/kernel/ao_serial.h
index baf213c0..baf213c0 100644
--- a/src/core/ao_serial.h
+++ b/src/kernel/ao_serial.h
diff --git a/src/core/ao_sqrt.c b/src/kernel/ao_sqrt.c
index 3a550eaa..3a550eaa 100644
--- a/src/core/ao_sqrt.c
+++ b/src/kernel/ao_sqrt.c
diff --git a/src/core/ao_state.c b/src/kernel/ao_state.c
index ed197aa5..ed197aa5 100644
--- a/src/core/ao_state.c
+++ b/src/kernel/ao_state.c
diff --git a/src/core/ao_stdio.c b/src/kernel/ao_stdio.c
index cd144d6b..99118137 100644
--- a/src/core/ao_stdio.c
+++ b/src/kernel/ao_stdio.c
@@ -51,6 +51,9 @@
#ifndef USE_SERIAL_9_STDIN
#define USE_SERIAL_9_STDIN 0
#endif
+#ifndef PACKET_HAS_SLAVE
+#define PACKET_HAS_SLAVE 0
+#endif
#define USE_SERIAL_STDIN (USE_SERIAL_0_STDIN + \
USE_SERIAL_1_STDIN + \
diff --git a/src/core/ao_storage.c b/src/kernel/ao_storage.c
index 6eddae7f..6eddae7f 100644
--- a/src/core/ao_storage.c
+++ b/src/kernel/ao_storage.c
diff --git a/src/core/ao_storage.h b/src/kernel/ao_storage.h
index 6cc6fcb7..6cc6fcb7 100644
--- a/src/core/ao_storage.h
+++ b/src/kernel/ao_storage.h
diff --git a/src/core/ao_task.c b/src/kernel/ao_task.c
index bafb4943..bafb4943 100644
--- a/src/core/ao_task.c
+++ b/src/kernel/ao_task.c
diff --git a/src/core/ao_task.h b/src/kernel/ao_task.h
index 9c56b480..9c56b480 100644
--- a/src/core/ao_task.h
+++ b/src/kernel/ao_task.h
diff --git a/src/core/ao_telem.h b/src/kernel/ao_telem.h
index 1a8da291..1a8da291 100644
--- a/src/core/ao_telem.h
+++ b/src/kernel/ao_telem.h
diff --git a/src/core/ao_telemetry.c b/src/kernel/ao_telemetry.c
index 5a00d825..9f778b09 100644
--- a/src/core/ao_telemetry.c
+++ b/src/kernel/ao_telemetry.c
@@ -187,7 +187,9 @@ ao_send_metrum_sensor(void)
telemetry.generic.type = AO_TELEMETRY_METRUM_SENSOR;
telemetry.metrum_sensor.state = ao_flight_state;
+#if HAS_ACCEL
telemetry.metrum_sensor.accel = ao_data_accel(packet);
+#endif
telemetry.metrum_sensor.pres = ao_data_pres(packet);
telemetry.metrum_sensor.temp = ao_data_temp(packet);
@@ -216,9 +218,15 @@ ao_send_metrum_data(void)
telemetry.generic.type = AO_TELEMETRY_METRUM_DATA;
telemetry.metrum_data.ground_pres = ao_ground_pres;
+#if HAS_ACCEL
telemetry.metrum_data.ground_accel = ao_ground_accel;
telemetry.metrum_data.accel_plus_g = ao_config.accel_plus_g;
telemetry.metrum_data.accel_minus_g = ao_config.accel_minus_g;
+#else
+ telemetry.metrum_data.ground_accel = 1;
+ telemetry.metrum_data.accel_plus_g = 0;
+ telemetry.metrum_data.accel_minus_g = 2;
+#endif
ao_radio_send(&telemetry, sizeof (telemetry));
ao_telemetry_metrum_data_cur = ao_telemetry_metrum_data_max;
@@ -297,8 +305,14 @@ ao_send_configuration(void)
#endif
telemetry.configuration.config_major = AO_CONFIG_MAJOR;
telemetry.configuration.config_minor = AO_CONFIG_MINOR;
+#if AO_idProduct_NUMBER == 0x25 && HAS_ADC
+ /* TeleGPS gets battery voltage instead of apogee delay */
+ telemetry.configuration.apogee_delay = ao_data_ring[ao_data_ring_prev(ao_data_head)].adc.v_batt;
+#else
telemetry.configuration.apogee_delay = ao_config.apogee_delay;
telemetry.configuration.main_deploy = ao_config.main_deploy;
+#endif
+
telemetry.configuration.flight_log_max = ao_config.flight_log_max >> 10;
ao_xmemcpy (telemetry.configuration.callsign,
ao_config.callsign,
diff --git a/src/core/ao_telemetry.h b/src/kernel/ao_telemetry.h
index 237a35ab..be7d0340 100644
--- a/src/core/ao_telemetry.h
+++ b/src/kernel/ao_telemetry.h
@@ -115,7 +115,7 @@ 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[1]; /* 31 */
+ uint8_t unused; /* 31 unused */
/* 32 */
};
@@ -154,7 +154,7 @@ struct ao_telemetry_companion {
uint16_t companion_data[AO_COMPANION_MAX_CHANNELS]; /* 8 */
/* 32 */
};
-
+
#define AO_TELEMETRY_MEGA_SENSOR 0x08
struct ao_telemetry_mega_sensor {
@@ -181,7 +181,7 @@ struct ao_telemetry_mega_sensor {
int16_t mag_z; /* 30 */
/* 32 */
};
-
+
#define AO_TELEMETRY_MEGA_DATA 0x09
struct ao_telemetry_mega_data {
@@ -231,7 +231,7 @@ struct ao_telemetry_metrum_sensor {
uint8_t pad[6]; /* 26 */
/* 32 */
};
-
+
#define AO_TELEMETRY_METRUM_DATA 0x0B
struct ao_telemetry_metrum_data {
diff --git a/src/kernel/ao_tracker.c b/src/kernel/ao_tracker.c
new file mode 100644
index 00000000..9febc7f0
--- /dev/null
+++ b/src/kernel/ao_tracker.c
@@ -0,0 +1,226 @@
+/*
+ * 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_flight.h>
+#include <ao_log.h>
+#include <ao_log_gps.h>
+#include <ao_distance.h>
+#include <ao_tracker.h>
+#include <ao_exti.h>
+
+static uint8_t ao_tracker_force_telem;
+
+#if HAS_USB_CONNECT
+static inline uint8_t
+ao_usb_connected(void)
+{
+ return ao_gpio_get(AO_USB_CONNECT_PORT, AO_USB_CONNECT_PIN, AO_USB_CONNECT) != 0;
+}
+#else
+#define ao_usb_connected() 1
+#endif
+
+struct gps_position {
+ int32_t latitude;
+ int32_t longitude;
+ int16_t altitude;
+};
+
+#define GPS_RING 16
+
+struct gps_position gps_position[GPS_RING];
+
+#define ao_gps_ring_next(n) (((n) + 1) & (GPS_RING - 1))
+#define ao_gps_ring_prev(n) (((n) - 1) & (GPS_RING - 1))
+
+static uint8_t gps_head;
+
+static uint8_t tracker_mutex;
+static uint8_t log_started;
+static struct ao_telemetry_location gps_data;
+static uint8_t tracker_running;
+static uint16_t tracker_interval;
+
+static void
+ao_tracker(void)
+{
+ uint8_t new;
+ int32_t ground_distance;
+ int16_t height;
+ uint16_t gps_tick;
+ uint8_t new_tracker_running;
+
+#if HAS_ADC
+ ao_timer_set_adc_interval(100);
+#endif
+
+#if !HAS_USB_CONNECT
+ ao_tracker_force_telem = 1;
+#endif
+ ao_log_scan();
+
+ ao_rdf_set(1);
+
+ tracker_interval = ao_config.tracker_interval;
+ ao_gps_set_rate(tracker_interval);
+
+ for (;;) {
+
+ /** Wait for new GPS data
+ */
+ while (!(new = ao_gps_new))
+ ao_sleep(&ao_gps_new);
+ ao_mutex_get(&ao_gps_mutex);
+ gps_data = ao_gps_data;
+ gps_tick = ao_gps_tick;
+ ao_gps_new = 0;
+ ao_mutex_put(&ao_gps_mutex);
+
+ new_tracker_running = ao_tracker_force_telem || !ao_usb_connected();
+
+ if (ao_config.tracker_interval != tracker_interval) {
+ tracker_interval = ao_config.tracker_interval;
+ ao_gps_set_rate(tracker_interval);
+
+ /* force telemetry interval to be reset */
+ tracker_running = 0;
+ }
+
+ if (new_tracker_running && !tracker_running)
+ ao_telemetry_set_interval(AO_SEC_TO_TICKS(tracker_interval));
+ else if (!new_tracker_running && tracker_running)
+ ao_telemetry_set_interval(0);
+
+ tracker_running = new_tracker_running;
+
+ if (new_tracker_running && !ao_log_running)
+ ao_log_start();
+ else if (!new_tracker_running && ao_log_running)
+ ao_log_stop();
+
+ if (!ao_log_running)
+ continue;
+
+ if (new & AO_GPS_NEW_DATA) {
+ if ((gps_data.flags & (AO_GPS_VALID|AO_GPS_COURSE_VALID)) ==
+ (AO_GPS_VALID|AO_GPS_COURSE_VALID))
+ {
+ uint8_t ring;
+ uint8_t moving = 0;
+
+ 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;
+ if (height < 0)
+ height = -height;
+
+ if (ao_tracker_force_telem)
+ printf("head %d ring %d ground_distance %d height %d\n", gps_head, ring, ground_distance, height);
+ if (ground_distance > ao_config.tracker_motion ||
+ height > (ao_config.tracker_motion << 1))
+ {
+ moving = 1;
+ break;
+ }
+ }
+ if (ao_tracker_force_telem) {
+ printf ("moving %d started %d\n", moving, log_started);
+ flush();
+ }
+ if (moving) {
+ ao_mutex_get(&tracker_mutex);
+ if (!log_started) {
+ ao_log_gps_flight();
+ log_started = 1;
+ }
+ 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_head = ao_gps_ring_next(gps_head);
+ ao_mutex_put(&tracker_mutex);
+ }
+ }
+ }
+ }
+}
+
+static uint8_t erasing_current;
+
+void
+ao_tracker_erase_start(uint16_t flight)
+{
+ erasing_current = flight == ao_flight_number;
+ if (erasing_current) {
+ ao_mutex_get(&tracker_mutex);
+ ao_log_stop();
+ if (++ao_flight_number == 0)
+ ao_flight_number = 1;
+ }
+}
+
+void
+ao_tracker_erase_end(void)
+{
+ if (erasing_current) {
+ ao_log_scan();
+ log_started = 0;
+ ao_mutex_put(&tracker_mutex);
+ }
+}
+
+static struct ao_task ao_tracker_task;
+
+static void
+ao_tracker_set_telem(void)
+{
+ uint8_t telem;
+ ao_cmd_hex();
+ telem = ao_cmd_lex_i;
+ if (ao_cmd_status == ao_cmd_success)
+ ao_tracker_force_telem = telem;
+ ao_cmd_status = ao_cmd_success;
+ printf ("flight: %d\n", ao_flight_number);
+ printf ("force_telem: %d\n", ao_tracker_force_telem);
+ printf ("tracker_running: %d\n", tracker_running);
+ 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 ("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);
+ printf ("log_end_pos: %ld\n", (long) ao_log_end_pos);
+}
+
+static const struct ao_cmds ao_tracker_cmds[] = {
+ { ao_tracker_set_telem, "t <d>\0Set telem on USB" },
+ { 0, NULL },
+};
+
+void
+ao_tracker_init(void)
+{
+#if HAS_USB_CONNECT
+ ao_enable_input(AO_USB_CONNECT_PORT, AO_USB_CONNECT_PIN, 0);
+#endif
+ ao_cmd_register(&ao_tracker_cmds[0]);
+ ao_add_task(&ao_tracker_task, ao_tracker, "tracker");
+}
diff --git a/src/kernel/ao_tracker.h b/src/kernel/ao_tracker.h
new file mode 100644
index 00000000..78c40cb4
--- /dev/null
+++ b/src/kernel/ao_tracker.h
@@ -0,0 +1,37 @@
+/*
+ * 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_TRACKER_H_
+#define _AO_TRACKER_H_
+
+/* Any motion more than this will result in a log entry */
+
+#define AO_TRACKER_MOTION_DEFAULT 10
+#define AO_TRACKER_INTERVAL_DEFAULT 1
+
+#define AO_TRACKER_MOTION_COUNT 10
+
+void
+ao_tracker_init(void);
+
+void
+ao_tracker_erase_start(uint16_t flight);
+
+void
+ao_tracker_erase_end(void);
+
+#endif /* _AO_TRACKER_H_ */
diff --git a/src/core/ao_usb.h b/src/kernel/ao_usb.h
index 35e64e65..1ce4f82f 100644
--- a/src/core/ao_usb.h
+++ b/src/kernel/ao_usb.h
@@ -137,4 +137,6 @@ struct ao_usb_line_coding {
uint8_t data_bits;
} ;
+extern __pdata uint8_t ao_usb_running;
+
#endif /* _AO_USB_H_ */
diff --git a/src/lpc/Makefile-lpc.defs b/src/lpc/Makefile-lpc.defs
index fecb9135..bccea5bc 100644
--- a/src/lpc/Makefile-lpc.defs
+++ b/src/lpc/Makefile-lpc.defs
@@ -4,7 +4,7 @@ endif
include $(TOPDIR)/Makedefs
-vpath % $(TOPDIR)/lpc:$(TOPDIR)/product:$(TOPDIR)/drivers:$(TOPDIR)/core:$(TOPDIR)/util:$(TOPDIR)/kalman:$(TOPDIR/aes):$(TOPDIR):$(TOPDIR)/math
+vpath % $(TOPDIR)/lpc:$(TOPDIR)/product:$(TOPDIR)/drivers:$(TOPDIR)/kernel:$(TOPDIR)/util:$(TOPDIR)/kalman:$(TOPDIR/aes):$(TOPDIR):$(TOPDIR)/math
vpath make-altitude $(TOPDIR)/util
vpath make-kalman $(TOPDIR)/util
vpath kalman.5c $(TOPDIR)/kalman
@@ -28,7 +28,7 @@ CC=$(ARM_CC)
WARN_FLAGS=-Wall -Wextra -Werror
-AO_CFLAGS=-I. -I$(TOPDIR)/lpc -I$(TOPDIR)/core -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) -I$(TOPDIR)/math -I$(TOPDIR) $(PDCLIB_INCLUDES)
+AO_CFLAGS=-I. -I$(TOPDIR)/lpc -I$(TOPDIR)/kernel -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) -I$(TOPDIR)/math -I$(TOPDIR) $(PDCLIB_INCLUDES)
LPC_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m0 -mthumb\
-ffreestanding -nostdlib $(AO_CFLAGS) $(WARN_FLAGS)
diff --git a/src/lpc/ao_adc_lpc.c b/src/lpc/ao_adc_lpc.c
index e1aae0e4..b24163ee 100644
--- a/src/lpc/ao_adc_lpc.c
+++ b/src/lpc/ao_adc_lpc.c
@@ -160,7 +160,7 @@ ao_adc_dump(void) __reentrant
#else
printf("tick: %5u", packet.tick);
d = (int16_t *) (&packet.adc);
- for (i = 0; i < AO_NUM_ADC; i++)
+ for (i = 0; i < AO_ADC_NUM; i++)
printf (" %2d: %5d", i, d[i]);
printf("\n");
#endif
diff --git a/src/lpc/ao_arch.h b/src/lpc/ao_arch.h
index d04bf2c8..5fbb8dfa 100644
--- a/src/lpc/ao_arch.h
+++ b/src/lpc/ao_arch.h
@@ -28,10 +28,10 @@
#define AO_STACK_SIZE 512
#endif
-#define AO_LED_TYPE uint16_t
-
#define AO_PORT_TYPE uint32_t
+#define AO_LED_TYPE AO_PORT_TYPE
+
#ifndef AO_TICK_TYPE
#define AO_TICK_TYPE uint16_t
#define AO_TICK_SIGNED int16_t
@@ -140,7 +140,12 @@ ao_serial_init(void);
#define AO_SPI_SPEED_FAST AO_SPI_SPEED_12MHz
#define AO_BOOT_APPLICATION_BASE ((uint32_t *) 0x00001000)
+#define AO_BOOT_APPLICATION_BOUND ((uint32_t *) (0x00000000 + 32 * 1024))
#define AO_BOOT_LOADER_BASE ((uint32_t *) 0x00000000)
#define HAS_BOOT_LOADER 1
+/* ADC definitions */
+
+#define AO_ADC_MAX 32767
+
#endif /* _AO_ARCH_H_ */
diff --git a/src/lpc/ao_boot_chain.c b/src/lpc/ao_boot_chain.c
index a08d1f2c..9e45ba27 100644
--- a/src/lpc/ao_boot_chain.c
+++ b/src/lpc/ao_boot_chain.c
@@ -43,14 +43,14 @@ struct ao_boot {
};
static struct ao_boot __attribute__ ((section(".boot"))) ao_boot;
-
+
int
ao_boot_check_chain(void)
{
if (ao_boot.signal == AO_BOOT_SIGNAL && ao_boot.check == AO_BOOT_CHECK) {
ao_boot.signal = 0;
ao_boot.check = 0;
- if (ao_boot.base == 0)
+ if (ao_boot.base == AO_BOOT_FORCE_LOADER)
return 0;
ao_boot_chain(ao_boot.base);
}
diff --git a/src/lpc/ao_exti_lpc.c b/src/lpc/ao_exti_lpc.c
index 941aa965..fdb6a1ca 100644
--- a/src/lpc/ao_exti_lpc.c
+++ b/src/lpc/ao_exti_lpc.c
@@ -69,7 +69,7 @@ _ao_exti_set_enable(uint8_t pint)
lpc_gpio_pin.sienr = mask;
else
lpc_gpio_pin.cienr = mask;
-
+
if (mode & AO_EXTI_MODE_FALLING)
lpc_gpio_pin.sienf = mask;
else
@@ -98,7 +98,7 @@ ao_exti_setup (uint8_t port, uint8_t pin, uint8_t mode, void (*callback)(void))
mask = (1 << pint);
ao_pint_inuse |= mask;
ao_pint_enabled &= ~mask;
-
+
ao_pint_map[id] = pint;
ao_exti_callback[pint] = callback;
diff --git a/src/lpc/ao_interrupt.c b/src/lpc/ao_interrupt.c
index c4dc7867..3318db2b 100644
--- a/src/lpc/ao_interrupt.c
+++ b/src/lpc/ao_interrupt.c
@@ -172,5 +172,5 @@ const void *lpc_interrupt_vector[] = {
i(0xb0, hardfault), /* IRQ28 */
i(0xb4, hardfault),
i(0xb8, usb_wakeup),
- i(0xbc, hardfault),
+ i(0xbc, hardfault),
};
diff --git a/src/lpc/ao_led_lpc.c b/src/lpc/ao_led_lpc.c
index 7bef51ba..d983437c 100644
--- a/src/lpc/ao_led_lpc.c
+++ b/src/lpc/ao_led_lpc.c
@@ -17,38 +17,38 @@
#include <ao.h>
-__pdata uint16_t ao_led_enable;
+__pdata AO_PORT_TYPE ao_led_enable;
void
-ao_led_on(uint16_t colors)
+ao_led_on(AO_PORT_TYPE colors)
{
lpc_gpio.pin[LED_PORT] |= colors;
}
void
-ao_led_off(uint16_t colors)
+ao_led_off(AO_PORT_TYPE colors)
{
lpc_gpio.pin[LED_PORT] &= ~colors;
}
void
-ao_led_set(uint16_t colors)
+ao_led_set(AO_PORT_TYPE colors)
{
- uint16_t on = colors & ao_led_enable;
- uint16_t off = ~colors & ao_led_enable;
+ AO_PORT_TYPE on = colors & ao_led_enable;
+ AO_PORT_TYPE off = ~colors & ao_led_enable;
ao_led_off(off);
ao_led_on(on);
}
void
-ao_led_toggle(uint16_t colors)
+ao_led_toggle(AO_PORT_TYPE colors)
{
lpc_gpio.pin[LED_PORT] ^= colors;
}
void
-ao_led_for(uint16_t colors, uint16_t ticks) __reentrant
+ao_led_for(AO_PORT_TYPE colors, uint16_t ticks) __reentrant
{
ao_led_on(colors);
ao_delay(ticks);
@@ -56,10 +56,8 @@ ao_led_for(uint16_t colors, uint16_t ticks) __reentrant
}
void
-ao_led_init(uint16_t enable)
+ao_led_init(AO_PORT_TYPE enable)
{
- int bit;
-
ao_led_enable = enable;
lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_GPIO);
lpc_gpio.dir[LED_PORT] |= enable;
diff --git a/src/lpc/ao_serial_lpc.c b/src/lpc/ao_serial_lpc.c
index 431ae98a..b0d5fcbc 100644
--- a/src/lpc/ao_serial_lpc.c
+++ b/src/lpc/ao_serial_lpc.c
@@ -206,8 +206,8 @@ ao_serial_init(void)
lpc_nvic_set_enable(LPC_ISR_USART_POS);
lpc_nvic_set_priority(LPC_ISR_USART_POS, 0);
#if USE_SERIAL_0_STDIN
- ao_add_stdio(_ao_serial_pollchar,
- ao_serial_putchar,
+ ao_add_stdio(_ao_serial0_pollchar,
+ ao_serial0_putchar,
NULL);
#endif
}
diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c
index d02ccdd6..12f5d8e6 100644
--- a/src/lpc/ao_usb_lpc.c
+++ b/src/lpc/ao_usb_lpc.c
@@ -109,7 +109,7 @@ static uint8_t ao_usb_in_pending;
* but not pulled to the shadow buffer.
*/
static uint8_t ao_usb_out_avail;
-static uint8_t ao_usb_running;
+uint8_t ao_usb_running;
static uint8_t ao_usb_configuration;
#define AO_USB_EP0_GOT_RESET 1
@@ -875,7 +875,7 @@ ao_usb_enable(void)
int t;
/* Enable USB pins */
-#if HAS_USB_CONNECT
+#if HAS_LPC_USB_CONNECT
lpc_ioconf.pio0_6 = ((LPC_IOCONF_FUNC_USB_CONNECT << LPC_IOCONF_FUNC) |
(LPC_IOCONF_MODE_INACTIVE << LPC_IOCONF_MODE) |
(0 << LPC_IOCONF_HYS) |
diff --git a/src/lpcxpresso/ao_pins.h b/src/lpcxpresso/ao_pins.h
index c0074ce2..0ffc2fad 100644
--- a/src/lpcxpresso/ao_pins.h
+++ b/src/lpcxpresso/ao_pins.h
@@ -16,7 +16,6 @@
*/
#define HAS_BEEP 0
-#define HAS_LED 1
/* Crystal on the board */
#define AO_LPC_CLKIN 12000000
diff --git a/src/megadongle-v0.1/Makefile b/src/megadongle-v0.1/Makefile
index 6035c348..ade8e496 100644
--- a/src/megadongle-v0.1/Makefile
+++ b/src/megadongle-v0.1/Makefile
@@ -9,6 +9,7 @@ INC = \
ao.h \
ao_arch.h \
ao_arch_funcs.h \
+ ao_boot.h \
ao_pins.h \
ao_product.h \
ao_cc1120_CC1120.h \
diff --git a/src/micropeak/Makefile b/src/micropeak/Makefile
index dcc32874..6ae3d0be 100644
--- a/src/micropeak/Makefile
+++ b/src/micropeak/Makefile
@@ -2,12 +2,15 @@
# Tiny AltOS build
#
#
-vpath % ../attiny:../drivers:../core:../product:..
+vpath % ../attiny:../drivers:../kernel:../product:..
vpath ao-make-product.5c ../util
vpath make-altitude-pa ../util
include ../avr/Makefile.defs
+PUBLISH_DIR=$(HOME)/altusmetrumllc/Binaries
+PUBLISH_FILE=$(PUBLISH_DIR)/$(PROG)-$(VERSION).hex
+
MCU=attiny85
DUDECPUTYPE=t85
#PROGRAMMER=stk500v2 -P usb
@@ -47,7 +50,7 @@ INC=\
IDPRODUCT=0
PRODUCT=MicroPeak-v0.1
PRODUCT_DEF=-DMICROPEAK
-CFLAGS = $(PRODUCT_DEF) -I. -I../attiny -I../core -I.. -I../drivers -I../product
+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
@@ -98,6 +101,16 @@ clean:
rm -f *.o $(PROG) $(PROG).hex
rm -f ao_product.h
+
+publish: $(PROG).hex
+ cp -a $(PROG).hex $(PUBLISH_FILE)
+
+load-product:
+ $(LOADCMD) $(LOADARG)$(PUBLISH_FILE)
+
+load-product-slow:
+ $(LOADCMD) $(LOADSLOW) $(LOADARG)$(PUBLISH_FILE)
+
../altitude-pa.h: make-altitude-pa
nickle $< > $@
diff --git a/src/microwater/.gitignore b/src/microwater/.gitignore
new file mode 100644
index 00000000..0573d989
--- /dev/null
+++ b/src/microwater/.gitignore
@@ -0,0 +1,2 @@
+ao_product.h
+microwater-*
diff --git a/src/microwater/Makefile b/src/microwater/Makefile
new file mode 100644
index 00000000..a49cda4b
--- /dev/null
+++ b/src/microwater/Makefile
@@ -0,0 +1,121 @@
+#
+# Tiny AltOS build
+#
+#
+vpath % ../attiny:../drivers:../kernel:../product:..
+vpath ao-make-product.5c ../util
+vpath make-altitude-pa ../util
+
+include ../avr/Makefile.defs
+
+PUBLISH_DIR=$(HOME)/altusmetrumllc/Binaries
+PUBLISH_FILE=$(PUBLISH_DIR)/$(PROG)-$(VERSION).hex
+
+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=MicroWater-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
+
+PROG=microwater-v0.1
+
+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) $(PROG).hex
+
+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)
+
+$(PROG).hex: $(PROG)
+ avr-size $(PROG)
+ $(OBJCOPY) -R .eeprom -O ihex $(PROG) $@
+
+
+load: $(PROG).hex
+ $(LOADCMD) $(LOADARG)$(PROG).hex
+
+load-slow: $(PROG).hex
+ $(LOADCMD) $(LOADSLOW) $(LOADARG)$(PROG).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) $(PROG).hex
+ rm -f ao_product.h
+
+
+publish: $(PROG).hex
+ cp -a $(PROG).hex $(PUBLISH_FILE)
+
+load-product:
+ $(LOADCMD) $(LOADARG)$(PUBLISH_FILE)
+
+load-product-slow:
+ $(LOADCMD) $(LOADSLOW) $(LOADARG)$(PUBLISH_FILE)
+
+../altitude-pa.h: make-altitude-pa
+ nickle $< > $@
+
+install:
+
+uninstall:
+
+$(OBJ): ao_product.h $(INC)
diff --git a/src/microwater/ao_pins.h b/src/microwater/ao_pins.h
new file mode 100644
index 00000000..37885ec2
--- /dev/null
+++ b/src/microwater/ao_pins.h
@@ -0,0 +1,70 @@
+/*
+ * 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)
+
+/* Pressure change (in Pa) to detect boost */
+#ifndef BOOST_DETECT
+#define BOOST_DETECT 120 /* 10m at sea level, 12m at 2000m */
+#endif
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/nanopeak-v0.1/Makefile b/src/nanopeak-v0.1/Makefile
index 04eea902..d3779594 100644
--- a/src/nanopeak-v0.1/Makefile
+++ b/src/nanopeak-v0.1/Makefile
@@ -2,7 +2,7 @@
# Tiny AltOS build
#
#
-vpath % ../attiny:../drivers:../core:../product:..
+vpath % ../attiny:../drivers:../kernel:../product:..
vpath ao-make-product.5c ../util
vpath make-altitude-pa ../util
@@ -47,7 +47,7 @@ INC=\
IDPRODUCT=0
PRODUCT=NanoPeak-v0.1
PRODUCT_DEF=-DNANOPEAK
-CFLAGS = $(PRODUCT_DEF) -I. -I../attiny -I../core -I.. -I../drivers -I../product
+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
diff --git a/src/product/Makefile.teledongle b/src/product/Makefile.teledongle
index da9bcba0..81151364 100644
--- a/src/product/Makefile.teledongle
+++ b/src/product/Makefile.teledongle
@@ -7,8 +7,8 @@
# TD_VER, TD_DEF and include
# this file
-vpath %.c ..:../core:../cc1111:../drivers:../product
-vpath %.h ..:../core:../cc1111:../drivers:../product
+vpath %.c ..:../kernel:../cc1111:../drivers:../product
+vpath %.h ..:../kernel:../cc1111:../drivers:../product
vpath ao-make-product.5c ../util
ifndef VERSION
diff --git a/src/product/Makefile.telelaunch b/src/product/Makefile.telelaunch
index a5e2eb7f..90fe7833 100644
--- a/src/product/Makefile.telelaunch
+++ b/src/product/Makefile.telelaunch
@@ -4,8 +4,8 @@
# define TELELAUNCH_VER, TELELAUNCH_DEF
# this file
-vpath %.c ..:../core:../cc1111:../drivers:../product
-vpath %.h ..:../core:../cc1111:../drivers:../product
+vpath %.c ..:../kernel:../cc1111:../drivers:../product
+vpath %.h ..:../kernel:../cc1111:../drivers:../product
vpath ao-make-product.5c ../util
ifndef VERSION
diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum
index c740a483..dbbf57d8 100644
--- a/src/product/Makefile.telemetrum
+++ b/src/product/Makefile.telemetrum
@@ -7,8 +7,8 @@
# TM_VER, TM_DEF, TM_INC and TM_SRC and include
# this file
-vpath %.c .:..:../core:../cc1111:../drivers:../product
-vpath %.h .:..:../core:../cc1111:../drivers:../product
+vpath %.c .:..:../kernel:../cc1111:../drivers:../product
+vpath %.h .:..:../kernel:../cc1111:../drivers:../product
vpath ao-make-product.5c ../util
ifndef VERSION
diff --git a/src/product/Makefile.telemini b/src/product/Makefile.telemini
index 0884079e..ff8b9d56 100644
--- a/src/product/Makefile.telemini
+++ b/src/product/Makefile.telemini
@@ -4,8 +4,8 @@
# Define TELEMINI_VER and TELEMINI_DEF and then
# include this file
-vpath %.c ..:../core:../cc1111:../drivers:../product
-vpath %.h ..:../core:../cc1111:../drivers:../product
+vpath %.c ..:../kernel:../cc1111:../drivers:../product
+vpath %.h ..:../kernel:../cc1111:../drivers:../product
vpath ao-make-product.5c ../util
ifndef VERSION
diff --git a/src/product/Makefile.telenano b/src/product/Makefile.telenano
index c31989ee..d2fcb6d8 100644
--- a/src/product/Makefile.telenano
+++ b/src/product/Makefile.telenano
@@ -4,8 +4,8 @@
# Define TELENANO_VER and TELENANO_DEF and then
# include this file
-vpath %.c ..:../core:../cc1111:../drivers:../product
-vpath %.h ..:../core:../cc1111:../drivers:../product
+vpath %.c ..:../kernel:../cc1111:../drivers:../product
+vpath %.h ..:../kernel:../cc1111:../drivers:../product
vpath ao-make-product.5c ../util
ifndef VERSION
diff --git a/src/product/ao_flash_task.c b/src/product/ao_flash_task.c
index 6cb308e1..9a12add6 100644
--- a/src/product/ao_flash_task.c
+++ b/src/product/ao_flash_task.c
@@ -79,6 +79,14 @@ ao_block_erase(void)
ao_flash_erase_page(p);
}
+static int
+ao_block_valid_address(uint32_t addr)
+{
+ if ((uint32_t) AO_BOOT_APPLICATION_BASE <= addr && addr <= (uint32_t) AO_BOOT_APPLICATION_BOUND - 256)
+ return 1;
+ return 0;
+}
+
static void
ao_block_write(void)
{
@@ -87,12 +95,10 @@ ao_block_write(void)
uint8_t data[256];
uint16_t i;
- if (addr < (uint32_t) AO_BOOT_APPLICATION_BASE) {
- ao_put_string("Invalid address\n");
- return;
- }
for (i = 0; i < 256; i++)
data[i] = ao_usb_getchar();
+ if (!ao_block_valid_address(addr))
+ return;
ao_flash_page(p, (void *) data);
}
@@ -104,18 +110,43 @@ ao_block_read(void)
uint16_t i;
uint8_t c;
+ if (!ao_block_valid_address(addr)) {
+ for (i = 0; i < 256; i++)
+ ao_usb_putchar(0xff);
+ return;
+ }
for (i = 0; i < 256; i++) {
c = *p++;
ao_usb_putchar(c);
}
}
+static inline void
+hexchar(uint8_t c)
+{
+ if (c > 10)
+ c += 'a' - ('9' + 1);
+ ao_usb_putchar(c + '0');
+}
+
+static void
+ao_put_hex(uint32_t u)
+{
+ int8_t i;
+ for (i = 28; i >= 0; i -= 4)
+ hexchar((u >> i) & 0xf);
+}
+
static void
ao_show_version(void)
{
ao_put_string("altos-loader");
ao_put_string("\nmanufacturer "); ao_put_string(ao_manufacturer);
ao_put_string("\nproduct "); ao_put_string(ao_product);
+ ao_put_string("\nflash-range ");
+ ao_put_hex((uint32_t) AO_BOOT_APPLICATION_BASE);
+ ao_usb_putchar(' ');
+ ao_put_hex((uint32_t) AO_BOOT_APPLICATION_BOUND);
ao_put_string("\nsoftware-version "); ao_put_string(ao_version);
ao_put_string("\n");
}
diff --git a/src/product/ao_micropeak.h b/src/product/ao_micropeak.h
index 0cefca6f..0ec407d7 100644
--- a/src/product/ao_micropeak.h
+++ b/src/product/ao_micropeak.h
@@ -25,7 +25,9 @@
#define GROUND_AVG (1 << GROUND_AVG_SHIFT)
/* Pressure change (in Pa) to detect boost */
+#ifndef BOOST_DETECT
#define BOOST_DETECT 360 /* 30m at sea level, 36m at 2000m */
+#endif
/* Wait after power on before doing anything to give the user time to assemble the rocket */
#define BOOST_DELAY AO_SEC_TO_TICKS(60)
diff --git a/src/spiradio-v0.1/.sdcdbrc b/src/spiradio-v0.1/.sdcdbrc
index b9f6129c..2c77e32b 100644
--- a/src/spiradio-v0.1/.sdcdbrc
+++ b/src/spiradio-v0.1/.sdcdbrc
@@ -1,2 +1,2 @@
---directory=../cc1111:../product:../core:../drivers:.
+--directory=../cc1111:../product:../kernel:../drivers:.
diff --git a/src/spiradio-v0.1/Makefile b/src/spiradio-v0.1/Makefile
index e644bc49..cd7a9cde 100644
--- a/src/spiradio-v0.1/Makefile
+++ b/src/spiradio-v0.1/Makefile
@@ -5,8 +5,8 @@
SPIRADIO_VER=0.1
SPIRADIO_DEF=0_1
-vpath %.c ..:../core:../cc1111:../drivers:../product
-vpath %.h ..:../core:../cc1111:../drivers:../product
+vpath %.c ..:../kernel:../cc1111:../drivers:../product
+vpath %.h ..:../kernel:../cc1111:../drivers:../product
vpath ao-make-product.5c ../util
ifndef VERSION
diff --git a/src/stm-bringup/Makefile b/src/stm-bringup/Makefile
index 797df2d6..b0943e56 100644
--- a/src/stm-bringup/Makefile
+++ b/src/stm-bringup/Makefile
@@ -1,4 +1,4 @@
-vpath % ..:../core:../product:../drivers:../stm
+vpath % ..:../kernel:../product:../drivers:../stm
vpath ao-make-product.5c ../util
ifndef VERSION
diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile
index 98fcd9e5..869fb32f 100644
--- a/src/stm-demo/Makefile
+++ b/src/stm-demo/Makefile
@@ -9,6 +9,7 @@ INC = \
ao.h \
ao_arch.h \
ao_arch_funcs.h \
+ ao_boot.h \
ao_pins.h \
ao_product.h
@@ -26,7 +27,6 @@ ALTOS_SRC = \
ao_stdio.c \
ao_panic.c \
ao_timer.c \
- ao_serial_stm.c \
ao_lcd_stm.c \
ao_lcd_font.c \
ao_mutex.c \
diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c
index 58cf651b..ffc5d2d8 100644
--- a/src/stm-demo/ao_demo.c
+++ b/src/stm-demo/ao_demo.c
@@ -171,12 +171,38 @@ ao_event(void)
}
#endif
+static uint8_t ao_blinking = 0;
+
+static void
+ao_blink(void)
+{
+ for (;;) {
+ while (!ao_blinking)
+ ao_sleep(&ao_blinking);
+ while (ao_blinking) {
+ ao_led_toggle(AO_LED_BLUE|AO_LED_GREEN);
+ ao_delay(AO_MS_TO_TICKS(500));
+ }
+ }
+}
+
+static struct ao_task ao_blink_task;
+
+static void
+ao_blink_toggle(void)
+{
+ ao_blinking = !ao_blinking;
+ ao_wakeup(&ao_blinking);
+}
+
+
__code struct ao_cmds ao_demo_cmds[] = {
{ ao_dma_test, "D\0DMA test" },
{ ao_spi_write, "W\0SPI write" },
{ ao_spi_read, "R\0SPI read" },
{ ao_i2c_write, "i\0I2C write" },
{ ao_temp, "t\0Show temp" },
+ { ao_blink_toggle, "b\0Toggle LED blinking" },
/* { ao_event, "e\0Monitor event queue" }, */
{ 0, NULL }
};
@@ -188,23 +214,26 @@ main(void)
ao_task_init();
- ao_serial_init();
+ ao_led_init(LEDS_AVAILABLE);
+ ao_led_on(AO_LED_GREEN);
+ ao_led_off(AO_LED_BLUE);
ao_timer_init();
ao_dma_init();
ao_cmd_init();
// ao_lcd_stm_init();
// ao_lcd_font_init();
- ao_spi_init();
- ao_i2c_init();
- ao_exti_init();
+// ao_spi_init();
+// ao_i2c_init();
+// ao_exti_init();
// ao_quadrature_init();
// ao_button_init();
- ao_timer_set_adc_interval(100);
+// ao_timer_set_adc_interval(100);
- ao_adc_init();
+// ao_adc_init();
ao_usb_init();
+ ao_add_task(&ao_blink_task, ao_blink, "blink");
ao_cmd_register(&ao_demo_cmds[0]);
ao_start_scheduler();
diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h
index 40e48a36..885b9db6 100644
--- a/src/stm-demo/ao_pins.h
+++ b/src/stm-demo/ao_pins.h
@@ -42,13 +42,13 @@
#define AO_APB2_PRESCALER 1
#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_1
-#define HAS_SERIAL_1 1
-#define USE_SERIAL_1_STDIN 1
+#define HAS_SERIAL_1 0
+#define USE_SERIAL_1_STDIN 0
#define SERIAL_1_PB6_PB7 1
#define SERIAL_1_PA9_PA10 0
#define HAS_SERIAL_2 0
-#define USE_SERIAL_2_STDIN 1
+#define USE_SERIAL_2_STDIN 0
#define SERIAL_2_PA2_PA3 0
#define SERIAL_2_PD5_PD6 1
@@ -70,7 +70,7 @@
#define AO_BOOT_CHAIN 1
-#define LOW_LEVEL_DEBUG 1
+#define LOW_LEVEL_DEBUG 0
#define LED_PORT_ENABLE STM_RCC_AHBENR_GPIOBEN
#define LED_PORT (&stm_gpiob)
@@ -78,8 +78,7 @@
#define LED_PIN_BLUE 6
#define AO_LED_GREEN (1 << LED_PIN_GREEN)
#define AO_LED_BLUE (1 << LED_PIN_BLUE)
-
-#define AO_LED_RED AO_LED_BLUE /* a patent lie */
+#define AO_LED_PANIC AO_LED_BLUE
#define LEDS_AVAILABLE (AO_LED_BLUE | AO_LED_GREEN)
diff --git a/src/stm-demo/flash-loader/Makefile b/src/stm-demo/flash-loader/Makefile
new file mode 100644
index 00000000..27e54278
--- /dev/null
+++ b/src/stm-demo/flash-loader/Makefile
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=stm-demo
+include $(TOPDIR)/stm/Makefile-flash.defs
diff --git a/src/stm-demo/flash-loader/ao_pins.h b/src/stm-demo/flash-loader/ao_pins.h
new file mode 100644
index 00000000..4c59101a
--- /dev/null
+++ b/src/stm-demo/flash-loader/ao_pins.h
@@ -0,0 +1,35 @@
+/*
+ * 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_
+
+/* Bridge SB17 on the board and use the MCO from the other chip */
+#define AO_HSE 8000000
+#define AO_HSE_BYPASS 1
+
+#include <ao_flash_stm_pins.h>
+
+/* Use the 'user switch' to force boot loader on power on */
+
+#define AO_BOOT_PIN 1
+#define AO_BOOT_APPLICATION_GPIO stm_gpioa
+#define AO_BOOT_APPLICATION_PIN 0
+#define AO_BOOT_APPLICATION_VALUE 0
+#define AO_BOOT_APPLICATION_MODE 0
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/stm-flash/Makefile b/src/stm-flash/Makefile
index 5c0699e1..568ab85a 100644
--- a/src/stm-flash/Makefile
+++ b/src/stm-flash/Makefile
@@ -9,6 +9,7 @@ INC = \
ao.h \
ao_arch.h \
ao_arch_funcs.h \
+ ao_boot.h \
ao_pins.h \
ao_product.h
diff --git a/src/stm/Makefile-flash.defs b/src/stm/Makefile-flash.defs
index 3890eff1..dde51a68 100644
--- a/src/stm/Makefile-flash.defs
+++ b/src/stm/Makefile-flash.defs
@@ -1,4 +1,4 @@
-vpath % $(TOPDIR)/stm:$(TOPDIR)/product:$(TOPDIR)/drivers:$(TOPDIR)/core:$(TOPDIR)/util:$(TOPDIR)
+vpath % $(TOPDIR)/stm:$(TOPDIR)/product:$(TOPDIR)/drivers:$(TOPDIR)/kernel:$(TOPDIR)/util:$(TOPDIR)
vpath ao-make-product.5c $(TOPDIR)/util
.SUFFIXES: .elf .ihx
@@ -14,7 +14,7 @@ include $(TOPDIR)/Makedefs
CC=$(ARM_CC)
LIBS=$(PDCLIB_LIBS_M3) -lgcc
-AO_CFLAGS=-I. -I$(TOPDIR)/stm -I$(TOPDIR)/core -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) $(PDCLIB_INCLUDES)
+AO_CFLAGS=-I. -I$(TOPDIR)/stm -I$(TOPDIR)/kernel -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) $(PDCLIB_INCLUDES)
STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS)
LDFLAGS=-L$(TOPDIR)/stm -Wl,-Taltos-loader.ld
diff --git a/src/stm/Makefile.defs b/src/stm/Makefile.defs
index 42adfd09..c3d2707f 100644
--- a/src/stm/Makefile.defs
+++ b/src/stm/Makefile.defs
@@ -1,4 +1,4 @@
-vpath % ../stm:../product:../drivers:../core:../util:../kalman:../aes:../math:..
+vpath % ../stm:../product:../drivers:../kernel:../util:../kalman:../aes:../math:..
vpath make-altitude ../util
vpath make-kalman ../util
vpath kalman.5c ../kalman
@@ -26,7 +26,7 @@ LIBS=$(PDCLIB_LIBS_M3) -lgcc
WARN_FLAGS=-Wall -Wextra -Werror
-AO_CFLAGS=-I. -I../stm -I../core -I../drivers -I../math -I.. $(PDCLIB_INCLUDES)
+AO_CFLAGS=-I. -I../stm -I../kernel -I../drivers -I../math -I.. $(PDCLIB_INCLUDES)
STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb \
-ffreestanding -nostdlib $(AO_CFLAGS) $(WARN_FLAGS)
diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h
index 76fa9194..a6276c5a 100644
--- a/src/stm/ao_arch.h
+++ b/src/stm/ao_arch.h
@@ -139,7 +139,8 @@ ao_adc_init();
#define AO_ADC_MAX 4095
#define AO_BOOT_APPLICATION_BASE ((uint32_t *) 0x08001000)
-#define AO_BOOT_LOADER_BASE ((uint32_t *) 0x0)
+#define AO_BOOT_APPLICATION_BOUND ((uint32_t *) (0x08000000 + stm_flash_size()))
+#define AO_BOOT_LOADER_BASE ((uint32_t *) 0x08000000)
#define HAS_BOOT_LOADER 1
#endif /* _AO_ARCH_H_ */
diff --git a/src/stm/ao_boot_chain.c b/src/stm/ao_boot_chain.c
index 6a3864a7..bcebf033 100644
--- a/src/stm/ao_boot_chain.c
+++ b/src/stm/ao_boot_chain.c
@@ -50,7 +50,7 @@ ao_boot_check_chain(void)
if (ao_boot.signal == AO_BOOT_SIGNAL && ao_boot.check == AO_BOOT_CHECK) {
ao_boot.signal = 0;
ao_boot.check = 0;
- if (ao_boot.base == 0)
+ if (ao_boot.base == AO_BOOT_FORCE_LOADER)
return 0;
ao_boot_chain(ao_boot.base);
}
diff --git a/src/stm/ao_boot_pin.c b/src/stm/ao_boot_pin.c
index 1000a65a..e825b618 100644
--- a/src/stm/ao_boot_pin.c
+++ b/src/stm/ao_boot_pin.c
@@ -26,7 +26,7 @@ ao_boot_check_pin(void)
/* Enable power interface clock */
stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN);
-
+
/* Enable the input pin */
ao_enable_input(&AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN,
AO_BOOT_APPLICATION_MODE);
diff --git a/src/stm/ao_fast_timer.c b/src/stm/ao_fast_timer.c
index d61b40c9..9a73eb51 100644
--- a/src/stm/ao_fast_timer.c
+++ b/src/stm/ao_fast_timer.c
@@ -88,7 +88,11 @@ void stm_tim6_isr(void)
#define TIMER_23467_SCALER 1
#endif
-#define TIMER_10kHz ((AO_PCLK1 * TIMER_23467_SCALER) / 10000)
+#ifndef FAST_TIMER_FREQ
+#define FAST_TIMER_FREQ 10000
+#endif
+
+#define TIMER_FAST ((AO_PCLK1 * TIMER_23467_SCALER) / FAST_TIMER_FREQ)
void
ao_fast_timer_init(void)
@@ -100,7 +104,7 @@ ao_fast_timer_init(void)
/* Turn on timer 6 */
stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM6EN);
- stm_tim6.psc = TIMER_10kHz;
+ stm_tim6.psc = TIMER_FAST;
stm_tim6.arr = 9;
stm_tim6.cnt = 0;
diff --git a/src/stm/ao_interrupt.c b/src/stm/ao_interrupt.c
index 969e6a0f..56cce0c0 100644
--- a/src/stm/ao_interrupt.c
+++ b/src/stm/ao_interrupt.c
@@ -39,6 +39,38 @@ void stm_ignore_isr(void)
const void *stm_interrupt_vector[];
+uint32_t
+stm_flash_size(void) {
+ uint16_t dev_id = stm_dev_id();
+ uint16_t kbytes = 0;
+
+ switch (dev_id) {
+ case 0x416: /* cat 1 */
+ kbytes = stm_flash_size_medium.f_size;
+ break;
+ case 0x429: /* cat 2 */
+ kbytes = stm_flash_size_medium.f_size & 0xff;
+ break;
+ case 0x427: /* cat 3 */
+ kbytes = stm_flash_size_large.f_size;
+ break;
+ case 0x436: /* cat 4 */
+ switch (stm_flash_size_large.f_size) {
+ case 0:
+ kbytes = 256;
+ break;
+ case 1:
+ kbytes = 384;
+ break;
+ }
+ break;
+ case 0x437: /* cat 5 */
+ kbytes = stm_flash_size_large.f_size;
+ break;
+ }
+ return (uint32_t) kbytes * 1024;
+}
+
void start(void)
{
#ifdef AO_BOOT_CHAIN
diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c
index d93531fc..8db62e76 100644
--- a/src/stm/ao_timer.c
+++ b/src/stm/ao_timer.c
@@ -17,6 +17,9 @@
#include "ao.h"
#include <ao_task.h>
+#if HAS_FAKE_FLIGHT
+#include <ao_fake_flight.h>
+#endif
#ifndef HAS_TICK
#define HAS_TICK 1
@@ -47,7 +50,12 @@ void stm_systick_isr(void)
#if AO_DATA_ALL
if (++ao_data_count == ao_data_interval) {
ao_data_count = 0;
- ao_adc_poll();
+#if HAS_FAKE_FLIGHT
+ if (ao_fake_flight_active)
+ ao_fake_flight_poll();
+ else
+#endif
+ ao_adc_poll();
#if (AO_DATA_ALL & ~(AO_DATA_ADC))
ao_wakeup((void *) &ao_data_count);
#endif
diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c
index 27b82357..4e9d1f14 100644
--- a/src/stm/ao_usb_stm.c
+++ b/src/stm/ao_usb_stm.c
@@ -117,7 +117,7 @@ static uint8_t ao_usb_in_pending;
* but not pulled to the shadow buffer.
*/
static uint8_t ao_usb_out_avail;
-static uint8_t ao_usb_running;
+uint8_t ao_usb_running;
static uint8_t ao_usb_configuration;
#define AO_USB_EP0_GOT_RESET 1
@@ -727,6 +727,9 @@ ao_usb_ep0_handle(uint8_t receive)
if (receive & AO_USB_EP0_GOT_TX_ACK) {
debug ("\tgot tx ack\n");
+#if HAS_FLIGHT && AO_USB_FORCE_IDLE
+ ao_flight_force_idle = 1;
+#endif
/* Wait until the IN packet is received from addr 0
* before assigning our local address
*/
diff --git a/src/stm/registers.ld b/src/stm/registers.ld
index 8318c75a..d40fd90f 100644
--- a/src/stm/registers.ld
+++ b/src/stm/registers.ld
@@ -52,5 +52,10 @@ stm_scb = 0xe000ed00;
stm_mpu = 0xe000ed90;
+stm_dbg_mcu = 0xe0042000;
+
/* calibration data in system memory */
stm_temp_cal = 0x1ff80078;
+stm_flash_size_medium = 0x1ff8004c;
+stm_flash_size_large = 0x1ff800cc;
+stm_device_id = 0x1ff80050;
diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h
index 302f4d24..799cccbd 100644
--- a/src/stm/stm32l.h
+++ b/src/stm/stm32l.h
@@ -176,12 +176,27 @@ stm_gpio_get_all(struct stm_gpio *gpio) {
return gpio->idr;
}
-extern struct stm_gpio stm_gpioa;
-extern struct stm_gpio stm_gpiob;
-extern struct stm_gpio stm_gpioc;
-extern struct stm_gpio stm_gpiod;
-extern struct stm_gpio stm_gpioe;
-extern struct stm_gpio stm_gpioh;
+/*
+ * We can't define these in registers.ld or our fancy
+ * ao_enable_gpio macro will expand into a huge pile of code
+ * as the compiler won't do correct constant folding and
+ * dead-code elimination
+
+ extern struct stm_gpio stm_gpioa;
+ extern struct stm_gpio stm_gpiob;
+ extern struct stm_gpio stm_gpioc;
+ extern struct stm_gpio stm_gpiod;
+ extern struct stm_gpio stm_gpioe;
+ extern struct stm_gpio stm_gpioh;
+
+*/
+
+#define stm_gpioh (*((struct stm_gpio *) 0x40021400))
+#define stm_gpioe (*((struct stm_gpio *) 0x40021000))
+#define stm_gpiod (*((struct stm_gpio *) 0x40020c00))
+#define stm_gpioc (*((struct stm_gpio *) 0x40020800))
+#define stm_gpiob (*((struct stm_gpio *) 0x40020400))
+#define stm_gpioa (*((struct stm_gpio *) 0x40020000))
struct stm_usart {
vuint32_t sr; /* status register */
@@ -1492,6 +1507,36 @@ extern struct stm_temp_cal stm_temp_cal;
#define stm_temp_cal_cold 25
#define stm_temp_cal_hot 110
+struct stm_dbg_mcu {
+ uint32_t idcode;
+};
+
+extern struct stm_dbg_mcu stm_dbg_mcu;
+
+static inline uint16_t
+stm_dev_id(void) {
+ return stm_dbg_mcu.idcode & 0xfff;
+}
+
+struct stm_flash_size {
+ uint16_t f_size;
+};
+
+extern struct stm_flash_size stm_flash_size_medium;
+extern struct stm_flash_size stm_flash_size_large;
+
+/* Returns flash size in bytes */
+extern uint32_t
+stm_flash_size(void);
+
+struct stm_device_id {
+ uint32_t u_id0;
+ uint32_t u_id1;
+ uint32_t u_id2;
+};
+
+extern struct stm_device_id stm_device_id;
+
#define STM_NUM_I2C 2
#define STM_I2C_INDEX(channel) ((channel) - 1)
diff --git a/src/teleballoon-v1.1/Makefile b/src/teleballoon-v1.1/Makefile
index 6ff076a9..c6f6345a 100644
--- a/src/teleballoon-v1.1/Makefile
+++ b/src/teleballoon-v1.1/Makefile
@@ -17,8 +17,8 @@ TELEBALLOON_SRC = \
ao_gps_skytraq.c \
ao_m25.c
-vpath %.c ..:../core:../cc1111:../drivers:../product:.
-vpath %.h ..:../core:../cc1111:../drivers:../product:.
+vpath %.c ..:../kernel:../cc1111:../drivers:../product:.
+vpath %.h ..:../kernel:../cc1111:../drivers:../product:.
vpath ao-make-product.5c ../util
ifndef VERSION
diff --git a/src/teleballoon-v1.1/ao_pins.h b/src/teleballoon-v1.1/ao_pins.h
index 7ba48c96..4c23ca88 100644
--- a/src/teleballoon-v1.1/ao_pins.h
+++ b/src/teleballoon-v1.1/ao_pins.h
@@ -28,6 +28,7 @@
#define HAS_FLIGHT 1
#define HAS_USB 1
#define HAS_BEEP 1
+ #define HAS_BATTERY_REPORT 1
#define HAS_GPS 1
#define HAS_SERIAL_1 1
#define HAS_ADC 1
diff --git a/src/teleballoon-v2.0/.gitignore b/src/teleballoon-v2.0/.gitignore
new file mode 100644
index 00000000..85f12553
--- /dev/null
+++ b/src/teleballoon-v2.0/.gitignore
@@ -0,0 +1,3 @@
+ao_product.h
+teleballoon-*.elf
+
diff --git a/src/teleballoon-v2.0/Makefile b/src/teleballoon-v2.0/Makefile
new file mode 100644
index 00000000..28588778
--- /dev/null
+++ b/src/teleballoon-v2.0/Makefile
@@ -0,0 +1,130 @@
+#
+# 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_mma655x.h \
+ ao_cc1120_CC1120.h \
+ ao_profile.h \
+ ao_task.h \
+ ao_whiten.h \
+ ao_sample_profile.h \
+ ao_mpu.h \
+ stm32l.h \
+ Makefile
+
+#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_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_serial_stm.c \
+ ao_gps_ublox.c \
+ ao_gps_show.c \
+ ao_gps_report_metrum.c \
+ ao_ignite.c \
+ ao_freq.c \
+ ao_dma_stm.c \
+ ao_spi_stm.c \
+ ao_cc1120.c \
+ ao_fec_tx.c \
+ ao_fec_rx.c \
+ ao_data.c \
+ ao_ms5607.c \
+ ao_mma655x.c \
+ ao_adc_stm.c \
+ ao_beep_stm.c \
+ ao_storage.c \
+ ao_m25.c \
+ ao_usb_stm.c \
+ ao_exti_stm.c \
+ ao_eeprom_stm.c \
+ ao_report.c \
+ ao_convert_pa.c \
+ ao_convert_volt.c \
+ ao_log.c \
+ ao_log_metrum.c \
+ ao_sample.c \
+ ao_kalman.c \
+ ao_balloon.c \
+ ao_telemetry.c \
+ ao_packet_slave.c \
+ ao_packet.c \
+ ao_companion.c \
+ ao_aprs.c \
+ $(MATH_SRC) \
+ $(PROFILE) \
+ $(SAMPLE_PROFILE) \
+ $(STACK_GUARD)
+
+PRODUCT=TeleBalloon-v2.0
+PRODUCT_DEF=-DTELEMETRUM_V_2_0
+IDPRODUCT=0x000b
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g
+
+PROGNAME=teleballoon-v2.0
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_teleballoon.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/teleballoon-v2.0/ao_pins.h b/src/teleballoon-v2.0/ao_pins.h
new file mode 100644
index 00000000..a369070f
--- /dev/null
+++ b/src/teleballoon-v2.0/ao_pins.h
@@ -0,0 +1,328 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#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 1
+
+#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 1
+#define USE_SERIAL_3_STDIN 0
+#define SERIAL_3_PB10_PB11 1
+#define SERIAL_3_PC10_PC11 0
+#define SERIAL_3_PD8_PD9 0
+
+#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX (512 * 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 BEEPER_CHANNEL 4
+#define HAS_RADIO 1
+#define HAS_TELEMETRY 1
+#define HAS_APRS 1
+
+#define HAS_SPI_1 1
+#define SPI_1_PA5_PA6_PA7 1 /* Barometer */
+#define SPI_1_PB3_PB4_PB5 1 /* Accelerometer */
+#define SPI_1_PE13_PE14_PE15 0
+#define SPI_1_OSPEEDR STM_OSPEEDR_10MHz
+
+#define HAS_SPI_2 1
+#define SPI_2_PB13_PB14_PB15 1 /* Flash, Companion, Radio */
+#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 0
+#define I2C_1_PB8_PB9 0
+
+#define HAS_I2C_2 0
+#define I2C_2_PB10_PB11 0
+
+#define PACKET_HAS_SLAVE 1
+#define PACKET_HAS_MASTER 0
+
+#define LOW_LEVEL_DEBUG 0
+
+#define LED_PORT_ENABLE STM_RCC_AHBENR_GPIOCEN
+#define LED_PORT (&stm_gpioc)
+#define LED_PIN_RED 14
+#define LED_PIN_GREEN 15
+#define AO_LED_RED (1 << LED_PIN_RED)
+#define AO_LED_GREEN (1 << LED_PIN_GREEN)
+
+#define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN)
+
+#define HAS_GPS 1
+#define HAS_FLIGHT 1
+#define HAS_ADC 1
+#define HAS_ADC_TEMP 1
+#define HAS_LOG 1
+#define AO_USB_FORCE_IDLE 0
+
+/*
+ * Igniter
+ */
+
+#define HAS_IGNITE 0
+#define HAS_IGNITE_REPORT 0
+
+#define AO_SENSE_DROGUE(p) ((p)->adc.sense_a)
+#define AO_SENSE_MAIN(p) ((p)->adc.sense_m)
+#define AO_IGNITER_CLOSED 400
+#define AO_IGNITER_OPEN 60
+
+/* Drogue */
+#define AO_IGNITER_DROGUE_PORT (&stm_gpioa)
+#define AO_IGNITER_DROGUE_PIN 8
+
+/* Main */
+#define AO_IGNITER_MAIN_PORT (&stm_gpioa)
+#define AO_IGNITER_MAIN_PIN 9
+
+#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 2
+
+struct ao_adc {
+ int16_t sense_a;
+ int16_t sense_m;
+ int16_t v_batt;
+ int16_t temp;
+};
+
+#define AO_ADC_DUMP(p) \
+ printf("tick: %5u drogue: %5d main: %5d batt: %5d\n", \
+ (p)->tick, \
+ (p)->adc.sense_a, (p)->adc.sense_m, \
+ (p)->adc.v_batt);
+
+#define AO_ADC_SENSE_DROGUE 0
+#define AO_ADC_SENSE_DROGUE_PORT (&stm_gpioa)
+#define AO_ADC_SENSE_DROGUE_PIN 0
+
+#define AO_ADC_SENSE_MAIN 1
+#define AO_ADC_SENSE_MAIN_PORT (&stm_gpioa)
+#define AO_ADC_SENSE_MAIN_PIN 1
+
+#define AO_ADC_V_BATT 8
+#define AO_ADC_V_BATT_PORT (&stm_gpiob)
+#define AO_ADC_V_BATT_PIN 0
+
+#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 3
+
+#define AO_ADC_PIN0_PORT AO_ADC_SENSE_DROGUE_PORT
+#define AO_ADC_PIN0_PIN AO_ADC_SENSE_DROGUE_PIN
+#define AO_ADC_PIN1_PORT AO_ADC_SENSE_MAIN_PORT
+#define AO_ADC_PIN1_PIN AO_ADC_SENSE_MAIN_PIN
+#define AO_ADC_PIN2_PORT AO_ADC_V_BATT_PORT
+#define AO_ADC_PIN2_PIN AO_ADC_V_BATT_PIN
+
+#define AO_NUM_ADC (AO_NUM_ADC_PIN + 1)
+
+#define AO_ADC_SQ1 AO_ADC_SENSE_DROGUE
+#define AO_ADC_SQ2 AO_ADC_SENSE_MAIN
+#define AO_ADC_SQ3 AO_ADC_V_BATT
+#define AO_ADC_SQ4 AO_ADC_TEMP
+
+/*
+ * Voltage divider on ADC battery sampler
+ */
+#define AO_BATTERY_DIV_PLUS 56 /* 5.6k */
+#define AO_BATTERY_DIV_MINUS 100 /* 10k */
+
+/*
+ * Voltage divider on ADC igniter samplers
+ */
+#define AO_IGNITE_DIV_PLUS 100 /* 100k */
+#define AO_IGNITE_DIV_MINUS 27 /* 27k */
+
+/*
+ * ADC reference in decivolts
+ */
+#define AO_ADC_REFERENCE_DV 33
+
+/*
+ * GPS
+ */
+
+#define AO_SERIAL_SPEED_UBLOX AO_SERIAL_SPEED_9600
+
+#define ao_gps_getchar ao_serial3_getchar
+#define ao_gps_putchar ao_serial3_putchar
+#define ao_gps_set_speed ao_serial3_set_speed
+#define ao_gps_fifo (ao_stm_usart3.rx_fifo)
+
+/*
+ * Pressure sensor settings
+ */
+#define HAS_MS5607 1
+#define HAS_MS5611 0
+#define AO_MS5607_PRIVATE_PINS 1
+#define AO_MS5607_CS_PORT (&stm_gpiob)
+#define AO_MS5607_CS_PIN 12
+#define AO_MS5607_CS_MASK (1 << AO_MS5607_CS)
+#define AO_MS5607_MISO_PORT (&stm_gpioa)
+#define AO_MS5607_MISO_PIN 6
+#define AO_MS5607_MISO_MASK (1 << AO_MS5607_MISO)
+#define AO_MS5607_SPI_INDEX AO_SPI_1_PA5_PA6_PA7
+
+/*
+ * SPI Flash memory
+ */
+
+#define M25_MAX_CHIPS 1
+#define AO_M25_SPI_CS_PORT (&stm_gpiob)
+#define AO_M25_SPI_CS_MASK (1 << 8)
+#define AO_M25_SPI_BUS AO_SPI_2_PB13_PB14_PB15
+
+/*
+ * Radio (cc1120)
+ */
+
+/* gets pretty close to 434.550 */
+
+#define AO_RADIO_CAL_DEFAULT 0x6ca333
+
+#define AO_FEC_DEBUG 0
+#define AO_CC1120_SPI_CS_PORT (&stm_gpioa)
+#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_gpioa)
+#define AO_CC1120_INT_PIN (3)
+#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
+
+#define AO_CC1120_MARC_GPIO 3
+#define AO_CC1120_MARC_GPIO_IOCFG CC1120_IOCFG3
+
+#define HAS_BOOT_RADIO 0
+
+#define HAS_HIGHG_ACCEL 0
+
+/* Disable accelerometer for balloon mode */
+
+#define HAS_ACCEL 0
+
+/*
+ * mma655x
+ */
+
+#define HAS_MMA655X 0
+#define AO_MMA655X_SPI_INDEX AO_SPI_1_PB3_PB4_PB5
+#define AO_MMA655X_CS_PORT (&stm_gpiob)
+#define AO_MMA655X_CS_PIN 9
+#define AO_MMA655X_INVERT 1
+
+#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 1
+#define AO_MONITOR_LED 0
+#define HAS_RSSI 0
+
+/*
+ * Profiling Viterbi decoding
+ */
+
+#ifndef AO_PROFILE
+#define AO_PROFILE 0
+#endif
+
+/*
+ * Teleballoon-specific bits
+ */
+
+#define AO_TELEMETRY_INTERVAL_BALLOON AO_MS_TO_TICKS(1000)
+
+#define AO_SEND_METRUM 1
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/teleballoon-v2.0/ao_teleballoon.c b/src/teleballoon-v2.0/ao_teleballoon.c
new file mode 100644
index 00000000..9b506814
--- /dev/null
+++ b/src/teleballoon-v2.0/ao_teleballoon.c
@@ -0,0 +1,92 @@
+/*
+ * 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_ms5607.h>
+#include <ao_mma655x.h>
+#include <ao_log.h>
+#include <ao_exti.h>
+#include <ao_packet.h>
+#include <ao_companion.h>
+#include <ao_eeprom.h>
+#include <ao_profile.h>
+#if HAS_SAMPLE_PROFILE
+#include <ao_sample_profile.h>
+#endif
+#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_serial_init();
+ ao_led_init(LEDS_AVAILABLE);
+ ao_led_on(AO_LED_RED);
+ ao_timer_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_MMA655X
+ ao_mma655x_init();
+#endif
+
+ ao_eeprom_init();
+
+ ao_storage_init();
+
+ ao_flight_init();
+ ao_log_init();
+ ao_report_init();
+
+ ao_usb_init();
+ ao_gps_init();
+ ao_gps_report_metrum_init();
+ ao_telemetry_init();
+ ao_radio_init();
+ ao_packet_slave_init(FALSE);
+ ao_companion_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/telebt-v1.0/.sdcdbrc b/src/telebt-v1.0/.sdcdbrc
index b9f6129c..2c77e32b 100644
--- a/src/telebt-v1.0/.sdcdbrc
+++ b/src/telebt-v1.0/.sdcdbrc
@@ -1,2 +1,2 @@
---directory=../cc1111:../product:../core:../drivers:.
+--directory=../cc1111:../product:../kernel:../drivers:.
diff --git a/src/telebt-v1.0/Makefile b/src/telebt-v1.0/Makefile
index 40853fc3..a7797499 100644
--- a/src/telebt-v1.0/Makefile
+++ b/src/telebt-v1.0/Makefile
@@ -5,8 +5,8 @@
TELEBT_VER=1.0
TELEBT_DEF=1_0
-vpath %.c ..:../core:../cc1111:../drivers:../product
-vpath %.h ..:../core:../cc1111:../drivers:../product
+vpath %.c ..:../kernel:../cc1111:../drivers:../product
+vpath %.h ..:../kernel:../cc1111:../drivers:../product
vpath ao-make-product.5c ../util
ifndef VERSION
diff --git a/src/telefire-v0.1/.sdcdbrc b/src/telefire-v0.1/.sdcdbrc
index b9f6129c..2c77e32b 100644
--- a/src/telefire-v0.1/.sdcdbrc
+++ b/src/telefire-v0.1/.sdcdbrc
@@ -1,2 +1,2 @@
---directory=../cc1111:../product:../core:../drivers:.
+--directory=../cc1111:../product:../kernel:../drivers:.
diff --git a/src/telefire-v0.1/Makefile b/src/telefire-v0.1/Makefile
index f9e11698..25267268 100644
--- a/src/telefire-v0.1/Makefile
+++ b/src/telefire-v0.1/Makefile
@@ -5,8 +5,8 @@
TELEFIRE_VER=0.1
TELEFIRE_DEF=0_1
-vpath %.c ..:../core:../cc1111:../drivers:../product
-vpath %.h ..:../core:../cc1111:../drivers:../product
+vpath %.c ..:../kernel:../cc1111:../drivers:../product
+vpath %.h ..:../kernel:../cc1111:../drivers:../product
vpath ao-make-product.5c ../util
ifndef VERSION
diff --git a/src/telefire-v0.2/.sdcdbrc b/src/telefire-v0.2/.sdcdbrc
index b9f6129c..2c77e32b 100644
--- a/src/telefire-v0.2/.sdcdbrc
+++ b/src/telefire-v0.2/.sdcdbrc
@@ -1,2 +1,2 @@
---directory=../cc1111:../product:../core:../drivers:.
+--directory=../cc1111:../product:../kernel:../drivers:.
diff --git a/src/telefire-v0.2/Makefile b/src/telefire-v0.2/Makefile
index a820990a..ad5065c1 100644
--- a/src/telefire-v0.2/Makefile
+++ b/src/telefire-v0.2/Makefile
@@ -5,8 +5,8 @@
TELEFIRE_VER=0.2
TELEFIRE_DEF=0_2
-vpath %.c ..:../core:../cc1111:../drivers:../product
-vpath %.h ..:../core:../cc1111:../drivers:../product
+vpath %.c ..:../kernel:../cc1111:../drivers:../product
+vpath %.h ..:../kernel:../cc1111:../drivers:../product
vpath ao-make-product.5c ../util
ifndef VERSION
diff --git a/src/telegps-v0.1/Makefile b/src/telegps-v0.1/Makefile
index 77ef9c4a..46eb0ac5 100644
--- a/src/telegps-v0.1/Makefile
+++ b/src/telegps-v0.1/Makefile
@@ -9,6 +9,7 @@ INC = \
ao.h \
ao_arch.h \
ao_arch_funcs.h \
+ ao_boot.h \
ao_pins.h \
ao_product.h \
ao_task.h \
diff --git a/src/telegps-v0.3/Makefile b/src/telegps-v0.3/Makefile
index 5aad32b5..1eaf7c47 100644
--- a/src/telegps-v0.3/Makefile
+++ b/src/telegps-v0.3/Makefile
@@ -11,6 +11,7 @@ INC = \
ao_arch_funcs.h \
ao_pins.h \
ao_product.h \
+ ao_tracker.h \
ao_task.h \
ao_whiten.h \
ao_cc115l.h \
@@ -19,9 +20,6 @@ INC = \
Makefile
-MATH_SRC=\
- ef_log.c
-
ALTOS_SRC = \
ao_interrupt.c \
ao_boot_chain.c \
@@ -44,13 +42,14 @@ ALTOS_SRC = \
ao_cc115l.c \
ao_fec_tx.c \
ao_aprs.c \
+ ao_tracker.c \
ao_telemetry.c \
ao_storage.c \
ao_m25.c \
ao_log.c \
- ao_log_mega.c \
- ao_gps_report_mega.c \
- $(MATH_SRC) \
+ ao_log_gps.c \
+ ao_distance.c \
+ ao_sqrt.c \
$(SAMPLE_PROFILE)
PRODUCT=TeleGPS-v0.3
@@ -61,11 +60,12 @@ CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) $(PROFILE_DEF) -Os -g
PROGNAME=telegps-v0.3
PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
SRC=$(ALTOS_SRC) ao_telegps.c
OBJ=$(SRC:.c=.o)
-all: $(PROG)
+all: $(PROG) $(HEX)
LDFLAGS=-L../lpc -Wl,-Taltos.ld
diff --git a/src/telegps-v0.3/ao_pins.h b/src/telegps-v0.3/ao_pins.h
index a4afaa54..d0e4d835 100644
--- a/src/telegps-v0.3/ao_pins.h
+++ b/src/telegps-v0.3/ao_pins.h
@@ -46,7 +46,7 @@
#define HAS_BEEP 0
#define HAS_RADIO 1
#define HAS_TELEMETRY 1
-#define HAS_RDF 0
+#define HAS_RDF 1
#define HAS_APRS 1
#define HAS_RADIO_RECV 0
@@ -69,9 +69,11 @@
#define HAS_FLIGHT 0
#define HAS_ADC 0
#define HAS_LOG 1
+#define HAS_TRACKER 1
-#define AO_CONFIG_DEFAULT_APRS_INTERVAL 5
+#define AO_CONFIG_DEFAULT_APRS_INTERVAL 0
#define AO_CONFIG_DEFAULT_RADIO_POWER 0xc0
+#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX 496 * 1024
/*
* GPS
@@ -85,9 +87,9 @@
/* gets pretty close to 434.550 */
-#define AO_RADIO_CAL_DEFAULT 0x10b6a5
+#define AO_RADIO_CAL_DEFAULT 1095378
-#define HAS_RADIO_POWER 1
+#define HAS_RADIO_POWER 0
#define AO_FEC_DEBUG 0
#define AO_CC115L_SPI_CS_PORT 0
#define AO_CC115L_SPI_CS_PIN 3
diff --git a/src/telegps-v0.3/ao_telegps.c b/src/telegps-v0.3/ao_telegps.c
index 608817e7..dd699ecf 100644
--- a/src/telegps-v0.3/ao_telegps.c
+++ b/src/telegps-v0.3/ao_telegps.c
@@ -17,15 +17,13 @@
#include <ao.h>
#include <ao_exti.h>
-#include <ao_fat.h>
-
-uint16_t ao_flight_number = 1;
+#include <ao_tracker.h>
int
main(void)
{
ao_clock_init();
-
+
#if HAS_STACK_GUARD
ao_mpu_init();
#endif
@@ -48,18 +46,18 @@ main(void)
ao_gps_init();
#if HAS_LOG
- ao_gps_report_mega_init();
ao_log_init();
#endif
+ ao_tracker_init();
+
ao_telemetry_init();
- ao_telemetry_set_interval(AO_SEC_TO_TICKS(1));
#if HAS_SAMPLE_PROFILE
ao_sample_profile_init();
#endif
ao_config_init();
-
+
ao_start_scheduler();
return 0;
}
diff --git a/src/telegps-v1.0/.gitignore b/src/telegps-v1.0/.gitignore
new file mode 100644
index 00000000..892c3acc
--- /dev/null
+++ b/src/telegps-v1.0/.gitignore
@@ -0,0 +1,3 @@
+ao_product.h
+ao_serial_lpc.h
+*.elf
diff --git a/src/telegps-v1.0/Makefile b/src/telegps-v1.0/Makefile
new file mode 100644
index 00000000..bd13cfe7
--- /dev/null
+++ b/src/telegps-v1.0/Makefile
@@ -0,0 +1,91 @@
+#
+# AltOS build
+#
+#
+
+include ../lpc/Makefile.defs
+
+INC = \
+ ao.h \
+ ao_arch.h \
+ ao_arch_funcs.h \
+ ao_pins.h \
+ ao_product.h \
+ ao_tracker.h \
+ ao_task.h \
+ ao_whiten.h \
+ ao_cc115l.h \
+ ao_fec.h \
+ lpc.h \
+ Makefile
+
+
+ALTOS_SRC = \
+ ao_interrupt.c \
+ ao_boot_chain.c \
+ ao_product.c \
+ ao_romconfig.c \
+ ao_cmd.c \
+ ao_config.c \
+ ao_task.c \
+ ao_stdio.c \
+ ao_panic.c \
+ ao_timer_lpc.c \
+ ao_mutex.c \
+ ao_freq.c \
+ ao_spi_lpc.c \
+ ao_usb_lpc.c \
+ ao_exti_lpc.c \
+ ao_serial_lpc.c \
+ ao_gps_ublox.c \
+ ao_gps_show.c \
+ ao_cc115l.c \
+ ao_fec_tx.c \
+ ao_aprs.c \
+ ao_tracker.c \
+ ao_telemetry.c \
+ ao_storage.c \
+ ao_m25.c \
+ ao_log.c \
+ ao_log_gps.c \
+ ao_distance.c \
+ ao_sqrt.c \
+ ao_data.c \
+ ao_adc_lpc.c \
+ ao_convert_volt.c \
+ $(SAMPLE_PROFILE)
+
+PRODUCT=TeleGPS-v1.0
+PRODUCT_DEF=-DTELEGPS
+IDPRODUCT=0x0025
+
+CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) $(PROFILE_DEF) -Os -g
+
+PROGNAME=telegps-v1.0
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_telegps.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+LDFLAGS=-L../lpc -Wl,-Taltos.ld
+
+$(PROG): Makefile $(OBJ) altos.ld
+ $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+$(OBJ): $(INC)
+
+ao_product.h: ao-make-product.5c ../Version
+ $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+distclean: clean
+
+clean:
+ rm -f *.o ao_serial_lpc.h $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+ rm -f ao_product.h
+
+install:
+
+uninstall:
diff --git a/src/telegps-v1.0/ao_pins.h b/src/telegps-v1.0/ao_pins.h
new file mode 100644
index 00000000..5f53dd9d
--- /dev/null
+++ b/src/telegps-v1.0/ao_pins.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define AO_STACK_SIZE 448
+
+#define IS_FLASH_LOADER 0
+
+/* Crystal on the board */
+#define AO_LPC_CLKIN 12000000
+
+/* Main clock frequency. 48MHz for USB so we don't use the USB PLL */
+#define AO_LPC_CLKOUT 48000000
+
+/* System clock frequency */
+#define AO_LPC_SYSCLK 24000000
+
+#define HAS_SERIAL_0 1
+#define SERIAL_0_18_19 1
+#define USE_SERIAL_0_STDIN 0
+
+#define ao_gps_getchar ao_serial0_getchar
+#define ao_gps_putchar ao_serial0_putchar
+#define ao_gps_set_speed ao_serial0_set_speed
+#define ao_gps_fifo (ao_usart_rx_fifo)
+
+#define HAS_EEPROM 1
+#define USE_INTERNAL_FLASH 0
+#define HAS_USB 1
+#define HAS_BEEP 0
+#define HAS_RADIO 1
+#define HAS_TELEMETRY 1
+#define HAS_RDF 1
+#define HAS_APRS 1
+#define HAS_RADIO_RECV 0
+
+#define HAS_USB_PULLUP 1
+#define AO_USB_PULLUP_PORT 0
+#define AO_USB_PULLUP_PIN 7
+#define HAS_USB_CONNECT 1
+#define AO_USB_CONNECT_PORT 1
+#define AO_USB_CONNECT_PIN 19
+
+/* Flash part */
+#define HAS_SPI_0 1
+#define SPI_SCK0_P0_6 1
+#define SPI_0_OSPEEDR AO_SPI_OSPEED_12MHz
+
+/* Radio */
+#define HAS_SPI_1 1
+#define SPI_SCK1_P1_15 1
+#define SPI_MISO1_P0_22 1
+#define SPI_MOSI1_P0_21 1
+
+#define HAS_GPS 1
+#define HAS_FLIGHT 0
+#define HAS_LOG 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
+ */
+
+#define AO_SERIAL_SPEED_UBLOX AO_SERIAL_SPEED_9600
+
+/*
+ * Radio (cc115l)
+ */
+
+/* gets pretty close to 434.550 */
+
+#define AO_RADIO_CAL_DEFAULT 1095378
+
+#define HAS_RADIO_POWER 0
+#define AO_FEC_DEBUG 0
+#define AO_CC115L_SPI_CS_PORT 0
+#define AO_CC115L_SPI_CS_PIN 3
+#define AO_CC115L_SPI_BUS 0
+
+#define AO_CC115L_FIFO_INT_GPIO_IOCFG CC115L_IOCFG2
+#define AO_CC115L_FIFO_INT_PORT 0
+#define AO_CC115L_FIFO_INT_PIN 20
+
+#define AO_CC115L_DONE_INT_GPIO_IOCFG CC115L_IOCFG0
+#define AO_CC115L_DONE_INT_PORT 0
+#define AO_CC115L_DONE_INT_PIN 2
+
+/*
+ * Flash (M25)
+ */
+#define M25_MAX_CHIPS 1
+#define AO_M25_SPI_CS_PORT 0
+#define AO_M25_SPI_CS_MASK (1 << 23)
+#define AO_M25_SPI_BUS 1
+
+#define PACKET_HAS_SLAVE 0
+
+/*
+ * ADC
+ */
+
+#define HAS_ADC 1
+#define LOG_ADC 0
+
+#define AO_DATA_RING 4
+
+#define AO_ADC_3 1
+
+struct ao_adc {
+ int16_t v_batt;
+};
+
+#define AO_ADC_DUMP(p) \
+ printf("tick: %5u batt: %5d\n", \
+ (p)->tick, \
+ (p)->adc.v_batt)
+
+/*
+ * Voltage divider on ADC battery sampler
+ */
+#define AO_BATTERY_DIV_PLUS 56 /* 5.6k */
+#define AO_BATTERY_DIV_MINUS 100 /* 10k */
+
+/*
+ * ADC reference in decivolts
+ */
+#define AO_ADC_REFERENCE_DV 33
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/telegps-v1.0/ao_telegps.c b/src/telegps-v1.0/ao_telegps.c
new file mode 100644
index 00000000..7a71699b
--- /dev/null
+++ b/src/telegps-v1.0/ao_telegps.c
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+#include <ao.h>
+#include <ao_exti.h>
+#include <ao_tracker.h>
+
+int
+main(void)
+{
+ ao_clock_init();
+
+#if HAS_STACK_GUARD
+ ao_mpu_init();
+#endif
+
+ ao_task_init();
+ ao_timer_init();
+
+ ao_spi_init();
+ ao_exti_init();
+
+ ao_storage_init();
+
+ ao_serial_init();
+
+ ao_cmd_init();
+
+ ao_usb_init();
+ ao_radio_init();
+
+#if HAS_ADC
+ ao_adc_init();
+#endif
+
+ ao_gps_init();
+#if HAS_LOG
+ ao_log_init();
+#endif
+
+ ao_tracker_init();
+
+ ao_telemetry_init();
+
+#if HAS_SAMPLE_PROFILE
+ ao_sample_profile_init();
+#endif
+ ao_config_init();
+
+ ao_start_scheduler();
+ return 0;
+}
diff --git a/src/telegps-v1.0/flash-loader/Makefile b/src/telegps-v1.0/flash-loader/Makefile
new file mode 100644
index 00000000..5283f554
--- /dev/null
+++ b/src/telegps-v1.0/flash-loader/Makefile
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=telegps-v1.0
+include $(TOPDIR)/lpc/Makefile-flash.defs
diff --git a/src/lpc/ao_boot.h b/src/telegps-v1.0/flash-loader/ao_pins.h
index e0ed4de7..91097a25 100644
--- a/src/lpc/ao_boot.h
+++ b/src/telegps-v1.0/flash-loader/ao_pins.h
@@ -15,25 +15,19 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef _AO_BOOT_H_
-#define _AO_BOOT_H_
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
-void
-ao_boot_chain(uint32_t *base);
+#include <ao_flash_lpc_pins.h>
-void
-ao_boot_check_pin(void);
+#define AO_BOOT_PIN 1
+#define AO_BOOT_APPLICATION_GPIO 0
+#define AO_BOOT_APPLICATION_PIN 19
+#define AO_BOOT_APPLICATION_VALUE 1
+#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP
-/* Return true to switch to application (if present) */
-int
-ao_boot_check_chain(void);
+#define HAS_USB_PULLUP 1
+#define AO_USB_PULLUP_PORT 0
+#define AO_USB_PULLUP_PIN 7
-void
-ao_boot_reboot(uint32_t *base);
-
-static inline void
-ao_boot_loader(void) {
- ao_boot_reboot(AO_BOOT_LOADER_BASE);
-}
-
-#endif /* _AO_BOOT_H_ */
+#endif /* _AO_PINS_H_ */
diff --git a/src/telelco-v0.1/Makefile b/src/telelco-v0.1/Makefile
index 44d9237f..f7628c30 100644
--- a/src/telelco-v0.1/Makefile
+++ b/src/telelco-v0.1/Makefile
@@ -9,6 +9,7 @@ INC = \
ao.h \
ao_arch.h \
ao_arch_funcs.h \
+ ao_boot.h \
ao_companion.h \
ao_data.h \
ao_sample.h \
diff --git a/src/telelco-v0.2/Makefile b/src/telelco-v0.2/Makefile
index f28bdd32..7a21f099 100644
--- a/src/telelco-v0.2/Makefile
+++ b/src/telelco-v0.2/Makefile
@@ -9,6 +9,7 @@ INC = \
ao.h \
ao_arch.h \
ao_arch_funcs.h \
+ ao_boot.h \
ao_companion.h \
ao_data.h \
ao_sample.h \
diff --git a/src/telelco-v0.2/ao_lco.c b/src/telelco-v0.2/ao_lco.c
index 0bbb76f1..b3f5bb16 100644
--- a/src/telelco-v0.2/ao_lco.c
+++ b/src/telelco-v0.2/ao_lco.c
@@ -251,18 +251,22 @@ ao_lco_search(void)
{
uint16_t tick_offset;
int8_t r;
+ int8_t try;
uint8_t box;
ao_lco_box_reset_present();
for (box = 0; box < AO_PAD_MAX_BOXES; box++) {
if ((box % 10) == 0)
ao_lco_set_box(box);
- tick_offset = 0;
- r = ao_lco_query(box, &ao_pad_query, &tick_offset);
- PRINTD("box %d result %d\n", box, r);
- if (r == AO_RADIO_CMAC_OK) {
- ao_lco_box_set_present(box);
- ao_delay(AO_MS_TO_TICKS(30));
+ for (try = 0; try < 5; try++) {
+ tick_offset = 0;
+ r = ao_lco_query(box, &ao_pad_query, &tick_offset);
+ PRINTD("box %d result %d\n", box, r);
+ if (r == AO_RADIO_CMAC_OK) {
+ ao_lco_box_set_present(box);
+ ao_delay(AO_MS_TO_TICKS(30));
+ break;
+ }
}
}
if (ao_lco_min_box <= ao_lco_max_box)
diff --git a/src/telelco-v0.2/ao_pins.h b/src/telelco-v0.2/ao_pins.h
index 62f221a1..a6fd4ff8 100644
--- a/src/telelco-v0.2/ao_pins.h
+++ b/src/telelco-v0.2/ao_pins.h
@@ -72,6 +72,8 @@
#define PACKET_HAS_SLAVE 0
#define PACKET_HAS_MASTER 0
+#define FAST_TIMER_FREQ 10000 /* .1ms for debouncing */
+
/*
* Radio is a cc1120 connected via SPI
*/
diff --git a/src/telemega-v0.1/ao_pins.h b/src/telemega-v0.1/ao_pins.h
index db397c66..2616e906 100644
--- a/src/telemega-v0.1/ao_pins.h
+++ b/src/telemega-v0.1/ao_pins.h
@@ -65,12 +65,17 @@
#define ao_gps_fifo (ao_stm_usart3.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 1
#define HAS_TELEMETRY 1
#define HAS_APRS 1
diff --git a/src/telemega-v1.0/Makefile b/src/telemega-v1.0/Makefile
index 7a0c1195..46c768e4 100644
--- a/src/telemega-v1.0/Makefile
+++ b/src/telemega-v1.0/Makefile
@@ -9,6 +9,7 @@ INC = \
ao.h \
ao_arch.h \
ao_arch_funcs.h \
+ ao_boot.h \
ao_companion.h \
ao_data.h \
ao_sample.h \
diff --git a/src/telemega-v1.0/ao_pins.h b/src/telemega-v1.0/ao_pins.h
index fe97c684..77b753d1 100644
--- a/src/telemega-v1.0/ao_pins.h
+++ b/src/telemega-v1.0/ao_pins.h
@@ -65,12 +65,17 @@
#define ao_gps_fifo (ao_stm_usart3.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 1
#define HAS_TELEMETRY 1
#define HAS_APRS 1
diff --git a/src/telemetrum-v1.0/.sdcdbrc b/src/telemetrum-v1.0/.sdcdbrc
index fbe9a599..e9a51ea6 100644
--- a/src/telemetrum-v1.0/.sdcdbrc
+++ b/src/telemetrum-v1.0/.sdcdbrc
@@ -1 +1 @@
---directory=../cc1111:../product:../core:../drivers:.
+--directory=../cc1111:../product:../kernel:../drivers:.
diff --git a/src/telemetrum-v1.1/.sdcdbrc b/src/telemetrum-v1.1/.sdcdbrc
index fbe9a599..e9a51ea6 100644
--- a/src/telemetrum-v1.1/.sdcdbrc
+++ b/src/telemetrum-v1.1/.sdcdbrc
@@ -1 +1 @@
---directory=../cc1111:../product:../core:../drivers:.
+--directory=../cc1111:../product:../kernel:../drivers:.
diff --git a/src/telemetrum-v1.1/Makefile b/src/telemetrum-v1.1/Makefile
index e44be7f9..61e9273b 100644
--- a/src/telemetrum-v1.1/Makefile
+++ b/src/telemetrum-v1.1/Makefile
@@ -12,6 +12,7 @@ TM_SRC = \
ao_companion.c \
ao_gps_skytraq.c \
ao_gps_show.c \
+ ao_convert_volt.c \
ao_m25.c
include ../product/Makefile.telemetrum
diff --git a/src/telemetrum-v1.2/Makefile b/src/telemetrum-v1.2/Makefile
index f2285fbe..38ba6d49 100644
--- a/src/telemetrum-v1.2/Makefile
+++ b/src/telemetrum-v1.2/Makefile
@@ -12,6 +12,7 @@ TM_SRC = \
ao_companion.c \
ao_gps_skytraq.c \
ao_gps_show.c \
+ ao_convert_volt.c \
ao_m25.c
include ../product/Makefile.telemetrum
diff --git a/src/telemetrum-v2.0/Makefile b/src/telemetrum-v2.0/Makefile
index 83a364dc..d77e9585 100644
--- a/src/telemetrum-v2.0/Makefile
+++ b/src/telemetrum-v2.0/Makefile
@@ -9,6 +9,7 @@ INC = \
ao.h \
ao_arch.h \
ao_arch_funcs.h \
+ ao_boot.h \
ao_companion.h \
ao_data.h \
ao_sample.h \
diff --git a/src/telemetrum-v2.0/ao_pins.h b/src/telemetrum-v2.0/ao_pins.h
index 1b5cedc7..a9a4b243 100644
--- a/src/telemetrum-v2.0/ao_pins.h
+++ b/src/telemetrum-v2.0/ao_pins.h
@@ -60,12 +60,17 @@
#define SERIAL_3_PD8_PD9 0
#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX (512 * 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 BEEPER_CHANNEL 4
#define HAS_RADIO 1
#define HAS_TELEMETRY 1
diff --git a/src/telemini-v1.0/.sdcdbrc b/src/telemini-v1.0/.sdcdbrc
index b9f6129c..2c77e32b 100644
--- a/src/telemini-v1.0/.sdcdbrc
+++ b/src/telemini-v1.0/.sdcdbrc
@@ -1,2 +1,2 @@
---directory=../cc1111:../product:../core:../drivers:.
+--directory=../cc1111:../product:../kernel:../drivers:.
diff --git a/src/telemini-v2.0/.sdcdbrc b/src/telemini-v2.0/.sdcdbrc
index b9f6129c..2c77e32b 100644
--- a/src/telemini-v2.0/.sdcdbrc
+++ b/src/telemini-v2.0/.sdcdbrc
@@ -1,2 +1,2 @@
---directory=../cc1111:../product:../core:../drivers:.
+--directory=../cc1111:../product:../kernel:../drivers:.
diff --git a/src/telemini-v2.0/Makefile b/src/telemini-v2.0/Makefile
index fcac2c48..ca69dc41 100644
--- a/src/telemini-v2.0/Makefile
+++ b/src/telemini-v2.0/Makefile
@@ -5,8 +5,8 @@
TELEMINI_VER=2.0
TELEMINI_DEF=2_0
-vpath %.c ..:../core:../cc1111:../drivers:../product
-vpath %.h ..:../core:../cc1111:../drivers:../product
+vpath %.c ..:../kernel:../cc1111:../drivers:../product
+vpath %.h ..:../kernel:../cc1111:../drivers:../product
vpath ao-make-product.5c ../util
ifndef VERSION
@@ -30,7 +30,6 @@ INC = \
CORE_SRC = \
ao_cmd.c \
ao_config.c \
- ao_convert.c \
ao_flight.c \
ao_kalman.c \
ao_log.c \
@@ -59,6 +58,7 @@ CC1111_SRC = \
ao_spi.c \
ao_usb.c \
ao_convert_pa.c \
+ ao_convert_volt.c \
ao_beep.c \
ao_timer.c \
ao_exti.c \
diff --git a/src/telemini-v2.0/ao_pins.h b/src/telemini-v2.0/ao_pins.h
index c4681ee2..f202ccd1 100644
--- a/src/telemini-v2.0/ao_pins.h
+++ b/src/telemini-v2.0/ao_pins.h
@@ -22,8 +22,16 @@
#define HAS_FLIGHT 1
#define HAS_USB 1
+
+#define HAS_USB_PULLUP 1
+#define AO_USB_PULLUP_PORT P1
+#define AO_USB_PULLUP_PIN 0
+#define AO_USB_PULLUP P1_0
+
#define USB_FORCE_FLIGHT_IDLE 1
#define HAS_BEEP 1
+#define HAS_BEEP_CONFIG 0
+#define HAS_BATTERY_REPORT 1
#define HAS_GPS 0
#define HAS_SERIAL_1 0
#define HAS_EEPROM 1
@@ -32,9 +40,8 @@
#define HAS_DBG 0
#define PACKET_HAS_SLAVE 1
-#define AO_LED_GREEN 1
#define AO_LED_RED 2
-#define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN)
+#define LEDS_AVAILABLE AO_LED_RED
#define HAS_EXTERNAL_TEMP 0
#define HAS_ACCEL 0
#define HAS_IGNITE 1
@@ -158,4 +165,21 @@ struct ao_adc {
ao_data_ring[ao_data_head].ms5607_raw.temp = ao_ms5607_current.temp; \
} while (0)
+/*
+ * Voltage divider on ADC battery sampler
+ */
+#define AO_BATTERY_DIV_PLUS 100 /* 100k */
+#define AO_BATTERY_DIV_MINUS 27 /* 27k */
+
+/*
+ * 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
+
#endif /* _AO_PINS_H_ */
diff --git a/src/telepyro-v0.1/Makefile b/src/telepyro-v0.1/Makefile
index 025b324a..dcac03dc 100644
--- a/src/telepyro-v0.1/Makefile
+++ b/src/telepyro-v0.1/Makefile
@@ -2,7 +2,7 @@
# AltOS build
#
#
-vpath % .:..:../core:../product:../drivers:../avr
+vpath % .:..:../kernel:../product:../drivers:../avr
vpath ao-make-product.5c ../util
include ../avr/Makefile.defs
@@ -45,7 +45,7 @@ PRODUCT=TelePyro-v0.1
MCU=atmega32u4
PRODUCT_DEF=-DTELEPYRO
IDPRODUCT=0x0011
-CFLAGS = $(PRODUCT_DEF) -I. -I../avr -I../core -I..
+CFLAGS = $(PRODUCT_DEF) -I. -I../avr -I../kernel -I..
CFLAGS += -mmcu=$(MCU) -Wall -Wstrict-prototypes -O3 -mcall-prologues -DAVR
NICKLE=nickle
diff --git a/src/telescience-pwm/Makefile b/src/telescience-pwm/Makefile
index de81b8d7..493bd480 100644
--- a/src/telescience-pwm/Makefile
+++ b/src/telescience-pwm/Makefile
@@ -2,7 +2,7 @@
# AltOS build
#
#
-vpath % ..:../core:../product:../drivers:../avr
+vpath % ..:../kernel:../product:../drivers:../avr
vpath ao-make-product.5c ../util
include ../avr/Makefile.defs
@@ -57,7 +57,7 @@ PRODUCT=TeleScience-PWM
MCU=atmega32u4
PRODUCT_DEF=-DTELESCIENCE -DTELESCIENCE_PWM
IDPRODUCT=0x0011
-CFLAGS = $(PRODUCT_DEF) -I. -I../avr -I../core -I..
+CFLAGS = $(PRODUCT_DEF) -I. -I../avr -I../kernel -I..
CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O3 -mcall-prologues -DAVR
NICKLE=nickle
diff --git a/src/telescience-v0.1/Makefile b/src/telescience-v0.1/Makefile
index 6e4eb6de..c55c48e2 100644
--- a/src/telescience-v0.1/Makefile
+++ b/src/telescience-v0.1/Makefile
@@ -2,7 +2,7 @@
# AltOS build
#
#
-vpath % ..:../core:../product:../drivers:../avr
+vpath % ..:../kernel:../product:../drivers:../avr
vpath ao-make-product.5c ../util
include ../avr/Makefile.defs
@@ -56,7 +56,7 @@ PRODUCT=TeleScience-v0.1
MCU=atmega32u4
PRODUCT_DEF=-DTELESCIENCE
IDPRODUCT=0x0011
-CFLAGS = $(PRODUCT_DEF) -I. -I../avr -I../core -I..
+CFLAGS = $(PRODUCT_DEF) -I. -I../avr -I../kernel -I..
CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O3 -mcall-prologues -DAVR
NICKLE=nickle
diff --git a/src/teleshield-v0.1/Makefile b/src/teleshield-v0.1/Makefile
index e8b262ef..f54488a2 100644
--- a/src/teleshield-v0.1/Makefile
+++ b/src/teleshield-v0.1/Makefile
@@ -17,8 +17,8 @@ TELESHIELD_SRC = \
ao_btm.c \
ao_spi.c
-vpath %.c ..:../core:../cc1111:../drivers:../product:.
-vpath %.h ..:../core:../cc1111:../drivers:../product:.
+vpath %.c ..:../kernel:../cc1111:../drivers:../product:.
+vpath %.h ..:../kernel:../cc1111:../drivers:../product:.
vpath ao-make-product.5c ../util
ifndef VERSION
diff --git a/src/teleterra-v0.2/.sdcdbrc b/src/teleterra-v0.2/.sdcdbrc
index fbe9a599..e9a51ea6 100644
--- a/src/teleterra-v0.2/.sdcdbrc
+++ b/src/teleterra-v0.2/.sdcdbrc
@@ -1 +1 @@
---directory=../cc1111:../product:../core:../drivers:.
+--directory=../cc1111:../product:../kernel:../drivers:.
diff --git a/src/teleterra-v0.2/Makefile b/src/teleterra-v0.2/Makefile
index 88637360..826c52e5 100644
--- a/src/teleterra-v0.2/Makefile
+++ b/src/teleterra-v0.2/Makefile
@@ -2,8 +2,8 @@
# TeleTerra build file
#
-vpath %.c ..:../core:../cc1111:../drivers:../product
-vpath %.h ..:../core:../cc1111:../drivers:../product
+vpath %.c ..:../kernel:../cc1111:../drivers:../product
+vpath %.h ..:../kernel:../cc1111:../drivers:../product
vpath ao-make-product.5c ../util
ifndef VERSION
diff --git a/src/test/Makefile b/src/test/Makefile
index c6025219..017f7f71 100644
--- a/src/test/Makefile
+++ b/src/test/Makefile
@@ -1,4 +1,4 @@
-vpath % ..:../core:../drivers:../util:../micropeak:../aes:../product
+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_gps_test ao_gps_test_skytraq ao_gps_test_ublox ao_convert_test ao_convert_pa_test ao_fec_test \
@@ -9,7 +9,7 @@ INCS=ao_kalman.h ao_ms5607.h ao_log.h ao_data.h altitude-pa.h altitude.h ao_quat
KALMAN=make-kalman
-CFLAGS=-I.. -I. -I../core -I../drivers -I../micropeak -I../product -O0 -g -Wall
+CFLAGS=-I.. -I. -I../kernel -I../drivers -I../micropeak -I../product -O0 -g -Wall
all: $(PROGS) ao_aprs_data.wav
@@ -52,10 +52,10 @@ ao_kalman.h: $(KALMAN)
(cd .. && make ao_kalman.h)
ao_fec_test: ao_fec_test.c ao_fec_tx.c ao_fec_rx.c
- cc $(CFLAGS) -DAO_FEC_DEBUG=1 -o $@ ao_fec_test.c ../core/ao_fec_tx.c ../core/ao_fec_rx.c -lm
+ cc $(CFLAGS) -DAO_FEC_DEBUG=1 -o $@ ao_fec_test.c ../kernel/ao_fec_tx.c ../kernel/ao_fec_rx.c -lm
ao_aprs_test: ao_aprs_test.c ao_aprs.c
- cc $(CFLAGS) -o $@ ao_aprs_test.c
+ cc $(CFLAGS) -o $@ ao_aprs_test.c -lm
SOX_INPUT_ARGS=--type raw --encoding unsigned-integer -b 8 -c 1 -r 9600
SOX_OUTPUT_ARGS=--type wav
diff --git a/src/test/ao_aprs_test.c b/src/test/ao_aprs_test.c
index 69147786..86cf527a 100644
--- a/src/test/ao_aprs_test.c
+++ b/src/test/ao_aprs_test.c
@@ -23,7 +23,16 @@
#include <ao_telemetry.h>
+#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)
+
struct ao_telemetry_location ao_gps_data;
+struct ao_telemetry_satellite ao_gps_tracking_data;
#define AO_APRS_TEST
@@ -73,7 +82,7 @@ ao_radio_send_aprs(ao_radio_fill_func fill);
* 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
- *
+ *
*/
@@ -88,14 +97,42 @@ 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_gps_data.flags = (AO_GPS_VALID|AO_GPS_RUNNING);
/* Transmit one packet */
ao_aprs_send();
diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c
index 0abb4090..0647fc6c 100644
--- a/src/test/ao_flight_test.c
+++ b/src/test/ao_flight_test.c
@@ -49,13 +49,12 @@ int ao_gps_new;
#define HAS_MPU6000 1
#define HAS_MMA655X 1
#define HAS_HMC5883 1
+#define HAS_BEEP 1
struct ao_adc {
int16_t sense[AO_ADC_NUM_SENSE];
int16_t v_batt;
int16_t v_pbatt;
- int16_t accel_ref;
- int16_t accel;
int16_t temp;
};
#else
@@ -309,7 +308,7 @@ struct ao_cmds {
#if TELEMEGA
#include "ao_convert_pa.c"
#include <ao_ms5607.h>
-struct ao_ms5607_prom ms5607_prom;
+struct ao_ms5607_prom ao_ms5607_prom;
#include "ao_ms5607_convert.c"
#define AO_PYRO_NUM 4
#include <ao_pyro.h>
@@ -317,22 +316,8 @@ struct ao_ms5607_prom ms5607_prom;
#include "ao_convert.c"
#endif
-struct ao_config {
- uint16_t main_deploy;
- int16_t accel_plus_g;
- int16_t accel_minus_g;
- uint8_t pad_orientation;
- uint16_t apogee_lockout;
-#if TELEMEGA
- struct ao_pyro pyro[AO_PYRO_NUM]; /* minor version 12 */
- int16_t accel_zero_along;
- int16_t accel_zero_across;
- int16_t accel_zero_through;
-#endif
-};
-
-#define AO_PAD_ORIENTATION_ANTENNA_UP 0
-#define AO_PAD_ORIENTATION_ANTENNA_DOWN 1
+#include <ao_config.h>
+#include <ao_fake_flight.h>
#define ao_config_get()
@@ -732,6 +717,18 @@ ao_sleep(void *wchan)
ao_flight_started = 1;
ao_ground_pres = int32(bytes, 4);
ao_ground_height = ao_pa_to_altitude(ao_ground_pres);
+ ao_ground_accel_along = int16(bytes, 8);
+ ao_ground_accel_across = int16(bytes, 10);
+ ao_ground_accel_through = int16(bytes, 12);
+ ao_ground_roll = int16(bytes, 14);
+ ao_ground_pitch = int16(bytes, 16);
+ ao_ground_yaw = int16(bytes, 18);
+ ao_ground_mpu6000.accel_x = ao_ground_accel_across;
+ ao_ground_mpu6000.accel_y = ao_ground_accel_along;
+ ao_ground_mpu6000.accel_z = ao_ground_accel_through;
+ ao_ground_mpu6000.gyro_x = ao_ground_pitch >> 9;
+ ao_ground_mpu6000.gyro_y = ao_ground_roll >> 9;
+ ao_ground_mpu6000.gyro_z = ao_ground_yaw >> 9;
break;
case 'A':
ao_data_static.tick = tick;
@@ -768,21 +765,21 @@ ao_sleep(void *wchan)
continue;
} else if (nword == 3 && strcmp(words[0], "ms5607") == 0) {
if (strcmp(words[1], "reserved:") == 0)
- ms5607_prom.reserved = strtoul(words[2], NULL, 10);
+ ao_ms5607_prom.reserved = strtoul(words[2], NULL, 10);
else if (strcmp(words[1], "sens:") == 0)
- ms5607_prom.sens = strtoul(words[2], NULL, 10);
+ ao_ms5607_prom.sens = strtoul(words[2], NULL, 10);
else if (strcmp(words[1], "off:") == 0)
- ms5607_prom.off = strtoul(words[2], NULL, 10);
+ ao_ms5607_prom.off = strtoul(words[2], NULL, 10);
else if (strcmp(words[1], "tcs:") == 0)
- ms5607_prom.tcs = strtoul(words[2], NULL, 10);
+ ao_ms5607_prom.tcs = strtoul(words[2], NULL, 10);
else if (strcmp(words[1], "tco:") == 0)
- ms5607_prom.tco = strtoul(words[2], NULL, 10);
+ ao_ms5607_prom.tco = strtoul(words[2], NULL, 10);
else if (strcmp(words[1], "tref:") == 0)
- ms5607_prom.tref = strtoul(words[2], NULL, 10);
+ ao_ms5607_prom.tref = strtoul(words[2], NULL, 10);
else if (strcmp(words[1], "tempsens:") == 0)
- ms5607_prom.tempsens = strtoul(words[2], NULL, 10);
+ ao_ms5607_prom.tempsens = strtoul(words[2], NULL, 10);
else if (strcmp(words[1], "crc:") == 0)
- ms5607_prom.crc = strtoul(words[2], NULL, 10);
+ ao_ms5607_prom.crc = strtoul(words[2], NULL, 10);
continue;
} else if (nword >= 3 && strcmp(words[0], "Pyro") == 0) {
int p = strtoul(words[1], NULL, 10);
@@ -791,7 +788,7 @@ ao_sleep(void *wchan)
for (i = 2; i < nword; i++) {
for (j = 0; j < NUM_PYRO_VALUES; j++)
- if (!strcmp (words[2], ao_pyro_values[j].name))
+ if (!strcmp (words[i], ao_pyro_values[j].name))
break;
if (j == NUM_PYRO_VALUES)
continue;
@@ -991,6 +988,7 @@ void run_flight_fixed(char *name, FILE *f, int summary, char *info)
emulator_in = f;
emulator_info = info;
ao_summary = summary;
+
ao_flight_init();
ao_flight();
}
diff --git a/src/test/ao_ms5607_convert_test.c b/src/test/ao_ms5607_convert_test.c
index ad593204..1c571f1c 100644
--- a/src/test/ao_ms5607_convert_test.c
+++ b/src/test/ao_ms5607_convert_test.c
@@ -23,7 +23,7 @@
#include <stdint.h>
#include <ao_ms5607.h>
-struct ao_ms5607_prom ms5607_prom = {
+struct ao_ms5607_prom ao_ms5607_prom = {
0x002c,
0xa6e0,
0x988e,
diff --git a/src/tidongle/Makefile b/src/tidongle/Makefile
index b2ba537b..0e90d744 100644
--- a/src/tidongle/Makefile
+++ b/src/tidongle/Makefile
@@ -2,8 +2,8 @@
# TIDongle build file
#
-vpath %.c ..:../core:../cc1111:../drivers:../product
-vpath %.h ..:../core:../cc1111:../drivers:../product
+vpath %.c ..:../kernel:../cc1111:../drivers:../product
+vpath %.h ..:../kernel:../cc1111:../drivers:../product
vpath ao-make-product.5c ../util
ifndef VERSION
diff --git a/src/usbrelay-v0.1/ao_pins.h b/src/usbrelay-v0.1/ao_pins.h
new file mode 100644
index 00000000..a72f6cc8
--- /dev/null
+++ b/src/usbrelay-v0.1/ao_pins.h
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+#define HAS_BEEP 0
+
+#define AO_STACK_SIZE 384
+
+#define IS_FLASH_LOADER 0
+
+/* Crystal on the board */
+#define AO_LPC_CLKIN 12000000
+
+/* Main clock frequency. 48MHz for USB so we don't use the USB PLL */
+#define AO_LPC_CLKOUT 48000000
+
+/* System clock frequency */
+#define AO_LPC_SYSCLK 24000000
+
+#define HAS_USB 1
+
+#define HAS_USB_CONNECT 0
+#define HAS_USB_VBUS 0
+#define HAS_USB_PULLUP 1
+#define AO_USB_PULLUP_PORT 0
+#define AO_USB_PULLUP_PIN 6
+
+/* USART */
+
+#define HAS_SERIAL 1
+#define USE_SERIAL_0_STDIN 0
+#define SERIAL_0_18_19 1
+#define SERIAL_0_14_15 0
+#define SERIAL_0_17_18 0
+#define SERIAL_0_26_27 0
+
+/* SPI */
+
+#define HAS_SPI_0 0
+#define SPI_SCK0_P0_6 0
+#define HAS_SPI_1 0
+#define SPI_SCK1_P1_15 0
+#define SPI_MISO1_P0_22 0
+#define SPI_MOSI1_P0_21 0
+
+/* LED */
+
+#define LED_PORT 0
+#define LED_PIN_RED 23
+#define LED_PIN_GREEN 7
+#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)
+
+/* RELAY */
+
+#define RELAY_PORT 0
+#define RELAY_PIN 3
+#define RELAY_BIT (1 << RELAY_PIN)
+
+/* Kludge the SPI driver to not configure any
+ * pin for SCK or MOSI
+ */
+#define HAS_SCK1 0
+#define HAS_MOSI1 0
diff --git a/src/usbrelay-v0.1/ao_serial_lpc.h b/src/usbrelay-v0.1/ao_serial_lpc.h
new file mode 100644
index 00000000..a95b6af1
--- /dev/null
+++ b/src/usbrelay-v0.1/ao_serial_lpc.h
@@ -0,0 +1,33 @@
+#define AO_LPC_USARTCLK 12000000
+
+static const struct {
+ uint16_t dl;
+ uint8_t divaddval;
+ uint8_t mulval;
+} ao_usart_speeds[] = {
+ [AO_SERIAL_SPEED_4800] = { /* actual = 4800.00 */
+ .dl = 125,
+ .divaddval = 1,
+ .mulval = 4
+ },
+ [AO_SERIAL_SPEED_9600] = { /* actual = 9603.07 */
+ .dl = 71,
+ .divaddval = 1,
+ .mulval = 10
+ },
+ [AO_SERIAL_SPEED_19200] = { /* actual = 19181.59 */
+ .dl = 23,
+ .divaddval = 7,
+ .mulval = 10
+ },
+ [AO_SERIAL_SPEED_57600] = { /* actual = 57692.31 */
+ .dl = 7,
+ .divaddval = 6,
+ .mulval = 7
+ },
+ [AO_SERIAL_SPEED_115200] = { /* actual = 115384.6 */
+ .dl = 4,
+ .divaddval = 5,
+ .mulval = 8
+ },
+};
diff --git a/src/usbrelay-v0.1/ao_usbrelay.c b/src/usbrelay-v0.1/ao_usbrelay.c
new file mode 100644
index 00000000..879094b5
--- /dev/null
+++ b/src/usbrelay-v0.1/ao_usbrelay.c
@@ -0,0 +1,90 @@
+/*
+ * 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>
+
+uint8_t relay_output;
+
+void
+ao_relay_init(void)
+{
+ lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_GPIO);
+ lpc_gpio.dir[RELAY_PORT] |= RELAY_BIT;
+}
+
+// switch relay to selected output, turn correct LED on as a side effect
+static void
+ao_relay_control(uint8_t output)
+{
+ switch (output) {
+ case 1:
+ lpc_gpio.pin[RELAY_PORT] |= RELAY_BIT;
+ ao_led_on(AO_LED_RED);
+ ao_led_off(AO_LED_GREEN);
+ break;
+ default:
+ lpc_gpio.pin[RELAY_PORT] &= ~RELAY_BIT;
+ ao_led_off(AO_LED_RED);
+ ao_led_on(AO_LED_GREEN);
+ }
+}
+
+static void
+ao_relay_select(void) __reentrant
+{
+ uint8_t output;
+
+ ao_cmd_decimal();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ output = ao_cmd_lex_i;
+ if (output > 1)
+ printf ("Invalid relay position %u\n", output);
+ else
+ ao_relay_control(output);
+}
+
+static __code struct ao_cmds ao_relay_cmds[] = {
+ { ao_relay_select, "R <output>\0Select relay output" },
+ { 0, NULL }
+};
+
+void
+main(void)
+{
+ ao_clock_init();
+ ao_task_init();
+ ao_timer_init();
+
+ ao_usb_init();
+
+ ao_serial_init();
+
+ ao_led_init(LEDS_AVAILABLE);
+
+ ao_relay_init();
+
+ // initialize to default output
+ relay_output = 0;
+ ao_relay_control(relay_output);
+
+ ao_cmd_init();
+
+ ao_cmd_register(ao_relay_cmds);
+
+ ao_start_scheduler();
+}
diff --git a/src/usbrelay-v0.1/flash-loader/ao_pins.h b/src/usbrelay-v0.1/flash-loader/ao_pins.h
new file mode 100644
index 00000000..a8046009
--- /dev/null
+++ b/src/usbrelay-v0.1/flash-loader/ao_pins.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#include <ao_flash_lpc_pins.h>
+
+#define AO_BOOT_PIN 1
+#define AO_BOOT_APPLICATION_GPIO 0
+#define AO_BOOT_APPLICATION_PIN 19
+#define AO_BOOT_APPLICATION_VALUE 1
+#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP
+
+#define HAS_USB_PULLUP 1
+#define AO_USB_PULLUP_PORT 0
+#define AO_USB_PULLUP_PIN 6
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/usbtrng/Makefile b/src/usbtrng/Makefile
new file mode 100644
index 00000000..80e137e7
--- /dev/null
+++ b/src/usbtrng/Makefile
@@ -0,0 +1,70 @@
+#
+# AltOS build
+#
+#
+
+include ../lpc/Makefile.defs
+
+INC = \
+ ao.h \
+ ao_arch.h \
+ ao_arch_funcs.h \
+ ao_pins.h \
+ ao_product.h \
+ lpc.h
+
+#
+# Common AltOS sources
+#
+ALTOS_SRC = \
+ ao_interrupt.c \
+ ao_boot_chain.c \
+ ao_romconfig.c \
+ ao_product.c \
+ ao_mutex.c \
+ ao_panic.c \
+ ao_stdio.c \
+ ao_task.c \
+ ao_cmd.c \
+ ao_timer_lpc.c \
+ ao_exti_lpc.c \
+ ao_usb_lpc.c \
+ ao_serial_lpc.c \
+ ao_spi_lpc.c \
+ ao_led_lpc.c
+
+PRODUCT=usbtrng-v0.1
+PRODUCT_DEF=-DUSBTRNG_V_0_1
+IDPRODUCT=0x0028
+
+CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) -g -Os
+
+PROGNAME=usbtrng-v0.1
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_usbtrng.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+ $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+ao_product.h: ao-make-product.5c ../Version
+ $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+$(OBJ): $(INC)
+
+load: $(PROG)
+ lpc-load $(PROG)
+
+distclean: clean
+
+clean:
+ rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+ rm -f ao_product.h
+
+install:
+
+uninstall:
diff --git a/src/usbtrng/ao_pins.h b/src/usbtrng/ao_pins.h
new file mode 100644
index 00000000..b1fa6eb9
--- /dev/null
+++ b/src/usbtrng/ao_pins.h
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+
+#define HAS_BEEP 0
+
+#define AO_STACK_SIZE 384
+
+#define IS_FLASH_LOADER 0
+
+/* Crystal on the board */
+#define AO_LPC_CLKIN 12000000
+
+/* Main clock frequency. 48MHz for USB so we don't use the USB PLL */
+#define AO_LPC_CLKOUT 48000000
+
+/* System clock frequency */
+#define AO_LPC_SYSCLK 24000000
+
+#define HAS_USB 1
+
+#define HAS_USB_CONNECT 0
+#define HAS_USB_VBUS 0
+#define HAS_USB_PULLUP 1
+#define AO_USB_PULLUP_PORT 0
+#define AO_USB_PULLUP_PIN 6
+
+/* USART */
+
+#define HAS_SERIAL 1
+#define USE_SERIAL_0_STDIN 0
+#define SERIAL_0_18_19 1
+#define SERIAL_0_14_15 0
+#define SERIAL_0_17_18 0
+#define SERIAL_0_26_27 0
+
+/* SPI */
+
+#define HAS_SPI_0 0
+#define SPI_SCK0_P0_6 0
+#define HAS_SPI_1 1
+#define SPI_SCK1_P1_15 0
+#define SPI_MISO1_P0_22 1
+#define SPI_MOSI1_P0_21 0
+
+/* LED */
+
+#define LED_PORT 0
+#define LED_PIN_RED 3
+#define LED_PIN_GREEN 21
+#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)
+
+/* Kludge the SPI driver to not configure any
+ * pin for SCK or MOSI
+ */
+#define HAS_SCK1 0
+#define HAS_MOSI1 0
diff --git a/src/usbtrng/ao_usbtrng.c b/src/usbtrng/ao_usbtrng.c
new file mode 100644
index 00000000..6b4d20fe
--- /dev/null
+++ b/src/usbtrng/ao_usbtrng.c
@@ -0,0 +1,63 @@
+/*
+ * 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>
+
+#define AO_TRNG_SPI_BUS 1
+#define AO_TRNG_SPI_SPEED AO_SPI_SPEED_250kHz
+
+static void
+ao_trng_test(void)
+{
+ static uint8_t random[32];
+ uint8_t i;
+
+ ao_spi_get(AO_TRNG_SPI_BUS, AO_TRNG_SPI_SPEED);
+ ao_spi_recv(random, sizeof (random), AO_TRNG_SPI_BUS);
+ ao_spi_put(AO_TRNG_SPI_BUS);
+ for (i = 0; i < sizeof (random); i++)
+ printf (" %02x", random[i]);
+ printf ("\n");
+}
+
+static const struct ao_cmds ao_trng_cmds[] = {
+ { ao_trng_test, "R\0Dump some random numbers" },
+ { 0, NULL }
+};
+
+void
+main(void)
+{
+ ao_clock_init();
+ ao_task_init();
+ ao_timer_init();
+
+ ao_spi_init();
+ ao_usb_init();
+
+ ao_serial_init();
+
+ ao_led_init(LEDS_AVAILABLE);
+
+ ao_led_on(AO_LED_GREEN);
+
+ ao_cmd_init();
+
+ ao_cmd_register(ao_trng_cmds);
+
+ ao_start_scheduler();
+}
diff --git a/src/usbtrng/flash-loader/Makefile b/src/usbtrng/flash-loader/Makefile
new file mode 100644
index 00000000..e34f1089
--- /dev/null
+++ b/src/usbtrng/flash-loader/Makefile
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=usbtrng-v0.1
+include $(TOPDIR)/lpc/Makefile-flash.defs
diff --git a/src/usbtrng/flash-loader/ao_pins.h b/src/usbtrng/flash-loader/ao_pins.h
new file mode 100644
index 00000000..a8046009
--- /dev/null
+++ b/src/usbtrng/flash-loader/ao_pins.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#include <ao_flash_lpc_pins.h>
+
+#define AO_BOOT_PIN 1
+#define AO_BOOT_APPLICATION_GPIO 0
+#define AO_BOOT_APPLICATION_PIN 19
+#define AO_BOOT_APPLICATION_VALUE 1
+#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP
+
+#define HAS_USB_PULLUP 1
+#define AO_USB_PULLUP_PORT 0
+#define AO_USB_PULLUP_PIN 6
+
+#endif /* _AO_PINS_H_ */
diff --git a/telegps/.gitignore b/telegps/.gitignore
new file mode 100644
index 00000000..edb509f2
--- /dev/null
+++ b/telegps/.gitignore
@@ -0,0 +1,27 @@
+windows/
+linux/
+macosx/
+fat/
+Manifest.txt
+Manifest-fat.txt
+AltosVersion.java
+Info.plist
+libaltosJNI
+classes
+telegps
+telegps-test
+telegps-jdb
+classtelegps.stamp
+telegps-windows.nsi
+TeleGPS-Linux-*.tar.bz2
+TeleGPS-Linux-*.sh
+TeleGPS-Mac-*.zip
+TeleGPS-Windows-*.exe
+telegps.desktop
+telegps-windows.log
+*.dll
+*.dylib
+*.so
+*.jar
+*.class
+*.dmg
diff --git a/telegps/Info.plist.in b/telegps/Info.plist.in
new file mode 100644
index 00000000..df05bb6e
--- /dev/null
+++ b/telegps/Info.plist.in
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.9">
+<dict>
+ <key>CFBundleName</key>
+ <string>TeleGPS</string>
+ <key>CFBundleVersion</key>
+ <string>@VERSION@</string>
+ <key>CFBundleAllowMixedLocalizations</key>
+ <string>true</string>
+ <key>CFBundleExecutable</key>
+ <string>JavaApplicationStub</string>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleIdentifier</key>
+ <string>org.altusmetrum.telegps</string>
+ <key>CFBundleSignature</key>
+ <string>Altu</string>
+ <key>CFBundleGetInfoString</key>
+ <string>TeleGPS version @VERSION@</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleIconFile</key>
+ <string>TeleGPS.icns</string>
+ <key>Java</key>
+ <dict>
+ <key>MainClass</key>
+ <string>org.altusmetrum.telegps.TeleGPS</string>
+ <key>JVMVersion</key>
+ <string>1.5+</string>
+ <key>ClassPath</key>
+ <array>
+ <string>$JAVAROOT/telegps.jar</string>
+ <string>$JAVAROOT/freetts.jar</string>
+ </array>
+ <key>VMOptions</key>
+ <array>
+ <string>-Xms512M</string>
+ <string>-Xmx512M</string>
+ <string>-Dosgi.clean=true</string>
+ </array>
+ </dict>
+</dict>
+</plist>
diff --git a/telegps/Makefile.am b/telegps/Makefile.am
new file mode 100644
index 00000000..7b550e9e
--- /dev/null
+++ b/telegps/Makefile.am
@@ -0,0 +1,294 @@
+JAVAROOT=classes
+AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked -source 6
+
+man_MANS=telegps.1
+
+altoslibdir=$(libdir)/altos
+
+CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:../altoslib/*:../altosuilib/*:../libaltos:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar:$(FREETTS)/freetts.jar"
+
+bin_SCRIPTS=telegps
+
+telegpsdir=$(datadir)/java
+
+telegps_JAVA= \
+ TeleGPS.java \
+ TeleGPSStatus.java \
+ TeleGPSStatusUpdate.java \
+ TeleGPSInfo.java \
+ TeleGPSState.java \
+ TeleGPSConfig.java \
+ TeleGPSConfigUI.java \
+ TeleGPSPreferences.java \
+ TeleGPSGraphUI.java \
+ TeleGPSDisplayThread.java
+
+JFREECHART_CLASS= \
+ jfreechart.jar
+
+JCOMMON_CLASS=\
+ jcommon.jar
+
+FREETTS_CLASS= \
+ cmudict04.jar \
+ cmulex.jar \
+ cmu_time_awb.jar \
+ cmutimelex.jar \
+ cmu_us_kal.jar \
+ en_us.jar \
+ freetts.jar
+
+JAR=telegps.jar
+
+FATJAR=telegps-fat.jar
+
+LIBALTOS= \
+ libaltos.so \
+ libaltos.dylib \
+ altos64.dll \
+ altos.dll
+
+ALTOSLIB_CLASS=\
+ altoslib_$(ALTOSLIB_VERSION).jar
+
+ALTOSUILIB_CLASS=\
+ altosuilib_$(ALTOSUILIB_VERSION).jar
+
+# Icons
+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
+
+# 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
+
+# Firmware
+FIRMWARE_TD_0_2=$(top_srcdir)/src/teledongle-v0.2/teledongle-v0.2-$(VERSION).ihx
+FIRMWARE_TD=$(FIRMWARE_TD_0_2)
+
+FIRMWARE_TBT_1_0=$(top_srcdir)/src/telebt-v1.0/telebt-v1.0-$(VERSION).ihx
+FIRMWARE_TBT=$(FIRMWARE_TBT_1_0)
+
+FIRMWARE_TG_1_0=$(top_srcdir)/src/telegps-v1.0/telegps-v1.0-$(VERSION).ihx
+FIRMWARE_TG=$(FIRMWARE_TG_1_0)
+
+FIRMWARE=$(FIRMWARE_TG) $(FIRMWARE_TD) $(FIRMWARE_TBT)
+
+desktopdir = $(datadir)/applications
+desktop_file = telegps.desktop
+desktop_SCRIPTS = $(desktop_file)
+
+all-local: telegps-test telegps-jdb $(JAR)
+
+clean-local:
+ -rm -rf classes $(JAR) $(FATJAR) \
+ TeleGPS-Linux-*.tar.bz2 TeleGPS-Mac-*.dmg TeleGPS-Windows-*.exe \
+ $(ALTOSLIB_CLASS) \
+ $(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
+
+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 > $@
+ chmod +x $@
+
+LINUX_DIST=TeleGPS-Linux-$(VERSION).tar.bz2
+LINUX_SH=TeleGPS-Linux-$(VERSION).sh
+MACOSX_DIST=TeleGPS-Mac-$(VERSION).dmg
+WINDOWS_DIST=TeleGPS-Windows-$(VERSION_DASH).exe
+
+TELEGPS_DOC=$(top_srcdir)/doc/telegps.pdf
+
+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
+
+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_EXTRA=$(FIRMWARE)
+
+WINDOWS_FILES=$(FAT_FILES) altos.dll altos64.dll $(top_srcdir)/altusmetrum.inf $(top_srcdir)/altusmetrum.cat $(DOC) $(WINDOWS_ICON)
+
+if FATINSTALL
+
+FATTARGET=$(FATDIR)/$(VERSION)
+
+LINUX_DIST_TARGET=$(FATTARGET)/$(LINUX_DIST)
+LINUX_SH_TARGET=$(FATTARGET)/$(LINUX_SH)
+MACOSX_DIST_TARGET=$(FATTARGET)/$(MACOSX_DIST)
+WINDOWS_DIST_TARGET=$(FATTARGET)/$(WINDOWS_DIST)
+
+fat: $(LINUX_DIST_TARGET) $(LINUX_SH_TARGET) $(MACOSX_DIST_TARGET) $(WINDOWS_DIST_TARGET)
+
+$(LINUX_DIST_TARGET): $(LINUX_DIST)
+ mkdir -p $(FATTARGET)
+ cp -p $< $@
+
+$(LINUX_SH_TARGET): $(LINUX_SH)
+ mkdir -p $(FATTARGET)
+ cp -p $< $@
+
+$(MACOSX_DIST_TARGET): $(MACOSX_DIST)
+ mkdir -p $(FATTARGET)
+ cp -p $< $@
+
+$(WINDOWS_DIST_TARGET): $(WINDOWS_DIST)
+ mkdir -p $(FATTARGET)
+ cp -p $< $@
+
+else
+fat: $(LINUX_DIST) $(LINUX_SH) $(MACOSX_DIST) $(WINDOWS_DIST)
+endif
+
+telegps: Makefile
+ echo "#!/bin/sh" > $@
+ echo 'exec java -Djava.library.path="$(altoslibdir)" -jar "$(telegpsdir)/telegps.jar" "$$@"' >> $@
+ chmod +x $@
+
+telegps-jdb: Makefile
+ echo "#!/bin/sh" > $@
+ echo 'exec jdb -classpath "classes:./*:../libaltos:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar" -Djava.library.path="../libaltos/.libs" org.altusmetrum.telegps.TeleGPS "$$@"' >> $@
+ chmod +x $@
+
+telegps-test: Makefile
+ echo "#!/bin/sh" > $@
+ echo 'exec java -Djava.library.path="../libaltos/.libs" -jar telegps.jar "$$@"' >> $@
+ chmod +x $@
+
+install-telegpsJAVA: telegps.jar
+ @$(NORMAL_INSTALL)
+ test -z "$(telegpsdir)" || $(MKDIR_P) "$(DESTDIR)$(telegpsdir)"
+ echo " $(INSTALL_DATA)" "$<" "'$(DESTDIR)$(telegpsdir)/telegps.jar'"; \
+ $(INSTALL_DATA) "$<" "$(DESTDIR)$(telegpsdir)"
+
+$(JAR): classtelegps.stamp Manifest.txt $(JAVA_ICONS) $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS)
+ jar cfm $@ Manifest.txt \
+ $(ICONJAR) \
+ -C classes org \
+ -C ../libaltos libaltosJNI
+
+$(FATJAR): classtelegps.stamp Manifest-fat.txt $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(JAVA_ICONS)
+ jar cfm $@ Manifest-fat.txt \
+ $(ICONJAR) \
+ -C classes org \
+ -C ../libaltos libaltosJNI
+
+classaltosui.stamp: $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS)
+
+libaltos.so: build-libaltos
+ -rm -f "$@"
+ $(LN_S) ../libaltos/.libs/"$@" .
+
+libaltos.dylib:
+ -rm -f "$@"
+ $(LN_S) ../libaltos/"$@" .
+
+altos.dll: ../libaltos/altos.dll
+ -rm -f "$@"
+ $(LN_S) ../libaltos/"$@" .
+
+altos64.dll: ../libaltos/altos64.dll
+ -rm -f "$@"
+ $(LN_S) ../libaltos/"$@" .
+
+../libaltos/.libs/libaltos.so: build-libaltos
+
+../libaltos/altos.dll: build-altos-dll
+
+../libaltos/altos64.dll: build-altos64-dll
+
+build-libaltos:
+ +cd ../libaltos && make libaltos.la
+build-altos-dll:
+ +cd ../libaltos && make altos.dll
+
+build-altos64-dll:
+ +cd ../libaltos && make altos64.dll
+
+$(ALTOSLIB_CLASS):
+ -rm -f "$@"
+ $(LN_S) ../altoslib/"$@" .
+
+$(ALTOSUILIB_CLASS):
+ -rm -f "$@"
+ $(LN_S) ../altosuilib/"$@" .
+
+$(FREETTS_CLASS):
+ -rm -f "$@"
+ $(LN_S) "$(FREETTS)"/"$@" .
+
+$(JFREECHART_CLASS):
+ -rm -f "$@"
+ $(LN_S) "$(JFREECHART)"/"$@" .
+
+$(JCOMMON_CLASS):
+ -rm -f "$@"
+ $(LN_S) "$(JCOMMON)"/"$@" .
+
+$(LINUX_DIST): $(LINUX_FILES) $(LINUX_EXTRA)
+ -rm -f $@
+ -rm -rf linux
+ mkdir -p linux/TeleGPS
+ cp -p $(LINUX_FILES) linux/TeleGPS
+ cp -p telegps-fat linux/TeleGPS/telegps
+ chmod +x linux/TeleGPS/telegps
+ tar cjf $@ -C linux TeleGPS
+
+$(LINUX_SH): $(LINUX_DIST) $(srcdir)/../altosui/linux-install.sh
+ sed 's/AltOS/TeleGPS/g' $(srcdir)/../altosui/linux-install.sh | cat - $(LINUX_DIST) > $@
+ chmod +x $@
+
+$(MACOSX_DIST): $(MACOSX_FILES) $(MACOSX_EXTRA) Makefile
+ -rm -f $@
+ -rm -rf macosx
+ mkdir macosx
+ cp -a TeleGPS.app macosx/
+ cp -a $(MACOSX_README) macosx/ReadMe.rtf
+ mkdir -p macosx/Doc
+ 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 $(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
+ cp -p $(ALTOSUILIB_CLASS) macosx/TeleGPS.app/Contents/Resources/Java
+ cp -p $(FREETTS_CLASS) macosx/TeleGPS.app/Contents/Resources/Java
+ cp -p $(JFREECHART_CLASS) macosx/TeleGPS.app/Contents/Resources/Java
+ cp -p $(JCOMMON_CLASS) macosx/TeleGPS.app/Contents/Resources/Java
+ cp -p $(MACOSX_EXTRA) macosx/AltOS-$(VERSION)
+ genisoimage -D -V TeleGPS-$(VERSION) -no-pad -r -apple -o $@ macosx
+
+$(WINDOWS_DIST): $(WINDOWS_FILES) telegps-windows.nsi
+ -rm -f $@
+ makensis -Otelegps-windows.log "-XOutFile $@" "-DVERSION=$(VERSION)" telegps-windows.nsi || (cat telegps-windows.log && exit 1)
+
+Manifest.txt: Makefile
+ echo 'Main-Class: org.altusmetrum.telegps.TeleGPS' > $@
+ echo "Class-Path: $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) $(FREETTS)/freetts.jar $(JCOMMON)/jcommon.jar $(JFREECHART)/jfreechart.jar" >> $@
+
+Manifest-fat.txt:
+ echo 'Main-Class: org.altusmetrum.telegps.TeleGPS' > $@
+ echo "Class-Path: $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) freetts.jar jcommon.jar jfreechart.jar" >> $@
+
diff --git a/telegps/ReadMe-Mac.rtf b/telegps/ReadMe-Mac.rtf
new file mode 100644
index 00000000..48a82ed3
--- /dev/null
+++ b/telegps/ReadMe-Mac.rtf
@@ -0,0 +1,58 @@
+{\rtf1\ansi\ansicpg1252\deff0\uc1
+{\fonttbl
+{\f0\fnil\fcharset0\fprq0\fttruetype Helvetica;}
+{\f1\fnil\fcharset0\fprq0\fttruetype Arial;}
+{\f2\fnil\fcharset0\fprq0\fttruetype Liberation Serif;}
+{\f3\fnil\fcharset0\fprq0\fttruetype Courier New;}}
+{\colortbl
+\red0\green0\blue0;
+\red255\green255\blue255;
+\red255\green255\blue255;}
+{\stylesheet
+{\s6\fi-431\li720\sbasedon28\snext28 Contents 1;}
+{\s7\fi-431\li1440\sbasedon28\snext28 Contents 2;}
+{\s1\fi-431\li720 Arrowhead List;}
+{\s27\fi-431\li720\sbasedon28 Lower Roman List;}
+{\s29\tx431\sbasedon20\snext28 Numbered Heading 1;}
+{\s30\tx431\sbasedon21\snext28 Numbered Heading 2;}
+{\s12\fi-431\li720 Diamond List;}
+{\s9\fi-431\li2880\sbasedon28\snext28 Contents 4;}
+{\s8\fi-431\li2160\sbasedon28\snext28 Contents 3;}
+{\s31\tx431\sbasedon22\snext28 Numbered Heading 3;}
+{\s32\fi-431\li720 Numbered List;}
+{\s15\sbasedon28 Endnote Text;}
+{\*\cs14\fs20\super Endnote Reference;}
+{\s4\fi-431\li720 Bullet List;}
+{\s5\tx1584\sbasedon29\snext28 Chapter Heading;}
+{\s35\fi-431\li720 Square List;}
+{\s11\fi-431\li720 Dashed List;}
+{\s22\sb440\sa60\f1\fs24\b\sbasedon28\snext28 Heading 3;}
+{\s37\fi-431\li720 Tick List;}
+{\s24\fi-431\li720 Heart List;}
+{\s40\fi-431\li720\sbasedon32 Upper Roman List;}
+{\s39\fi-431\li720\sbasedon32 Upper Case List;}
+{\s16\fi-288\li288\fs20\sbasedon28 Footnote;}
+{\s19\fi-431\li720 Hand List;}
+{\s18\fs20\sbasedon28 Footnote Text;}
+{\s20\sb440\sa60\f1\fs34\b\sbasedon28\snext28 Heading 1;}
+{\s21\sb440\sa60\f1\fs28\b\sbasedon28\snext28 Heading 2;}
+{\s10\qc\sb240\sa120\f1\fs32\b\sbasedon28\snext28 Contents Header;}
+{\s23\sb440\sa60\f1\fs24\b\sbasedon28\snext28 Heading 4;}
+{\s28\f2\fs24 Normal;}
+{\s26\fi-431\li720\sbasedon32 Lower Case List;}
+{\s2\li1440\ri1440\sa120\sbasedon28 Block Text;}
+{\s33\f3\sbasedon28 Plain Text;}
+{\s34\tx1584\sbasedon29\snext28 Section Heading;}
+{\s25\fi-431\li720 Implies List;}
+{\s3\fi-431\li720 Box List;}
+{\s36\fi-431\li720 Star List;}
+{\*\cs17\fs20\super Footnote Reference;}
+{\s38\fi-431\li720 Triangle List;}
+{\s13\fi-288\li288\sbasedon28 Endnote;}}
+\kerning0\cf0\ftnbj\fet2\ftnstart1\ftnnar\aftnnar\ftnstart1\aftnstart1\aenddoc\revprop3{\*\rdf}{\info\uc1}\deftab720\viewkind1\paperw12240\paperh15840\margl1440\margr1440\widowctrl
+\sectd\sbknone\colsx0\pgncont\ltrsect
+\pard\plain\ltrpar\ql\sl240\slmult1\itap0\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640{\f0\fs24\lang1033{\*\listtag0}\abinodiroverride\ltrch Installing }{\f0\fs24\lang1033{\*\listtag0}TeleGPS}{\f0\fs24\lang1033{\*\listtag0} software for Mac OS X computers}{\f0\fs24\lang1033{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\sl240\slmult1\itap0\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640{\f0\fs24\lang1033{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\sl240\slmult1\itap0\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640{\f0\fs24\lang1033{\*\listtag0}\abinodiroverride\ltrch As with most Mac OS X applications, install }{\f0\fs24\lang1033{\*\listtag0}TeleGPS}{\f0\fs24\lang1033{\*\listtag0} by dragging it from the distribution disk image to a suitable place on your computer.}{\f0\fs24\lang1033{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\sl240\slmult1\itap0\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640{\f0\fs24\lang1033{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\sl240\slmult1\itap0\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640{\f0\fs24\lang1033{\*\listtag0}\abinodiroverride\ltrch Thanks for choosing AltusMetrum products!}{\f0\fs24\lang1033{\*\listtag0}\par}} \ No newline at end of file
diff --git a/telegps/TeleGPS.app/Contents/MacOS/JavaApplicationStub b/telegps/TeleGPS.app/Contents/MacOS/JavaApplicationStub
new file mode 100755
index 00000000..c661d3e1
--- /dev/null
+++ b/telegps/TeleGPS.app/Contents/MacOS/JavaApplicationStub
Binary files differ
diff --git a/telegps/TeleGPS.app/Contents/PkgInfo b/telegps/TeleGPS.app/Contents/PkgInfo
new file mode 100644
index 00000000..8a43480f
--- /dev/null
+++ b/telegps/TeleGPS.app/Contents/PkgInfo
@@ -0,0 +1 @@
+APPLAM.O
diff --git a/telegps/TeleGPS.app/Contents/Resources/TeleGPSIcon.icns b/telegps/TeleGPS.app/Contents/Resources/TeleGPSIcon.icns
new file mode 100644
index 00000000..44e2bceb
--- /dev/null
+++ b/telegps/TeleGPS.app/Contents/Resources/TeleGPSIcon.icns
Binary files differ
diff --git a/telegps/TeleGPS.java b/telegps/TeleGPS.java
new file mode 100644
index 00000000..6e68dd30
--- /dev/null
+++ b/telegps/TeleGPS.java
@@ -0,0 +1,668 @@
+/*
+ * 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.telegps;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import java.io.*;
+import java.util.concurrent.*;
+import java.util.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
+
+public class TeleGPS
+ extends AltosUIFrame
+ implements AltosFlightDisplay, AltosFontListener, AltosUnitsListener, ActionListener
+{
+
+ static String[] telegps_icon_names = {
+ "/telegps-16.png",
+ "/telegps-32.png",
+ "/telegps-48.png",
+ "/telegps-64.png",
+ "/telegps-128.png",
+ "/telegps-256.png"
+ };
+
+ static { set_icon_names(telegps_icon_names); }
+
+ static AltosVoice voice;
+
+ static AltosVoice voice() {
+ if (voice == null)
+ voice = new AltosVoice();
+ return voice;
+ }
+
+ AltosFlightReader reader;
+ TeleGPSDisplayThread thread;
+
+ JMenuBar menu_bar;
+
+ JMenu file_menu;
+ JMenu monitor_menu;
+ JMenu device_menu;
+ AltosFreqList frequencies;
+ ActionListener frequency_listener;
+
+ Container bag;
+
+ TeleGPSStatus telegps_status;
+ TeleGPSStatusUpdate status_update;
+ javax.swing.Timer status_timer;
+
+ JTabbedPane pane;
+
+ AltosUIMap map;
+ TeleGPSInfo gps_info;
+ TeleGPSState gps_state;
+ AltosInfoTable info_table;
+
+ LinkedList<AltosFlightDisplay> displays;
+
+ /* File menu */
+ final static String new_command = "new";
+ final static String graph_command = "graph";
+ final static String export_command = "export";
+ final static String load_maps_command = "loadmaps";
+ final static String preferences_command = "preferences";
+ final static String close_command = "close";
+ final static String exit_command = "exit";
+
+ static final String[][] file_menu_entries = new String[][] {
+ { "New Window", new_command },
+ { "Graph Data", graph_command },
+ { "Export Data", export_command },
+ { "Load Maps", load_maps_command },
+ { "Preferences", preferences_command },
+ { "Close", close_command },
+ { "Exit", exit_command },
+ };
+
+ /* Monitor menu */
+ final static String connect_command = "connect";
+ final static String disconnect_command = "disconnect";
+ final static String scan_command = "scan";
+
+ static final String[][] monitor_menu_entries = new String[][] {
+ { "Connect Device", connect_command },
+ { "Disconnect", disconnect_command },
+ { "Scan Channels", scan_command },
+ };
+
+ /* Device menu */
+ final static String download_command = "download";
+ final static String configure_command = "configure";
+ final static String flash_command = "flash";
+
+ static final String[][] device_menu_entries = new String[][] {
+ { "Download Data", download_command },
+ { "Configure Device", configure_command },
+ { "Flash Device", flash_command },
+ };
+
+ void stop_display() {
+ if (thread != null && thread.isAlive()) {
+ thread.interrupt();
+ try {
+ thread.join();
+ } catch (InterruptedException ie) {}
+ }
+ thread = null;
+ }
+
+ public void reset() {
+ for (AltosFlightDisplay display : displays)
+ display.reset();
+ }
+
+ public void font_size_changed(int font_size) {
+ for (AltosFlightDisplay display : displays)
+ display.font_size_changed(font_size);
+ }
+
+ public void units_changed(boolean imperial_units) {
+ for (AltosFlightDisplay display : displays)
+ display.units_changed(imperial_units);
+ }
+
+ public void show(AltosState state, AltosListenerState listener_state) {
+ try {
+ status_update.saved_state = state;
+
+ if (state == null)
+ state = new AltosState();
+
+ int i = 0;
+ for (AltosFlightDisplay display : displays) {
+ display.show(state, listener_state);
+ i++;
+ }
+ } catch (Exception ex) {
+ System.out.printf("Exception %s\n", ex.toString());
+ for (StackTraceElement e : ex.getStackTrace())
+ System.out.printf("%s\n", e.toString());
+ }
+ }
+
+ void new_window() {
+ new TeleGPS();
+ }
+
+ void preferences() {
+ new TeleGPSPreferences(this, voice());
+ }
+
+ void load_maps() {
+ new AltosUIMapPreload(this);
+ }
+
+ void disconnect() {
+ setTitle("TeleGPS");
+ stop_display();
+ if (status_timer != null) {
+ status_timer.stop();
+ status_timer = null;
+ status_update = null;
+ }
+
+ telegps_status.disable_receive();
+ disable_frequency_menu();
+ }
+
+ void connect(AltosDevice device) {
+ if (reader != null)
+ disconnect();
+ try {
+ AltosFlightReader reader = new AltosTelemetryReader(new AltosSerial(device));
+ set_reader(reader, device);
+ } catch (FileNotFoundException ee) {
+ JOptionPane.showMessageDialog(this,
+ ee.getMessage(),
+ String.format ("Cannot open %s", device.toShortString()),
+ JOptionPane.ERROR_MESSAGE);
+ } catch (AltosSerialInUseException si) {
+ JOptionPane.showMessageDialog(this,
+ String.format("Device \"%s\" already in use",
+ device.toShortString()),
+ "Device in use",
+ JOptionPane.ERROR_MESSAGE);
+ } catch (IOException ee) {
+ JOptionPane.showMessageDialog(this,
+ String.format ("Unknown I/O error on %s", device.toShortString()),
+ "Unknown I/O error",
+ JOptionPane.ERROR_MESSAGE);
+ } catch (TimeoutException te) {
+ JOptionPane.showMessageDialog(this,
+ String.format ("Timeout on %s", device.toShortString()),
+ "Timeout error",
+ JOptionPane.ERROR_MESSAGE);
+ } catch (InterruptedException ie) {
+ JOptionPane.showMessageDialog(this,
+ String.format("Interrupted %s", device.toShortString()),
+ "Interrupted exception",
+ JOptionPane.ERROR_MESSAGE);
+ }
+ }
+
+ void connect() {
+ AltosDevice device = AltosDeviceUIDialog.show(this,
+ AltosLib.product_basestation);
+ if (device == null)
+ return;
+ connect(device);
+ }
+
+ public void scan_device_selected(AltosDevice device) {
+ connect(device);
+ }
+
+ void scan() {
+ new AltosScanUI(this, false);
+ }
+
+ void download(){
+ new AltosEepromManage(this, AltosLib.product_telegps);
+ }
+
+ void configure() {
+ new TeleGPSConfig(this);
+ }
+
+ void export() {
+ AltosDataChooser chooser;
+ chooser = new AltosDataChooser(this);
+ AltosStateIterable states = chooser.runDialog();
+ if (states == null)
+ return;
+ new AltosCSVUI(this, states, chooser.file());
+ }
+
+ void graph() {
+ AltosDataChooser chooser;
+ chooser = new AltosDataChooser(this);
+ AltosStateIterable states = chooser.runDialog();
+ if (states == null)
+ return;
+ try {
+ new TeleGPSGraphUI(states, chooser.file());
+ } catch (InterruptedException ie) {
+ } catch (IOException ie) {
+ }
+ }
+
+ void flash() {
+ AltosFlashUI.show(this);
+ }
+
+ public void actionPerformed(ActionEvent ev) {
+
+ /* File menu */
+ if (new_command.equals(ev.getActionCommand())) {
+ new_window();
+ return;
+ }
+ if (preferences_command.equals(ev.getActionCommand())) {
+ preferences();
+ return;
+ }
+ if (load_maps_command.equals(ev.getActionCommand())) {
+ load_maps();
+ return;
+ }
+ if (close_command.equals(ev.getActionCommand())) {
+ close();
+ return;
+ }
+ if (exit_command.equals(ev.getActionCommand()))
+ System.exit(0);
+
+ /* Monitor menu */
+ if (connect_command.equals(ev.getActionCommand())) {
+ connect();
+ return;
+ }
+ if (disconnect_command.equals(ev.getActionCommand())) {
+ disconnect();
+ return;
+ }
+ if (scan_command.equals(ev.getActionCommand())) {
+ scan();
+ return;
+ }
+
+ /* Device menu */
+ if (download_command.equals(ev.getActionCommand())) {
+ download();
+ return;
+ }
+ if (configure_command.equals(ev.getActionCommand())) {
+ configure();
+ return;
+ }
+ if (export_command.equals(ev.getActionCommand())) {
+ export();
+ return;
+ }
+ if (graph_command.equals(ev.getActionCommand())) {
+ graph();
+ return;
+ }
+ if (flash_command.equals(ev.getActionCommand())) {
+ flash();
+ return;
+ }
+ }
+
+ void enable_frequency_menu(int serial, final AltosFlightReader reader) {
+
+ if (frequency_listener != null)
+ disable_frequency_menu();
+
+ frequency_listener = new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ double frequency = frequencies.frequency();
+ try {
+ reader.set_frequency(frequency);
+ } catch (TimeoutException te) {
+ } catch (InterruptedException ie) {
+ }
+ reader.save_frequency();
+ }
+ };
+
+ frequencies.addActionListener(frequency_listener);
+ frequencies.set_product("Monitor");
+ frequencies.set_serial(serial);
+ frequencies.set_frequency(AltosUIPreferences.frequency(serial));
+ frequencies.setEnabled(true);
+
+ }
+
+ void disable_frequency_menu() {
+ if (frequency_listener != null) {
+ frequencies.removeActionListener(frequency_listener);
+ frequencies.setEnabled(false);
+ frequency_listener = null;
+ }
+
+ }
+
+ public void set_reader(AltosFlightReader reader, AltosDevice device) {
+ status_update = new TeleGPSStatusUpdate(telegps_status);
+
+ status_timer = new javax.swing.Timer(100, status_update);
+ status_timer.start();
+
+ setTitle(String.format("TeleGPS %s", reader.name));
+ thread = new TeleGPSDisplayThread(this, voice(), this, reader);
+ thread.start();
+
+ if (device != null)
+ enable_frequency_menu(device.getSerial(), reader);
+ }
+
+ static int number_of_windows;
+
+ static public void add_window() {
+ ++number_of_windows;
+ }
+
+ static public void subtract_window() {
+ --number_of_windows;
+ if (number_of_windows == 0)
+ System.exit(0);
+ }
+
+ private void close() {
+ disconnect();
+ AltosUIPreferences.unregister_font_listener(this);
+ AltosPreferences.unregister_units_listener(this);
+ setVisible(false);
+ dispose();
+ subtract_window();
+ }
+
+ private void add_menu(JMenu menu, String label, String action) {
+ JMenuItem item = new JMenuItem(label);
+ menu.add(item);
+ item.addActionListener(this);
+ item.setActionCommand(action);
+ }
+
+
+ private JMenu make_menu(String label, String[][] items) {
+ JMenu menu = new JMenu(label);
+ for (int i = 0; i < items.length; i++)
+ add_menu(menu, items[i][0], items[i][1]);
+ menu_bar.add(menu);
+ return menu;
+ }
+
+ public TeleGPS() {
+
+ AltosUIPreferences.set_component(this);
+
+ reader = null;
+
+ bag = getContentPane();
+ bag.setLayout(new GridBagLayout());
+
+ GridBagConstraints c = new GridBagConstraints();
+
+ setTitle("TeleGPS");
+
+ menu_bar = new JMenuBar();
+ setJMenuBar(menu_bar);
+
+ 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.setEnabled(false);
+ menu_bar.add(frequencies);
+
+ displays = new LinkedList<AltosFlightDisplay>();
+
+ int serial = -1;
+
+ /* TeleGPS status is always visible */
+ telegps_status = new TeleGPSStatus();
+ c.gridx = 0;
+ c.gridy = 1;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.weightx = 1;
+ c.gridwidth = 2;
+ bag.add(telegps_status, c);
+ c.gridwidth = 1;
+ displays.add(telegps_status);
+
+
+ /* The rest of the window uses a tabbed pane to
+ * show one of the alternate data views
+ */
+ pane = new JTabbedPane();
+
+ /* Make the tabbed pane use the rest of the window space */
+ c.gridx = 0;
+ c.gridy = 2;
+ c.fill = GridBagConstraints.BOTH;
+ c.weightx = 1;
+ c.weighty = 1;
+ c.gridwidth = 2;
+ bag.add(pane, c);
+
+ map = new AltosUIMap();
+ pane.add(map.getName(), map);
+ displays.add(map);
+
+ gps_info = new TeleGPSInfo();
+ pane.add(gps_info.getName(), gps_info);
+ displays.add(gps_info);
+
+ gps_state = new TeleGPSState();
+ pane.add(gps_state.getName(), gps_state);
+ displays.add(gps_state);
+
+ info_table = new AltosInfoTable();
+ pane.add("Table", info_table);
+ displays.add(info_table);
+
+ setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
+
+ AltosUIPreferences.register_font_listener(this);
+ AltosPreferences.register_units_listener(this);
+
+ addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowClosing(WindowEvent e) {
+ close();
+ }
+ });
+
+ pack();
+ setVisible(true);
+
+ add_window();
+ }
+
+ public TeleGPS(AltosFlightReader reader) {
+ this();
+ set_reader(reader, null);
+ }
+
+ public TeleGPS(AltosDevice device) {
+ this();
+ connect(device);
+ }
+
+ static AltosStateIterable record_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);
+ }
+
+ static AltosReplayReader replay_file(File file) {
+ AltosStateIterable states = record_iterable(file);
+ if (states == null)
+ return null;
+ return new AltosReplayReader(states.iterator(), file);
+ }
+
+ static boolean process_graph(File file) {
+ AltosStateIterable states = record_iterable(file);
+ if (states == null)
+ return false;
+ try {
+ new TeleGPSGraphUI(states, file);
+ } catch (Exception e) {
+ return false;
+ }
+ return true;
+ }
+
+ static boolean process_replay(File file) {
+ AltosReplayReader new_reader = replay_file(file);
+ if (new_reader == null)
+ return false;
+
+ new TeleGPS(new_reader);
+ return true;
+ }
+
+ static final int process_none = 0;
+ static final int process_csv = 1;
+ static final int process_kml = 2;
+ static final int process_graph = 3;
+ static final int process_replay = 4;
+ static final int process_summary = 5;
+ static final int process_cat = 6;
+
+ public static boolean load_library(Frame frame) {
+ if (!AltosUILib.load_library()) {
+ JOptionPane.showMessageDialog(frame,
+ String.format("No AltOS library in \"%s\"",
+ System.getProperty("java.library.path","<undefined>")),
+ "Cannot load device access library",
+ JOptionPane.ERROR_MESSAGE);
+ return false;
+ }
+ return true;
+ }
+
+ public static void help(int code) {
+ System.out.printf("Usage: altosui [OPTION]... [FILE]...\n");
+ System.out.printf(" Options:\n");
+ System.out.printf(" --fetchmaps <lat> <lon>\tpre-fetch maps for site map view\n");
+ System.out.printf(" --replay <filename>\t\trelive the glory of past flights \n");
+ System.out.printf(" --graph <filename>\t\tgraph a flight\n");
+ System.out.printf(" --csv\tgenerate comma separated output for spreadsheets, etc\n");
+ System.out.printf(" --kml\tgenerate KML output for use with Google Earth\n");
+ System.exit(code);
+ }
+
+ public static void main(String[] args) {
+ int errors = 0;
+
+ load_library(null);
+ try {
+ UIManager.setLookAndFeel(AltosUIPreferences.look_and_feel());
+ } catch (Exception e) {
+ }
+
+ boolean any_created = false;
+
+
+ /* Handle batch-mode */
+ int process = process_none;
+ for (int i = 0; i < args.length; i++) {
+ if (args[i].equals("--help"))
+ help(0);
+ else if (args[i].equals("--fetchmaps")) {
+ if (args.length < i + 3) {
+ help(1);
+ } else {
+ double lat = Double.parseDouble(args[i+1]);
+ double lon = Double.parseDouble(args[i+2]);
+ AltosUIMap.prefetch_maps(lat, lon);
+ i += 2;
+ }
+ } else if (args[i].equals("--replay"))
+ process = process_replay;
+ else if (args[i].equals("--kml"))
+ process = process_kml;
+ else if (args[i].equals("--csv"))
+ process = process_csv;
+ else if (args[i].equals("--graph"))
+ process = process_graph;
+ else if (args[i].equals("--summary"))
+ process = process_summary;
+ else if (args[i].equals("--cat"))
+ process = process_cat;
+ else if (args[i].startsWith("--"))
+ help(1);
+ else {
+ File file = new File(args[i]);
+ switch (process) {
+ case process_none:
+ case process_graph:
+ if (!process_graph(file))
+ ++errors;
+ break;
+ case process_replay:
+ if (!process_replay(file))
+ ++errors;
+ any_created = true;
+ break;
+ case process_kml:
+ ++errors;
+ break;
+ case process_csv:
+ ++errors;
+ break;
+ case process_summary:
+ ++errors;
+ break;
+ case process_cat:
+ ++errors;
+ }
+ }
+ }
+ if (errors != 0)
+ System.exit(errors);
+ if (number_of_windows == 0) {
+ java.util.List<AltosDevice> devices = AltosUSBDevice.list(AltosLib.product_basestation);
+ if (devices != null)
+ for (AltosDevice device : devices) {
+ new TeleGPS(device);
+ any_created = true;
+ }
+ if (number_of_windows == 0)
+ new TeleGPS();
+ }
+ }
+}
diff --git a/telegps/TeleGPSConfig.java b/telegps/TeleGPSConfig.java
new file mode 100644
index 00000000..3505b0bb
--- /dev/null
+++ b/telegps/TeleGPSConfig.java
@@ -0,0 +1,297 @@
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.telegps;
+
+import java.awt.event.*;
+import javax.swing.*;
+import java.io.*;
+import java.util.concurrent.*;
+import java.text.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
+
+public class TeleGPSConfig implements ActionListener {
+
+ class int_ref {
+ int value;
+
+ public int get() {
+ return value;
+ }
+ public void set(int i) {
+ value = i;
+ }
+ public int_ref(int i) {
+ value = i;
+ }
+ }
+
+ class string_ref {
+ String value;
+
+ public String get() {
+ return value;
+ }
+ public void set(String i) {
+ value = i;
+ }
+ public string_ref(String i) {
+ value = i;
+ }
+ }
+
+ JFrame owner;
+ AltosDevice device;
+ AltosSerial serial_line;
+
+ AltosConfigData data;
+ TeleGPSConfigUI config_ui;
+ boolean serial_started;
+ boolean made_visible;
+
+ void start_serial() throws InterruptedException, TimeoutException {
+ serial_started = true;
+ }
+
+ void stop_serial() throws InterruptedException {
+ if (!serial_started)
+ return;
+ serial_started = false;
+ }
+
+ void update_ui() {
+ data.set_values(config_ui);
+ config_ui.set_clean();
+ if (!made_visible) {
+ made_visible = true;
+ config_ui.make_visible();
+ }
+ }
+
+ int pyro;
+
+ final static int serial_mode_read = 0;
+ final static int serial_mode_save = 1;
+ final static int serial_mode_reboot = 2;
+
+ class SerialData implements Runnable {
+ TeleGPSConfig config;
+ int serial_mode;
+
+ void callback(String in_cmd) {
+ final String cmd = in_cmd;
+ Runnable r = new Runnable() {
+ public void run() {
+ if (cmd.equals("abort")) {
+ abort();
+ } else if (cmd.equals("all finished")) {
+ if (serial_line != null)
+ update_ui();
+ }
+ }
+ };
+ SwingUtilities.invokeLater(r);
+ }
+
+ void get_data() {
+ data = null;
+ try {
+ start_serial();
+ data = new AltosConfigData(config.serial_line);
+ } catch (InterruptedException ie) {
+ } catch (TimeoutException te) {
+ try {
+ stop_serial();
+ callback("abort");
+ } catch (InterruptedException ie) {
+ }
+ } finally {
+ try {
+ stop_serial();
+ } catch (InterruptedException ie) {
+ }
+ }
+ callback("all finished");
+ }
+
+ void save_data() {
+ try {
+ start_serial();
+ data.save(serial_line, false);
+ } catch (InterruptedException ie) {
+ } catch (TimeoutException te) {
+ } finally {
+ try {
+ stop_serial();
+ } catch (InterruptedException ie) {
+ }
+ }
+ }
+
+ void reboot() {
+ try {
+ start_serial();
+ serial_line.printf("r eboot\n");
+ serial_line.flush_output();
+ } catch (InterruptedException ie) {
+ } catch (TimeoutException te) {
+ } finally {
+ try {
+ stop_serial();
+ serial_line.close();
+ } catch (InterruptedException ie) {
+ }
+ }
+ }
+
+ public void run () {
+ switch (serial_mode) {
+ case serial_mode_save:
+ save_data();
+ /* fall through ... */
+ case serial_mode_read:
+ get_data();
+ break;
+ case serial_mode_reboot:
+ reboot();
+ break;
+ }
+ }
+
+ public SerialData(TeleGPSConfig in_config, int in_serial_mode) {
+ config = in_config;
+ serial_mode = in_serial_mode;
+ }
+ }
+
+ void run_serial_thread(int serial_mode) {
+ SerialData sd = new SerialData(this, serial_mode);
+ Thread st = new Thread(sd);
+ st.start();
+ }
+
+ void init_ui () throws InterruptedException, TimeoutException {
+ config_ui = new TeleGPSConfigUI(owner);
+ config_ui.addActionListener(this);
+ serial_line.set_frame(owner);
+ set_ui();
+ }
+
+ void abort() {
+ if (serial_line != null) {
+ serial_line.close();
+ serial_line = null;
+ }
+ JOptionPane.showMessageDialog(owner,
+ String.format("Connection to \"%s\" failed",
+ device.toShortString()),
+ "Connection Failed",
+ JOptionPane.ERROR_MESSAGE);
+ config_ui.setVisible(false);
+ }
+
+ void set_ui() throws InterruptedException, TimeoutException {
+ if (serial_line != null)
+ run_serial_thread(serial_mode_read);
+ else
+ update_ui();
+ }
+
+ double frequency() {
+ return AltosConvert.radio_to_frequency(data.radio_frequency,
+ data.radio_setting,
+ data.radio_calibration,
+ data.radio_channel);
+ }
+
+ void save_data() {
+
+ try {
+ /* bounds check stuff */
+ if (config_ui.flight_log_max() > data.log_space()/1024) {
+ JOptionPane.showMessageDialog(owner,
+ String.format("Requested flight log, %dk, is larger than the available space, %dk.\n",
+ config_ui.flight_log_max(),
+ data.log_space()/1024),
+ "Maximum Flight Log Too Large",
+ JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+
+ /* Pull data out of the UI and stuff back into our local data record */
+
+ data.get_values(config_ui);
+ run_serial_thread(serial_mode_save);
+ } catch (AltosConfigDataException ae) {
+ JOptionPane.showMessageDialog(owner,
+ ae.getMessage(),
+ "Configuration Data Error",
+ JOptionPane.ERROR_MESSAGE);
+ }
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ String cmd = e.getActionCommand();
+ try {
+ if (cmd.equals("Save")) {
+ save_data();
+ } else if (cmd.equals("Reset")) {
+ set_ui();
+ } else if (cmd.equals("Reboot")) {
+ if (serial_line != null)
+ run_serial_thread(serial_mode_reboot);
+ } else if (cmd.equals("Close")) {
+ if (serial_line != null)
+ serial_line.close();
+ }
+ } catch (InterruptedException ie) {
+ abort();
+ } catch (TimeoutException te) {
+ abort();
+ }
+ }
+
+ public TeleGPSConfig(JFrame given_owner) {
+ owner = given_owner;
+
+ device = AltosDeviceUIDialog.show(owner, AltosLib.product_telegps);
+ if (device != null) {
+ try {
+ serial_line = new AltosSerial(device);
+ try {
+ init_ui();
+ } catch (InterruptedException ie) {
+ abort();
+ } catch (TimeoutException te) {
+ abort();
+ }
+ } catch (FileNotFoundException ee) {
+ JOptionPane.showMessageDialog(owner,
+ ee.getMessage(),
+ "Cannot open target device",
+ JOptionPane.ERROR_MESSAGE);
+ } catch (AltosSerialInUseException si) {
+ JOptionPane.showMessageDialog(owner,
+ String.format("Device \"%s\" already in use",
+ device.toShortString()),
+ "Device in use",
+ JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ }
+}
diff --git a/telegps/TeleGPSConfigUI.java b/telegps/TeleGPSConfigUI.java
new file mode 100644
index 00000000..5f269fd3
--- /dev/null
+++ b/telegps/TeleGPSConfigUI.java
@@ -0,0 +1,785 @@
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.telegps;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
+
+public class TeleGPSConfigUI
+ extends AltosUIDialog
+ implements ActionListener, ItemListener, DocumentListener, AltosConfigValues, AltosUnitsListener
+{
+
+ Container pane;
+ JLabel product_label;
+ JLabel version_label;
+ JLabel serial_label;
+ JLabel frequency_label;
+ JLabel radio_calibration_label;
+ JLabel radio_frequency_label;
+ JLabel radio_enable_label;
+ JLabel aprs_interval_label;
+ JLabel flight_log_max_label;
+ JLabel callsign_label;
+ JLabel tracker_motion_label;
+ JLabel tracker_interval_label;
+
+ public boolean dirty;
+
+ JFrame owner;
+ JLabel product_value;
+ JLabel version_value;
+ JLabel serial_value;
+ AltosFreqList radio_frequency_value;
+ JTextField radio_calibration_value;
+ JRadioButton radio_enable_value;
+ JComboBox<String> aprs_interval_value;
+ JComboBox<String> flight_log_max_value;
+ JTextField callsign_value;
+ JComboBox<String> tracker_motion_value;
+ JComboBox<String> tracker_interval_value;
+
+ JButton save;
+ JButton reset;
+ JButton reboot;
+ JButton close;
+
+ ActionListener listener;
+
+ static String[] aprs_interval_values = {
+ "Disabled",
+ "2",
+ "5",
+ "10"
+ };
+
+ static String[] tracker_motion_values_m = {
+ "2",
+ "5",
+ "10",
+ "25",
+ };
+
+ static String[] tracker_motion_values_ft = {
+ "5",
+ "20",
+ "50",
+ "100"
+ };
+
+ static String[] tracker_interval_values = {
+ "1",
+ "2",
+ "5",
+ "10"
+ };
+
+ /* A window listener to catch closing events and tell the config code */
+ class ConfigListener extends WindowAdapter {
+ TeleGPSConfigUI ui;
+
+ public ConfigListener(TeleGPSConfigUI this_ui) {
+ ui = this_ui;
+ }
+
+ public void windowClosing(WindowEvent e) {
+ ui.actionPerformed(new ActionEvent(e.getSource(),
+ ActionEvent.ACTION_PERFORMED,
+ "Close"));
+ }
+ }
+
+ public void set_pyros(AltosPyro[] new_pyros) {
+ }
+
+ public AltosPyro[] pyros() {
+ return null;
+ }
+
+ public void set_pyro_firing_time(double new_pyro_firing_time) {
+ }
+
+ public double pyro_firing_time() {
+ return -1;
+ }
+
+ boolean is_telemetrum() {
+ String product = product_value.getText();
+ return product != null && product.startsWith("TeleGPS");
+ }
+
+ void set_radio_calibration_tool_tip() {
+ if (radio_calibration_value.isEnabled())
+ radio_calibration_value.setToolTipText("Tune radio output to match desired frequency");
+ else
+ radio_calibration_value.setToolTipText("Cannot tune radio while connected over packet mode");
+ }
+
+ void set_radio_enable_tool_tip() {
+ if (radio_enable_value.isEnabled())
+ radio_enable_value.setToolTipText("Enable/Disable telemetry and RDF transmissions");
+ else
+ radio_enable_value.setToolTipText("Firmware version does not support disabling radio");
+ }
+
+ void set_aprs_interval_tool_tip() {
+ if (aprs_interval_value.isEnabled())
+ aprs_interval_value.setToolTipText("Enable APRS and set the interval between APRS reports");
+ 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)");
+ else
+ flight_log_max_value.setToolTipText("Cannot set max value with flight logs in memory");
+ }
+
+ /* Build the UI using a grid bag */
+ public TeleGPSConfigUI(JFrame in_owner) {
+ super (in_owner, "Configure Device", false);
+
+ owner = in_owner;
+ GridBagConstraints c;
+ int row = 0;
+
+ Insets il = new Insets(4,4,4,4);
+ Insets ir = new Insets(4,4,4,4);
+
+ pane = getContentPane();
+ pane.setLayout(new GridBagLayout());
+
+ /* Product */
+ c = new GridBagConstraints();
+ c.gridx = 0; c.gridy = row;
+ c.gridwidth = 4;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = il;
+ product_label = new JLabel("Product:");
+ pane.add(product_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;
+ product_value = new JLabel("");
+ pane.add(product_value, c);
+ row++;
+
+ /* Version */
+ 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;
+ version_label = new JLabel("Software version:");
+ pane.add(version_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;
+ version_value = new JLabel("");
+ pane.add(version_value, c);
+ row++;
+
+ /* Serial */
+ 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;
+ serial_label = new JLabel("Serial:");
+ pane.add(serial_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;
+ serial_value = new JLabel("");
+ pane.add(serial_value, c);
+ row++;
+
+ /* Frequency */
+ 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;
+ radio_frequency_label = new JLabel("Frequency:");
+ pane.add(radio_frequency_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;
+ radio_frequency_value = new AltosFreqList();
+ radio_frequency_value.addItemListener(this);
+ pane.add(radio_frequency_value, c);
+ radio_frequency_value.setToolTipText("Telemetry, RDF and packet frequency");
+ row++;
+
+ /* Radio Calibration */
+ 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;
+ radio_calibration_label = new JLabel("RF Calibration:");
+ pane.add(radio_calibration_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;
+ radio_calibration_value = new JTextField(String.format("%d", 1186611));
+ radio_calibration_value.getDocument().addDocumentListener(this);
+ pane.add(radio_calibration_value, c);
+ set_radio_calibration_tool_tip();
+ row++;
+
+ /* Radio Enable */
+ 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;
+ radio_enable_label = new JLabel("Telemetry/RDF/APRS Enable:");
+ 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;
+ radio_enable_value = new JRadioButton("Enabled");
+ radio_enable_value.addItemListener(this);
+ pane.add(radio_enable_value, c);
+ set_radio_enable_tool_tip();
+ row++;
+
+ /* APRS interval */
+ 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_interval_label = new JLabel("APRS Interval(s):");
+ pane.add(aprs_interval_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_interval_value = new JComboBox<String>(aprs_interval_values);
+ aprs_interval_value.setEditable(true);
+ aprs_interval_value.addItemListener(this);
+ pane.add(aprs_interval_value, c);
+ set_aprs_interval_tool_tip();
+ row++;
+
+ /* Callsign */
+ 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;
+ callsign_label = new JLabel("Callsign:");
+ pane.add(callsign_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;
+ callsign_value = new JTextField(AltosUIPreferences.callsign());
+ callsign_value.getDocument().addDocumentListener(this);
+ pane.add(callsign_value, c);
+ callsign_value.setToolTipText("Callsign reported in telemetry data");
+ row++;
+
+ /* Flight log max */
+ 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;
+ flight_log_max_label = new JLabel("Maximum Log Size (kB):");
+ pane.add(flight_log_max_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;
+ flight_log_max_value = new JComboBox<String>();
+ flight_log_max_value.setEditable(true);
+ flight_log_max_value.addItemListener(this);
+ pane.add(flight_log_max_value, c);
+ set_flight_log_max_tool_tip();
+ row++;
+
+ /* Tracker triger horiz distances */
+ 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;
+ tracker_motion_label = new JLabel(get_tracker_motion_label());
+ pane.add(tracker_motion_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;
+ tracker_motion_value = new JComboBox<String>(tracker_motion_values());
+ tracker_motion_value.setEditable(true);
+ tracker_motion_value.addItemListener(this);
+ pane.add(tracker_motion_value, c);
+ row++;
+
+ /* Tracker triger vert distances */
+ 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;
+ tracker_interval_label = new JLabel("Position Reporting Interval (s):");
+ pane.add(tracker_interval_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;
+ tracker_interval_value = new JComboBox<String>(tracker_interval_values);
+ tracker_interval_value.setEditable(true);
+ tracker_interval_value.addItemListener(this);
+ pane.add(tracker_interval_value, c);
+ set_tracker_tool_tip();
+ row++;
+
+ /* Buttons */
+ c = new GridBagConstraints();
+ c.gridx = 0; c.gridy = row;
+ c.gridwidth = 2;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = il;
+ save = new JButton("Save");
+ pane.add(save, c);
+ save.addActionListener(this);
+ save.setActionCommand("Save");
+
+ c = new GridBagConstraints();
+ c.gridx = 2; c.gridy = row;
+ c.gridwidth = 2;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.CENTER;
+ c.insets = il;
+ reset = new JButton("Reset");
+ pane.add(reset, c);
+ reset.addActionListener(this);
+ reset.setActionCommand("Reset");
+
+ c = new GridBagConstraints();
+ c.gridx = 4; c.gridy = row;
+ c.gridwidth = 2;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.CENTER;
+ c.insets = il;
+ reboot = new JButton("Reboot");
+ pane.add(reboot, c);
+ reboot.addActionListener(this);
+ reboot.setActionCommand("Reboot");
+
+ c = new GridBagConstraints();
+ c.gridx = 6; c.gridy = row;
+ c.gridwidth = 2;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.LINE_END;
+ c.insets = il;
+ close = new JButton("Close");
+ pane.add(close, c);
+ close.addActionListener(this);
+ close.setActionCommand("Close");
+
+ addWindowListener(new ConfigListener(this));
+ AltosPreferences.register_units_listener(this);
+ }
+
+ /* Once the initial values are set, the config code will show the dialog */
+ public void make_visible() {
+ pack();
+ setLocationRelativeTo(owner);
+ setVisible(true);
+ }
+
+ /* If any values have been changed, confirm before closing */
+ public boolean check_dirty(String operation) {
+ if (dirty) {
+ Object[] options = { String.format("%s anyway", operation), "Keep editing" };
+ int i;
+ i = JOptionPane.showOptionDialog(this,
+ String.format("Configuration modified. %s anyway?", operation),
+ "Configuration Modified",
+ JOptionPane.DEFAULT_OPTION,
+ JOptionPane.WARNING_MESSAGE,
+ null, options, options[1]);
+ if (i != 0)
+ return false;
+ }
+ return true;
+ }
+
+ void set_dirty() {
+ dirty = true;
+ save.setEnabled(true);
+ }
+
+ public void set_clean() {
+ dirty = false;
+ save.setEnabled(false);
+ }
+
+ public void dispose() {
+ AltosPreferences.unregister_units_listener(this);
+ super.dispose();
+ }
+
+ /* Listen for events from our buttons */
+ public void actionPerformed(ActionEvent e) {
+ String cmd = e.getActionCommand();
+
+ if (cmd.equals("Close") || cmd.equals("Reboot"))
+ if (!check_dirty(cmd))
+ return;
+ listener.actionPerformed(e);
+ if (cmd.equals("Close") || cmd.equals("Reboot")) {
+ setVisible(false);
+ dispose();
+ }
+ set_clean();
+ }
+
+ /* ItemListener interface method */
+ public void itemStateChanged(ItemEvent e) {
+ set_dirty();
+ }
+
+ /* DocumentListener interface methods */
+ public void changedUpdate(DocumentEvent e) {
+ set_dirty();
+ }
+
+ public void insertUpdate(DocumentEvent e) {
+ set_dirty();
+ }
+
+ public void removeUpdate(DocumentEvent e) {
+ set_dirty();
+ }
+
+ /* Let the config code hook on a listener */
+ public void addActionListener(ActionListener l) {
+ listener = l;
+ }
+
+ public void units_changed(boolean imperial_units) {
+ 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));
+ }
+ }
+
+ /* set and get all of the dialog values */
+ public void set_product(String product) {
+ radio_frequency_value.set_product(product);
+ product_value.setText(product);
+ set_flight_log_max_tool_tip();
+ }
+
+ public void set_version(String version) {
+ version_value.setText(version);
+ }
+
+ public void set_serial(int serial) {
+ radio_frequency_value.set_serial(serial);
+ serial_value.setText(String.format("%d", serial));
+ }
+
+ public void set_main_deploy(int new_main_deploy) {
+ }
+
+ public int main_deploy() {
+ return -1;
+ }
+
+ public void set_apogee_delay(int new_apogee_delay) { }
+
+ public int apogee_delay() {
+ return -1;
+ }
+
+ public void set_apogee_lockout(int new_apogee_lockout) { }
+
+ public int apogee_lockout() { return -1; }
+
+ public void set_radio_frequency(double new_radio_frequency) {
+ radio_frequency_value.set_frequency(new_radio_frequency);
+ }
+
+ public double radio_frequency() {
+ return radio_frequency_value.frequency();
+ }
+
+ public void set_radio_calibration(int new_radio_calibration) {
+ radio_calibration_value.setVisible(new_radio_calibration >= 0);
+ if (new_radio_calibration < 0)
+ radio_calibration_value.setText("Disabled");
+ else
+ radio_calibration_value.setText(String.format("%d", new_radio_calibration));
+ }
+
+ private int parse_int(String name, String s, boolean split) throws AltosConfigDataException {
+ String v = s;
+ if (split)
+ v = s.split("\\s+")[0];
+ try {
+ return Integer.parseInt(v);
+ } catch (NumberFormatException ne) {
+ throw new AltosConfigDataException("Invalid %s \"%s\"", name, s);
+ }
+ }
+
+ public int radio_calibration() throws AltosConfigDataException {
+ return parse_int("radio calibration", radio_calibration_value.getText(), false);
+ }
+
+ public void set_radio_enable(int new_radio_enable) {
+ if (new_radio_enable >= 0) {
+ radio_enable_value.setSelected(new_radio_enable > 0);
+ 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();
+ }
+
+ public int radio_enable() {
+ if (radio_enable_value.isEnabled())
+ return radio_enable_value.isSelected() ? 1 : 0;
+ else
+ return -1;
+ }
+
+ public void set_callsign(String new_callsign) {
+ callsign_value.setVisible(new_callsign != null);
+ callsign_value.setText(new_callsign);
+ }
+
+ public String callsign() {
+ return callsign_value.getText();
+ }
+
+ int flight_log_max_limit;
+ int flight_log_max;
+
+ public String flight_log_max_label(int flight_log_max) {
+ if (flight_log_max_limit != 0) {
+ int nflight = flight_log_max_limit / flight_log_max;
+ String plural = nflight > 1 ? "s" : "";
+
+ return String.format("%d (%d flight%s)", flight_log_max, nflight, plural);
+ }
+ return String.format("%d", flight_log_max);
+ }
+
+ public void set_flight_log_max(int new_flight_log_max) {
+ 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();
+ }
+
+ public void set_flight_log_max_enabled(boolean enable) {
+ flight_log_max_value.setEnabled(enable);
+ set_flight_log_max_tool_tip();
+ }
+
+ public int flight_log_max() throws AltosConfigDataException {
+ return parse_int("flight log max", flight_log_max_value.getSelectedItem().toString(), true);
+ }
+
+ public void set_flight_log_max_limit(int new_flight_log_max_limit) {
+ flight_log_max_limit = new_flight_log_max_limit;
+ flight_log_max_value.removeAllItems();
+ for (int i = 8; i >= 1; i--) {
+ int size = flight_log_max_limit / i;
+ flight_log_max_value.addItem(String.format("%d (%d flights)", size, i));
+ }
+ if (flight_log_max != 0)
+ set_flight_log_max(flight_log_max);
+ }
+
+ public void set_ignite_mode(int new_ignite_mode) { }
+ public int ignite_mode() { return -1; }
+
+
+ public void set_pad_orientation(int new_pad_orientation) { }
+ public int pad_orientation() { return -1; }
+
+ public void set_beep(int new_beep) { }
+
+ public int beep() { return -1; }
+
+ String[] tracker_motion_values() {
+ if (AltosConvert.imperial_units)
+ return tracker_motion_values_ft;
+ else
+ return tracker_motion_values_m;
+ }
+
+ void set_tracker_motion_values() {
+ String[] v = tracker_motion_values();
+ while (tracker_motion_value.getItemCount() > 0)
+ tracker_motion_value.removeItemAt(0);
+ for (int i = 0; i < v.length; i++)
+ tracker_motion_value.addItem(v[i]);
+ tracker_motion_value.setMaximumRowCount(v.length);
+ }
+
+ String get_tracker_motion_label() {
+ return String.format("Logging Trigger Motion (%s):", AltosConvert.height.show_units());
+ }
+
+ void set_tracker_tool_tip() {
+ if (tracker_motion_value.isEnabled())
+ tracker_motion_value.setToolTipText("How far the device must move before logging");
+ else
+ tracker_motion_value.setToolTipText("This device doesn't disable logging when stationary");
+ if (tracker_interval_value.isEnabled())
+ tracker_interval_value.setToolTipText("How often to report GPS position");
+ else
+ tracker_interval_value.setToolTipText("This device can't configure interval");
+ }
+
+ public void set_tracker_motion(int tracker_motion) {
+ tracker_motion_value.setSelectedItem(AltosConvert.height.say(tracker_motion));
+ }
+
+ public int tracker_motion() throws AltosConfigDataException {
+ return (int) AltosConvert.height.parse(tracker_motion_value.getSelectedItem().toString());
+ }
+
+ public void set_tracker_interval(int tracker_interval) {
+ tracker_interval_value.setSelectedItem(String.format("%d", tracker_interval));
+ }
+
+ public int tracker_interval() throws AltosConfigDataException {
+ return parse_int ("tracker interval", tracker_interval_value.getSelectedItem().toString(), false);
+ }
+
+ public void set_aprs_interval(int new_aprs_interval) {
+ String s;
+
+ if (new_aprs_interval <= 0)
+ s = "Disabled";
+ 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();
+ }
+
+ public int aprs_interval() throws AltosConfigDataException {
+ String s = aprs_interval_value.getSelectedItem().toString();
+
+ if (s.equals("Disabled"))
+ return 0;
+ return parse_int("aprs interval", s, false);
+ }
+}
diff --git a/telegps/TeleGPSDisplayThread.java b/telegps/TeleGPSDisplayThread.java
new file mode 100644
index 00000000..a3d4ea07
--- /dev/null
+++ b/telegps/TeleGPSDisplayThread.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.telegps;
+
+import java.awt.*;
+import javax.swing.*;
+import java.io.*;
+import java.text.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
+
+public class TeleGPSDisplayThread extends Thread {
+
+ Frame parent;
+ IdleThread idle_thread;
+ AltosVoice voice;
+ AltosFlightReader reader;
+ AltosState old_state, state;
+ AltosListenerState listener_state;
+ AltosFlightDisplay display;
+
+ synchronized void show_safely() {
+ final AltosState my_state = state;
+ final AltosListenerState my_listener_state = listener_state;
+ Runnable r = new Runnable() {
+ public void run() {
+ try {
+ display.show(my_state, my_listener_state);
+ } catch (Exception ex) {
+ }
+ }
+ };
+ SwingUtilities.invokeLater(r);
+ }
+
+ void reading_error_internal() {
+ JOptionPane.showMessageDialog(parent,
+ String.format("Error reading from \"%s\"", reader.name),
+ "Telemetry Read Error",
+ JOptionPane.ERROR_MESSAGE);
+ }
+
+ void reading_error_safely() {
+ Runnable r = new Runnable() {
+ public void run() {
+ try {
+ reading_error_internal();
+ } catch (Exception ex) {
+ }
+ }
+ };
+ SwingUtilities.invokeLater(r);
+ }
+
+ class IdleThread extends Thread {
+
+ boolean started;
+ int report_interval;
+ long report_time;
+
+ public synchronized void report(boolean last) {
+ if (state == null)
+ return;
+
+ if (state.height() != AltosLib.MISSING) {
+ if (state.from_pad != null) {
+ voice.speak("Height %s, bearing %s %d, elevation %d, range %s, .\n",
+ AltosConvert.height.say(state.gps_height()),
+ state.from_pad.bearing_words(
+ AltosGreatCircle.BEARING_VOICE),
+ (int) (state.from_pad.bearing + 0.5),
+ (int) (state.elevation + 0.5),
+ AltosConvert.distance.say(state.range));
+ } else {
+ voice.speak("Height %s.\n",
+ AltosConvert.height.say(state.height()));
+ }
+ }
+ }
+
+ long now () {
+ return System.currentTimeMillis();
+ }
+
+ void set_report_time() {
+ report_time = now() + report_interval;
+ }
+
+ public void run () {
+ try {
+ for (;;) {
+ if (reader.has_monitor_battery()) {
+ listener_state.battery = reader.monitor_battery();
+ show_safely();
+ }
+ set_report_time();
+ for (;;) {
+ voice.drain();
+ synchronized (this) {
+ long sleep_time = report_time - now();
+ if (sleep_time <= 0)
+ break;
+ wait(sleep_time);
+ }
+ }
+
+ report(false);
+ }
+ } catch (InterruptedException ie) {
+ try {
+ voice.drain();
+ } catch (InterruptedException iie) { }
+ }
+ }
+
+ public synchronized void notice(boolean spoken) {
+ if (old_state != null && old_state.state != state.state) {
+ report_time = now();
+ this.notify();
+ } else if (spoken)
+ set_report_time();
+ }
+
+ public IdleThread() {
+ report_interval = 10000;
+ }
+ }
+
+ synchronized boolean tell() {
+ boolean ret = false;
+ if (old_state == null || old_state.gps_ready != state.gps_ready) {
+ if (state.gps_ready) {
+ voice.speak("GPS ready");
+ ret = true;
+ }
+ else if (old_state != null) {
+ voice.speak("GPS lost");
+ ret = true;
+ }
+ }
+ old_state = state;
+ return ret;
+ }
+
+ public void run() {
+ boolean interrupted = false;
+ boolean told;
+
+ idle_thread = new IdleThread();
+ idle_thread.start();
+
+ try {
+ for (;;) {
+ try {
+ state = reader.read();
+ if (state == null)
+ break;
+ reader.update(state);
+ show_safely();
+ told = tell();
+ idle_thread.notice(told);
+ } catch (ParseException pp) {
+ System.out.printf("Parse error: %d \"%s\"\n", pp.getErrorOffset(), pp.getMessage());
+ } catch (AltosCRCException ce) {
+ ++listener_state.crc_errors;
+ show_safely();
+ }
+ }
+ } catch (InterruptedException ee) {
+ interrupted = true;
+ } catch (IOException ie) {
+ reading_error_safely();
+ } finally {
+ if (!interrupted)
+ idle_thread.report(true);
+ reader.close(interrupted);
+ idle_thread.interrupt();
+ try {
+ idle_thread.join();
+ } catch (InterruptedException ie) {}
+ }
+ }
+
+ public TeleGPSDisplayThread(Frame in_parent, AltosVoice in_voice, AltosFlightDisplay in_display, AltosFlightReader in_reader) {
+ listener_state = new AltosListenerState();
+ parent = in_parent;
+ voice = in_voice;
+ display = in_display;
+ reader = in_reader;
+ display.reset();
+ }
+}
diff --git a/telegps/TeleGPSGraphUI.java b/telegps/TeleGPSGraphUI.java
new file mode 100644
index 00000000..244eb7b9
--- /dev/null
+++ b/telegps/TeleGPSGraphUI.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright © 2010 Anthony Towns
+ *
+ * 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 or any later version 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.telegps;
+
+import java.io.*;
+import java.util.ArrayList;
+
+import java.awt.*;
+import java.awt.event.*;
+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.jfree.chart.ChartPanel;
+import org.jfree.chart.JFreeChart;
+import org.jfree.ui.RefineryUtilities;
+
+public class TeleGPSGraphUI extends AltosUIFrame
+{
+ JTabbedPane pane;
+ AltosGraph graph;
+ AltosUIEnable enable;
+ AltosUIMap map;
+ AltosState state;
+ AltosFlightStats stats;
+ AltosGraphDataSet graphDataSet;
+ AltosFlightStatsTable statsTable;
+
+ void fill_map(AltosStateIterable states) {
+ for (AltosState state : states) {
+ if (state.gps != null && state.gps.locked && state.gps.nsat >= 4)
+ map.show(state, null);
+ }
+ }
+
+ private void close() {
+ setVisible(false);
+ dispose();
+ TeleGPS.subtract_window();
+ }
+
+ TeleGPSGraphUI(AltosStateIterable states, File file) throws InterruptedException, IOException {
+ super(file.getName());
+ state = null;
+
+ pane = new JTabbedPane();
+
+ enable = new AltosUIEnable();
+ stats = new AltosFlightStats(states);
+ graphDataSet = new AltosGraphDataSet(states);
+ graph = new AltosGraph(enable, stats, graphDataSet);
+ statsTable = new AltosFlightStatsTable(stats);
+
+ map = new AltosUIMap();
+
+ pane.add("Graph", graph.panel);
+ pane.add("Configure Graph", enable);
+ pane.add("Statistics", statsTable);
+ fill_map(states);
+ pane.add("Map", map);
+
+ setContentPane (pane);
+
+ addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowClosing(WindowEvent e) {
+ close();
+ }
+ });
+
+ pack();
+
+ setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
+
+ TeleGPS.add_window();
+
+ setVisible(true);
+
+ if (state != null)
+ map.centre(state);
+
+ }
+}
diff --git a/telegps/TeleGPSInfo.java b/telegps/TeleGPSInfo.java
new file mode 100644
index 00000000..e87fea90
--- /dev/null
+++ b/telegps/TeleGPSInfo.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.telegps;
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
+
+public class TeleGPSInfo extends AltosUIFlightTab {
+
+ JLabel cur, max;
+
+ abstract class Value extends AltosUIUnitsIndicator {
+ public abstract void show(AltosState state, AltosListenerState listener_state);
+
+ public Value (Container container, int y, AltosUnits units, String text) {
+ super(container, y, units, text, 1, false, 2);
+ }
+ }
+
+ abstract class DualValue extends AltosUIUnitsIndicator {
+ public DualValue (Container container, int y, AltosUnits units, String text) {
+ super(container, y, units, text, 2, false, 1);
+ }
+ }
+
+ abstract class ValueHold extends DualValue {
+ public void reset() {
+ super.reset();
+ }
+ public ValueHold (Container container, int y, AltosUnits units, String text) {
+ super(container, y, units, text);
+ }
+ }
+
+ class Altitude extends ValueHold {
+ public double value(AltosState state, int i) {
+ if (i == 0)
+ return state.altitude();
+ else
+ return state.max_altitude();
+ }
+
+ public Altitude (Container container, int y) {
+ super (container, y, AltosConvert.height, "Altitude");
+ }
+ }
+
+ class AscentRate extends ValueHold {
+ public double value(AltosState state, int i) {
+ if (i == 0)
+ return state.gps_ascent_rate();
+ else
+ return state.max_gps_ascent_rate();
+ }
+ public AscentRate (Container container, int y) {
+ super (container, y, AltosConvert.speed, "Ascent Rate");
+ }
+ }
+
+ class GroundSpeed extends ValueHold {
+ public double value(AltosState state, int i) {
+ if (i == 0)
+ return state.gps_ground_speed();
+ else
+ return state.max_gps_ground_speed();
+ }
+ public GroundSpeed (Container container, int y) {
+ super (container, y, AltosConvert.speed, "Ground Speed");
+ }
+ }
+
+ class Course extends AltosUIIndicator {
+
+ public void show (AltosState state, AltosListenerState listener_state) {
+ double course = state.gps_course();
+ if (course == AltosLib.MISSING)
+ show("Missing", "Missing");
+ else
+ show( String.format("%3.0f°", course),
+ AltosConvert.bearing_to_words(
+ AltosConvert.BEARING_LONG,
+ course));
+ }
+ public Course (Container container, int y) {
+ super (container, y, "Course", 2, false, 1);
+ }
+ }
+
+ class Lat extends AltosUIIndicator {
+
+ String pos(double p, String pos, String neg) {
+ String h = pos;
+ if (p < 0) {
+ h = neg;
+ p = -p;
+ }
+ int deg = (int) Math.floor(p);
+ double min = (p - Math.floor(p)) * 60.0;
+ return String.format("%s %4d° %9.6f", h, deg, min);
+ }
+
+ public void show (AltosState state, AltosListenerState listener_state) {
+ if (state.gps != null && state.gps.connected && state.gps.lat != AltosLib.MISSING)
+ show(pos(state.gps.lat,"N", "S"));
+ else
+ show("Missing");
+ }
+ public Lat (Container container, int y) {
+ super (container, y, "Latitude", 1, false, 2);
+ }
+ }
+
+ class Lon extends AltosUIIndicator {
+
+ String pos(double p, String pos, String neg) {
+ String h = pos;
+ if (p < 0) {
+ h = neg;
+ p = -p;
+ }
+ int deg = (int) Math.floor(p);
+ double min = (p - Math.floor(p)) * 60.0;
+ return String.format("%s %4d° %9.6f", h, deg, min);
+ }
+
+ public void show (AltosState state, AltosListenerState listener_state) {
+ if (state.gps != null && state.gps.connected && state.gps.lon != AltosLib.MISSING)
+ show(pos(state.gps.lon,"E", "W"));
+ else
+ show("Missing");
+ }
+ public Lon (Container container, int y) {
+ super (container, y, "Longitude", 1, false, 2);
+ }
+ }
+
+ class GPSLocked extends AltosUIIndicator {
+
+ public void show (AltosState state, AltosListenerState listener_state) {
+ if (state == null || state.gps == null)
+ hide();
+ else {
+ int soln = state.gps.nsat;
+ int nsat = state.gps.cc_gps_sat != null ? state.gps.cc_gps_sat.length : 0;
+ show("%4d in solution", soln,
+ "%4d in view", nsat);
+ set_lights(state.gps.locked && soln >= 4);
+ }
+ }
+ public GPSLocked (Container container, int y) {
+ super (container, y, "GPS Locked", 2, true, 1);
+ }
+ }
+
+ public void font_size_changed(int font_size) {
+ cur.setFont(AltosUILib.label_font);
+ max.setFont(AltosUILib.label_font);
+ super.font_size_changed(font_size);
+ }
+
+ public void labels(Container container, int y) {
+ GridBagLayout layout = (GridBagLayout)(container.getLayout());
+ GridBagConstraints c;
+
+ cur = new JLabel("Current");
+ cur.setFont(AltosUILib.label_font);
+ c = new GridBagConstraints();
+ c.gridx = 2; c.gridy = y;
+ c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad);
+ layout.setConstraints(cur, c);
+ add(cur);
+
+ max = new JLabel("Maximum");
+ max.setFont(AltosUILib.label_font);
+ c.gridx = 3; c.gridy = y;
+ layout.setConstraints(max, c);
+ add(max);
+ }
+
+ public String getName() {
+ return "Location";
+ }
+
+ public TeleGPSInfo() {
+ int y = 0;
+ labels(this, y++);
+ add(new Altitude(this, y++));
+ add(new GroundSpeed(this, y++));
+ add(new AscentRate(this, y++));
+ add(new Course(this, y++));
+ add(new Lat(this, y++));
+ add(new Lon(this, y++));
+ add(new GPSLocked(this, y++));
+ }
+}
diff --git a/telegps/TeleGPSPreferences.java b/telegps/TeleGPSPreferences.java
new file mode 100644
index 00000000..8bd371f4
--- /dev/null
+++ b/telegps/TeleGPSPreferences.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.telegps;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.beans.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import org.altusmetrum.altosuilib_2.*;
+
+public class TeleGPSPreferences
+ extends AltosUIConfigure
+ implements DocumentListener
+{
+ AltosVoice voice;
+
+ public JTextField callsign_value;
+ public JComboBox<String> position_value;
+
+ /* DocumentListener interface methods */
+ public void insertUpdate(DocumentEvent e) {
+ changedUpdate(e);
+ }
+
+ public void removeUpdate(DocumentEvent e) {
+ changedUpdate(e);
+ }
+
+ public void changedUpdate(DocumentEvent e) {
+ if (callsign_value != null)
+ AltosUIPreferences.set_callsign(callsign_value.getText());
+ }
+
+ public void add_voice() {
+
+ /* Voice settings */
+ pane.add(new JLabel("Voice"), constraints(0, 1));
+
+ JRadioButton enable_voice = new JRadioButton("Enable", AltosUIPreferences.voice());
+ enable_voice.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ JRadioButton item = (JRadioButton) e.getSource();
+ boolean enabled = item.isSelected();
+ AltosUIPreferences.set_voice(enabled);
+ if (enabled)
+ voice.speak_always("Enable voice.");
+ else
+ voice.speak_always("Disable voice.");
+ }
+ });
+ pane.add(enable_voice, constraints(1, 1));
+ enable_voice.setToolTipText("Enable/Disable all audio in-flight announcements");
+
+ JButton test_voice = new JButton("Test Voice");
+ test_voice.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ voice.speak("That's one small step for man; one giant leap for mankind.");
+ }
+ });
+ pane.add(test_voice, constraints(2, 1));
+ test_voice.setToolTipText("Play a stock audio clip to check volume");
+ row++;
+ }
+
+ public void add_callsign() {
+ /* Callsign setting */
+ pane.add(new JLabel("Callsign"), constraints(0, 1));
+
+ callsign_value = new JTextField(AltosUIPreferences.callsign());
+ callsign_value.getDocument().addDocumentListener(this);
+ callsign_value.setToolTipText("Callsign sent in packet mode");
+ pane.add(callsign_value, constraints(1, 2, GridBagConstraints.BOTH));
+ row++;
+ }
+
+ public void add_bluetooth() {
+ JButton manage_bluetooth = new JButton("Manage Bluetooth");
+ manage_bluetooth.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ AltosBTManage.show(owner, AltosBTKnown.bt_known());
+ }
+ });
+ pane.add(manage_bluetooth, constraints(0, 2));
+ /* in the same row as add_frequencies, so don't bump row */
+ }
+
+ public void add_frequencies() {
+ JButton manage_frequencies = new JButton("Manage Frequencies");
+ manage_frequencies.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ AltosConfigFreqUI.show(owner);
+ }
+ });
+ manage_frequencies.setToolTipText("Configure which values are shown in frequency menus");
+ pane.add(manage_frequencies, constraints(2, 1));
+ row++;
+ }
+
+ public TeleGPSPreferences(JFrame owner, AltosVoice voice) {
+ super(owner, "TeleGPS Preferences", "Configure TeleGPS");
+
+ this.voice = voice;
+ }
+}
diff --git a/telegps/TeleGPSState.java b/telegps/TeleGPSState.java
new file mode 100644
index 00000000..a76182ed
--- /dev/null
+++ b/telegps/TeleGPSState.java
@@ -0,0 +1,207 @@
+/*
+ * 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.telegps;
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
+
+public class TeleGPSState extends AltosUIFlightTab {
+
+ JLabel cur, max;
+
+ abstract class Value extends AltosUIUnitsIndicator {
+ public Value (Container container, int y, AltosUnits units, String text) {
+ super(container, y, units, text, 1, false, 2);
+ }
+ }
+
+ abstract class DualValue extends AltosUIUnitsIndicator {
+ public DualValue (Container container, int y, AltosUnits units, String text) {
+ super(container, y, units, text, 2, false, 1);
+ }
+ }
+
+ abstract class ValueHold extends DualValue {
+ public ValueHold (Container container, int y, AltosUnits units, String text) {
+ super(container, y, units, text);
+ }
+ }
+
+ class Height extends ValueHold {
+ public double value(AltosState state, int i) {
+ if (i == 0)
+ return state.height();
+ else
+ return state.max_height();
+ }
+
+ public Height(Container container, int y) {
+ super(container, y, AltosConvert.height, "Height");
+ }
+ }
+
+ class Speed extends ValueHold {
+ public double value(AltosState state, int i) {
+ if (i == 0)
+ return state.gps_speed();
+ else
+ return state.max_gps_speed();
+ }
+
+ public Speed(Container container, int y) {
+ super(container, y, AltosConvert.speed, "Speed");
+ }
+ }
+
+ class Distance extends Value {
+ public double value(AltosState state, int i) {
+ if (state.from_pad != null)
+ return state.from_pad.distance;
+ else
+ return AltosLib.MISSING;
+ }
+
+ public Distance(Container container, int y) {
+ super(container, y, AltosConvert.distance, "Distance");
+ }
+ }
+
+ class Range extends Value {
+ public double value(AltosState state, int i) {
+ return state.range;
+ }
+ public Range (Container container, int y) {
+ super (container, y, AltosConvert.distance, "Range");
+ }
+ }
+
+ class Bearing extends AltosUIIndicator {
+ public void show (AltosState state, AltosListenerState listener_state) {
+ if (state.from_pad != null && state.from_pad.bearing != AltosLib.MISSING) {
+ show( String.format("%3.0f°", state.from_pad.bearing),
+ state.from_pad.bearing_words(
+ AltosGreatCircle.BEARING_LONG));
+ } else {
+ show("Missing", "Missing");
+ }
+ }
+ public Bearing (Container container, int y) {
+ super (container, y, "Bearing", 2, false, 1);
+ }
+ }
+
+ class Elevation extends AltosUIIndicator {
+ public void show (AltosState state, AltosListenerState listener_state) {
+ if (state.elevation == AltosLib.MISSING)
+ show("Missing");
+ else
+ show("%3.0f°", state.elevation);
+ }
+ public Elevation (Container container, int y) {
+ super (container, y, "Elevation", 1, false, 2);
+ }
+ }
+
+ class FirmwareVersion extends AltosUIIndicator {
+ public void show(AltosState state, AltosListenerState listener_state) {
+ if (state.firmware_version == null)
+ show("Missing");
+ else
+ show(state.firmware_version);
+ }
+
+ public FirmwareVersion(Container container, int y) {
+ super(container, y, "Firmware Version", 1, false, 2);
+ }
+ }
+
+ class FlightLogMax extends AltosUIIndicator {
+ public void show(AltosState state, AltosListenerState listener_state) {
+ if (state.flight_log_max == AltosLib.MISSING)
+ show("Missing");
+ else
+ show(String.format("%dkB", state.flight_log_max));
+ }
+
+ public FlightLogMax(Container container, int y) {
+ super(container, y, "Flight Log Storage", 1, false, 2);
+ }
+ }
+
+ class BatteryVoltage extends AltosUIVoltageIndicator {
+ public double voltage(AltosState state) {
+ return state.battery_voltage;
+ }
+
+ public double good() {
+ return AltosLib.ao_battery_good;
+ }
+
+ public BatteryVoltage(Container container, int y) {
+ super(container, y, "Battery Voltage", 2);
+ }
+ }
+
+
+ public void labels(Container container, int y) {
+ GridBagLayout layout = (GridBagLayout)(container.getLayout());
+ GridBagConstraints c;
+
+ cur = new JLabel("Current");
+ cur.setFont(AltosUILib.label_font);
+ c = new GridBagConstraints();
+ c.gridx = 2; c.gridy = y;
+ c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad);
+ layout.setConstraints(cur, c);
+ add(cur);
+
+ max = new JLabel("Maximum");
+ max.setFont(AltosUILib.label_font);
+ c.gridx = 3; c.gridy = y;
+ layout.setConstraints(max, c);
+ add(max);
+ }
+
+ public void font_size_changed(int font_size) {
+ cur.setFont(AltosUILib.label_font);
+ max.setFont(AltosUILib.label_font);
+ super.font_size_changed(font_size);
+ }
+
+ public String getName() {
+ return "Status";
+ }
+
+ public TeleGPSState() {
+ int y = 0;
+ labels(this, y++);
+ add(new Height(this, y++));
+ add(new Speed(this, y++));
+ add(new Distance(this, y++));
+ add(new Range(this, y++));
+ add(new Bearing(this, y++));
+ add(new Elevation(this, y++));
+ add(new FirmwareVersion(this, y++));
+ add(new FlightLogMax(this, y++));
+ add(new BatteryVoltage(this, y++));
+ }
+}
diff --git a/telegps/TeleGPSStatus.java b/telegps/TeleGPSStatus.java
new file mode 100644
index 00000000..f3951a37
--- /dev/null
+++ b/telegps/TeleGPSStatus.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.telegps;
+
+import java.awt.*;
+import javax.swing.*;
+import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altosuilib_2.*;
+
+public class TeleGPSStatus extends JComponent implements AltosFlightDisplay {
+ GridBagLayout layout;
+
+ public class Value {
+ JLabel label;
+ JTextField value;
+
+ void show(AltosState state, AltosListenerState listener_state) {}
+
+ void reset() {
+ value.setText("");
+ }
+
+ void set_font() {
+ label.setFont(AltosUILib.status_font);
+ value.setFont(AltosUILib.status_font);
+ }
+
+ void setVisible(boolean visible) {
+ label.setVisible(visible);
+ value.setVisible(visible);
+ }
+
+ public Value (GridBagLayout layout, int x, String text) {
+ GridBagConstraints c = new GridBagConstraints();
+ c.insets = new Insets(5, 5, 5, 5);
+ c.anchor = GridBagConstraints.CENTER;
+ c.fill = GridBagConstraints.BOTH;
+ c.weightx = 1;
+ c.weighty = 1;
+
+ label = new JLabel(text);
+ label.setFont(AltosUILib.status_font);
+ label.setHorizontalAlignment(SwingConstants.CENTER);
+ c.gridx = x; c.gridy = 0;
+ layout.setConstraints(label, c);
+ add(label);
+
+ value = new JTextField("");
+ value.setEditable(false);
+ value.setFont(AltosUILib.status_font);
+ value.setHorizontalAlignment(SwingConstants.CENTER);
+ c.gridx = x; c.gridy = 1;
+ layout.setConstraints(value, c);
+ add(value);
+ }
+ }
+
+ class Call extends Value {
+ String call;
+
+ void show(AltosState state, AltosListenerState listener_state) {
+ if (state.callsign != call) {
+ value.setText(state.callsign);
+ call = state.callsign;
+ }
+ if (state.callsign == null)
+ setVisible(false);
+ else
+ setVisible(true);
+ }
+
+ public void reset() {
+ super.reset();
+ call = "";
+ }
+
+ public Call (GridBagLayout layout, int x) {
+ super (layout, x, "Callsign");
+ }
+ }
+
+ Call call;
+
+ class Serial extends Value {
+ int serial = -1;
+ void show(AltosState state, AltosListenerState listener_state) {
+ if (state.serial != serial) {
+ if (state.serial == AltosLib.MISSING)
+ value.setText("none");
+ else
+ value.setText(String.format("%d", state.serial));
+ serial = state.serial;
+ }
+ }
+
+ public void reset() {
+ super.reset();
+ serial = -1;
+ }
+
+ public Serial (GridBagLayout layout, int x) {
+ super (layout, x, "Serial");
+ }
+ }
+
+ Serial serial;
+
+ class Flight extends Value {
+
+ int last_flight = -1;
+
+ void show(AltosState state, AltosListenerState listener_state) {
+ if (state.flight != last_flight) {
+ if (state.flight == AltosLib.MISSING)
+ value.setText("none");
+ else
+ value.setText(String.format("%d", state.flight));
+ last_flight = state.flight;
+ }
+ }
+
+ public void reset() {
+ super.reset();
+ last_flight = -1;
+ }
+
+ public Flight (GridBagLayout layout, int x) {
+ super (layout, x, "Flight");
+ }
+ }
+
+ Flight flight;
+
+ class RSSI extends Value {
+ int rssi = 10000;
+
+ void show(AltosState state, AltosListenerState listener_state) {
+ int new_rssi = state.rssi();
+
+ if (new_rssi != rssi) {
+ value.setText(String.format("%d", new_rssi));
+ if (state.rssi == AltosLib.MISSING)
+ setVisible(false);
+ else
+ setVisible(true);
+ rssi = new_rssi;
+ }
+ }
+
+ public void reset() {
+ super.reset();
+ rssi = 10000;
+ }
+
+ public RSSI (GridBagLayout layout, int x) {
+ super (layout, x, "RSSI");
+ }
+ }
+
+ RSSI rssi;
+
+ class LastPacket extends Value {
+
+ long last_secs = -1;
+
+ void show(AltosState state, AltosListenerState listener_state) {
+ long secs = (System.currentTimeMillis() - state.received_time + 500) / 1000;
+
+ if (secs != last_secs) {
+ value.setText(String.format("%d", secs));
+ last_secs = secs;
+ }
+ }
+
+ void reset() {
+ super.reset();
+ last_secs = -1;
+ }
+
+ void disable() {
+ value.setText("");
+ }
+
+ public LastPacket(GridBagLayout layout, int x) {
+ super (layout, x, "Age");
+ }
+ }
+
+ LastPacket last_packet;
+
+ public void disable_receive() {
+ last_packet.disable();
+ }
+
+ public void reset () {
+ call.reset();
+ serial.reset();
+ flight.reset();
+ rssi.reset();
+ last_packet.reset();
+ }
+
+ public void font_size_changed(int font_size) {
+ call.set_font();
+ serial.set_font();
+ flight.set_font();
+ rssi.set_font();
+ last_packet.set_font();
+ }
+
+ public void units_changed(boolean imperial_units) {
+ }
+
+ public void show (AltosState state, AltosListenerState listener_state) {
+ call.show(state, listener_state);
+ serial.show(state, listener_state);
+ flight.show(state, listener_state);
+ rssi.show(state, listener_state);
+ last_packet.show(state, listener_state);
+ }
+
+ public int height() {
+ Dimension d = layout.preferredLayoutSize(this);
+ return d.height;
+ }
+
+ public TeleGPSStatus() {
+ layout = new GridBagLayout();
+
+ setLayout(layout);
+
+ call = new Call(layout, 0);
+ serial = new Serial(layout, 1);
+ flight = new Flight(layout, 2);
+ rssi = new RSSI(layout, 4);
+ last_packet = new LastPacket(layout, 5);
+ }
+}
diff --git a/telegps/TeleGPSStatusUpdate.java b/telegps/TeleGPSStatusUpdate.java
new file mode 100644
index 00000000..e7684d88
--- /dev/null
+++ b/telegps/TeleGPSStatusUpdate.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.telegps;
+
+import java.awt.event.*;
+import org.altusmetrum.altoslib_4.*;
+
+public class TeleGPSStatusUpdate implements ActionListener {
+
+ public AltosState saved_state;
+ public AltosListenerState saved_listener_state;
+ TeleGPSStatus status;
+
+ public void actionPerformed (ActionEvent e) {
+ if (saved_state != null) {
+ if (saved_listener_state == null)
+ saved_listener_state = new AltosListenerState();
+ status.show(saved_state, saved_listener_state);
+ }
+ }
+
+ public TeleGPSStatusUpdate (TeleGPSStatus in_status) {
+ status = in_status;
+ }
+}
+
diff --git a/telegps/telegps-fat b/telegps/telegps-fat
new file mode 100755
index 00000000..87491248
--- /dev/null
+++ b/telegps/telegps-fat
@@ -0,0 +1,4 @@
+#!/bin/sh
+me=`which "$0"`
+dir=`dirname "$me"`
+exec java -cp "$dir/*" -Djava.library.path="$dir" -jar "$dir"/telegps-fat.jar "$@"
diff --git a/telegps/telegps-windows.nsi.in b/telegps/telegps-windows.nsi.in
new file mode 100644
index 00000000..e6798c46
--- /dev/null
+++ b/telegps/telegps-windows.nsi.in
@@ -0,0 +1,194 @@
+!addplugindir ../altosui/Instdrv/NSIS/Plugins
+!include x64.nsh
+; Definitions for Java 1.7 Detection
+!define JRE_VERSION "1.7"
+!define JRE_ALTERNATE "1.6"
+!define JRE32_URL "http://javadl.sun.com/webapps/download/AutoDL?BundleId=83383&/jre-7u51-windows-i586.exe"
+!define JRE64_URL "http://javadl.sun.com/webapps/download/AutoDL?BundleId=83385&/jre-7u51-windows-x64.exe"
+!define PRODUCT_NAME "TeleGPS Windows Software"
+
+Name "TeleGPS Installer"
+
+; Default install directory
+InstallDir "$PROGRAMFILES\AltusMetrum"
+
+; Tell the installer where to re-install a new version
+InstallDirRegKey HKLM "Software\AltusMetrum" "Install_Dir"
+
+LicenseText "GNU General Public License Version 2"
+LicenseData "../COPYING"
+
+; Need admin privs for Vista or Win7
+RequestExecutionLevel admin
+
+ShowInstDetails Show
+
+ComponentText "TeleGPS Software Installer"
+
+Function .onInit
+ DetailPrint "Checking host operating system"
+ ${If} ${RunningX64}
+ DetailPrint "Installer running on 64-bit host"
+ SetRegView 64
+ StrCpy $INSTDIR "$PROGRAMFILES64\AltusMetrum"
+ ${DisableX64FSRedirection}
+ ${EndIf}
+FunctionEnd
+
+Var JavaDownload
+Var JavaBits
+
+Function GetJRE
+ ${If} ${RunningX64}
+ StrCpy $JavaDownload ${JRE64_URL}
+ StrCpy $JavaBits "64"
+ ${Else}
+ StrCpy $JavaDownload ${JRE32_URL}
+ StrCpy $JavaBits "32"
+ ${EndIf}
+
+ MessageBox MB_OK "${PRODUCT_NAME} uses Java ${JRE_VERSION}, \
+ $JavaBits bits, it will now \
+ be downloaded and installed"
+
+ StrCpy $2 "$TEMP\Java Runtime Environment.exe"
+ nsisdl::download /TIMEOUT=30000 $JavaDownload $2
+ Pop $R0 ;Get the return value
+ StrCmp $R0 "success" +3
+ MessageBox MB_OK "Download failed: $R0"
+ Quit
+ ExecWait $2
+ Delete $2
+FunctionEnd
+
+Function DetectJRE
+ ReadRegStr $2 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment" \
+ "CurrentVersion"
+
+ StrCmp $2 ${JRE_VERSION} done
+
+ StrCmp $2 ${JRE_ALTERNATE} done
+
+ Call GetJRE
+
+ done:
+FunctionEnd
+
+; Pages to present
+
+Page license
+Page components
+Page directory
+Page instfiles
+
+UninstPage uninstConfirm
+UninstPage instfiles
+
+; And the stuff to install
+
+Section "Install Driver" InstDriver
+
+ InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} AltusMetrumSerial
+ Pop $0
+ DetailPrint "InitDriverSetup: $0"
+ InstDrv::DeleteOemInfFiles /NOUNLOAD
+ InstDrv::CreateDevice /NOUNLOAD
+
+ SetOutPath $INSTDIR
+ File "../altusmetrum.inf"
+ File "../altusmetrum.cat"
+
+ ${DisableX64FSRedirection}
+ IfFileExists $WINDIR\System32\PnPutil.exe 0 nopnp
+ ${DisableX64FSRedirection}
+ nsExec::ExecToLog '"$WINDIR\System32\PnPutil.exe" -i -a "$INSTDIR\altusmetrum.inf"'
+ Goto done
+nopnp:
+ InstDrv::InstallDriver /NOUNLOAD "$INSTDIR\altusmetrum.inf"
+done:
+
+SectionEnd
+
+Section "TeleGPS Application"
+ Call DetectJRE
+
+ SetOutPath $INSTDIR
+
+ File "telegps-fat.jar"
+ File "altoslib_@ALTOSLIB_VERSION@.jar"
+ File "altosuilib_@ALTOSUILIB_VERSION@.jar"
+ File "cmudict04.jar"
+ File "cmulex.jar"
+ File "cmu_time_awb.jar"
+ File "cmutimelex.jar"
+ File "cmu_us_kal.jar"
+ File "en_us.jar"
+ File "freetts.jar"
+ File "jfreechart.jar"
+ File "jcommon.jar"
+
+ File "*.dll"
+
+ File "../icon/*.ico"
+
+ CreateShortCut "$SMPROGRAMS\TeleGPS.lnk" "$SYSDIR\javaw.exe" "-jar telegps-fat.jar" "$INSTDIR\telegps.ico"
+SectionEnd
+
+Section "TeleGPS Desktop Shortcut"
+ CreateShortCut "$DESKTOP\TeleGPS.lnk" "$INSTDIR\telegps-fat.jar" "" "$INSTDIR\telegps.ico"
+SectionEnd
+
+Section "TeleGPS, TeleDongle and TeleBT Firmware"
+
+ SetOutPath $INSTDIR
+
+ File "../src/telegps-v1.0/telegps-v1.0-${VERSION}.ihx"
+ File "../src/teledongle-v0.2/teledongle-v0.2-${VERSION}.ihx"
+ File "../src/telebt-v1.0/telebt-v1.0-${VERSION}.ihx"
+
+SectionEnd
+
+Section "Documentation"
+
+ SetOutPath $INSTDIR
+
+ File "../doc/telegps.pdf"
+ File "../doc/altos.pdf"
+ File "../doc/telemetry.pdf"
+SectionEnd
+
+Section "Uninstaller"
+
+ ; Deal with the uninstaller
+
+ SetOutPath $INSTDIR
+
+ ; Write the install path to the registry
+ WriteRegStr HKLM SOFTWARE\AltusMetrum "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"
+
+ WriteUninstaller "uninstall.exe"
+SectionEnd
+
+Section "Uninstall"
+ DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum"
+ DeleteRegKey HKLM "Software\AltusMetrum"
+
+ Delete "$INSTDIR\*.*"
+ RMDir "$INSTDIR"
+
+ ; Remove devices
+ InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} AltusMetrumSerial
+ InstDrv::DeleteOemInfFiles /NOUNLOAD
+ InstDrv::RemoveAllDevices
+
+ ; Remove shortcuts, if any
+ Delete "$SMPROGRAMS\TeleGPS.lnk"
+ Delete "$DESKTOP\TeleGPS.lnk"
+
+SectionEnd
diff --git a/telegps/telegps.1 b/telegps/telegps.1
new file mode 100644
index 00000000..57fa4489
--- /dev/null
+++ b/telegps/telegps.1
@@ -0,0 +1,46 @@
+.\"
+.\" Copyright © 2010 Bdale Garbee <bdale@gag.com>
+.\"
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful, but
+.\" WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+.\" General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License along
+.\" with this program; if not, write to the Free Software Foundation, Inc.,
+.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+.\"
+.\"
+.TH ALTOSUI 1 "altosui" ""
+.SH NAME
+altosui \- Rocket flight monitor
+.SH SYNOPSIS
+.B "altosui"
+.SH DESCRIPTION
+.I altosui
+connects to a TeleDongle or TeleMetrum device through a USB serial device.
+It provides a menu-oriented
+user interface to monitor, record and review rocket flight data.
+.SH USAGE
+When connected to a TeleDongle device, altosui turns on the radio
+receiver and listens for telemetry packets. It displays the received
+telemetry data, and reports flight status via voice synthesis. All
+received telemetry information is recorded to a file.
+.P
+When connected to a TeleMetrum device, altosui can be used to configure the
+TeleMetrum, and to downloads the eeprom data and store it in a file.
+.P
+A number of other menu options exist, including the ability to export flight
+data in different formats.
+.SH FILES
+All data log files are recorded into a user-specified directory
+(default ~/TeleMetrum). Files are named using the current date, the serial
+number of the reporting device, the flight number recorded in the data
+and either '.telem' for telemetry data or '.eeprom' for eeprom data.
+.SH AUTHOR
+Keith Packard
diff --git a/telegps/telegps.desktop.in b/telegps/telegps.desktop.in
new file mode 100644
index 00000000..3d249d8a
--- /dev/null
+++ b/telegps/telegps.desktop.in
@@ -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%/telegps.svg
+Exec=%bindir%/telegps %f
+Terminal=false
+MimeType=text/plain;
+Categories=Education;Electronics;Science;