Merge branch 'master' into branch-1.6
authorBdale Garbee <bdale@gag.com>
Fri, 6 May 2016 23:59:39 +0000 (17:59 -0600)
committerBdale Garbee <bdale@gag.com>
Fri, 6 May 2016 23:59:39 +0000 (17:59 -0600)
425 files changed:
Makefile.am
Releasing
altosdroid/.gitignore
altosdroid/AndroidManifest.xml.in
altosdroid/Makefile.am
altosdroid/res/layout/device_list.xml
altosdroid/res/layout/frequency.xml [new file with mode: 0644]
altosdroid/res/layout/idle_mode.xml [new file with mode: 0644]
altosdroid/res/layout/igniter_status.xml [new file with mode: 0644]
altosdroid/res/layout/igniters.xml [new file with mode: 0644]
altosdroid/res/layout/manage_frequencies.xml [new file with mode: 0644]
altosdroid/res/layout/setup.xml [new file with mode: 0644]
altosdroid/res/menu/option_menu.xml
altosdroid/res/values/strings.xml
altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosDebug.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidLink.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapInterface.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapSourceListener.java [new file with mode: 0644]
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOffline.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOnline.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosUsb.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java
altosdroid/src/org/altusmetrum/AltosDroid/IdleModeActivity.java [new file with mode: 0644]
altosdroid/src/org/altusmetrum/AltosDroid/IgniterActivity.java [new file with mode: 0644]
altosdroid/src/org/altusmetrum/AltosDroid/ManageFrequenciesActivity.java [new file with mode: 0644]
altosdroid/src/org/altusmetrum/AltosDroid/MapTypeActivity.java
altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java
altosdroid/src/org/altusmetrum/AltosDroid/SetupActivity.java [new file with mode: 0644]
altosdroid/src/org/altusmetrum/AltosDroid/TabFlight.java
altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java
altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java
altosdroid/src/org/altusmetrum/AltosDroid/TabRecover.java
altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java
altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java
altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java
altosdroid/src/org/altusmetrum/AltosDroid/TelemetryState.java
altoslib/AltosAccel.java
altoslib/AltosCRCException.java
altoslib/AltosCSV.java
altoslib/AltosCompanion.java
altoslib/AltosConfigData.java
altoslib/AltosConfigDataException.java
altoslib/AltosConfigValues.java
altoslib/AltosConvert.java
altoslib/AltosDebug.java
altoslib/AltosDistance.java
altoslib/AltosEeprom.java
altoslib/AltosEepromChunk.java
altoslib/AltosEepromDownload.java
altoslib/AltosEepromFile.java
altoslib/AltosEepromGPS.java
altoslib/AltosEepromHeader.java
altoslib/AltosEepromIterable.java
altoslib/AltosEepromList.java
altoslib/AltosEepromLog.java
altoslib/AltosEepromMega.java
altoslib/AltosEepromMetrum2.java
altoslib/AltosEepromMini.java
altoslib/AltosEepromMonitor.java
altoslib/AltosEepromTM.java
altoslib/AltosEepromTMini.java [new file with mode: 0644]
altoslib/AltosEepromTm.java [deleted file]
altoslib/AltosFile.java
altoslib/AltosFlash.java
altoslib/AltosFlashListener.java
altoslib/AltosFlightDisplay.java
altoslib/AltosFlightReader.java
altoslib/AltosFlightStats.java
altoslib/AltosFontListener.java
altoslib/AltosFrequency.java
altoslib/AltosGPS.java
altoslib/AltosGPSSat.java
altoslib/AltosGreatCircle.java
altoslib/AltosHeight.java
altoslib/AltosHexfile.java
altoslib/AltosHexsym.java
altoslib/AltosIMU.java
altoslib/AltosIdle.java
altoslib/AltosIdleFetch.java
altoslib/AltosIdleMonitor.java
altoslib/AltosIdleMonitorListener.java
altoslib/AltosIgnite.java
altoslib/AltosImage.java
altoslib/AltosKML.java
altoslib/AltosLatLon.java
altoslib/AltosLatitude.java
altoslib/AltosLaunchSite.java
altoslib/AltosLaunchSiteListener.java
altoslib/AltosLaunchSites.java
altoslib/AltosLib.java
altoslib/AltosLine.java
altoslib/AltosLink.java
altoslib/AltosListenerState.java
altoslib/AltosLocation.java
altoslib/AltosLog.java
altoslib/AltosLongitude.java
altoslib/AltosMag.java
altoslib/AltosMap.java
altoslib/AltosMapCache.java
altoslib/AltosMapCacheListener.java
altoslib/AltosMapInterface.java
altoslib/AltosMapLine.java
altoslib/AltosMapLoader.java
altoslib/AltosMapLoaderListener.java
altoslib/AltosMapMark.java
altoslib/AltosMapPath.java
altoslib/AltosMapPathPoint.java
altoslib/AltosMapRectangle.java
altoslib/AltosMapStore.java
altoslib/AltosMapStoreListener.java
altoslib/AltosMapTile.java
altoslib/AltosMapTileListener.java
altoslib/AltosMapTransform.java
altoslib/AltosMapTypeListener.java [new file with mode: 0644]
altoslib/AltosMapZoomListener.java
altoslib/AltosMma655x.java
altoslib/AltosMs5607.java
altoslib/AltosNoSymbol.java
altoslib/AltosOrient.java
altoslib/AltosParse.java
altoslib/AltosPointDouble.java
altoslib/AltosPointInt.java
altoslib/AltosPreferences.java
altoslib/AltosPreferencesBackend.java
altoslib/AltosProgrammer.java
altoslib/AltosPyro.java
altoslib/AltosQuaternion.java
altoslib/AltosRectangle.java
altoslib/AltosReplayReader.java
altoslib/AltosRomconfig.java
altoslib/AltosRotation.java
altoslib/AltosSavedState.java
altoslib/AltosSelfFlash.java
altoslib/AltosSensorEMini.java
altoslib/AltosSensorMM.java
altoslib/AltosSensorMega.java
altoslib/AltosSensorMetrum.java
altoslib/AltosSensorTGPS.java
altoslib/AltosSensorTM.java
altoslib/AltosSensorTMini.java
altoslib/AltosSpeed.java
altoslib/AltosState.java
altoslib/AltosStateIterable.java
altoslib/AltosStateUpdate.java
altoslib/AltosTelemetry.java
altoslib/AltosTelemetryCompanion.java
altoslib/AltosTelemetryConfiguration.java
altoslib/AltosTelemetryFile.java
altoslib/AltosTelemetryIterable.java
altoslib/AltosTelemetryLegacy.java
altoslib/AltosTelemetryLocation.java
altoslib/AltosTelemetryMap.java
altoslib/AltosTelemetryMegaData.java
altoslib/AltosTelemetryMegaSensor.java
altoslib/AltosTelemetryMetrumData.java
altoslib/AltosTelemetryMetrumSensor.java
altoslib/AltosTelemetryMini.java
altoslib/AltosTelemetryRaw.java
altoslib/AltosTelemetryReader.java
altoslib/AltosTelemetrySatellite.java
altoslib/AltosTelemetrySensor.java
altoslib/AltosTelemetryStandard.java
altoslib/AltosTemperature.java
altoslib/AltosUnits.java
altoslib/AltosUnitsListener.java
altoslib/AltosUnknownProduct.java [new file with mode: 0644]
altoslib/AltosVersion.java.in
altoslib/AltosVoltage.java
altoslib/AltosWriter.java
altoslib/Makefile.am
altosui/Altos.java
altosui/AltosAscent.java
altosui/AltosCompanionInfo.java
altosui/AltosConfig.java
altosui/AltosConfigPyroUI.java
altosui/AltosConfigTD.java
altosui/AltosConfigTDUI.java
altosui/AltosConfigUI.java
altosui/AltosConfigureUI.java
altosui/AltosDescent.java
altosui/AltosFlightStatus.java
altosui/AltosFlightStatusTableModel.java
altosui/AltosFlightStatusUpdate.java
altosui/AltosFlightUI.java
altosui/AltosGraphUI.java
altosui/AltosIdleMonitorUI.java
altosui/AltosIgniteUI.java
altosui/AltosIgnitor.java
altosui/AltosLanded.java
altosui/AltosLaunch.java
altosui/AltosLaunchUI.java
altosui/AltosPad.java
altosui/AltosUI.java
altosui/Instdrv/NSIS/Includes/java.nsh
altosuilib/AltosBTDevice.java
altosuilib/AltosBTDeviceIterator.java
altosuilib/AltosBTKnown.java
altosuilib/AltosBTManage.java
altosuilib/AltosCSVUI.java
altosuilib/AltosConfigFreqUI.java
altosuilib/AltosDataChooser.java
altosuilib/AltosDevice.java
altosuilib/AltosDeviceDialog.java
altosuilib/AltosDeviceUIDialog.java
altosuilib/AltosDisplayThread.java
altosuilib/AltosEepromDelete.java
altosuilib/AltosEepromManage.java
altosuilib/AltosEepromMonitor.java
altosuilib/AltosEepromMonitorUI.java
altosuilib/AltosEepromSelect.java
altosuilib/AltosFlashUI.java
altosuilib/AltosFlightInfoTableModel.java
altosuilib/AltosFlightStatsTable.java
altosuilib/AltosGraph.java
altosuilib/AltosGraphDataPoint.java
altosuilib/AltosGraphDataSet.java
altosuilib/AltosInfoTable.java
altosuilib/AltosLed.java
altosuilib/AltosLights.java
altosuilib/AltosPositionListener.java
altosuilib/AltosRomconfigUI.java
altosuilib/AltosScanUI.java
altosuilib/AltosSerial.java
altosuilib/AltosSerialInUseException.java
altosuilib/AltosUIAxis.java
altosuilib/AltosUIConfigure.java
altosuilib/AltosUIDataMissing.java
altosuilib/AltosUIDataPoint.java
altosuilib/AltosUIDataSet.java
altosuilib/AltosUIDialog.java
altosuilib/AltosUIEnable.java
altosuilib/AltosUIFlightTab.java
altosuilib/AltosUIFrame.java
altosuilib/AltosUIFreqList.java
altosuilib/AltosUIGraph.java
altosuilib/AltosUIGrapher.java
altosuilib/AltosUIImage.java
altosuilib/AltosUIIndicator.java
altosuilib/AltosUILib.java
altosuilib/AltosUIListener.java
altosuilib/AltosUIMapNew.java
altosuilib/AltosUIMapPreloadNew.java
altosuilib/AltosUIMarker.java
altosuilib/AltosUIPreferences.java
altosuilib/AltosUIPreferencesBackend.java
altosuilib/AltosUIRateList.java
altosuilib/AltosUISeries.java
altosuilib/AltosUITelemetryList.java
altosuilib/AltosUIUnitsIndicator.java
altosuilib/AltosUIVoltageIndicator.java
altosuilib/AltosUSBDevice.java
altosuilib/AltosVoice.java
altosuilib/GrabNDrag.java
altosuilib/OSXAdapter.java
ao-bringup/cal-freq
ao-bringup/test-telemega
ao-bringup/turnon_chaoskey [new file with mode: 0755]
ao-tools/Makefile.am
ao-tools/ao-chaosread/.gitignore [new file with mode: 0644]
ao-tools/ao-chaosread/Makefile.am [new file with mode: 0644]
ao-tools/ao-chaosread/ao-chaosread.1 [new file with mode: 0644]
ao-tools/ao-chaosread/ao-chaosread.c [new file with mode: 0644]
ao-tools/ao-dump-up/ao-dump-up.c
ao-tools/ao-makebin/Makefile.am [new file with mode: 0644]
ao-tools/ao-makebin/ao-makebin.1 [new file with mode: 0644]
ao-tools/ao-makebin/ao-makebin.c [new file with mode: 0644]
ao-tools/lib/Makefile.am
ao-tools/lib/ao-dfu.c [new file with mode: 0644]
ao-tools/lib/ao-dfu.h [new file with mode: 0644]
ao-tools/lib/ao-elf.c
ao-tools/lib/ao-hex.c
ao-tools/lib/ao-hex.h
configure.ac
doc/Makefile
doc/altosdroid.inc
doc/altusmetrum-docinfo.xml
doc/easymini-docinfo.xml
doc/easymini-release-notes.inc
doc/release-notes-1.6.3.inc [new file with mode: 0644]
doc/release-notes.inc
doc/telegps-release-notes.inc
doc/usage.inc
libaltos/Makefile-standalone
libaltos/Makefile.am
libaltos/libaltos.c [deleted file]
libaltos/libaltos.dylib
libaltos/libaltos_common.c [new file with mode: 0644]
libaltos/libaltos_darwin.c [new file with mode: 0644]
libaltos/libaltos_linux.c [new file with mode: 0644]
libaltos/libaltos_posix.c [new file with mode: 0644]
libaltos/libaltos_posix.h [new file with mode: 0644]
libaltos/libaltos_private.h [new file with mode: 0644]
libaltos/libaltos_windows.c [new file with mode: 0644]
micropeak/MicroData.java
micropeak/MicroDataPoint.java
micropeak/MicroDeviceDialog.java
micropeak/MicroDownload.java
micropeak/MicroExport.java
micropeak/MicroFile.java
micropeak/MicroFileChooser.java
micropeak/MicroFrame.java
micropeak/MicroGraph.java
micropeak/MicroPeak.java
micropeak/MicroRaw.java
micropeak/MicroSave.java
micropeak/MicroSerial.java
micropeak/MicroSerialLog.java
micropeak/MicroStats.java
micropeak/MicroStatsTable.java
micropeak/MicroUSB.java
micropeak/micropeak-windows.nsi.in
src/Makefile
src/cc1111/ao_arch_funcs.h
src/chaoskey-v0.1/Makefile
src/chaoskey-v0.1/ao_pins.h
src/chaoskey-v1.0/.gitignore [new file with mode: 0644]
src/chaoskey-v1.0/Makefile [new file with mode: 0644]
src/chaoskey-v1.0/ao_chaoskey.c [new file with mode: 0644]
src/chaoskey-v1.0/ao_pins.h [new file with mode: 0644]
src/chaoskey-v1.0/flash-loader/.gitignore [new file with mode: 0644]
src/chaoskey-v1.0/flash-loader/Makefile [new file with mode: 0644]
src/chaoskey-v1.0/flash-loader/ao_pins.h [new file with mode: 0644]
src/detherm/.gitignore [new file with mode: 0644]
src/detherm/Makefile [new file with mode: 0644]
src/detherm/ao_detherm.c [new file with mode: 0644]
src/detherm/ao_pins.h [new file with mode: 0644]
src/detherm/flash-loader/.gitignore [new file with mode: 0644]
src/detherm/flash-loader/Makefile [new file with mode: 0644]
src/detherm/flash-loader/ao_pins.h [new file with mode: 0644]
src/drivers/ao_button.c
src/drivers/ao_cc1200.c
src/drivers/ao_event.c
src/drivers/ao_event.h
src/drivers/ao_lco_two.c [new file with mode: 0644]
src/drivers/ao_ms5607.c
src/drivers/ao_packet_master.c
src/drivers/ao_pad.c
src/drivers/ao_servo.c [new file with mode: 0644]
src/drivers/ao_servo.h [new file with mode: 0644]
src/drivers/ao_trng_send.c
src/easymega-v1.0/ao_pins.h
src/kernel/ao.h
src/kernel/ao_config.c
src/kernel/ao_config.h
src/kernel/ao_data.h
src/kernel/ao_fast_timer.h [new file with mode: 0644]
src/kernel/ao_flight.c
src/kernel/ao_log.h
src/kernel/ao_log_mini.c
src/kernel/ao_panic.c
src/kernel/ao_power.c [new file with mode: 0644]
src/kernel/ao_power.h [new file with mode: 0644]
src/kernel/ao_product.c
src/kernel/ao_task.c
src/kernel/ao_task.h
src/kernel/ao_usb.h
src/lpc/ao_arch_funcs.h
src/lpc/ao_fast_timer_lpc.c [new file with mode: 0644]
src/lpc/ao_timer_lpc.c
src/lpc/lpc.h
src/lpc/registers.ld
src/stm/ao_arch.h
src/stm/ao_arch_funcs.h
src/stm/ao_fast_timer.h [deleted file]
src/stm/ao_serial_stm.c
src/stm/ao_timer.c
src/stm/stm32l.h
src/stmf0/Makefile-flash.defs
src/stmf0/ao_adc_fast.c
src/stmf0/ao_arch.h
src/stmf0/ao_arch_funcs.h
src/stmf0/ao_dma_stm.c
src/stmf0/ao_exti.h
src/stmf0/ao_exti_stm.c [new file with mode: 0644]
src/stmf0/ao_gpio.c [new file with mode: 0644]
src/stmf0/ao_pwm.c [new file with mode: 0644]
src/stmf0/ao_spi_stm.c [new file with mode: 0644]
src/stmf0/ao_timer.c
src/stmf0/ao_usb_stm.c
src/stmf0/registers.ld
src/stmf0/stm32f0.h
src/telebt-v3.0/ao_pins.h
src/telebt-v3.0/ao_telebt.c
src/telefire-v0.1/ao_pins.h
src/telefiretwo-v0.1/.gitignore [new file with mode: 0644]
src/telefiretwo-v0.1/Makefile [new file with mode: 0644]
src/telefiretwo-v0.1/ao_pins.h [new file with mode: 0644]
src/telefiretwo-v0.1/ao_telefiretwo.c [new file with mode: 0644]
src/telefiretwo-v0.1/flash-loader/.gitignore [new file with mode: 0644]
src/telefiretwo-v0.1/flash-loader/Makefile [new file with mode: 0644]
src/telefiretwo-v0.1/flash-loader/ao_pins.h [new file with mode: 0644]
src/telefiretwo-v0.2/.gitignore [new file with mode: 0644]
src/telefiretwo-v0.2/Makefile [new file with mode: 0644]
src/telefiretwo-v0.2/ao_pins.h [new file with mode: 0644]
src/telefiretwo-v0.2/ao_telefiretwo.c [new file with mode: 0644]
src/telefiretwo-v0.2/flash-loader/.gitignore [new file with mode: 0644]
src/telefiretwo-v0.2/flash-loader/Makefile [new file with mode: 0644]
src/telefiretwo-v0.2/flash-loader/ao_pins.h [new file with mode: 0644]
src/telelco-v0.2/Makefile
src/telelco-v0.3/Makefile
src/telelcotwo-v0.1/.gitignore [new file with mode: 0644]
src/telelcotwo-v0.1/Makefile [new file with mode: 0644]
src/telelcotwo-v0.1/ao_pins.h [new file with mode: 0644]
src/telelcotwo-v0.1/ao_telelcotwo.c [new file with mode: 0644]
src/telelcotwo-v0.1/flash-loader/Makefile [new file with mode: 0644]
src/telelcotwo-v0.1/flash-loader/ao_pins.h [new file with mode: 0644]
src/telemega-v0.1/ao_pins.h
src/telemega-v1.0/ao_pins.h
src/telemega-v2.0/ao_pins.h
src/test/plotem [new file with mode: 0755]
telegps/TeleGPS.java
telegps/TeleGPSConfig.java
telegps/TeleGPSConfigUI.java
telegps/TeleGPSDisplayThread.java
telegps/TeleGPSGraphUI.java
telegps/TeleGPSInfo.java
telegps/TeleGPSPreferences.java
telegps/TeleGPSState.java
telegps/TeleGPSStatus.java
telegps/TeleGPSStatusUpdate.java

index e4b9664b4c39c7b520de6bf68e595b8bcb6a17d8..0bb01619603f3974703cb306221fe18808b370f4 100644 (file)
@@ -38,9 +38,13 @@ fat_windows = \
        telegps/TeleGPS-Windows-$(VERSION_DASH).exe \
        micropeak/MicroPeak-Windows-$(VERSION_DASH).exe
 
+fat_android = \
+       altosdroid/bin/AltosDroid-debug.apk \
+       altosdroid/bin/AltosDroid-release.apk
+
 keithp-fat: fat
        ssh keithp.com mkdir -p public_html/altos-$(VERSION)
-       scp -p $(fat_linux) $(fat_mac) $(fat_windows) keithp.com:public_html/altos-$(VERSION)
+       scp -p $(fat_linux) $(fat_mac) $(fat_windows) $(fat_android) keithp.com:public_html/altos-$(VERSION)
 
 set-java-versions:
        $(top_srcdir)/fix-java-versions org.altusmetrum.altoslib=$(ALTOSLIB_VERSION) org.altusmetrum.altosuilib=$(ALTOSUILIB_VERSION)
index a570645a860ab67252902115ca349ce33c9f3a03..fd5227978b4f821cc828ec64e2180a90bd1b83ef 100644 (file)
--- a/Releasing
+++ b/Releasing
@@ -74,6 +74,7 @@ These are Bdale's notes on how to do a release.
           src/teledongle-v3.0/*.elf \
           src/telegps-v1.0/*.elf \
           src/telemega-v1.0/*.elf \
+          src/telemega-v2.0/*.elf \
           src/telemetrum-v2.0/*.elf \
           ~/altusmetrumllc/Binaries/
        cp src/easymega-v1.0/flash-loader/*.elf \
@@ -82,6 +83,7 @@ These are Bdale's notes on how to do a release.
           src/teledongle-v3.0/flash-loader/*.elf \
           src/telegps-v1.0/flash-loader/*.elf \
           src/telemega-v1.0/flash-loader/*.elf \
+          src/telemega-v2.0/flash-loader/*.elf \
           src/telemetrum-v2.0/flash-loader/*.elf \
           ~/altusmetrumllc/Binaries/loaders/
        (cd ~/altusmetrumllc ; git add Binaries ; git commit -a) 
index 7f0858eafbaefc752503fb6f4e89da24ca3ac5cc..cf7ad5a8bea9e5c8321dee3b62fb4740450b9353 100644 (file)
@@ -5,3 +5,4 @@ libs
 google-play-services_lib
 src/org/altusmetrum/AltosDroid/BuildInfo.java
 res/drawable/*led.png
+AndroidManifest.xml
index 2403579642957d4af2cb195fa84e0a2e92c83790..2644d747917480b274aa1a96f7ae5feae578ae99 100644 (file)
@@ -39,7 +39,7 @@
     <uses-permission android:name="org.altusmetrum.AltosDroid.permission.MAPS_RECEIVE"/>
 
     <!-- Permissions needed to access USB OTG -->
-    <uses-feature android:name="android.hardware.usb.host" />
+    <uses-feature android:name="android.hardware.usb.host" android:required="false" />
 
     <application android:label="@string/app_name"
                  android:icon="@drawable/app_icon"
                   android:theme="@android:style/Theme.Dialog"
                   android:configChanges="orientation|keyboardHidden" />
 
+        <activity android:name=".IdleModeActivity"
+                  android:label="@string/idle_mode"
+                  android:theme="@android:style/Theme.Dialog"
+                  android:configChanges="orientation|keyboardHidden" />
+
+        <activity android:name=".IgniterActivity"
+                  android:label="@string/igniters"
+                  android:theme="@android:style/Theme.Dialog"
+                  android:configChanges="orientation|keyboardHidden" />
+
+       <activity android:name=".SetupActivity"
+                 android:label="@string/setup"
+                  android:theme="@android:style/Theme.Dialog"
+                  android:configChanges="orientation" />
+                 
+       <activity android:name=".ManageFrequenciesActivity"
+                 android:label="@string/manage_frequencies"
+                  android:theme="@android:style/Theme.Dialog"
+                  android:configChanges="orientation|keyboard" />
+                 
         <service android:name=".TelemetryService" />
 
         <meta-data android:name="com.google.android.maps.v2.API_KEY"
-                   android:value="AIzaSyDSr6u4i9TJmVGhgGk4g0wUUhTy9FGyn0s"/>
+                   android:value="@GOOGLEKEY@"/>
         <meta-data android:name="com.google.android.gms.version"
                    android:value="@integer/google_play_services_version" />
     </application>
index 26e14ee7edaa5879525d0f6ffec72267243aa300..295abbc57347ca611fafe3b5890020b03fe2392e 100644 (file)
@@ -47,7 +47,7 @@ DRAWABLES=\
 LAYOUTS=$(LAYOUT_DIR)/*.xml
 MENUS=$(MENU_DIR)/*.xml
 VALUES=$(VALUES_DIR)/*.xml
-XMLS=$(XML_DIR)/*.xml
+XMLS=$(XML_DIR)/*.xml AndroidManifest.xml
 
 RES=$(LAYOUTS) $(MENUS) $(VALUES) $(XMLS)
 
index bf295e4c5e0fc8eba7a146cefb66c8d1902d78c5..57e5501e1aaecb886c95cf64f0586aad719fb782 100644 (file)
@@ -1,17 +1,21 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!--
 
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
+ Copyright © 2016 Keith Packard <keithp@keithp.com>
 
-          http://www.apache.org/licenses/LICENSE-2.0
+ 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.
 
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
 -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="vertical"
diff --git a/altosdroid/res/layout/frequency.xml b/altosdroid/res/layout/frequency.xml
new file mode 100644 (file)
index 0000000..7f8d404
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright © 2016 Keith Packard <keithp@keithp.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; 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.
+
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="horizontal"
+    >
+  <TextView
+      android:id="@+id/frequency"
+      android:layout_width="wrap_content"
+      android:layout_height="fill_parent"
+      android:padding="10dp"
+      android:layout_weight="1"
+      />
+</LinearLayout>
diff --git a/altosdroid/res/layout/idle_mode.xml b/altosdroid/res/layout/idle_mode.xml
new file mode 100644 (file)
index 0000000..d6a05fb
--- /dev/null
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright © 2016 Keith Packard <keithp@keithp.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; 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.
+
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    >
+      <TextView android:id="@+id/set_callsign_label"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:text="@string/set_callsign_label"
+               />
+      <EditText android:id="@+id/set_callsign"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:hint="@string/set_callsign_label"/>
+      <Button android:id="@+id/connect_idle"
+              android:layout_width="match_parent"
+              android:layout_height="wrap_content"
+              android:text="@string/connect_idle"
+             />
+      <Button android:id="@+id/disconnect_idle"
+              android:layout_width="match_parent"
+              android:layout_height="wrap_content"
+              android:text="@string/disconnect_idle"
+             />
+      <Button android:id="@+id/reboot_idle"
+              android:layout_width="match_parent"
+              android:layout_height="wrap_content"
+              android:text="@string/reboot_idle"
+             />
+      <Button android:id="@+id/igniters_idle"
+              android:layout_width="match_parent"
+              android:layout_height="wrap_content"
+              android:text="@string/igniters_idle"
+             />
+</LinearLayout>
diff --git a/altosdroid/res/layout/igniter_status.xml b/altosdroid/res/layout/igniter_status.xml
new file mode 100644 (file)
index 0000000..298f915
--- /dev/null
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright © 2016 Keith Packard <keithp@keithp.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; 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.
+
+-->
+<RelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+  <TextView
+      android:id="@+id/igniter_status"
+      android:layout_width="wrap_content"
+      android:layout_height="fill_parent"
+      android:padding="10dp"
+      android:layout_alignParentRight="true"
+      />
+  <TextView
+      android:id="@+id/igniter_name"
+      android:layout_width="fill_parent"
+      android:layout_height="fill_parent"  
+      android:padding="10dp"
+      android:layout_alignParentLeft="@+id/igniter_status"
+      />
+</RelativeLayout>
diff --git a/altosdroid/res/layout/igniters.xml b/altosdroid/res/layout/igniters.xml
new file mode 100644 (file)
index 0000000..350a1e5
--- /dev/null
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright © 2016 Keith Packard <keithp@keithp.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; 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.
+
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    >
+
+    <ListView android:id="@+id/igniters"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+       android:fadeScrollbars="false"
+       android:scrollbars="vertical"
+       android:choiceMode="singleChoice"
+       />
+
+    <ToggleButton android:id="@+id/igniter_arm"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:textOn="@string/igniter_armed"
+            android:textOff="@string/igniter_arm"
+           />
+    
+    <Button android:id="@+id/igniter_fire"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/igniter_fire"
+           />
+    
+</LinearLayout>
diff --git a/altosdroid/res/layout/manage_frequencies.xml b/altosdroid/res/layout/manage_frequencies.xml
new file mode 100644 (file)
index 0000000..77ded1d
--- /dev/null
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright © 2016 Keith Packard <keithp@keithp.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; 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.
+
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    >
+
+    <LinearLayout
+       xmlns:android="http://schemas.android.com/apk/res/android"
+       android:id="@+id/set_layout"
+       android:layout_width="fill_parent"
+       android:layout_height="wrap_content"
+       android:orientation="horizontal"
+       >
+      <EditText
+         android:id="@+id/set_frequency"
+         android:layout_width="wrap_content"
+         android:layout_height="fill_parent"
+         android:padding="10dp"
+         android:layout_weight="1"
+         android:hint="@string/frequency"
+         android:inputType="number|numberDecimal"/>
+      />
+      <TextView
+         android:id="@+id/mhz"
+         android:layout_width="wrap_content"
+         android:layout_height="fill_parent"
+         android:padding="10dp"
+         android:layout_weight="0"
+         android:text="@string/mhz"
+         />
+      <EditText
+         android:id="@+id/set_description"
+         android:layout_width="wrap_content"
+         android:layout_height="fill_parent"  
+         android:padding="10dp"
+         android:layout_weight="2"
+         android:hint="@string/description"
+         />
+    </LinearLayout>
+    <LinearLayout
+       android:orientation="horizontal"
+       android:layout_width="match_parent"
+       android:layout_height="wrap_content"
+       >
+      <Button android:id="@+id/set"
+              android:layout_width="wrap_content"
+              android:layout_height="wrap_content"
+              android:text="@string/set"
+             android:layout_weight="1"
+             />
+      
+      <Button android:id="@+id/remove"
+              android:layout_width="wrap_content"
+              android:layout_height="wrap_content"
+              android:text="@string/remove"
+             android:layout_weight="1"
+             />
+      
+      <Button android:id="@+id/done"
+              android:layout_width="wrap_content"
+              android:layout_height="wrap_content"
+              android:text="@string/done"
+             android:layout_weight="1"
+             />
+    </LinearLayout>
+
+    <ListView android:id="@+id/frequencies"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+       android:fadeScrollbars="false"
+       android:scrollbars="vertical"
+       android:choiceMode="singleChoice"
+       />
+
+    
+</LinearLayout>
diff --git a/altosdroid/res/layout/setup.xml b/altosdroid/res/layout/setup.xml
new file mode 100644 (file)
index 0000000..630378a
--- /dev/null
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright © 2016 Keith Packard <keithp@keithp.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; 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.
+
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    >
+  <TableLayout
+      xmlns:android="http://schemas.android.com/apk/res/android"
+      android:stretchColumns="2,3"
+      android:layout_weight="0"
+      android:layout_width="fill_parent"
+      android:layout_height="wrap_content">
+
+    <TableRow
+       android:layout_gravity="center"
+       android:layout_weight="1"
+       android:padding="2dip"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content">
+      <TextView
+         android:id="@+id/select_rate_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text="@string/telemetry_rate"
+         />
+      <Spinner android:id="@+id/select_rate"
+              android:layout_width="fill_parent"
+              android:layout_height="wrap_content"
+              android:prompt="@string/telemetry_rate"
+              android:spinnerMode="dropdown"
+              />
+    </TableRow>
+    <TableRow
+       android:layout_gravity="center"
+       android:layout_weight="1"
+       android:padding="2dip"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content">
+      <TextView
+         android:id="@+id/set_units_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text="@string/set_units"
+         />
+      <Spinner android:id="@+id/set_units"
+              android:layout_width="fill_parent"
+              android:layout_height="wrap_content"
+              android:prompt="@string/set_units"
+              android:spinnerMode="dropdown"
+              />
+    </TableRow>
+    <TableRow
+       android:layout_gravity="center"
+       android:layout_weight="1"
+       android:padding="2dip"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content">
+      <TextView
+         android:id="@+id/map_type_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text="@string/map_type"
+         />
+      <Spinner android:id="@+id/map_type"
+              android:layout_width="fill_parent"
+              android:layout_height="wrap_content"
+              android:prompt="@string/map_type"
+              android:spinnerMode="dropdown"
+              />
+    </TableRow>
+    <TableRow
+       android:layout_gravity="center"
+       android:layout_weight="1"
+       android:padding="2dip"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content">
+      <TextView
+         android:id="@+id/map_source_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text="@string/map_source"
+         />
+      <Spinner android:id="@+id/map_source"
+              android:layout_width="fill_parent"
+              android:layout_height="wrap_content"
+              android:prompt="@string/map_source"
+              android:spinnerMode="dropdown"
+              />
+    </TableRow>
+  </TableLayout>
+  <Button android:id="@+id/preload_maps"
+          android:layout_width="match_parent"
+          android:layout_height="wrap_content"
+         android:text="@string/preload_maps"
+         />
+  <Button android:id="@+id/manage_frequencies"
+          android:layout_width="match_parent"
+          android:layout_height="wrap_content"
+         android:text="@string/manage_frequencies"
+         />
+  <Button android:id="@+id/done"
+          android:layout_width="match_parent"
+          android:layout_height="wrap_content"
+         android:text="@string/done"
+         />
+</LinearLayout>
index 7e08c80333c30a3c8958f52533e4cb8d9a68fe00..b2ca01a4c33f9acbb79eb30d190331dcf49e6b67 100644 (file)
     <item android:id="@+id/select_freq"
           android:icon="@android:drawable/ic_menu_preferences"
           android:title="@string/select_freq" />
-    <item android:id="@+id/select_rate"
-          android:icon="@android:drawable/ic_menu_preferences"
-          android:title="@string/select_rate" />
-    <item android:id="@+id/change_units"
-         android:icon="@android:drawable/ic_menu_view"
-         android:title="@string/change_units" />
-    <item android:id="@+id/preload_maps"
-         android:icon="@android:drawable/ic_menu_mapmode"
-         android:title="@string/preload_maps" />
-    <item android:id="@+id/map_type"
-         android:icon="@android:drawable/ic_menu_mapmode"
-         android:title="@string/map_type" />
-    <item android:id="@+id/map_source"
-         android:icon="@android:drawable/ic_menu_mapmode"
-         android:title="@string/map_source" />
+
     <item android:id="@+id/select_tracker"
          android:icon="@android:drawable/ic_menu_view"
          android:title="@string/select_tracker"/>
     <item android:id="@+id/delete_track"
          android:icon="@android:drawable/ic_notification_clear_all"
          android:title="@string/delete_track"/>
+
+    <item android:id="@+id/setup"
+          android:icon="@android:drawable/ic_menu_preferences"
+          android:title="@string/setup" />
+    <item android:id="@+id/idle_mode"
+          android:icon="@android:drawable/ic_menu_preferences"
+          android:title="@string/idle_mode" />
+
     <item android:id="@+id/quit"
           android:icon="@android:drawable/ic_menu_close_clear_cancel"
           android:title="@string/quit" />
index e7014fc934db5f76555d064c2f9ff6ce2cf65083..4380d62da413a1774507521a487f01394ae6bd03 100644 (file)
@@ -29,6 +29,7 @@
        <string name="connect_device">Connect a device</string>
        <string name="disconnect_device">Disconnect device</string>
        <string name="quit">Quit</string>
+       <string name="setup">Setup</string>
        <string name="select_freq">Select radio frequency</string>
        <string name="select_rate">Select data rate</string>
        <string name="change_units">Change units</string>
        <string name="preload_radius">Radius</string>
        
        <string name="preload_load">Load Map</string>
+
+       <!-- Idle mode -->
+       <string name="idle_mode">Idle Mode</string>
+       <string name="set_callsign_label">Callsign</string>
+       <string name="connect_idle">Monitor</string>
+       <string name="disconnect_idle">Disconnect</string>
+       <string name="reboot_idle">Reboot</string>
+       <string name="igniters_idle">Fire Igniters</string>
+
+       <!-- igniters -->
+       <string name="igniters">Igniters</string>
+       <string name="igniter_arm">Arm</string>
+       <string name="igniter_armed">Armed</string>
+       <string name="igniter_fire">Fire</string>
+       
+       <!-- setup -->
+       <string name="telemetry_rate">Telemetry Rate</string>
+       <string name="set_units">Units</string>
+       <string name="map_type">Map Type</string>
+       <string name="map_source">Map Source</string>
+       <string name="preload_maps">Preload Maps</string>
+       <string name="manage_frequencies">Manage Frequencies</string>
+       <string name="done">OK</string>
+       
+       <!-- manage frequencies -->
+       <string name="set">Set</string>
+       <string name="mhz">MHz</string>
+       <string name="remove">Remove</string>
+       <string name="done">OK</string>
+       <string name="frequency">Frequency</string>
+       <string name="description">Description</string>
 </resources>
index baf38fb71aa854a24a24a30abac96c3eddd61182..15efc0e2a72294765626ce97fa5ace879f4b8702 100644 (file)
@@ -30,7 +30,7 @@ import android.bluetooth.BluetoothSocket;
 import android.os.Handler;
 //import android.os.Message;
 
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public class AltosBluetooth extends AltosDroidLink {
 
index df348c9d9aa65da09ced454a72f0671891ebc463..64980dc7af020ded43140768249b2ec14d59aafb 100644 (file)
@@ -20,7 +20,7 @@ import java.util.Arrays;
 import java.io.*;
 import java.lang.*;
 
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 import android.app.Activity;
 import android.graphics.*;
index b26a9bc8d5f56e9d455f459fa74c0a857564ce9b..026e836df1e4f8c10038f0bb1879ad84b5089643 100644 (file)
@@ -45,13 +45,15 @@ import android.view.*;
 import android.widget.*;
 import android.app.AlertDialog;
 import android.location.Location;
+import android.location.LocationManager;
+import android.location.LocationListener;
 import android.hardware.usb.*;
 import android.graphics.*;
 import android.graphics.drawable.*;
 
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
-public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
+public class AltosDroid extends FragmentActivity implements AltosUnitsListener, LocationListener {
 
        // Actions sent to the telemetry server at startup time
 
@@ -62,14 +64,26 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
 
        public static final int MSG_STATE           = 1;
        public static final int MSG_UPDATE_AGE      = 2;
+       public static final int MSG_IDLE_MODE       = 3;
+       public static final int MSG_IGNITER_STATUS  = 4;
 
        // Intent request codes
        public static final int REQUEST_CONNECT_DEVICE = 1;
        public static final int REQUEST_ENABLE_BT      = 2;
        public static final int REQUEST_PRELOAD_MAPS   = 3;
-       public static final int REQUEST_MAP_TYPE       = 4;
+       public static final int REQUEST_IDLE_MODE      = 5;
+       public static final int REQUEST_IGNITERS       = 6;
+       public static final int REQUEST_SETUP          = 7;
 
-       public int map_type = AltosMap.maptype_hybrid;
+       public static final String EXTRA_IDLE_MODE = "idle_mode";
+       public static final String EXTRA_IDLE_RESULT = "idle_result";
+       public static final String EXTRA_TELEMETRY_SERVICE = "telemetry_service";
+
+       // Setup result bits
+       public static final int SETUP_BAUD = 1;
+       public static final int SETUP_UNITS = 2;
+       public static final int SETUP_MAP_SOURCE = 4;
+       public static final int SETUP_MAP_TYPE = 8;
 
        public static FragmentManager   fm;
 
@@ -95,8 +109,9 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
        // field to display the version at the bottom of the screen
        private TextView mVersion;
 
-       private double frequency;
-       private int telemetry_rate;
+       private boolean idle_mode = false;
+
+       public Location location = null;
 
        // Tabs
        TabHost         mTabHost;
@@ -142,6 +157,10 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
                        case MSG_UPDATE_AGE:
                                ad.update_age();
                                break;
+                       case MSG_IDLE_MODE:
+                               ad.idle_mode = (Boolean) msg.obj;
+                               ad.update_state(null);
+                               break;
                        }
                }
        };
@@ -212,8 +231,8 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
                switch (telemetry_state.connect) {
                case TelemetryState.CONNECT_CONNECTED:
                        if (telemetry_state.config != null) {
-                               String str = String.format("S/N %d %6.3f MHz", telemetry_state.config.serial,
-                                                          telemetry_state.frequency);
+                               String str = String.format("S/N %d %6.3f MHz%s", telemetry_state.config.serial,
+                                                          telemetry_state.frequency, idle_mode ? " (idle)" : "");
                                if (telemetry_state.telemetry_rate != AltosLib.ao_telemetry_rate_38400)
                                        str = str.concat(String.format(" %d bps",
                                                                       AltosLib.ao_telemetry_rate_values[telemetry_state.telemetry_rate]));
@@ -314,7 +333,7 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
                                state = newest_state;
                }
 
-               update_ui(telemetry_state, state, telemetry_state.location);
+               update_ui(telemetry_state, state);
 
                start_timer();
        }
@@ -379,7 +398,7 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
                }
        }
 
-       void update_ui(TelemetryState telem_state, AltosState state, Location location) {
+       void update_ui(TelemetryState telem_state, AltosState state) {
 
                int prev_state = AltosLib.ao_flight_invalid;
 
@@ -440,7 +459,10 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
                                mCallsignView.setText(state.callsign);
                        }
                        if (saved_state == null || state.serial != saved_state.serial) {
-                               mSerialView.setText(String.format("%d", state.serial));
+                               if (state.serial == AltosLib.MISSING)
+                                       mSerialView.setText("");
+                               else
+                                       mSerialView.setText(String.format("%d", state.serial));
                        }
                        if (saved_state == null || state.flight != saved_state.flight) {
                                if (state.flight == AltosLib.MISSING)
@@ -457,7 +479,10 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
                                }
                        }
                        if (saved_state == null || state.rssi != saved_state.rssi) {
-                               mRSSIView.setText(String.format("%d", state.rssi));
+                               if (state.rssi == AltosLib.MISSING)
+                                       mRSSIView.setText("");
+                               else
+                                       mRSSIView.setText(String.format("%d", state.rssi));
                        }
                }
 
@@ -510,11 +535,6 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
                return tab_view;
        }
 
-       public void set_map_source(int source) {
-               for (AltosDroidTab mTab : mTabs)
-                       mTab.set_map_source(source);
-       }
-
        @Override
        public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
@@ -560,22 +580,15 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
                mAgeOldColor   = getResources().getColor(R.color.old_color);
        }
 
-       private boolean ensureBluetooth() {
+       private void ensureBluetooth() {
                // Get local Bluetooth adapter
                mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
 
-               // If the adapter is null, then Bluetooth is not supported
-               if (mBluetoothAdapter == null) {
-                       Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();
-                       return false;
-               }
-
-               if (!mBluetoothAdapter.isEnabled()) {
+               /* if there is a BT adapter and it isn't turned on, then turn it on */
+               if (mBluetoothAdapter != null && !mBluetoothAdapter.isEnabled()) {
                        Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                        startActivityForResult(enableIntent, AltosDroid.REQUEST_ENABLE_BT);
                }
-
-               return true;
        }
 
        private boolean check_usb() {
@@ -641,9 +654,7 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
                                        return;
                        }
                        AltosDebug.debug("Starting by looking for bluetooth devices");
-                       if (ensureBluetooth())
-                               return;
-                       finish();
+                       ensureBluetooth();
                }
        }
 
@@ -679,12 +690,27 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
        public void onResume() {
                super.onResume();
                AltosDebug.debug("+ ON RESUME +");
+
+               // Listen for GPS and Network position updates
+               LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
+               locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, this);
+
+               location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
+
+               if (location != null)
+                       AltosDebug.debug("Resume, location is %f,%f\n",
+                                        location.getLatitude(),
+                                        location.getLongitude());
+
+               update_ui(telemetry_state, saved_state);
        }
 
        @Override
        public void onPause() {
                super.onPause();
                AltosDebug.debug("- ON PAUSE -");
+               // Stop listening for location updates
+               ((LocationManager) getSystemService(Context.LOCATION_SERVICE)).removeUpdates(this);
        }
 
        @Override
@@ -720,19 +746,46 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
                        if (resultCode == Activity.RESULT_OK) {
                                // Bluetooth is now enabled, so set up a chat session
                                //setupChat();
+                               AltosDebug.debug("BT enabled");
+                               bluetoothEnabled(data);
                        } else {
                                // User did not enable Bluetooth or an error occured
-                               AltosDebug.error("BT not enabled");
-                               stopService(new Intent(AltosDroid.this, TelemetryService.class));
-                               Toast.makeText(this, R.string.bt_not_enabled, Toast.LENGTH_SHORT).show();
-                               finish();
+                               AltosDebug.debug("BT not enabled");
                        }
                        break;
-               case REQUEST_MAP_TYPE:
+               case REQUEST_IDLE_MODE:
                        if (resultCode == Activity.RESULT_OK)
-                               set_map_type(data);
+                               idle_mode(data);
+                       break;
+               case REQUEST_IGNITERS:
                        break;
+               case REQUEST_SETUP:
+                       if (resultCode == Activity.RESULT_OK)
+                               note_setup_changes(data);
+                       break;
+               }
+       }
+
+       private void note_setup_changes(Intent data) {
+               int changes = data.getIntExtra(SetupActivity.EXTRA_SETUP_CHANGES, 0);
+
+               if ((changes & SETUP_BAUD) != 0) {
+                       try {
+                               mService.send(Message.obtain(null, TelemetryService.MSG_SETBAUD,
+                                                            AltosPreferences.telemetry_rate(1)));
+                       } catch (RemoteException re) {
+                       }
+               }
+               if ((changes & SETUP_UNITS) != 0) {
+                       /* nothing to do here */
+               }
+               if ((changes & SETUP_MAP_SOURCE) != 0) {
+                       /* nothing to do here */
                }
+               if ((changes & SETUP_MAP_TYPE) != 0) {
+                       /* nothing to do here */
+               }
+               set_switch_time();
        }
 
        private void connectUsb(UsbDevice device) {
@@ -749,6 +802,14 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
                }
        }
 
+       private void bluetoothEnabled(Intent data) {
+               try {
+                       mService.send(Message.obtain(null, TelemetryService.MSG_BLUETOOTH_ENABLED, null));
+               } catch (RemoteException e) {
+                       AltosDebug.debug("send BT enabled message failed");
+               }
+       }
+
        private void connectDevice(Intent data) {
                // Attempt to connect to the device
                try {
@@ -771,14 +832,37 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
                }
        }
 
-       private void set_map_type(Intent data) {
-               int type = data.getIntExtra(MapTypeActivity.EXTRA_MAP_TYPE, -1);
+       private void idle_mode(Intent data) {
+               int type = data.getIntExtra(IdleModeActivity.EXTRA_IDLE_RESULT, -1);
+               Message msg;
 
-               AltosDebug.debug("intent set_map_type %d\n", type);
-               if (type != -1) {
-                       map_type = type;
-                       for (AltosDroidTab mTab : mTabs)
-                               mTab.set_map_type(map_type);
+               AltosDebug.debug("intent idle_mode %d", type);
+               switch (type) {
+               case IdleModeActivity.IDLE_MODE_CONNECT:
+                       msg = Message.obtain(null, TelemetryService.MSG_MONITOR_IDLE_START);
+                       try {
+                               mService.send(msg);
+                       } catch (RemoteException re) {
+                       }
+                       break;
+               case IdleModeActivity.IDLE_MODE_DISCONNECT:
+                       msg = Message.obtain(null, TelemetryService.MSG_MONITOR_IDLE_STOP);
+                       try {
+                               mService.send(msg);
+                       } catch (RemoteException re) {
+                       }
+                       break;
+               case IdleModeActivity.IDLE_MODE_REBOOT:
+                       msg = Message.obtain(null, TelemetryService.MSG_REBOOT);
+                       try {
+                               mService.send(msg);
+                       } catch (RemoteException re) {
+                       }
+                       break;
+               case IdleModeActivity.IDLE_MODE_IGNITERS:
+                       Intent serverIntent = new Intent(this, IgniterActivity.class);
+                       startActivityForResult(serverIntent, REQUEST_IGNITERS);
+                       break;
                }
        }
 
@@ -797,11 +881,8 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
                }
        }
 
-       void setFrequency(String freq) {
-               try {
-                       setFrequency (AltosParse.parse_double_net(freq.substring(11, 17)));
-               } catch (ParseException e) {
-               }
+       void setFrequency(AltosFrequency frequency) {
+               setFrequency (frequency.frequency);
        }
 
        void setBaud(int baud) {
@@ -889,11 +970,10 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
                Intent serverIntent = null;
                switch (item.getItemId()) {
                case R.id.connect_scan:
-                       if (ensureBluetooth()) {
-                               // Launch the DeviceListActivity to see devices and do scan
-                               serverIntent = new Intent(this, DeviceListActivity.class);
-                               startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
-                       }
+                       ensureBluetooth();
+                       // Launch the DeviceListActivity to see devices and do scan
+                       serverIntent = new Intent(this, DeviceListActivity.class);
+                       startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
                        return true;
                case R.id.disconnect:
                        /* Disconnect the device
@@ -905,25 +985,21 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
                        disconnectDevice();
                        finish();
                        return true;
+               case R.id.setup:
+                       serverIntent = new Intent(this, SetupActivity.class);
+                       startActivityForResult(serverIntent, REQUEST_SETUP);
+                       return true;
                case R.id.select_freq:
                        // Set the TBT radio frequency
 
-                       final String[] frequencies = {
-                               "Channel 0 (434.550MHz)",
-                               "Channel 1 (434.650MHz)",
-                               "Channel 2 (434.750MHz)",
-                               "Channel 3 (434.850MHz)",
-                               "Channel 4 (434.950MHz)",
-                               "Channel 5 (435.050MHz)",
-                               "Channel 6 (435.150MHz)",
-                               "Channel 7 (435.250MHz)",
-                               "Channel 8 (435.350MHz)",
-                               "Channel 9 (435.450MHz)"
-                       };
+                       final AltosFrequency[] frequencies = AltosPreferences.common_frequencies();
+                       String[] frequency_strings = new String[frequencies.length];
+                       for (int i = 0; i < frequencies.length; i++)
+                               frequency_strings[i] = frequencies[i].toString();
 
                        AlertDialog.Builder builder_freq = new AlertDialog.Builder(this);
                        builder_freq.setTitle("Pick a frequency");
-                       builder_freq.setItems(frequencies,
+                       builder_freq.setItems(frequency_strings,
                                         new DialogInterface.OnClickListener() {
                                                 public void onClick(DialogInterface dialog, int item) {
                                                         setFrequency(frequencies[item]);
@@ -932,44 +1008,6 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
                        AlertDialog alert_freq = builder_freq.create();
                        alert_freq.show();
                        return true;
-               case R.id.select_rate:
-                       // Set the TBT baud rate
-
-                       final String[] rates = {
-                               "38400",
-                               "9600",
-                               "2400",
-                       };
-
-                       AlertDialog.Builder builder_rate = new AlertDialog.Builder(this);
-                       builder_rate.setTitle("Pick a baud rate");
-                       builder_rate.setItems(rates,
-                                        new DialogInterface.OnClickListener() {
-                                                public void onClick(DialogInterface dialog, int item) {
-                                                        setBaud(rates[item]);
-                                                }
-                                        });
-                       AlertDialog alert_rate = builder_rate.create();
-                       alert_rate.show();
-                       return true;
-               case R.id.change_units:
-                       boolean imperial = AltosPreferences.imperial_units();
-                       AltosPreferences.set_imperial_units(!imperial);
-                       return true;
-               case R.id.preload_maps:
-                       serverIntent = new Intent(this, PreloadMapActivity.class);
-                       startActivityForResult(serverIntent, REQUEST_PRELOAD_MAPS);
-                       return true;
-               case R.id.map_type:
-                       serverIntent = new Intent(this, MapTypeActivity.class);
-                       startActivityForResult(serverIntent, REQUEST_MAP_TYPE);
-                       return true;
-               case R.id.map_source:
-                       int source = AltosDroidPreferences.map_source();
-                       int new_source = source == AltosDroidPreferences.MAP_SOURCE_ONLINE ? AltosDroidPreferences.MAP_SOURCE_OFFLINE : AltosDroidPreferences.MAP_SOURCE_ONLINE;
-                       AltosDroidPreferences.set_map_source(new_source);
-                       set_map_source(new_source);
-                       return true;
                case R.id.select_tracker:
                        if (serials != null) {
                                String[] trackers = new String[serials.length+1];
@@ -1010,12 +1048,17 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
 
                        }
                        return true;
+               case R.id.idle_mode:
+                       serverIntent = new Intent(this, IdleModeActivity.class);
+                       serverIntent.putExtra(EXTRA_IDLE_MODE, idle_mode);
+                       startActivityForResult(serverIntent, REQUEST_IDLE_MODE);
+                       return true;
                }
                return false;
        }
 
        static String direction(AltosGreatCircle from_receiver,
-                            Location receiver) {
+                               Location receiver) {
                if (from_receiver == null)
                        return null;
 
@@ -1044,4 +1087,24 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
                else
                        return String.format("right %d°", iheading);
        }
+
+       public void onLocationChanged(Location location) {
+               this.location = location;
+               AltosDebug.debug("Location changed to %f,%f",
+                                location.getLatitude(),
+                                location.getLongitude());
+               update_ui(telemetry_state, saved_state);
+       }
+
+       public void onStatusChanged(String provider, int status, Bundle extras) {
+               AltosDebug.debug("Location status now %d\n", status);
+       }
+
+       public void onProviderEnabled(String provider) {
+               AltosDebug.debug("Location provider enabled %s\n", provider);
+       }
+
+       public void onProviderDisabled(String provider) {
+               AltosDebug.debug("Location provider disabled %s\n", provider);
+       }
 }
index 0e3511d3778c562264d4f53c656f0f226c642cb0..0fd9af75bf1f76302663eb7e30f98e665aaf6b4c 100644 (file)
@@ -24,7 +24,7 @@ import java.util.UUID;
 
 import android.os.Handler;
 
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public abstract class AltosDroidLink extends AltosLink {
 
@@ -170,8 +170,8 @@ public abstract class AltosDroidLink extends AltosLink {
                        }
                        buffer_off = 0;
                }
-               if (AltosDebug.D)
-                       debug_input(in_buffer[buffer_off]);
+//             if (AltosDebug.D)
+//                     debug_input(in_buffer[buffer_off]);
                return in_buffer[buffer_off++];
        }
 
@@ -207,10 +207,9 @@ public abstract class AltosDroidLink extends AltosLink {
 
        public void print(String data) {
                byte[] bytes = data.getBytes();
-               AltosDebug.debug("print(): begin");
+//             AltosDebug.debug(data.replace('\n', '\\'));
                for (byte b : bytes)
                        putchar(b);
-               AltosDebug.debug("print(): Wrote bytes: '" + data.replace('\n', '\\') + "'");
        }
 
        public AltosDroidLink(Handler handler) {
index 59f08c341e4f80f3ac7042c3b3c003f2edd4a0a9..43abef0fad6d92515550eb87e524f90d502436d8 100644 (file)
@@ -20,11 +20,13 @@ package org.altusmetrum.AltosDroid;
 import java.util.*;
 import java.io.*;
 import android.location.Location;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public interface AltosDroidMapInterface {
        public void onCreateView(AltosDroid altos_droid);
 
+       public void onDestroyView();
+
        public void set_visible(boolean visible);
 
        public void center(double lat, double lon, double accuracy);
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapSourceListener.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapSourceListener.java
new file mode 100644 (file)
index 0000000..e2775ef
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+public interface AltosDroidMapSourceListener {
+       public void map_source_changed(int map_source);
+}
index 02defbcb6aac4492d3d53ea423adc4604333eb7a..dd86c818b06b5822af48335ca465e23ec69c7fdf 100644 (file)
  */
 package org.altusmetrum.AltosDroid;
 
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
 import android.content.Context;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public class AltosDroidPreferences extends AltosPreferences {
 
@@ -65,12 +69,19 @@ public class AltosDroidPreferences extends AltosPreferences {
                }
        }
 
+       static LinkedList<AltosDroidMapSourceListener> map_source_listeners;
+
        public static void set_map_source(int map_source) {
                synchronized(backend) {
                        AltosDroidPreferences.map_source = map_source;
                        backend.putInt(mapSourcePreference, map_source);
                        flush_preferences();
                }
+               if (map_source_listeners != null) {
+                       for (AltosDroidMapSourceListener l : map_source_listeners) {
+                               l.map_source_changed(map_source);
+                       }
+               }
        }
 
        public static int map_source() {
@@ -78,4 +89,18 @@ public class AltosDroidPreferences extends AltosPreferences {
                        return map_source;
                }
        }
+
+       public static void register_map_source_listener(AltosDroidMapSourceListener l) {
+               synchronized(backend) {
+                       if (map_source_listeners == null)
+                               map_source_listeners = new LinkedList<AltosDroidMapSourceListener>();
+                       map_source_listeners.add(l);
+               }
+       }
+
+       public static void unregister_map_source_listener(AltosDroidMapSourceListener l) {
+               synchronized(backend) {
+                       map_source_listeners.remove(l);
+               }
+       }
 }
index 14e6ce73359ebbd099343ecf00d5bfaea339d991..5c7ec513eb19f78e55f5c3c670d97378094c87dd 100644 (file)
@@ -24,9 +24,9 @@ import android.content.SharedPreferences;
 import android.os.Environment;
 import android.util.*;
 
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
-public class AltosDroidPreferencesBackend implements AltosPreferencesBackend {
+public class AltosDroidPreferencesBackend extends AltosPreferencesBackend {
        public final static String        NAME    = "org.altusmetrum.AltosDroid";
        private Context                   context = null;
        private SharedPreferences         prefs   = null;
@@ -53,6 +53,8 @@ public class AltosDroidPreferencesBackend implements AltosPreferencesBackend {
        }
 
        public AltosPreferencesBackend node(String key) {
+               if (!nodeExists(key))
+                       putBoolean(key, true);
                return new AltosDroidPreferencesBackend(context, key);
        }
 
@@ -120,4 +122,8 @@ public class AltosDroidPreferencesBackend implements AltosPreferencesBackend {
        public File homeDirectory() {
                return Environment.getExternalStorageDirectory();
        }
+
+       public void debug(String format, Object ... arguments) {
+               AltosDebug.debug(format, arguments);
+       }
 }
index 792d06215bcb9ee08b38b1ed25393686558e206c..77dbbcb117935f96ae3cbfc5f4e62dfdcc1d4715 100644 (file)
@@ -17,7 +17,7 @@
 
 package org.altusmetrum.AltosDroid;
 
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 import android.location.Location;
 import android.app.Activity;
 import android.graphics.Color;
@@ -39,12 +39,6 @@ public abstract class AltosDroidTab extends Fragment implements AltosUnitsListen
 
        public abstract String tab_name();
 
-       public void set_map_type(int map_type) {
-       }
-
-       public void set_map_source(int map_source) {
-       }
-
        public void units_changed(boolean imperial_units) {
                if (!isHidden())
                        show(last_telem_state, last_state, last_from_receiver, last_receiver);
index 2875211050ebc21a436186ca5005b44e0c63cb53..ab142b175c43f4ba4a4e6d2cb23d46778bac835c 100644 (file)
@@ -20,7 +20,7 @@ package org.altusmetrum.AltosDroid;
 import java.util.*;
 import java.io.*;
 
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 import android.app.Activity;
 import android.graphics.*;
@@ -79,7 +79,7 @@ class Rocket implements Comparable {
        }
 }
 
-public class AltosMapOffline extends View implements ScaleGestureDetector.OnScaleGestureListener, AltosMapInterface, AltosDroidMapInterface {
+public class AltosMapOffline extends View implements ScaleGestureDetector.OnScaleGestureListener, AltosMapInterface, AltosDroidMapInterface, AltosMapTypeListener {
        ScaleGestureDetector    scale_detector;
        boolean                 scaling;
        AltosMap                map;
@@ -133,7 +133,7 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal
                        if (canvas.quickReject(pt.x, pt.y, pt.x + px_size, pt.y + px_size, Canvas.EdgeType.AA))
                                return;
 
-                       AltosImage              altos_image = cache.get(this, store, px_size, px_size);
+                       AltosImage              altos_image = this.get_image();
 
                        MapImage                map_image = (MapImage) altos_image;
 
@@ -150,8 +150,8 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal
                                if (t.has_location()) {
                                        String  message = null;
                                        switch (status) {
-                                       case AltosMapTile.loading:
-                                               message = "Loading...";
+                                       case AltosMapTile.fetching:
+                                               message = "Fetching...";
                                                break;
                                        case AltosMapTile.bad_request:
                                                message = "Internal error";
@@ -181,14 +181,14 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal
                        }
                }
 
-               public MapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
-                       super(listener, upper_left, center, zoom, maptype, px_size, 2);
+               public MapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
+                       super(cache, upper_left, center, zoom, maptype, px_size, 2);
                }
 
        }
 
-       public AltosMapTile new_tile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
-               return new MapTile(listener, upper_left, center, zoom, maptype, px_size);
+       public AltosMapTile new_tile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
+               return new MapTile(cache, upper_left, center, zoom, maptype, px_size);
        }
 
        public AltosMapPath new_path() {
@@ -441,6 +441,8 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal
        }
 
        public void show(TelemetryState telem_state, AltosState state, AltosGreatCircle from_receiver, Location receiver) {
+               boolean changed = false;
+
                if (state != null) {
                        map.show(state, null);
                        if (state.pad_lat != AltosLib.MISSING && pad == null)
@@ -479,14 +481,20 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal
                        }
                }
                if (receiver != null) {
-                       here = new AltosLatLon(receiver.getLatitude(), receiver.getLongitude());
+                       AltosLatLon new_here = new AltosLatLon(receiver.getLatitude(), receiver.getLongitude());
+                       if (!new_here.equals(here)) {
+                               here = new_here;
+                               AltosDebug.debug("Location changed, redraw");
+                               repaint();
+                       }
                }
        }
 
        public void onCreateView(AltosDroid altos_droid) {
                this.altos_droid = altos_droid;
                map = new AltosMap(this);
-               map.set_maptype(altos_droid.map_type);
+               AltosPreferences.register_map_type_listener(this);
+               map.set_maptype(AltosPreferences.map_type());
 
                pad_bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pad);
                /* arrow at the bottom of the launchpad image */
@@ -504,7 +512,11 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal
                here_off_y = here_bitmap.getHeight() / 2;
        }
 
-       public void set_map_type(int map_type) {
+       public void onDestroyView() {
+               AltosPreferences.unregister_map_type_listener(this);
+       }
+
+       public void map_type_changed(int map_type) {
                if (map != null)
                        map.set_maptype(map_type);
        }
index 1032709168fb8689706efa6b5ba870dccb89c107..fcdb930b4e688600df4bd9660227dc86c20f0887 100644 (file)
@@ -19,7 +19,7 @@ package org.altusmetrum.AltosDroid;
 
 import java.util.*;
 
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 import com.google.android.gms.maps.*;
 import com.google.android.gms.maps.model.*;
@@ -102,7 +102,7 @@ class RocketOnline implements Comparable {
        }
 }
 
-public class AltosMapOnline implements AltosDroidMapInterface, GoogleMap.OnMarkerClickListener, GoogleMap.OnMapClickListener {
+public class AltosMapOnline implements AltosDroidMapInterface, GoogleMap.OnMarkerClickListener, GoogleMap.OnMapClickListener, AltosMapTypeListener {
        public SupportMapFragment mMapFragment;
        private GoogleMap mMap;
        private boolean mapLoaded = false;
@@ -124,7 +124,8 @@ public class AltosMapOnline implements AltosDroidMapInterface, GoogleMap.OnMarke
 
        public void onCreateView(AltosDroid altos_droid) {
                this.altos_droid = altos_droid;
-               final int map_type = altos_droid.map_type;
+               final int map_type = AltosPreferences.map_type();
+               AltosPreferences.register_map_type_listener(this);
                mMapFragment = new SupportMapFragment() {
                        @Override
                        public void onActivityCreated(Bundle savedInstanceState) {
@@ -144,9 +145,9 @@ public class AltosMapOnline implements AltosDroidMapInterface, GoogleMap.OnMarke
                };
        }
 
-//     public void onActivityCreated() {
-//             getChildFragmentManager().beginTransaction().add(R.id.map, mMapFragment).commit();
-//     }
+       public void onDestroyView() {
+               AltosPreferences.unregister_map_type_listener(this);
+       }
 
        private double pixel_distance(LatLng a, LatLng b) {
                Projection projection = mMap.getProjection();
@@ -190,7 +191,7 @@ public class AltosMapOnline implements AltosDroidMapInterface, GoogleMap.OnMarke
        public void setupMap(int map_type) {
                mMap = mMapFragment.getMap();
                if (mMap != null) {
-                       set_map_type(map_type);
+                       map_type_changed(map_type);
                        mMap.setMyLocationEnabled(true);
                        mMap.getUiSettings().setTiltGesturesEnabled(false);
                        mMap.getUiSettings().setZoomControlsEnabled(false);
@@ -281,7 +282,7 @@ public class AltosMapOnline implements AltosDroidMapInterface, GoogleMap.OnMarke
                                        mPadMarker.setVisible(true);
                                }
                        }
-                       if (state.gps != null) {
+                       if (state.gps != null && state.gps.lat != AltosLib.MISSING) {
 
                                target_position = new AltosLatLon(state.gps.lat, state.gps.lon);
                                if (state.gps.locked && state.gps.nsat >= 4)
@@ -308,7 +309,7 @@ public class AltosMapOnline implements AltosDroidMapInterface, GoogleMap.OnMarke
 
        }
 
-       public void set_map_type(int map_type) {
+       public void map_type_changed(int map_type) {
                if (mMap != null) {
                        if (map_type == AltosMap.maptype_hybrid)
                                mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
index 12055dc51f74c507e82d4e39b409266dfeaafb7c..4660512a7067e96aa12d17e043a005fc532b1a44 100644 (file)
@@ -28,7 +28,7 @@ import android.hardware.usb.*;
 import android.app.*;
 import android.os.Handler;
 
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public class AltosUsb extends AltosDroidLink {
 
index bdc80003fef282890c0cc22d2748737a1528b9f3..542ba1f581f1d24b698149ef882164c053a56584 100644 (file)
@@ -22,7 +22,7 @@ import android.speech.tts.TextToSpeech;
 import android.speech.tts.TextToSpeech.OnInitListener;
 import android.location.Location;
 
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public class AltosVoice {
 
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/IdleModeActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/IdleModeActivity.java
new file mode 100644 (file)
index 0000000..ec12c19
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.util.*;
+import org.altusmetrum.AltosDroid.R;
+
+import android.app.Activity;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.view.View;
+import android.view.Window;
+import android.view.View.OnClickListener;
+import android.widget.*;
+import android.widget.AdapterView.*;
+
+import org.altusmetrum.altoslib_10.*;
+
+public class IdleModeActivity extends Activity {
+       private EditText callsign;
+       private Button connect;
+       private Button disconnect;
+       private Button reboot;
+       private Button igniters;
+
+       public static final String EXTRA_IDLE_MODE = "idle_mode";
+       public static final String EXTRA_IDLE_RESULT = "idle_result";
+
+       public static final int IDLE_MODE_CONNECT = 1;
+       public static final int IDLE_MODE_REBOOT = 2;
+       public static final int IDLE_MODE_IGNITERS = 3;
+       public static final int IDLE_MODE_DISCONNECT = 4;
+
+       private void done(int type) {
+               AltosPreferences.set_callsign(callsign());
+               Intent intent = new Intent();
+               intent.putExtra(EXTRA_IDLE_RESULT, type);
+               setResult(Activity.RESULT_OK, intent);
+               finish();
+       }
+
+       private String callsign() {
+               return callsign.getEditableText().toString();
+       }
+
+       public void connect_idle() {
+               done(IDLE_MODE_CONNECT);
+       }
+
+       public void disconnect_idle() {
+               AltosDebug.debug("Disconnect idle button pressed");
+               done(IDLE_MODE_DISCONNECT);
+       }
+
+       public void reboot_idle() {
+               done(IDLE_MODE_REBOOT);
+       }
+
+       public void igniters_idle() {
+               done(IDLE_MODE_IGNITERS);
+       }
+
+       @Override
+       protected void onCreate(Bundle savedInstanceState) {
+               super.onCreate(savedInstanceState);
+
+               // Setup the window
+               requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+               setContentView(R.layout.idle_mode);
+
+               callsign = (EditText) findViewById(R.id.set_callsign);
+               callsign.setText(new StringBuffer(AltosPreferences.callsign()));
+
+               connect = (Button) findViewById(R.id.connect_idle);
+               connect.setOnClickListener(new OnClickListener() {
+                               public void onClick(View v) {
+                                       connect_idle();
+                               }
+                       });
+               disconnect = (Button) findViewById(R.id.disconnect_idle);
+               disconnect.setOnClickListener(new OnClickListener() {
+                               public void onClick(View v) {
+                                       disconnect_idle();
+                               }
+                       });
+
+               boolean idle_mode = getIntent().getBooleanExtra(AltosDroid.EXTRA_IDLE_MODE, false);
+
+               if (idle_mode)
+                       connect.setVisibility(View.GONE);
+               else
+                       disconnect.setVisibility(View.GONE);
+
+               reboot = (Button) findViewById(R.id.reboot_idle);
+               reboot.setOnClickListener(new OnClickListener() {
+                               public void onClick(View v) {
+                                       reboot_idle();
+                               }
+                       });
+               igniters = (Button) findViewById(R.id.igniters_idle);
+               igniters.setOnClickListener(new OnClickListener() {
+                               public void onClick(View v) {
+                                       igniters_idle();
+                               }
+                       });
+
+               // Set result CANCELED incase the user backs out
+               setResult(Activity.RESULT_CANCELED);
+       }
+}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/IgniterActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/IgniterActivity.java
new file mode 100644 (file)
index 0000000..931c3cf
--- /dev/null
@@ -0,0 +1,413 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.lang.ref.WeakReference;
+import java.util.*;
+import org.altusmetrum.AltosDroid.R;
+
+import android.app.Activity;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.content.*;
+import android.graphics.*;
+import android.os.*;
+import android.view.*;
+import android.view.View.*;
+import android.widget.*;
+import android.widget.AdapterView.*;
+
+import org.altusmetrum.altoslib_10.*;
+
+class IgniterItem {
+       public String name;
+       public String pretty;
+       public String status;
+       public LinearLayout igniter_view = null;
+       public TextView pretty_view = null;
+       public TextView status_view = null;
+
+       private void update() {
+               if (pretty_view != null)
+                       pretty_view.setText(pretty);
+               if (status_view != null)
+                       status_view.setText(status);
+       }
+
+       public void set(String name, String pretty, String status) {
+               if (!name.equals(this.name) ||
+                   !pretty.equals(this.pretty) ||
+                   !status.equals(this.status))
+               {
+                       this.name = name;
+                       this.pretty = pretty;
+                       this.status = status;
+                       update();
+               }
+       }
+
+       public void realize(LinearLayout igniter_view,
+                           TextView pretty_view,
+                           TextView status_view) {
+               if (igniter_view != this.igniter_view ||
+                   pretty_view != this.pretty_view ||
+                   status_view != this.status_view)
+               {
+                       this.igniter_view = igniter_view;
+                       this.pretty_view = pretty_view;
+                       this.status_view = status_view;
+                       update();
+               }
+       }
+
+       public IgniterItem() {
+       }
+}
+
+class IgniterAdapter extends ArrayAdapter<IgniterItem> {
+       int resource;
+       int selected_item = -1;
+
+       public IgniterAdapter(Context context, int in_resource) {
+               super(context, in_resource);
+               resource = in_resource;
+       }
+
+       @Override
+       public View getView(int position, View convertView, ViewGroup parent) {
+               IgniterItem item = getItem(position);
+               if (item.igniter_view == null) {
+                       LinearLayout igniter_view = new LinearLayout(getContext());
+                       String inflater = Context.LAYOUT_INFLATER_SERVICE;
+                       LayoutInflater li = (LayoutInflater) getContext().getSystemService(inflater);
+                       li.inflate(resource, igniter_view, true);
+
+                       item.realize(igniter_view,
+                                    (TextView) igniter_view.findViewById(R.id.igniter_name),
+                                    (TextView) igniter_view.findViewById(R.id.igniter_status));
+               }
+               if (position == selected_item)
+                       item.igniter_view.setBackgroundColor(Color.RED);
+               else
+                       item.igniter_view.setBackgroundColor(Color.BLACK);
+               return item.igniter_view;
+       }
+}
+
+public class IgniterActivity extends Activity {
+       private ListView igniters_view;
+       private ToggleButton arm;
+       private Button fire;
+
+       private HashMap<String,IgniterItem> igniters = new HashMap<String,IgniterItem>();;
+
+       private IgniterAdapter igniters_adapter;
+
+       private boolean is_bound;
+       private Messenger service = null;
+       private final Messenger messenger = new Messenger(new IncomingHandler(this));
+
+       private Timer query_timer;
+       private boolean query_timer_running;
+
+       private Timer arm_timer;
+       private int arm_remaining;
+
+       public static final int IGNITER_QUERY = 1;
+       public static final int IGNITER_FIRE = 2;
+
+       // The Handler that gets information back from the Telemetry Service
+       static class IncomingHandler extends Handler {
+               private final WeakReference<IgniterActivity> igniter_activity;
+               IncomingHandler(IgniterActivity ia) { igniter_activity = new WeakReference<IgniterActivity>(ia); }
+
+               @Override
+               public void handleMessage(Message msg) {
+                       IgniterActivity ia = igniter_activity.get();
+
+                       switch (msg.what) {
+                       case AltosDroid.MSG_IGNITER_STATUS:
+                               ia.igniter_status((HashMap <String,Integer>) msg.obj);
+                               break;
+                       }
+               }
+       };
+
+
+       private ServiceConnection connection = new ServiceConnection() {
+               public void onServiceConnected(ComponentName className, IBinder binder) {
+                       service = new Messenger(binder);
+                       query_timer_tick();
+               }
+
+               public void onServiceDisconnected(ComponentName className) {
+                       // This is called when the connection with the service has been unexpectedly disconnected - process crashed.
+                       service = null;
+               }
+       };
+
+       void doBindService() {
+               bindService(new Intent(this, TelemetryService.class), connection, Context.BIND_AUTO_CREATE);
+               is_bound = true;
+       }
+
+       void doUnbindService() {
+               if (is_bound) {
+                       // If we have received the service, and hence registered with it, then now is the time to unregister.
+                       unbindService(connection);
+                       is_bound = false;
+               }
+       }
+
+       private void done() {
+               Intent intent = new Intent();
+               setResult(Activity.RESULT_OK, intent);
+               finish();
+       }
+
+       class FireThread extends Thread {
+               private final String igniter;
+
+               @Override
+               public void run() {
+                       Message msg = Message.obtain(null, TelemetryService.MSG_IGNITER_FIRE, igniter);
+                       try {
+                               service.send(msg);
+                       } catch (RemoteException re) {
+                       }
+               }
+
+               public FireThread(String igniter) {
+                       this.igniter = igniter;
+               }
+       }
+
+       private void fire_igniter() {
+               if (igniters_adapter.selected_item >= 0) {
+                       IgniterItem     item = igniters_adapter.getItem(igniters_adapter.selected_item);
+                       FireThread      ft = new FireThread(item.name);
+                       ft.run();
+                       arm.setChecked(false);
+               }
+       }
+
+       private void arm_igniter(boolean is_checked) {
+               if (is_checked) {
+                       arm_timer_stop();
+                       arm_timer = new Timer();
+                       arm_remaining = 10;
+                       arm_set_text();
+                       fire.setEnabled(true);
+                       arm_timer.scheduleAtFixedRate(new TimerTask() {
+                                       public void run() {
+                                               arm_timer_tick();
+                                       }},
+                               1000L, 1000L);
+               } else {
+                       arm_timer_stop();
+                       fire.setEnabled(false);
+               }
+       }
+
+       private synchronized void query_timer_tick() {
+               if (query_timer_running)
+                       return;
+               if (service == null)
+                       return;
+               query_timer_running = true;
+               Thread thread = new Thread(new Runnable() {
+                               public void run() {
+                                       try {
+                                               Message msg = Message.obtain(null, TelemetryService.MSG_IGNITER_QUERY);
+                                               msg.replyTo = messenger;
+                                               if (service == null) {
+                                                       synchronized(IgniterActivity.this) {
+                                                               query_timer_running = false;
+                                                       }
+                                               } else
+                                                       service.send(msg);
+                                       } catch (RemoteException re) {
+                                               AltosDebug.debug("igniter query thread failed");
+                                               synchronized(IgniterActivity.this) {
+                                                       query_timer_running = false;
+                                               }
+                                       }
+                               }
+                       });
+               thread.start();
+       }
+
+       private boolean set_igniter(HashMap <String,Integer> status, String name, String pretty) {
+               if (!status.containsKey(name))
+                       return false;
+
+               IgniterItem item;
+               if (!igniters.containsKey(name)) {
+                       item = new IgniterItem();
+                       igniters.put(name, item);
+                       igniters_adapter.add(item);
+               } else
+                       item = igniters.get(name);
+
+               item.set(name, pretty, AltosIgnite.status_string(status.get(name)));
+               return true;
+       }
+
+       private synchronized void igniter_status(HashMap <String,Integer> status) {
+               query_timer_running = false;
+               if (status == null) {
+                       AltosDebug.debug("no igniter status");
+                       return;
+               }
+               set_igniter(status, "drogue", "Apogee");
+               set_igniter(status, "main", "Main");
+               for (int extra = 0;; extra++) {
+                       String  name = String.format("%d", extra);
+                       String  pretty = String.format("%c", 'A' + extra);
+                       if (!set_igniter(status, name, pretty))
+                               break;
+               }
+       }
+
+       private synchronized void arm_timer_stop() {
+               if (arm_timer != null) {
+                       arm_timer.cancel();
+                       arm_timer = null;
+               }
+               arm_remaining = 0;
+       }
+
+       private void arm_set_text() {
+               String  text = String.format("Armed %d", arm_remaining);
+
+               if (arm.isChecked())
+                       arm.setText(text);
+               arm.setTextOn(text);
+       }
+
+       private void arm_timer_tick() {
+               --arm_remaining;
+               if (arm_remaining <= 0) {
+                       arm_timer_stop();
+                       runOnUiThread(new Runnable() {
+                                       public void run() {
+                                               arm.setChecked(false);
+                                               fire.setEnabled(false);
+                                       }
+                               });
+               } else {
+                       runOnUiThread(new Runnable() {
+                                       public void run() {
+                                               arm_set_text();
+                                       }
+                               });
+               }
+       }
+
+       private void select_item(int position) {
+               if (position != igniters_adapter.selected_item) {
+                       if (igniters_adapter.selected_item >= 0)
+                               igniters_view.setItemChecked(igniters_adapter.selected_item, false);
+                       if (position >= 0) {
+                               igniters_view.setItemChecked(position, true);
+                               arm.setEnabled(true);
+                       } else
+                               arm.setEnabled(false);
+                       igniters_adapter.selected_item = position;
+               }
+       }
+
+       private class IgniterItemClickListener implements ListView.OnItemClickListener {
+               @Override
+               public void onItemClick(AdapterView<?> av, View v, int position, long id) {
+                       AltosDebug.debug("select %d\n", position);
+                       select_item(position);
+               }
+       }
+
+       @Override
+       protected void onCreate(Bundle savedInstanceState) {
+               super.onCreate(savedInstanceState);
+
+               // Setup the window
+               requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+               setContentView(R.layout.igniters);
+
+               igniters_view = (ListView) findViewById(R.id.igniters);
+               igniters_view.setClickable(true);
+
+               igniters_adapter = new IgniterAdapter(this, R.layout.igniter_status);
+
+               igniters_view.setAdapter(igniters_adapter);
+               igniters_view.setOnItemClickListener(new IgniterItemClickListener());
+
+               fire = (Button) findViewById(R.id.igniter_fire);
+               fire.setEnabled(false);
+               fire.setOnClickListener(new OnClickListener() {
+                               public void onClick(View v) {
+                                       fire_igniter();
+                               }
+                       });
+
+               arm = (ToggleButton) findViewById(R.id.igniter_arm);
+               arm.setEnabled(false);
+               arm.setOnCheckedChangeListener(new ToggleButton.OnCheckedChangeListener() {
+                               public void onCheckedChanged(CompoundButton v, boolean is_checked) {
+                                       arm_igniter(is_checked);
+                               }
+                       });
+
+               // Set result CANCELED incase the user backs out
+               setResult(Activity.RESULT_CANCELED);
+       }
+
+       @Override
+       protected void onStart() {
+               super.onStart();
+               doBindService();
+       }
+
+       @Override
+       protected void onResume() {
+               super.onResume();
+               query_timer = new Timer(true);
+               query_timer.scheduleAtFixedRate(new TimerTask() {
+                               public void run() {
+                                       query_timer_tick();
+                               }},
+                       0L, 5000L);
+       }
+
+       @Override
+       protected void onPause() {
+               super.onPause();
+               if (query_timer != null) {
+                       query_timer.cancel();
+                       query_timer = null;
+               }
+               arm_timer_stop();
+               arm.setChecked(false);
+               fire.setEnabled(false);
+       }
+
+       @Override
+       protected void onStop() {
+               super.onStop();
+               doUnbindService();
+       }
+}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/ManageFrequenciesActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/ManageFrequenciesActivity.java
new file mode 100644 (file)
index 0000000..401cdc9
--- /dev/null
@@ -0,0 +1,289 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.lang.ref.WeakReference;
+import java.util.*;
+import java.text.*;
+import org.altusmetrum.AltosDroid.R;
+
+import android.app.Activity;
+import android.content.*;
+import android.graphics.*;
+import android.os.*;
+import android.view.*;
+import android.view.View.*;
+import android.view.inputmethod.*;
+import android.widget.*;
+import android.widget.AdapterView.*;
+
+import org.altusmetrum.altoslib_10.*;
+
+class FrequencyItem {
+       public AltosFrequency frequency;
+       public LinearLayout frequency_view = null;
+       public TextView pretty_view = null;
+
+       private void update() {
+               if (pretty_view != null && frequency != null)
+                       pretty_view.setText(frequency.toString());
+       }
+
+       public void realize(LinearLayout frequency_view,
+                           TextView pretty_view) {
+               if (frequency_view != this.frequency_view ||
+                   pretty_view != this.pretty_view)
+               {
+                       this.frequency_view = frequency_view;
+                       this.pretty_view = pretty_view;
+                       update();
+               }
+       }
+
+       public void set_frequency(AltosFrequency frequency) {
+               this.frequency = frequency;
+               update();
+       }
+
+       public FrequencyItem(AltosFrequency frequency) {
+               this.frequency = frequency;
+       }
+}
+
+class FrequencyAdapter extends ArrayAdapter<FrequencyItem> {
+       int resource;
+       int selected_item = -1;
+
+       public FrequencyAdapter(Context context, int in_resource) {
+               super(context, in_resource);
+               resource = in_resource;
+       }
+
+       public int count() {
+               int     count;
+
+               for (count = 0;; count++) {
+                       try {
+                               getItem(count);
+                       } catch (IndexOutOfBoundsException ie) {
+                               return count;
+                       }
+               }
+       }
+
+       @Override
+       public View getView(int position, View convertView, ViewGroup parent) {
+               FrequencyItem item = getItem(position);
+               if (item.frequency_view == null) {
+                       LinearLayout frequency_view = new LinearLayout(getContext());
+                       String inflater = Context.LAYOUT_INFLATER_SERVICE;
+                       LayoutInflater li = (LayoutInflater) getContext().getSystemService(inflater);
+                       li.inflate(resource, frequency_view, true);
+
+                       item.realize(frequency_view,
+                                    (TextView) frequency_view.findViewById(R.id.frequency));
+               }
+               if (position == selected_item)
+                       item.frequency_view.setBackgroundColor(Color.RED);
+               else
+                       item.frequency_view.setBackgroundColor(Color.BLACK);
+               return item.frequency_view;
+       }
+}
+
+public class ManageFrequenciesActivity extends Activity {
+       private ListView frequencies_view;
+
+       private Button set;
+       private Button remove;
+       private Button done;
+
+       private EditText set_frequency;
+       private EditText set_description;
+
+       private HashMap<String,FrequencyItem> frequencies = new HashMap<String,FrequencyItem>();;
+
+       private FrequencyAdapter frequencies_adapter;
+
+       private boolean is_bound;
+       private boolean changed = false;
+
+       private void done() {
+
+               if (changed) {
+                       AltosFrequency[] frequencies = new AltosFrequency[frequencies_adapter.count()];
+                       for (int i = 0; i < frequencies.length; i++)
+                               frequencies[i] = frequencies_adapter.getItem(i).frequency;
+                       AltosPreferences.set_common_frequencies(frequencies);
+               }
+
+               Intent intent = new Intent();
+               setResult(Activity.RESULT_OK, intent);
+               finish();
+       }
+
+       private void load_item() {
+               if (frequencies_adapter.selected_item >= 0) {
+                       FrequencyItem item = frequencies_adapter.getItem(frequencies_adapter.selected_item);
+
+                       set_frequency.setText(item.frequency.frequency_string());
+                       set_description.setText(item.frequency.description);
+               } else {
+                       set_frequency.setText("");
+                       set_description.setText("");
+               }
+       }
+
+       private void select_item(int position) {
+               if (position != frequencies_adapter.selected_item) {
+                       if (frequencies_adapter.selected_item >= 0)
+                               frequencies_view.setItemChecked(frequencies_adapter.selected_item, false);
+                       if (position >= 0)
+                               frequencies_view.setItemChecked(position, true);
+                       frequencies_adapter.selected_item = position;
+               } else {
+                       if (frequencies_adapter.selected_item >= 0)
+                               frequencies_view.setItemChecked(frequencies_adapter.selected_item, false);
+                       frequencies_adapter.selected_item = -1;
+               }
+               load_item();
+       }
+
+       private int insert_item(AltosFrequency frequency) {
+               FrequencyItem new_item = new FrequencyItem(frequency);
+               int     pos;
+               for (pos = 0; pos < frequencies_adapter.getCount(); pos++) {
+                       FrequencyItem   item = frequencies_adapter.getItem(pos);
+                       if (item.frequency.frequency == new_item.frequency.frequency) {
+                               item.set_frequency(frequency);
+                               return pos;
+                       }
+                       if (item.frequency.frequency > new_item.frequency.frequency)
+                               break;
+               }
+               frequencies_adapter.insert(new_item, pos);
+               return pos;
+       }
+
+       private class FrequencyItemClickListener implements ListView.OnItemClickListener {
+               @Override
+               public void onItemClick(AdapterView<?> av, View v, int position, long id) {
+                       select_item(position);
+               }
+       }
+
+       private void hide_keyboard() {
+               InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
+               View view = getCurrentFocus();
+               if (view != null)
+                       imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
+       }
+
+       private void set() {
+               String  frequency_text = set_frequency.getEditableText().toString();
+               String  description_text = set_description.getEditableText().toString();
+
+               try {
+                       double  f = AltosParse.parse_double_locale(frequency_text);
+
+                       int pos = insert_item(new AltosFrequency(f, description_text));
+                       frequencies_adapter.selected_item = -1;
+                       select_item(pos);
+                       changed = true;
+               } catch (ParseException pe) {
+               }
+               hide_keyboard();
+       }
+
+       private void remove() {
+               if (frequencies_adapter.selected_item >= 0) {
+                       frequencies_adapter.remove(frequencies_adapter.getItem(frequencies_adapter.selected_item));
+                       select_item(-1);
+                       frequencies_view.setAdapter(frequencies_adapter);
+                       changed = true;
+               }
+       }
+
+       @Override
+       protected void onCreate(Bundle savedInstanceState) {
+               super.onCreate(savedInstanceState);
+
+               // Setup the window
+               requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+               setContentView(R.layout.manage_frequencies);
+
+               frequencies_view = (ListView) findViewById(R.id.frequencies);
+               frequencies_view.setClickable(true);
+
+               frequencies_adapter = new FrequencyAdapter(this, R.layout.frequency);
+
+               frequencies_view.setAdapter(frequencies_adapter);
+               frequencies_view.setOnItemClickListener(new FrequencyItemClickListener());
+
+               AltosFrequency[] frequencies = AltosPreferences.common_frequencies();
+               for (AltosFrequency frequency : frequencies)
+                       insert_item(frequency);
+
+               set_frequency = (EditText) findViewById(R.id.set_frequency);
+               set_description = (EditText) findViewById(R.id.set_description);
+
+               set = (Button) findViewById(R.id.set);
+               set.setOnClickListener(new OnClickListener() {
+                               public void onClick(View v) {
+                                       set();
+                               }
+                       });
+
+               remove = (Button) findViewById(R.id.remove);
+               remove.setOnClickListener(new OnClickListener() {
+                               public void onClick(View v) {
+                                       remove();
+                               }
+                       });
+
+               done = (Button) findViewById(R.id.done);
+               done.setOnClickListener(new OnClickListener() {
+                               public void onClick(View v) {
+                                       done();
+                               }
+                       });
+
+               // Set result CANCELED incase the user backs out
+               setResult(Activity.RESULT_CANCELED);
+       }
+
+       @Override
+       protected void onStart() {
+               super.onStart();
+       }
+
+       @Override
+       protected void onResume() {
+               super.onResume();
+       }
+
+       @Override
+       protected void onPause() {
+               super.onPause();
+       }
+
+       @Override
+       protected void onStop() {
+               super.onStop();
+       }
+}
index e1677ce6a760ad6922f2361802defa9425fc2b3d..cfbcdafc3b6e4e195c41de12fdf80bcb8ff0a4bd 100644 (file)
@@ -34,7 +34,7 @@ import android.view.View.OnClickListener;
 import android.widget.*;
 import android.widget.AdapterView.*;
 
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public class MapTypeActivity extends Activity {
        private Button hybrid;
index e6ce38093a78d657ff74d576e7dfc2cb3f21c188..13a44e1f6902f3def172a88c8b31adb776729860 100644 (file)
@@ -41,7 +41,7 @@ import android.location.LocationManager;
 import android.location.LocationListener;
 import android.location.Criteria;
 
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 /**
  * This Activity appears as a dialog. It lists any paired devices and
@@ -107,7 +107,6 @@ public class PreloadMapActivity extends Activity implements AltosLaunchSiteListe
        }
 
        AltosMap        map;
-       AltosMapLoader  loader;
 
        class PreloadMapImage implements AltosImage {
                public void flush() {
@@ -137,14 +136,14 @@ public class PreloadMapActivity extends Activity implements AltosLaunchSiteListe
                public void paint(AltosMapTransform t) {
                }
 
-               public PreloadMapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
-                       super(listener, upper_left, center, zoom, maptype, px_size, 2);
+               public PreloadMapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
+                       super(cache, upper_left, center, zoom, maptype, px_size, 2);
                }
 
        }
 
-       public AltosMapTile new_tile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
-               return new PreloadMapTile(listener, upper_left, center, zoom, maptype, px_size);
+       public AltosMapTile new_tile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
+               return new PreloadMapTile(cache, upper_left, center, zoom, maptype, px_size);
        }
 
        public int width() {
@@ -265,7 +264,7 @@ public class PreloadMapActivity extends Activity implements AltosLaunchSiteListe
 
                        AltosDebug.debug("PreloadMap load %f %f %d %d %f %d\n",
                                         lat, lon, min, max, r, t);
-                       loader.load(lat, lon, min, max, r, t);
+                       new AltosMapLoader(map, this, lat, lon, min, max, r, t);
                } catch (ParseException e) {
                        AltosDebug.debug("PreloadMap load raised exception %s", e.toString());
                }
@@ -398,8 +397,6 @@ public class PreloadMapActivity extends Activity implements AltosLaunchSiteListe
 
                map = new AltosMap(this);
 
-               loader = new AltosMapLoader(map, this);
-
                // Listen for GPS and Network position updates
                LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
 
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/SetupActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/SetupActivity.java
new file mode 100644 (file)
index 0000000..fdffc2b
--- /dev/null
@@ -0,0 +1,339 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.lang.ref.WeakReference;
+import java.util.*;
+import org.altusmetrum.AltosDroid.R;
+
+import android.app.Activity;
+import android.bluetooth.*;
+import android.content.*;
+import android.os.*;
+import android.view.*;
+import android.view.View.*;
+import android.widget.*;
+import android.widget.AdapterView.*;
+
+import org.altusmetrum.altoslib_10.*;
+
+public class SetupActivity extends Activity {
+       private Spinner select_rate;
+       private Spinner set_units;
+       private Spinner map_type;
+       private Spinner map_source;
+       private Button manage_frequencies;
+       private Button preload_maps;
+       private Button done;
+
+       private boolean is_bound;
+       private Messenger service = null;
+
+       public final static String EXTRA_SETUP_CHANGES = "setup_changes";
+
+       private ServiceConnection connection = new ServiceConnection() {
+               public void onServiceConnected(ComponentName className, IBinder binder) {
+                       service = new Messenger(binder);
+               }
+
+               public void onServiceDisconnected(ComponentName className) {
+                       // This is called when the connection with the service has been unexpectedly disconnected - process crashed.
+                       service = null;
+               }
+       };
+
+       void doBindService() {
+               bindService(new Intent(this, TelemetryService.class), connection, Context.BIND_AUTO_CREATE);
+               is_bound = true;
+       }
+
+       void doUnbindService() {
+               if (is_bound) {
+                       // If we have received the service, and hence registered with it, then now is the time to unregister.
+                       unbindService(connection);
+                       is_bound = false;
+               }
+       }
+
+       static final String[] rates = {
+               "38400",
+               "9600",
+               "2400",
+       };
+
+       static final String[] map_types = {
+               "Hybrid",
+               "Satellite",
+               "Roadmap",
+               "Terrain"
+       };
+
+       static final int[] map_type_values = {
+               AltosMap.maptype_hybrid,
+               AltosMap.maptype_satellite,
+               AltosMap.maptype_roadmap,
+               AltosMap.maptype_terrain,
+       };
+
+       static final String[] map_sources = {
+               "Online",
+               "Offline"
+       };
+
+       private int     set_telemetry_rate;
+       private int     set_map_source;
+       private int     set_map_type;
+       private boolean set_imperial_units;
+
+       private int     changes = 0;
+
+       private void add_change(int change) {
+               changes |= change;
+       }
+
+       private void done() {
+               Intent intent = new Intent();
+               if ((changes & AltosDroid.SETUP_BAUD) != 0)
+                       AltosPreferences.set_telemetry_rate(1, set_telemetry_rate);
+               if ((changes & AltosDroid.SETUP_UNITS) != 0)
+                       AltosPreferences.set_imperial_units(set_imperial_units);
+               if ((changes & AltosDroid.SETUP_MAP_SOURCE) != 0)
+                       AltosDroidPreferences.set_map_source(set_map_source);
+               if ((changes & AltosDroid.SETUP_MAP_TYPE) != 0)
+                       AltosPreferences.set_map_type(set_map_type);
+               intent.putExtra(EXTRA_SETUP_CHANGES, changes);
+               setResult(Activity.RESULT_OK, intent);
+               finish();
+       }
+
+       private void add_strings(Spinner spinner, String[] strings, int def) {
+               ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item);
+
+               for (int i = 0; i < strings.length; i++)
+                       adapter.add(strings[i]);
+
+               spinner.setAdapter(adapter);
+               if (def >= 0)
+                       spinner.setSelection(def);
+       }
+
+       private int default_rate_pos() {
+               int     default_rate = AltosPreferences.telemetry_rate(1);
+
+               for (int pos = 0; pos < rates.length; pos++) {
+                       if (string_to_rate(rates[pos]) == default_rate)
+                               return pos;
+               }
+               return -1;
+       }
+
+       private void setBaud(int baud) {
+               try {
+                       service.send(Message.obtain(null, TelemetryService.MSG_SETBAUD, baud));
+                       set_telemetry_rate = baud;
+                       add_change(AltosDroid.SETUP_BAUD);
+               } catch (RemoteException e) {
+               }
+       }
+
+       private int string_to_rate(String baud) {
+               int     rate = AltosLib.ao_telemetry_rate_38400;
+               try {
+                       int     value = Integer.parseInt(baud);
+                       switch (value) {
+                       case 2400:
+                               rate = AltosLib.ao_telemetry_rate_2400;
+                               break;
+                       case 9600:
+                               rate = AltosLib.ao_telemetry_rate_9600;
+                               break;
+                       case 38400:
+                               rate = AltosLib.ao_telemetry_rate_38400;
+                               break;
+                       }
+               } catch (NumberFormatException e) {
+               }
+               return rate;
+       }
+
+       private void setBaud(String baud) {
+               setBaud(string_to_rate(baud));
+       }
+
+       private void select_rate(int pos) {
+               setBaud(rates[pos]);
+       }
+
+       static final String[] units = {
+               "Metric",
+               "Imperial"
+       };
+
+       private int default_units_pos() {
+               boolean imperial = AltosPreferences.imperial_units();
+
+               if (imperial)
+                       return 1;
+               return 0;
+       }
+
+       private void set_units(int pos) {
+               switch (pos) {
+               default:
+                       set_imperial_units = false;
+                       break;
+               case 1:
+                       set_imperial_units = true;
+                       break;
+               }
+               add_change(AltosDroid.SETUP_UNITS);
+       }
+
+       private int default_map_type_pos() {
+               int     default_map_type = AltosPreferences.map_type();
+
+               for (int pos = 0; pos < map_types.length; pos++)
+                       if (map_type_values[pos] == default_map_type)
+                               return pos;
+               return 0;
+       }
+
+       private void select_map_type(int pos) {
+               set_map_type = map_type_values[pos];
+               add_change(AltosDroid.SETUP_MAP_TYPE);
+       }
+
+       private int default_map_source_pos() {
+               int     default_source = AltosDroidPreferences.map_source();
+
+               switch (default_source) {
+               case AltosDroidPreferences.MAP_SOURCE_OFFLINE:
+                       return 1;
+               default:
+                       return 0;
+               }
+       }
+
+       private void select_map_source(int pos) {
+               switch (pos) {
+               default:
+                       set_map_source = AltosDroidPreferences.MAP_SOURCE_ONLINE;
+                       break;
+               case 1:
+                       set_map_source = AltosDroidPreferences.MAP_SOURCE_OFFLINE;
+                       break;
+               }
+               add_change(AltosDroid.SETUP_MAP_SOURCE);
+       }
+
+       private void manage_frequencies(){
+               Intent intent = new Intent(this, ManageFrequenciesActivity.class);
+               startActivity(intent);
+       }
+
+       private void preload_maps(){
+               Intent intent = new Intent(this, PreloadMapActivity.class);
+               startActivity(intent);
+       }
+
+       @Override
+       protected void onCreate(Bundle savedInstanceState) {
+               super.onCreate(savedInstanceState);
+
+               // Setup the window
+               requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+               setContentView(R.layout.setup);
+
+               select_rate = (Spinner) findViewById(R.id.select_rate);
+               add_strings(select_rate, rates, default_rate_pos());
+               select_rate.setOnItemSelectedListener(new OnItemSelectedListener() {
+                               public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+                                       select_rate(pos);
+                               }
+                               public void onNothingSelected(AdapterView<?> parent) {
+                               }
+                       });
+
+               set_units = (Spinner) findViewById(R.id.set_units);
+               add_strings(set_units, units, default_units_pos());
+               set_units.setOnItemSelectedListener(new OnItemSelectedListener() {
+                               public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+                                       set_units(pos);
+                               }
+                               public void onNothingSelected(AdapterView<?> parent) {
+                               }
+                       });
+
+               map_type = (Spinner) findViewById(R.id.map_type);
+               add_strings(map_type, map_types, default_map_type_pos());
+               map_type.setOnItemSelectedListener(new OnItemSelectedListener() {
+                               public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+                                       select_map_type(pos);
+                               }
+                               public void onNothingSelected(AdapterView<?> parent) {
+                               }
+                       });
+
+               map_source = (Spinner) findViewById(R.id.map_source);
+               add_strings(map_source, map_sources, default_map_source_pos());
+               map_source.setOnItemSelectedListener(new OnItemSelectedListener() {
+                               public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+                                       select_map_source(pos);
+                               }
+                               public void onNothingSelected(AdapterView<?> parent) {
+                               }
+                       });
+
+
+               manage_frequencies = (Button) findViewById(R.id.manage_frequencies);
+               manage_frequencies.setOnClickListener(new OnClickListener() {
+                               public void onClick(View v) {
+                                       manage_frequencies();
+                               }
+                       });
+
+               preload_maps = (Button) findViewById(R.id.preload_maps);
+               preload_maps.setOnClickListener(new OnClickListener() {
+                               public void onClick(View v) {
+                                       preload_maps();
+                               }
+                       });
+
+               done = (Button) findViewById(R.id.done);
+               done.setOnClickListener(new OnClickListener() {
+                               public void onClick(View v) {
+                                       done();
+                               }
+                       });
+
+               // Set result for when the user backs out
+               setResult(Activity.RESULT_CANCELED);
+       }
+
+       @Override
+       protected void onStart() {
+               super.onStart();
+               doBindService();
+       }
+
+       @Override
+       protected void onStop() {
+               super.onStop();
+               doUnbindService();
+       }
+}
index 095d6b3349223e7a4e3aaf09125d95d6816198ca..9bbdc0605dfcfcf6e9d93152ab0a823282b6a5bf 100644 (file)
@@ -17,7 +17,7 @@
 
 package org.altusmetrum.AltosDroid;
 
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 import android.app.Activity;
 import android.os.Bundle;
@@ -87,7 +87,7 @@ public class TabFlight extends AltosDroidTab {
                        set_value(speed_view, AltosConvert.speed, 6, state.speed());
                        set_value(height_view, AltosConvert.height, 6, state.height());
                        set_value(max_speed_view, AltosConvert.speed, 6, state.max_speed());
-                       set_value(max_height_view, AltosConvert.speed, 6, state.max_height());
+                       set_value(max_height_view, AltosConvert.height, 6, state.max_height());
                        if (from_receiver != null) {
                                elevation_view.setText(AltosDroid.number("%3.0f°", from_receiver.elevation));
                                set_value(range_view, AltosConvert.distance, 6, from_receiver.range);
index 3c236d58e84f642168fac6f4330300177a6464cf..19ce86c9f75c5e80448486e8ab11174c95a94c69 100644 (file)
@@ -20,7 +20,7 @@ package org.altusmetrum.AltosDroid;
 import java.util.*;
 import java.io.*;
 
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 import android.app.Activity;
 import android.graphics.*;
@@ -32,7 +32,7 @@ import android.widget.*;
 import android.location.Location;
 import android.content.*;
 
-public class TabMap extends AltosDroidTab {
+public class TabMap extends AltosDroidTab implements AltosDroidMapSourceListener {
 
        AltosLatLon     here;
 
@@ -74,7 +74,8 @@ public class TabMap extends AltosDroidTab {
                map_offline.onCreateView(altos_droid);
                map_online = new AltosMapOnline(view.getContext());
                map_online.onCreateView(altos_droid);
-               set_map_source(AltosDroidPreferences.map_source());
+               map_source_changed(AltosDroidPreferences.map_source());
+               AltosDroidPreferences.register_map_source_listener(this);
                return view;
        }
 
@@ -88,6 +89,9 @@ public class TabMap extends AltosDroidTab {
        @Override
        public void onDestroyView() {
                super.onDestroyView();
+               map_offline.onDestroyView();
+               map_online.onDestroyView();
+               AltosDroidPreferences.unregister_map_source_listener(this);
        }
 
        public String tab_name() { return AltosDroid.tab_map_name; }
@@ -144,16 +148,7 @@ public class TabMap extends AltosDroidTab {
                }
        }
 
-       @Override
-       public void set_map_type(int map_type) {
-               if (map_offline != null)
-                       map_offline.set_map_type(map_type);
-               if (map_online != null)
-                       map_online.set_map_type(map_type);
-       }
-
-       @Override
-       public void set_map_source(int map_source) {
+       public void map_source_changed(int map_source) {
                this.map_source = map_source;
                if (map_source == AltosDroidPreferences.MAP_SOURCE_OFFLINE) {
                        if (map_online != null)
index f5fbaf61ba710205897692a611942093956fa7e6..1194eb002665d011e538cc932092677c0eef5959 100644 (file)
@@ -17,7 +17,7 @@
 
 package org.altusmetrum.AltosDroid;
 
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 import android.app.Activity;
 import android.os.Bundle;
index ee82d391e9e730e1c5052a7fbb4e6690f17bfd4a..8742227b7507130fd036e82b3d2e9d73c411df83 100644 (file)
@@ -17,7 +17,7 @@
 
 package org.altusmetrum.AltosDroid;
 
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 import android.app.Activity;
 import android.os.Bundle;
index 6f595817f556dc0c68b8f4135b5c5b4798486fa3..bdea0986cf62d605b842afa2bd6035ad9daca6e8 100644 (file)
@@ -1,6 +1,6 @@
 package org.altusmetrum.AltosDroid;
 
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 import android.content.BroadcastReceiver;
 import android.content.Context;
index 473a4bfb3dd5b07f06dfbf9209f6c705c77e665e..0ac6bb5c1429938676feb24e5418a7ffd19a21db 100644 (file)
@@ -25,7 +25,7 @@ import java.util.*;
 import java.util.concurrent.*;
 import android.os.Handler;
 
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 
 public class TelemetryReader extends Thread {
index 92a7ecfa3863b2497986fe621da7f26e92a7bea3..3c1a17823d595c681cfa61a938e6537093df173f 100644 (file)
@@ -38,14 +38,11 @@ import android.os.Messenger;
 import android.os.RemoteException;
 import android.os.Looper;
 import android.widget.Toast;
-import android.location.Location;
-import android.location.LocationManager;
-import android.location.LocationListener;
 import android.location.Criteria;
 
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
-public class TelemetryService extends Service implements LocationListener {
+public class TelemetryService extends Service implements AltosIdleMonitorListener {
 
        static final int MSG_REGISTER_CLIENT   = 1;
        static final int MSG_UNREGISTER_CLIENT = 2;
@@ -60,6 +57,12 @@ public class TelemetryService extends Service implements LocationListener {
        static final int MSG_SETBAUD           = 11;
        static final int MSG_DISCONNECT        = 12;
        static final int MSG_DELETE_SERIAL     = 13;
+       static final int MSG_BLUETOOTH_ENABLED = 14;
+       static final int MSG_MONITOR_IDLE_START= 15;
+       static final int MSG_MONITOR_IDLE_STOP = 16;
+       static final int MSG_REBOOT            = 17;
+       static final int MSG_IGNITER_QUERY     = 18;
+       static final int MSG_IGNITER_FIRE      = 19;
 
        // Unique Identification Number for the Notification.
        // We use it on Notification start, and to cancel it.
@@ -82,6 +85,13 @@ public class TelemetryService extends Service implements LocationListener {
        // Last data seen; send to UI when it starts
        private TelemetryState  telemetry_state;
 
+       // Idle monitor if active
+       AltosIdleMonitor idle_monitor = null;
+
+       // Igniter bits
+       AltosIgnite ignite = null;
+       boolean ignite_running;
+
        // Handler of incoming messages from clients.
        static class IncomingHandler extends Handler {
                private final WeakReference<TelemetryService> service;
@@ -89,10 +99,13 @@ public class TelemetryService extends Service implements LocationListener {
 
                @Override
                public void handleMessage(Message msg) {
+                       DeviceAddress address;
+
                        TelemetryService s = service.get();
                        AltosDroidLink bt = null;
                        if (s == null)
                                return;
+
                        switch (msg.what) {
 
                                /* Messages from application */
@@ -104,7 +117,7 @@ public class TelemetryService extends Service implements LocationListener {
                                break;
                        case MSG_CONNECT:
                                AltosDebug.debug("Connect command received");
-                               DeviceAddress address = (DeviceAddress) msg.obj;
+                               address = (DeviceAddress) msg.obj;
                                AltosDroidPreferences.set_active_device(address);
                                s.start_altos_bluetooth(address, false);
                                break;
@@ -206,6 +219,32 @@ public class TelemetryService extends Service implements LocationListener {
                                s.telemetry_state.crc_errors = (Integer) msg.obj;
                                s.send_to_clients();
                                break;
+                       case MSG_BLUETOOTH_ENABLED:
+                               AltosDebug.debug("TelemetryService notes that BT is now enabled");
+                               address = AltosDroidPreferences.active_device();
+                               if (address != null && !address.address.startsWith("USB"))
+                                       s.start_altos_bluetooth(address, false);
+                               break;
+                       case MSG_MONITOR_IDLE_START:
+                               AltosDebug.debug("start monitor idle");
+                               s.start_idle_monitor();
+                               break;
+                       case MSG_MONITOR_IDLE_STOP:
+                               AltosDebug.debug("stop monitor idle");
+                               s.stop_idle_monitor();
+                               break;
+                       case MSG_REBOOT:
+                               AltosDebug.debug("reboot");
+                               s.reboot_remote();
+                               break;
+                       case MSG_IGNITER_QUERY:
+                               AltosDebug.debug("igniter query");
+                               s.igniter_query(msg.replyTo);
+                               break;
+                       case MSG_IGNITER_FIRE:
+                               AltosDebug.debug("igniter fire");
+                               s.igniter_fire((String) msg.obj);
+                               break;
                        default:
                                super.handleMessage(msg);
                        }
@@ -224,7 +263,7 @@ public class TelemetryService extends Service implements LocationListener {
                telem.update_state(state);
                telemetry_state.states.put(telem.serial, state);
                if (state != null) {
-                       AltosPreferences.set_state(telem.serial, state, null);
+                       AltosPreferences.set_state(state);
                }
                send_to_clients();
        }
@@ -248,7 +287,8 @@ public class TelemetryService extends Service implements LocationListener {
 
                /* On connect, send the current state to the new client
                 */
-               send_to_client(client, message());
+               send_to_client(client);
+               send_idle_mode_to_client(client);
 
                /* If we've got an address from a previous session, then
                 * go ahead and try to reconnect to the device
@@ -275,7 +315,8 @@ public class TelemetryService extends Service implements LocationListener {
                 }
        }
 
-       private void send_to_client(Messenger client, Message m) {
+       private void send_to_client(Messenger client) {
+               Message m = message();
                try {
                        client.send(m);
                } catch (RemoteException e) {
@@ -285,22 +326,33 @@ public class TelemetryService extends Service implements LocationListener {
        }
 
        private void send_to_clients() {
-               Message m = message();
                for (Messenger client : clients)
-                       send_to_client(client, m);
+                       send_to_client(client);
        }
 
-       private void disconnect(boolean notify) {
-               AltosDebug.debug("disconnect(): begin");
-
-               telemetry_state.connect = TelemetryState.CONNECT_DISCONNECTED;
-               telemetry_state.address = null;
+       private void send_idle_mode_to_client(Messenger client) {
+               Message m = Message.obtain(null, AltosDroid.MSG_IDLE_MODE, idle_monitor != null);
+               try {
+                       client.send(m);
+               } catch (RemoteException e) {
+                       AltosDebug.error("Client %s disappeared", client.toString());
+                       remove_client(client);
+               }
+       }
 
-               if (altos_link != null)
-                       altos_link.closing();
+       private void send_idle_mode_to_clients() {
+               for (Messenger client : clients)
+                       send_idle_mode_to_client(client);
+       }
 
-               stop_receiver_voltage_timer();
+       private void telemetry_start() {
+               if (telemetry_reader == null && idle_monitor == null && !ignite_running) {
+                       telemetry_reader = new TelemetryReader(altos_link, handler);
+                       telemetry_reader.start();
+               }
+       }
 
+       private void telemetry_stop() {
                if (telemetry_reader != null) {
                        AltosDebug.debug("disconnect(): stopping TelemetryReader");
                        telemetry_reader.interrupt();
@@ -310,6 +362,23 @@ public class TelemetryService extends Service implements LocationListener {
                        }
                        telemetry_reader = null;
                }
+       }
+
+       private void disconnect(boolean notify) {
+               AltosDebug.debug("disconnect(): begin");
+
+               telemetry_state.connect = TelemetryState.CONNECT_DISCONNECTED;
+               telemetry_state.address = null;
+
+               if (idle_monitor != null)
+                       stop_idle_monitor();
+
+               if (altos_link != null)
+                       altos_link.closing();
+
+               stop_receiver_voltage_timer();
+
+               telemetry_stop();
                if (telemetry_logger != null) {
                        AltosDebug.debug("disconnect(): stopping TelemetryLogger");
                        telemetry_logger.stop();
@@ -319,6 +388,7 @@ public class TelemetryService extends Service implements LocationListener {
                        AltosDebug.debug("disconnect(): stopping AltosDroidLink");
                        altos_link.close();
                        altos_link = null;
+                       ignite = null;
                }
                telemetry_state.config = null;
                if (notify) {
@@ -351,10 +421,14 @@ public class TelemetryService extends Service implements LocationListener {
        }
 
        private void start_altos_bluetooth(DeviceAddress address, boolean pause) {
-               // Get the BLuetoothDevice object
-               BluetoothDevice device = bluetooth_adapter.getRemoteDevice(address.address);
+               if (bluetooth_adapter == null || !bluetooth_adapter.isEnabled())
+                       return;
 
                disconnect(false);
+
+               // Get the BluetoothDevice object
+               BluetoothDevice device = bluetooth_adapter.getRemoteDevice(address.address);
+
                this.address = address;
                AltosDebug.debug("start_altos_bluetooth(): Connecting to %s (%s)", device.getName(), device.getAddress());
                altos_link = new AltosBluetooth(device, handler, pause);
@@ -363,14 +437,95 @@ public class TelemetryService extends Service implements LocationListener {
                send_to_clients();
        }
 
+       private void start_idle_monitor() {
+               if (altos_link != null && idle_monitor == null) {
+                       telemetry_stop();
+                       idle_monitor = new AltosIdleMonitor(this, altos_link, true, false);
+                       idle_monitor.set_callsign(AltosPreferences.callsign());
+                       idle_monitor.start();
+                       send_idle_mode_to_clients();
+               }
+       }
+
+       private void stop_idle_monitor() {
+               if (idle_monitor != null) {
+                       try {
+                               idle_monitor.abort();
+                       } catch (InterruptedException ie) {
+                       }
+                       idle_monitor = null;
+                       telemetry_start();
+                       send_idle_mode_to_clients();
+               }
+       }
+
+       private void reboot_remote() {
+               if (altos_link != null) {
+                       stop_idle_monitor();
+                       try {
+                               altos_link.start_remote();
+                               altos_link.printf("r eboot\n");
+                               altos_link.flush_output();
+                       } catch (TimeoutException te) {
+                       } catch (InterruptedException ie) {
+                       } finally {
+                               try {
+                                       altos_link.stop_remote();
+                               } catch (InterruptedException ie) {
+                               }
+                       }
+               }
+       }
+
+       private void ensure_ignite() {
+               if (ignite == null)
+                       ignite = new AltosIgnite(altos_link, true, false);
+       }
+
+       private synchronized void igniter_query(Messenger client) {
+               ensure_ignite();
+               HashMap<String,Integer> status_map = null;
+               ignite_running = true;
+               try {
+                       stop_idle_monitor();
+                       try {
+                               status_map = ignite.status();
+                       } catch (InterruptedException ie) {
+                               AltosDebug.debug("ignite.status interrupted");
+                       } catch (TimeoutException te) {
+                               AltosDebug.debug("ignite.status timeout");
+                       }
+               } finally {
+                       ignite_running = false;
+               }
+               Message m = Message.obtain(null, AltosDroid.MSG_IGNITER_STATUS, status_map);
+               try {
+                       client.send(m);
+               } catch (RemoteException e) {
+               }
+       }
+
+       private synchronized void igniter_fire(String igniter) {
+               ensure_ignite();
+               ignite_running = true;
+               stop_idle_monitor();
+               try {
+                       ignite.fire(igniter);
+               } catch (InterruptedException ie) {
+               } finally {
+                       ignite_running = false;
+               }
+       }
+
        // Timer for receiver battery voltage monitoring
        Timer receiver_voltage_timer;
 
        private void update_receiver_voltage() {
-               if (altos_link != null) {
+               if (altos_link != null && idle_monitor == null && !ignite_running) {
                        try {
                                double  voltage = altos_link.monitor_battery();
                                telemetry_state.receiver_battery = voltage;
+                               send_to_clients();
                        } catch (InterruptedException ie) {
                        }
                }
@@ -418,8 +573,7 @@ public class TelemetryService extends Service implements LocationListener {
                telemetry_state.connect = TelemetryState.CONNECT_CONNECTED;
                telemetry_state.address = address;
 
-               telemetry_reader = new TelemetryReader(altos_link, handler);
-               telemetry_reader.start();
+               telemetry_start();
 
                AltosDebug.debug("connected TelemetryReader started");
 
@@ -444,11 +598,6 @@ public class TelemetryService extends Service implements LocationListener {
                // Get local Bluetooth adapter
                bluetooth_adapter = BluetoothAdapter.getDefaultAdapter();
 
-               // If the adapter is null, then Bluetooth is not supported
-               if (bluetooth_adapter == null) {
-                       Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();
-               }
-
                telemetry_state = new TelemetryState();
 
                // Create a reference to the NotificationManager so that we can update our notifcation text later
@@ -464,31 +613,23 @@ public class TelemetryService extends Service implements LocationListener {
                telemetry_state.latest_serial = AltosPreferences.latest_state();
 
                for (int serial : serials) {
-                       AltosSavedState saved_state = AltosPreferences.state(serial);
+                       AltosState saved_state = AltosPreferences.state(serial);
                        if (saved_state != null) {
-                               if (serial == 0) {
-                                       serial = saved_state.state.serial;
-                                       AltosPreferences.set_state(serial, saved_state.state, saved_state.listener_state);
-                                       AltosPreferences.remove_state(0);
-                               }
                                if (telemetry_state.latest_serial == 0)
                                        telemetry_state.latest_serial = serial;
 
-                               AltosDebug.debug("recovered old state serial %d flight %d\n",
+                               AltosDebug.debug("recovered old state serial %d flight %d",
                                                 serial,
-                                                saved_state.state.flight);
-                               if (saved_state.state.gps != null)
-                                       AltosDebug.debug("\tposition %f,%f\n",
-                                                        saved_state.state.gps.lat,
-                                                        saved_state.state.gps.lon);
-                               telemetry_state.states.put(serial, saved_state.state);
+                                                saved_state.flight);
+                               if (saved_state.gps != null)
+                                       AltosDebug.debug("\tposition %f,%f",
+                                                        saved_state.gps.lat,
+                                                        saved_state.gps.lon);
+                               telemetry_state.states.put(serial, saved_state);
+                       } else {
+                               AltosDebug.debug("Failed to recover state for %d", serial);
                        }
                }
-
-               // Listen for GPS and Network position updates
-               LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
-
-               locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, this);
        }
 
        @Override
@@ -535,9 +676,6 @@ public class TelemetryService extends Service implements LocationListener {
        @Override
        public void onDestroy() {
 
-               // Stop listening for location updates
-               ((LocationManager) getSystemService(Context.LOCATION_SERVICE)).removeUpdates(this);
-
                // Stop the bluetooth Comms threads
                disconnect(true);
 
@@ -553,20 +691,17 @@ public class TelemetryService extends Service implements LocationListener {
                return messenger.getBinder();
        }
 
-
-       public void onLocationChanged(Location location) {
-               telemetry_state.location = location;
-               AltosDebug.debug("location changed");
+       /* AltosIdleMonitorListener */
+       public void update(AltosState state, AltosListenerState listener_state) {
+               telemetry_state.states.put(state.serial, state);
+               telemetry_state.receiver_battery = listener_state.battery;
                send_to_clients();
        }
 
-       public void onStatusChanged(String provider, int status, Bundle extras) {
+       public void failed() {
        }
 
-       public void onProviderEnabled(String provider) {
+       public void error(String reason) {
+               stop_idle_monitor();
        }
-
-       public void onProviderDisabled(String provider) {
-       }
-
 }
index c81dfcd2845453f6e0ab2514e41bec3e95638300..d3ccf0a9d8e576bab5e75c5cb96f2d0906790677 100644 (file)
@@ -18,7 +18,7 @@
 package org.altusmetrum.AltosDroid;
 
 import java.util.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 import android.location.Location;
 
 public class TelemetryState {
@@ -30,7 +30,6 @@ public class TelemetryState {
        int             connect;
        DeviceAddress   address;
        AltosConfigData config;
-       Location        location;
        int             crc_errors;
        double          receiver_battery;
        double          frequency;
@@ -44,7 +43,6 @@ public class TelemetryState {
                connect = CONNECT_NONE;
                config = null;
                states = new HashMap<Integer,AltosState>();
-               location = null;
                crc_errors = 0;
                receiver_battery = AltosLib.MISSING;
                frequency = AltosPreferences.frequency(0);
index e12b637564d884d28d7f4b5613c3a92cb710c7d8..2c563f66153c1e361e7aaa094a107b246f80a6a4 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 
index d233751252abf4a4f53d86f296a17db7fee82f2c..03dad1375c1857172d57af9a36a188f3d1c4217d 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public class AltosCRCException extends Exception {
        public int rssi;
index 8a389812643af28fd207d5573782967842a5b2a0..fa515b311858c4bb7fe6280be5f6b018740c7768 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.util.*;
index 87e701cfa6703375bab0f209ec433322c0cc2385..dc33daccf907bd46d2507ae7eccde1dd722af472 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 
index 7a518ab4e1babff32b65137ff6e98399b6e2634a..812296f33dff04483f08d8ed9ebfb78102096920 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.util.*;
 import java.text.*;
@@ -476,6 +476,18 @@ public class AltosConfigData implements Iterable<String> {
        }
 
 
+       public boolean mma655x_inverted() throws AltosUnknownProduct {
+               if (product.startsWith("EasyMega-v1"))
+                       return false;
+               if (product.startsWith("TeleMetrum-v2"))
+                       return true;
+               if (product.startsWith("TeleMega-v2"))
+                       return false;
+               if (product.startsWith("TeleMega-v1"))
+                       return false;
+               throw new AltosUnknownProduct(product);
+       }
+
        public void get_values(AltosConfigValues source) throws AltosConfigDataException {
 
                /* HAS_FLIGHT */
@@ -493,8 +505,6 @@ public class AltosConfigData implements Iterable<String> {
                        radio_enable = source.radio_enable();
                if (callsign != null)
                        callsign = source.callsign();
-               if (radio_calibration >= 0)
-                       radio_calibration = source.radio_calibration();
                if (telemetry_rate >= 0)
                        telemetry_rate = source.telemetry_rate();
 
@@ -601,10 +611,6 @@ public class AltosConfigData implements Iterable<String> {
                if (apogee_lockout >= 0)
                        link.printf("c L %d\n", apogee_lockout);
 
-               /* Don't mess with radio calibration when remote */
-               if (radio_calibration > 0 && !remote)
-                       link.printf("c f %d\n", radio_calibration);
-
                /* HAS_RADIO */
                if (has_frequency()) {
                        boolean has_frequency = radio_frequency >= 0;
index d1d0d8d0ba42ed40e0712d8b35e23ec0f83ca071..75cd1695543ff11714d838d03ff729317d00673f 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public class AltosConfigDataException extends Exception {
 
index 3306aa4bfe2c0844758d9d3e21e5e036d21f884a..aab0892a0537218810debbc68cb9b298028c21bb 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public interface AltosConfigValues {
        /* set and get all of the dialog values */
@@ -45,8 +45,6 @@ public interface AltosConfigValues {
 
        public abstract void set_radio_calibration(int new_radio_calibration);
 
-       public abstract int radio_calibration() throws AltosConfigDataException;
-
        public abstract void set_radio_enable(int new_radio_enable);
 
        public abstract int radio_enable();
index 59092a6fcfa262442cf4f903e7b7307eaa3c59ef..265b5f0f633e26a544203d83b188a52971166468 100644 (file)
@@ -18,7 +18,7 @@
 /*
  * Sensor data conversion functions
  */
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public class AltosConvert {
        /*
@@ -325,6 +325,14 @@ public class AltosConvert {
                return miles_to_meters(mps) / 3600;
        }
 
+       public static double mps_to_fps(double mps) {
+               return meters_to_miles(mps) * 5280;
+       }
+
+       public static double fps_to_mps(double mps) {
+               return miles_to_meters(mps) / 5280;
+       }
+
        public static double meters_to_mach(double meters) {
                return meters / 343;            /* something close to mach at usual rocket sites */
        }
index 35f51dd4f941722e35078f37c17f56ae6c475a37..e93c2d2de74720a8d81783f1249545714fc4164c 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 
index fe18250e6d72d19893ca0ac13ca271bcd95c72d1..b68a4525d79c8565951930b91c2b1db0b8f020fb 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public class AltosDistance extends AltosUnits {
 
index 7379b5106b31ab44f2063214bd1e3687e806495c..5f0a349fb8207f6ba769040ab499cd749b46b864 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.util.*;
index b996eb008508fa2d60e16a97255f8f9282d8883a..7a80e29489df6e7ba60ff34915f19224325f8f32 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.text.*;
 import java.util.concurrent.*;
@@ -69,7 +69,7 @@ public class AltosEepromChunk {
                        eeprom = new AltosEepromTM(this, offset);
                        break;
                case AltosLib.AO_LOG_FORMAT_TINY:
-                       eeprom = new AltosEepromTm(this, offset, state);
+                       eeprom = new AltosEepromTMini(this, offset, state);
                        break;
                case AltosLib.AO_LOG_FORMAT_TELEMETRY:
                case AltosLib.AO_LOG_FORMAT_TELESCIENCE:
index 67f7fc57fc841b105056b4c1403f2f219b24b0fc..1a02cb9c1baf14ea2993af1416407f3d5cb10249 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.util.*;
index d88aeab9e77a33fd6e567b69a913cc527efd0c9a..000bb1be4d33c7530c03bdcf9a652af348be6622 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.util.*;
@@ -89,7 +89,7 @@ public class AltosEepromFile extends AltosStateIterable {
                        body = new AltosEepromIterable(AltosEepromTM.read(input));
                        break;
                case AltosLib.AO_LOG_FORMAT_TINY:
-                       body = new AltosEepromIterable(AltosEepromTm.read(input));
+                       body = new AltosEepromIterable(AltosEepromTMini.read(input));
                        break;
                case AltosLib.AO_LOG_FORMAT_TELEMETRY:
                case AltosLib.AO_LOG_FORMAT_TELESCIENCE:
index 07ef2920a7d49490a399cba5307372c453644b8f..a0a074ee2533ce396da4a0fb88105091111b6a8c 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.util.*;
index e7ed93b09162f766a9842511e56ce4a2702a7013..6c8c56d45c403a25f61fc889216c3f414c207e6c 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.util.*;
index f607fbd2733866ea8e64ae4936c4ef7d30c823f5..97bb9285667fd703ab337615f76794a7eed2f5eb 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.util.*;
index 12d10b6e002bf01ce79c18c1c978758c0d4e1d10..4d511ead917d3002688c3919d85031094e052c9e 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.util.*;
index d1a1ab6caaed0372372808d4ec3d683f299773d8..f0ed2db4c91f663862848e2d16d9a55d0e8da6cc 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.text.*;
 import java.util.concurrent.*;
index db8ab3a86ca1ea2d85c29c4deab6a4e2dcaffe43..29f0aa905dc51442d1ec3878d8d8df85de4e4349 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.util.*;
index df0075b990e895a203fd7a0ab258e85d8138d799..5662c8e56e00939915c66f384436770ab63d566e 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.util.*;
index 228145eb4a0bd74079b686d0b25cf71d8ea106e3..f429a0e8d73908bd295d5d3d7fa0ee526c08de7a 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.util.*;
index 800dc0b937b1fae01b116a8f33e6ec286485ddff..a966c63165524f7fff3e8093ec53867f223c5210 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public interface AltosEepromMonitor {
 
index 316058e2141b1adc4079057fd17865fbe479a42c..7a27a234cf16148ab8b3f94ab783e8b5162b6937 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.util.*;
diff --git a/altoslib/AltosEepromTMini.java b/altoslib/AltosEepromTMini.java
new file mode 100644 (file)
index 0000000..8f01c08
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * 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.altoslib_10;
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
+public class AltosEepromTMini extends AltosEeprom {
+       public int      i;
+       public int      a;
+       public int      b;
+
+       public static final int record_length = 2;
+
+       public void write(PrintStream out) {
+               out.printf("%c %4x %4x %4x\n", cmd, tick, a, b);
+       }
+
+       public int record_length() { return record_length; }
+
+       public String string() {
+               return String.format("%c %4x %4x %4x\n", cmd, tick, a, b);
+       }
+
+       public void update_state(AltosState state) {
+               super.update_state(state);
+
+               switch (cmd) {
+               case AltosLib.AO_LOG_FLIGHT:
+                       state.set_state(AltosLib.ao_flight_boost);
+                       state.set_flight(b);
+                       break;
+               case AltosLib.AO_LOG_PRESSURE:
+                       if (tick == 0)
+                               state.set_ground_pressure(AltosConvert.barometer_to_pressure(b));
+                       else
+                               state.set_pressure(AltosConvert.barometer_to_pressure(b));
+                       break;
+               case AltosLib.AO_LOG_STATE:
+                       state.set_state(a);
+                       break;
+               }
+       }
+
+       public AltosEepromTMini (AltosEepromChunk chunk, int start, AltosState state) throws ParseException {
+               int     value = chunk.data16(start);
+
+               int     i = (chunk.address + start) / record_length;
+
+               cmd = chunk.data(start);
+               valid = true;
+
+               valid = !chunk.erased(start, record_length);
+
+               switch (i) {
+               case 0:
+                       cmd = AltosLib.AO_LOG_FLIGHT;
+                       tick = 0;
+                       a = 0;
+                       b = value;
+                       break;
+               case 1:
+                       cmd = AltosLib.AO_LOG_PRESSURE;
+                       tick = 0;
+                       a = 0;
+                       b = value;
+                       break;
+               default:
+                       if ((value & 0x8000) != 0) {
+                               cmd = AltosLib.AO_LOG_STATE;
+                               tick = state.tick;
+                               a = value & 0x7fff;
+                               b = 0;
+                       } else {
+                               if (state.ascent)
+                                       tick = state.tick + 10;
+                               else
+                                       tick = state.tick + 100;
+                               cmd = AltosLib.AO_LOG_PRESSURE;
+                               a = 0;
+                               b = value;
+                       }
+                       break;
+               }
+       }
+
+       public AltosEepromTMini (String line) {
+               valid = false;
+               tick = 0;
+               a = 0;
+               b = 0;
+               if (line == null) {
+                       cmd = AltosLib.AO_LOG_INVALID;
+               } else {
+                       try {
+                               String[] tokens = line.split("\\s+");
+
+                               if (tokens[0].length() == 1) {
+                                       if (tokens.length != 4) {
+                                               cmd = AltosLib.AO_LOG_INVALID;
+                                       } else {
+                                               cmd = tokens[0].codePointAt(0);
+                                               tick = Integer.parseInt(tokens[1],16);
+                                               valid = true;
+                                               a = Integer.parseInt(tokens[2],16);
+                                               b = Integer.parseInt(tokens[3],16);
+                                       }
+                               } else {
+                                       cmd = AltosLib.AO_LOG_INVALID;
+                               }
+                       } catch (NumberFormatException ne) {
+                               cmd = AltosLib.AO_LOG_INVALID;
+                       }
+               }
+       }
+
+       public AltosEepromTMini(int in_cmd, int in_tick, int in_a, int in_b) {
+               valid = true;
+               cmd = in_cmd;
+               tick = in_tick;
+               a = in_a;
+               b = in_b;
+       }
+
+       static public LinkedList<AltosEeprom> read(FileInputStream input) {
+               LinkedList<AltosEeprom> tms = new LinkedList<AltosEeprom>();
+
+               for (;;) {
+                       try {
+                               String line = AltosLib.gets(input);
+                               if (line == null)
+                                       break;
+                               AltosEepromTMini tm = new AltosEepromTMini(line);
+                               tms.add(tm);
+                       } catch (IOException ie) {
+                               break;
+                       }
+               }
+
+               return tms;
+       }
+
+}
diff --git a/altoslib/AltosEepromTm.java b/altoslib/AltosEepromTm.java
deleted file mode 100644 (file)
index 090b65e..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * 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.altoslib_9;
-
-import java.io.*;
-import java.util.*;
-import java.text.*;
-
-public class AltosEepromTm extends AltosEeprom {
-       public int      i;
-       public int      a;
-       public int      b;
-
-       public static final int record_length = 2;
-
-       public void write(PrintStream out) {
-               out.printf("%c %4x %4x %4x\n", cmd, tick, a, b);
-       }
-
-       public int record_length() { return record_length; }
-
-       public String string() {
-               return String.format("%c %4x %4x %4x\n", cmd, tick, a, b);
-       }
-
-       public void update_state(AltosState state) {
-               super.update_state(state);
-
-               switch (cmd) {
-               case AltosLib.AO_LOG_FLIGHT:
-                       state.set_state(AltosLib.ao_flight_boost);
-                       state.set_flight(b);
-                       break;
-               case AltosLib.AO_LOG_PRESSURE:
-                       if (tick == 0)
-                               state.set_ground_pressure(AltosConvert.barometer_to_pressure(b));
-                       else
-                               state.set_pressure(AltosConvert.barometer_to_pressure(b));
-                       break;
-               case AltosLib.AO_LOG_STATE:
-                       state.set_state(a);
-                       break;
-               }
-       }
-
-       public AltosEepromTm (AltosEepromChunk chunk, int start, AltosState state) throws ParseException {
-               int     value = chunk.data16(start);
-
-               int     i = (chunk.address + start) / record_length;
-
-               cmd = chunk.data(start);
-               valid = true;
-
-               valid = !chunk.erased(start, record_length);
-
-               switch (i) {
-               case 0:
-                       cmd = AltosLib.AO_LOG_FLIGHT;
-                       tick = 0;
-                       a = 0;
-                       b = value;
-                       break;
-               case 1:
-                       cmd = AltosLib.AO_LOG_PRESSURE;
-                       tick = 0;
-                       a = 0;
-                       b = value;
-                       break;
-               default:
-                       if ((value & 0x8000) != 0) {
-                               cmd = AltosLib.AO_LOG_STATE;
-                               tick = state.tick;
-                               a = value & 0x7fff;
-                               b = 0;
-                       } else {
-                               if (state.ascent)
-                                       tick = state.tick + 10;
-                               else
-                                       tick = state.tick + 100;
-                               cmd = AltosLib.AO_LOG_PRESSURE;
-                               a = 0;
-                               b = value;
-                       }
-                       break;
-               }
-       }
-
-       public AltosEepromTm (String line) {
-               valid = false;
-               tick = 0;
-               a = 0;
-               b = 0;
-               if (line == null) {
-                       cmd = AltosLib.AO_LOG_INVALID;
-               } else {
-                       try {
-                               String[] tokens = line.split("\\s+");
-
-                               if (tokens[0].length() == 1) {
-                                       if (tokens.length != 4) {
-                                               cmd = AltosLib.AO_LOG_INVALID;
-                                       } else {
-                                               cmd = tokens[0].codePointAt(0);
-                                               tick = Integer.parseInt(tokens[1],16);
-                                               valid = true;
-                                               a = Integer.parseInt(tokens[2],16);
-                                               b = Integer.parseInt(tokens[3],16);
-                                       }
-                               } else {
-                                       cmd = AltosLib.AO_LOG_INVALID;
-                               }
-                       } catch (NumberFormatException ne) {
-                               cmd = AltosLib.AO_LOG_INVALID;
-                       }
-               }
-       }
-
-       public AltosEepromTm(int in_cmd, int in_tick, int in_a, int in_b) {
-               valid = true;
-               cmd = in_cmd;
-               tick = in_tick;
-               a = in_a;
-               b = in_b;
-       }
-
-       static public LinkedList<AltosEeprom> read(FileInputStream input) {
-               LinkedList<AltosEeprom> tms = new LinkedList<AltosEeprom>();
-
-               for (;;) {
-                       try {
-                               String line = AltosLib.gets(input);
-                               if (line == null)
-                                       break;
-                               AltosEepromTm tm = new AltosEepromTm(line);
-                               tms.add(tm);
-                       } catch (IOException ie) {
-                               break;
-                       }
-               }
-
-               return tms;
-       }
-
-}
index b8d62179b6f27dfd08b3020482917c64a5182729..d1d1761072cb4ecfde8a2e8877ee7478c56b969d 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.File;
 import java.util.*;
index 627b758b3800559c51750355106f82fc8467810e..d79edf686ee0a801093852139879798b309ef57c 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 
index e977c579bed8e04ecd7e691b691b40574ccf4cf7..8d171baf32abe5a686e5bcbff409815cccb0da5c 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public interface AltosFlashListener {
        public void position(String label, int percent);
index 912f470f07c98db37565316d0b0ad1c5b76ca85d..4b57526a219d35734c5de773f9f274e1efa40559 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public interface AltosFlightDisplay extends AltosUnitsListener, AltosFontListener {
        void reset();
index 84b2392befa33113124d56fba76605c0783d0fa0..62f24e9f5aa98cc79ad63268afc8b6247e9f47c9 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.text.*;
 import java.io.*;
index 39e8cdae106ea3ea165fdc6c32e802172c2eaa23..1c7d67e0719d3d7c3a7df5b091423da1b81ceace 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 
@@ -57,7 +57,7 @@ public class AltosFlightStats {
                }
 
                if (state == null)
-                       return 0;
+                       return AltosLib.MISSING;
 
                double  landed_height = state.height();
 
@@ -65,7 +65,7 @@ public class AltosFlightStats {
 
                boolean above = true;
 
-               double  landed_time = -1000;
+               double  landed_time = AltosLib.MISSING;
 
                for (AltosState s : states) {
                        state = s;
@@ -73,14 +73,12 @@ public class AltosFlightStats {
                        if (state.height() > landed_height + 10) {
                                above = true;
                        } else {
-                               if (above && state.height() < landed_height + 2) {
+                               if (above && Math.abs(state.height() - landed_height) < 2) {
                                        above = false;
                                        landed_time = state.time;
                                }
                        }
                }
-               if (landed_time == -1000)
-                       landed_time = state.time;
                return landed_time;
        }
 
@@ -96,10 +94,8 @@ public class AltosFlightStats {
                                break;
                }
                if (state == null)
-                       return 0;
+                       return AltosLib.MISSING;
 
-               if (boost_time == AltosLib.MISSING)
-                       boost_time = state.time;
                return boost_time;
        }
 
@@ -122,6 +118,13 @@ public class AltosFlightStats {
                has_imu = false;
                has_mag = false;
                has_orient = false;
+
+               for (int s = AltosLib.ao_flight_startup; s <= AltosLib.ao_flight_landed; s++) {
+                       state_count[s] = 0;
+                       state_speed[s] = 0.0;
+                       state_accel[s] = 0.0;
+               }
+
                for (AltosState state : states) {
                        if (serial == AltosLib.MISSING && state.serial != AltosLib.MISSING)
                                serial = state.serial;
@@ -139,10 +142,13 @@ public class AltosFlightStats {
                                has_flight_data = true;
 
                        int state_id = state.state();
-                       if (state.time >= boost_time && state_id < AltosLib.ao_flight_boost)
+                       if (boost_time != AltosLib.MISSING && 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)
+                       }
+                       if (landed_time != AltosLib.MISSING && 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;
index ae23e13cf8bfc8a0688cfe27b85f84204c20f0bd..565f50e41b110f3347b1f5523f79ea1af88e794d 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public interface AltosFontListener {
        void font_size_changed(int font_size);
index 7c6ffe61d5120ac05041316d13978604922817e8..9542fe333858cdac0cbe715db08b1b4001cc41ed 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
-public class AltosFrequency {
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
+public class AltosFrequency implements Serializable {
        public double   frequency;
        public String   description;
 
@@ -44,6 +48,10 @@ public class AltosFrequency {
                                     frequency, description);
        }
 
+       public String frequency_string() {
+               return String.format("%7.3f", frequency);
+       }
+
        public boolean close(double f) {
                double  diff = Math.abs(frequency - f);
 
index a4cd20618f7c93345b488d5f703f2bc57ba07729..c5290a3a0be52afa70d1dbf967dc459508264e5a 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.text.*;
 import java.util.concurrent.*;
index 3f9e479e36614bee3900b2119fa9ed1c7ff46907..c853b634f49514c1827600ff3470d2d139ffe896 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
+import java.text.*;
+import java.util.concurrent.*;
+import java.io.*;
 
-public class AltosGPSSat {
+public class AltosGPSSat implements Serializable {
        public int      svid;
        public int      c_n0;
 
index 9ced17e7c82dd8b8dad66f7a467001ccff1cc111..de3904bff1cbadd38489115d3ac0ccfe9bebe9bd 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.lang.Math;
 import java.io.*;
index 5cc3c20c7039e98536303a9061948271e79eff89..2bae25664975b161ce7f2e1992be4504c05cdd0f 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public class AltosHeight extends AltosUnits {
 
index fb036d0c1944b4445a9732a42d1ddddfdcedbe87..f72d4183fa307a1b4abdcf3131fcc27a4f12ccdc 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.util.LinkedList;
index 0149fde1f6052fdc78f44d2f1bcfb9b52c84cf70..1d9cbb186cc30d49b8b5824f837e47a7ce7da0cf 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public class AltosHexsym {
        String  name;
index 285de8cc9302e931c761648387112d792a5d2bea..62539e08cd3531342af6b1aae3180a9a53481851 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.util.concurrent.*;
 import java.io.*;
index 2e5981dbaa73a8ecc3e98cc1231a07bb1ff90344..07a628c314abcf3b3afe66bc1e1bf2ebb6f56ec9 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.util.*;
index 48db6ab444983a752b5d93eab32ee1c247739f27..0095bb732899d81ffa445db1049bc5aece33efcb 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.util.*;
@@ -40,7 +40,7 @@ class AltosIdler {
        static final int        idle_sensor_tmini = 14;
        static final int        idle_sensor_tgps = 15;
 
-       public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException, TimeoutException {
+       public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException, TimeoutException, AltosUnknownProduct {
                for (int idler : idlers) {
                        AltosIdle idle = null;
                        switch (idler) {
@@ -137,8 +137,9 @@ public class AltosIdleFetch implements AltosStateUpdate {
        double                  frequency;
        String                  callsign;
 
-       public void update_state(AltosState state) throws InterruptedException {
+       public void update_state(AltosState state) throws InterruptedException, AltosUnknownProduct {
                try {
+                       boolean matched = false;
                        /* Fetch config data from remote */
                        AltosConfigData config_data = new AltosConfigData(link);
                        state.set_state(AltosLib.ao_flight_stateless);
@@ -150,9 +151,12 @@ public class AltosIdleFetch implements AltosStateUpdate {
                        for (AltosIdler idler : idlers) {
                                if (idler.matches(config_data)) {
                                        idler.update_state(state, link, config_data);
+                                       matched = true;
                                        break;
                                }
                        }
+                       if (!matched)
+                               throw new AltosUnknownProduct(config_data.product);
                        state.set_received_time(System.currentTimeMillis());
                } catch (TimeoutException te) {
                }
index d5c1a4283d41b33f0735cb2e4e7f6f946ff655d2..c67b4d8aa6b5f08e696959323bd0af1aef28d851 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.util.concurrent.*;
@@ -28,6 +28,7 @@ public class AltosIdleMonitor extends Thread {
        AltosIdleFetch          fetch;
 
        boolean                 remote;
+       boolean                 close_on_exit;
        double                  frequency;
        String                  callsign;
 
@@ -50,7 +51,7 @@ public class AltosIdleMonitor extends Thread {
                return link.reply_abort;
        }
 
-       boolean update_state(AltosState state) throws InterruptedException, TimeoutException {
+       boolean update_state(AltosState state) throws InterruptedException, TimeoutException, AltosUnknownProduct {
                boolean         worked = false;
                boolean         aborted = false;
 
@@ -98,6 +99,8 @@ public class AltosIdleMonitor extends Thread {
                                        update_state(state);
                                        listener.update(state, listener_state);
                                } catch (TimeoutException te) {
+                               } catch (AltosUnknownProduct ae) {
+                                       listener.error(String.format("Unknown product \"%s\"", ae.product));
                                }
                                if (link.has_error || link.reply_abort) {
                                        listener.failed();
@@ -107,18 +110,25 @@ public class AltosIdleMonitor extends Thread {
                        }
                } catch (InterruptedException ie) {
                }
-               try {
-                       link.close();
-               } catch (InterruptedException ie) {
+               if (close_on_exit) {
+                       try {
+                               link.close();
+                       } catch (InterruptedException ie) {
+                       }
                }
        }
 
-       public AltosIdleMonitor(AltosIdleMonitorListener in_listener, AltosLink in_link, boolean in_remote)
-               throws FileNotFoundException, InterruptedException, TimeoutException {
+       public AltosIdleMonitor(AltosIdleMonitorListener in_listener, AltosLink in_link, boolean in_remote, boolean in_close_on_exit) {
                listener = in_listener;
                link = in_link;
                remote = in_remote;
+               close_on_exit = in_close_on_exit;
                listener_state = new AltosListenerState();
                fetch = new AltosIdleFetch(link);
        }
+
+       public AltosIdleMonitor(AltosIdleMonitorListener in_listener, AltosLink in_link, boolean in_remote) {
+               this(in_listener, in_link, in_remote, true);
+       }
 }
+
index 5b751e52e3b1f35c532fae855abccb4cd0b63d6b..36857f588d5e98fcb634a4d257a3c464a112ba99 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public interface AltosIdleMonitorListener {
        public void update(AltosState state, AltosListenerState listener_state);
+       public void error(String reason);
        public void failed();
 }
index d5348628c73ce500565997a56189830ed2f82ab1..ab9c2da667b72991d976b505324869382bd3865c 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.util.*;
 import java.io.*;
@@ -24,6 +24,7 @@ import java.util.concurrent.*;
 public class AltosIgnite {
        AltosLink       link;
        boolean         remote;
+       boolean         close_on_exit;
        boolean         link_started;
        boolean         have_npyro = false;
        int             npyro;
@@ -180,14 +181,18 @@ public class AltosIgnite {
 
        public void close() throws InterruptedException {
                stop_link();
-               link.close();
+               if (close_on_exit)
+                       link.close();
                link = null;
        }
 
-       public AltosIgnite(AltosLink in_link, boolean in_remote)
-               throws FileNotFoundException, TimeoutException, InterruptedException {
-
+       public AltosIgnite(AltosLink in_link, boolean in_remote, boolean in_close_on_exit) {
                link = in_link;
                remote = in_remote;
+               close_on_exit = in_close_on_exit;
+       }
+
+       public AltosIgnite(AltosLink in_link, boolean in_remote) {
+               this(in_link, in_remote, true);
        }
-}
\ No newline at end of file
+}
index 7a0fe9dd781c8a11326fdb8885d770fc9f33c44c..d54335c7f18b87fe1e9edc10ecd17958c6b2d9ca 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 
index d302535fabb1bd4646983cae63cdbe7922536f41..ac5e0257cec482e7bc9ba2980cbd8dd7ad5d6c6a 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.util.*;
index 8cd851e58d18ec6f18aa5020c31e0e3f4511a5cc..d39fe15f38feaf71468cd6c2c42caeb4bd77b8e5 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public class AltosLatLon {
        public double   lat;
index 51d77785a3a7e35077ce4c0a3e5d2eef75628b5d..e0deb504dfe0a93427136cff44703633798d7444 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public class AltosLatitude extends AltosLocation {
        public String pos() { return "N"; }
index 7958d186c6afb9fe942d324685d2a408ba0e390d..ee2a60e9c9b16559e0ea328d5f379e1d9a88beed 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.lang.*;
index 4270dc4ac60766390d1566c5be61fad4fa112a05..c77eadc5e7cad800af54ab7502875b406ac76708 100644 (file)
@@ -14,7 +14,7 @@
  * 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_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.lang.*;
index 4e843c10dd26b14c74e4d42c763f1f05afa536aa..3ebac60142889b4eebd81154efaf6c1862417244 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.lang.*;
@@ -47,7 +47,12 @@ public class AltosLaunchSites extends Thread {
 
        public void run() {
                try {
-                       url = new URL(AltosLib.launch_sites_url);
+                       String  path;
+
+                       path = System.getenv(AltosLib.launch_sites_env);
+                       if (path == null)
+                               path = AltosLib.launch_sites_url;
+                       url = new URL(path);
                        URLConnection uc = url.openConnection();
 
                        InputStreamReader in_stream = new InputStreamReader(uc.getInputStream(), AltosLib.unicode_set);
@@ -60,6 +65,7 @@ public class AltosLaunchSites extends Thread {
                                add(line);
                        }
                } catch (Exception e) {
+                       System.out.printf("file exception %s\n", e.toString());
                } finally {
                        notify_complete();
                }
index 575cfc1a13721b4af9070e96767bd52ddfe4c131..a73a7759b6a26422d9877e8c865e4d506998908d 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.util.*;
 import java.io.*;
@@ -198,6 +198,7 @@ public class AltosLib {
        };
 
        public static final String launch_sites_url = "http://www.altusmetrum.org/AltOS/launch-sites.txt";
+       public static final String launch_sites_env = "LAUNCH_SITES";
 //     public static final String launch_sites_url = "file:///home/keithp/misc/text/altusmetrum/AltOS/launch-sites.txt";
 
        public static final int ao_telemetry_standard_len = 32;
index cf3a1984ba836c2983c3e7e1669dee6cee4f7f41..876cb7dfb491f4069a1a2eb12fb7321251209023 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public class AltosLine {
        public String   line;
index 109674175cab607949142b3c3a9642a7e9ef17d2..cd8609c037a00dac6d81eddde1c0ce806ddca80d 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.util.concurrent.*;
@@ -170,8 +170,8 @@ public abstract class AltosLink implements Runnable {
                boolean can_cancel = can_cancel_reply();
                String  reply = null;
 
-               if (!can_cancel && remote)
-                       System.out.printf("Uh-oh, reading remote serial device from swing thread\n");
+//             if (!can_cancel && remote)
+//                     System.out.printf("Uh-oh, reading remote serial device from swing thread\n");
 
                if (remote && can_cancel) {
                        timeout = 500;
@@ -539,15 +539,15 @@ public abstract class AltosLink implements Runnable {
 
                if (config_data.has_monitor_battery()) {
                        try {
-                       String[] items = adc();
-                       for (int i = 0; i < items.length;) {
-                               if (items[i].equals("batt")) {
-                                       monitor_batt = Integer.parseInt(items[i+1]);
-                                       i += 2;
-                                       continue;
+                               String[] items = adc();
+                               for (int i = 0; i < items.length;) {
+                                       if (items[i].equals("batt")) {
+                                               monitor_batt = Integer.parseInt(items[i+1]);
+                                               i += 2;
+                                               continue;
+                                       }
+                                       i++;
                                }
-                               i++;
-                       }
                        } catch (TimeoutException te) {
                        }
                }
index 7df5c9bfa2724a38024d94efcd69f94f58f8a2c6..389e392f115916f4a30a6e7c38934f8162ba40e4 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 
index 436e4b0277f1a6960ec9dbf2542abea873bba644..df1c9d6382f557263f03d4fdfd8c3cc04d9b7703 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public abstract class AltosLocation extends AltosUnits {
 
index 58306d5570742da65abbf69fd962df6b993f6279..a6e042151f99227fb9cd4de46298faa85966faea 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.text.*;
index bc0886027c18afaaf5e702599e2dd5bd69c5ea81..61d74afc63b12cea777b02eeb5505ae947a3bcf9 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public class AltosLongitude extends AltosLocation {
        public String pos() { return "E"; }
index 3643ca9e652228be76b13bcac7baeb31e340f725..ce5a48c305aaa18bb6006dc8f8dbfc622600577d 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.util.concurrent.*;
 import java.io.*;
index 6c08f2d73ddcae1d0cc31caa89da8e93528cc424..1841277f8bd61889390f0d5802dff09a7584b603 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.lang.*;
@@ -308,7 +308,11 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener {
                        upper_left = floor(transform.screen_point(new AltosPointInt(0, 0)));
                        lower_right = floor(transform.screen_point(new AltosPointInt(width(), height())));
                }
-               for (AltosPointInt point : tiles.keySet()) {
+
+               Enumeration<AltosPointInt> keyEnumeration = tiles.keys();
+
+               while (keyEnumeration.hasMoreElements()) {
+                       AltosPointInt point = keyEnumeration.nextElement();
                        if (point.x < upper_left.x || lower_right.x < point.x ||
                            point.y < upper_left.y || lower_right.y < point.y) {
                                tiles.remove(point);
@@ -324,7 +328,8 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener {
                                if (!tiles.containsKey(point)) {
                                        AltosLatLon     ul = transform.lat_lon(point);
                                        AltosLatLon     center = transform.lat_lon(new AltosPointDouble(x + AltosMap.px_size/2, y + AltosMap.px_size/2));
-                                       AltosMapTile tile = map_interface.new_tile(this, ul, center, zoom, maptype, px_size);
+                                       AltosMapTile tile = map_interface.new_tile(cache, ul, center, zoom, maptype, px_size);
+                                       tile.add_listener(this);
                                        tiles.put(point, tile);
                                }
                        }
@@ -341,11 +346,6 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener {
                centre(lat, lon);
                tiles.clear();
                make_tiles();
-               for (AltosMapTile tile : tiles.values()) {
-                       tile.add_store_listener(this);
-                       if (tile.store_status() != AltosMapTile.loading)
-                               listener.notify_tile(tile, tile.store_status());
-               }
                repaint();
        }
 
@@ -377,7 +377,10 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener {
 
        /* AltosMapTileListener methods */
        public synchronized void notify_tile(AltosMapTile tile, int status) {
-               for (AltosPointInt point : tiles.keySet()) {
+               Enumeration<AltosPointInt> keyEnumeration = tiles.keys();
+
+               while (keyEnumeration.hasMoreElements()) {
+                       AltosPointInt point = keyEnumeration.nextElement();
                        if (tile == tiles.get(point)) {
                                AltosPointInt   screen = transform.screen(point);
                                repaint(screen.x, screen.y, AltosMap.px_size, AltosMap.px_size);
@@ -414,10 +417,8 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener {
                if (distance > drag_far)
                        dragged = true;
 
-               if (transform == null) {
-                       debug("Transform not set in drag\n");
+               if (transform == null)
                        return;
-               }
 
                AltosLatLon new_centre = transform.screen_lat_lon(new AltosPointInt(width() / 2 - dx, height() / 2 - dy));
                centre(new_centre);
@@ -432,7 +433,6 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener {
        private void drag_stop(int x, int y) {
                if (!dragged) {
                        if (transform == null) {
-                               debug("Transform not set in stop\n");
                                return;
                        }
                        map_interface.select_object (transform.screen_lat_lon(new AltosPointInt(x,y)));
@@ -440,14 +440,14 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener {
        }
 
        private void line_start(int x, int y) {
-               if (line != null) {
+               if (line != null && transform != null) {
                        line.pressed(new AltosPointInt(x, y), transform);
                        repaint();
                }
        }
 
        private void line(int x, int y) {
-               if (line != null) {
+               if (line != null && transform != null) {
                        line.dragged(new AltosPointInt(x, y), transform);
                        repaint();
                }
index 744790c6964c236928081a36cc00f5c20849579f..38e0f769871a186d4ae434ce4d24668ba32e2e4c 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.net.*;
@@ -23,25 +23,20 @@ import java.net.*;
 public class AltosMapCache implements AltosMapCacheListener {
 
        /* An entry in the MapCache */
-       class MapCacheElement implements AltosMapStoreListener {
+       class MapCacheElement implements AltosMapTileListener {
 
                AltosMapTile            tile;           /* Notify when image has been loaded */
                AltosImage              image;
-               AltosMapStore           store;
                long                    used;
 
                class loader implements Runnable {
                        public void run() {
-                               if (image != null)
-                                       tile.notify_image(image);
-                               try {
-                                       image = map_interface.load_image(store.file);
-                               } catch (Exception ex) {
+                               if (image == null) {
+                                       try {
+                                               image = map_interface.load_image(tile.store.file);
+                                       } catch (Exception ex) {
+                                       }
                                }
-                               if (image == null)
-                                       tile.set_status(AltosMapTile.failed);
-                               else
-                                       tile.set_status(AltosMapTile.success);
                                tile.notify_image(image);
                        }
                }
@@ -60,41 +55,21 @@ public class AltosMapCache implements AltosMapCacheListener {
                }
 
                public boolean has_map() {
-                       return store.status() == AltosMapTile.success;
+                       return tile.status == AltosMapTile.loaded;
                }
 
-               public synchronized void notify_store(AltosMapStore store, int status) {
-                       switch (status) {
-                       case AltosMapTile.loading:
-                               break;
-                       case AltosMapTile.success:
+               public synchronized void notify_tile(AltosMapTile tile, int status) {
+                       if (status == AltosMapTile.fetched) {
+                               System.out.printf("tile fetched, loading image\n");
                                load();
-                               break;
-                       default:
-                               tile.set_status(status);
-                               tile.notify_image(null);
                        }
                }
 
-               public MapCacheElement(AltosMapTile tile, AltosMapStore store) throws IOException {
+               public MapCacheElement(AltosMapTile tile) {
                        this.tile = tile;
                        this.image = null;
-                       this.store = store;
                        this.used = 0;
-
-                       int status = store.status();
-                       switch (status) {
-                       case AltosMapTile.loading:
-                               store.add_listener(this);
-                               break;
-                       case AltosMapTile.success:
-                               load();
-                               break;
-                       default:
-                               tile.set_status(status);
-                               tile.notify_image(null);
-                               break;
-                       }
+                       tile.add_listener(this);
                }
        }
 
@@ -135,7 +110,7 @@ public class AltosMapCache implements AltosMapCacheListener {
                }
        }
 
-       public AltosImage get(AltosMapTile tile, AltosMapStore store, int width, int height) {
+       public AltosImage get(AltosMapTile tile) {
                int             oldest = -1;
                long            age = used;
 
@@ -148,7 +123,7 @@ public class AltosMapCache implements AltosMapCacheListener {
                                        oldest = i;
                                        break;
                                }
-                               if (store.equals(element.store)) {
+                               if (tile.store.equals(element.tile.store)) {
                                        element.used = used++;
                                        return element.image;
                                }
@@ -158,24 +133,15 @@ public class AltosMapCache implements AltosMapCacheListener {
                                }
                        }
 
-                       try {
-                               element = new MapCacheElement(tile, store);
-                               element.used = used++;
-                               if (elements[oldest] != null)
-                                       elements[oldest].flush();
+                       element = new MapCacheElement(tile);
+                       element.used = used++;
+                       if (elements[oldest] != null)
+                               elements[oldest].flush();
 
-                               elements[oldest] = element;
-
-                               if (element.image == null)
-                                       tile.set_status(AltosMapTile.loading);
-                               else
-                                       tile.set_status(AltosMapTile.success);
-
-                               return element.image;
-                       } catch (IOException e) {
-                               tile.set_status(AltosMapTile.failed);
-                               return null;
-                       }
+                       elements[oldest] = element;
+                       System.out.printf("AltosMapCache.get image ? %s\n",
+                                         element.image == null ? "false" : "true");
+                       return element.image;
                }
        }
 
index c040963021042a8920f7c48a80fd07c5406e05e9..4984d9e568ace788b94ae760259ade3b511637f3 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public interface AltosMapCacheListener {
        public void map_cache_changed(int map_cache);
index 0a59a808710342d1bbbb25bc01bc9812f719370c..756a78f20e88c437d9fef8c2bd9767c2b47d104e 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.net.*;
@@ -29,7 +29,7 @@ public interface AltosMapInterface {
 
        public abstract AltosMapMark new_mark(double lat, double lon, int state);
 
-       public abstract AltosMapTile new_tile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size);
+       public abstract AltosMapTile new_tile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size);
 
        public abstract int width();
 
index 061f226e141737aa6569b3ad7d2f9851343e9c9d..bd5901367fae2a7a1ddcee938cda18b188bb6637 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.lang.Math;
index 9ed93a42c1d05320aa112738e1075fd2ffd1b9cc..7112a1c4d22f06e8c7af078ff8b4ef2c93957fe7 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.util.*;
@@ -24,7 +24,7 @@ import java.lang.Math;
 import java.net.URL;
 import java.net.URLConnection;
 
-public class AltosMapLoader implements AltosMapTileListener, AltosMapStoreListener {
+public class AltosMapLoader extends Thread implements AltosMapTileListener {
        AltosMapLoaderListener  listener;
 
        double  latitude, longitude;
@@ -88,14 +88,11 @@ public class AltosMapLoader implements AltosMapTileListener, AltosMapStoreListen
 
                for (int y = (int) upper_left.y; y <= lower_right.y; y += AltosMap.px_size) {
                        for (int x = (int) upper_left.x; x <= lower_right.x; x += AltosMap.px_size) {
-                               listener.debug("Make tile at %d, %d\n", x, y);
                                AltosPointInt   point = new AltosPointInt(x, y);
                                AltosLatLon     ul = transform.lat_lon(point);
                                AltosLatLon     center = transform.lat_lon(new AltosPointDouble(x + AltosMap.px_size/2, y + AltosMap.px_size/2));
-                               AltosMapTile    tile = map.map_interface.new_tile(this, ul, center, zoom, maptype, AltosMap.px_size);
-                               tile.add_store_listener(this);
-                               if (tile.store_status() != AltosMapTile.loading)
-                                       notify_tile(tile, tile.store_status());
+                               AltosMapTile    tile = map.map_interface.new_tile(null, ul, center, zoom, maptype, AltosMap.px_size);
+                               tile.add_listener(this);
                        }
                }
        }
@@ -124,7 +121,7 @@ public class AltosMapLoader implements AltosMapTileListener, AltosMapStoreListen
                do_load();
        }
 
-       private void start_load() {
+       public void run() {
 
                cur_z = min_z;
                int ntype = 0;
@@ -139,67 +136,64 @@ public class AltosMapLoader implements AltosMapTileListener, AltosMapStoreListen
 
                cur_type = next_type(0);
 
+               tiles_total = 0;
                for (int z = min_z; z <= max_z; z++)
-                       tiles_total += tiles_per_layer(z);
+                       tiles_total += tiles_per_layer(z) * ntype;
 
                layers_total = (max_z - min_z + 1) * ntype;
                layers_loaded = 0;
                tiles_loaded_total = 0;
 
-               listener.debug("total tiles %d\n", tiles_total);
+               listener.debug("total tiles %d layers %d\n", tiles_total, layers_total);
 
                listener.loader_start(tiles_total);
                do_load();
        }
 
-       public void load(double latitude, double longitude, int min_z, int max_z, double radius, int all_types) {
-               listener.debug("lat %f lon %f min_z %d max_z %d radius %f all_types %d\n",
-                              latitude, longitude, min_z, max_z, radius, all_types);
-               this.latitude = latitude;
-               this.longitude = longitude;
-               this.min_z = min_z;
-               this.max_z = max_z;
-               this.radius = radius;
-               this.all_types = all_types;
-               start_load();
-       }
-
-       public synchronized void notify_store(AltosMapStore store, int status) {
+       public synchronized void notify_tile(AltosMapTile tile, int status) {
                boolean do_next = false;
-               if (status == AltosMapTile.loading)
+               if (status == AltosMapTile.fetching)
                        return;
 
+               tile.remove_listener(this);
+
                if (layers_loaded >= layers_total)
                        return;
 
                ++tiles_loaded_total;
                ++tiles_loaded_layer;
-               listener.debug("total %d layer %d\n", tiles_loaded_total, tiles_loaded_layer);
+
+               listener.debug("AltosMapLoader.notify_tile status %d total %d of %d layer %d of %d\n",
+                              status, tiles_loaded_total, tiles_total, tiles_loaded_layer, tiles_this_layer);
 
                if (tiles_loaded_layer == tiles_this_layer) {
                        ++layers_loaded;
                        listener.debug("%d layers loaded\n", layers_loaded);
-                       if (layers_loaded == layers_total) {
-                               listener.loader_done(tiles_total);
-                               return;
-                       } else {
-                               do_next = true;
-                       }
+                       do_next = true;
                }
-               listener.loader_notify(tiles_loaded_total,
-                                      tiles_total, store.file.toString());
-               if (do_next)
-                       next_load();
-       }
 
-       public synchronized void notify_tile(AltosMapTile tile, int status) {
-               notify_store(tile.store, status);
+               if (tiles_loaded_total == tiles_total)
+                       listener.loader_done(tiles_total);
+               else {
+                       listener.loader_notify(tiles_loaded_total,
+                                              tiles_total, tile.store.file.toString());
+                       if (do_next)
+                               next_load();
+               }
        }
 
-       public AltosMapCache cache() { return map.cache(); }
-
-       public AltosMapLoader(AltosMap map, AltosMapLoaderListener listener) {
+       public AltosMapLoader(AltosMap map, AltosMapLoaderListener listener,
+                             double latitude, double longitude, int min_z, int max_z, double radius, int all_types) {
+               listener.debug("lat %f lon %f min_z %d max_z %d radius %f all_types %d\n",
+                              latitude, longitude, min_z, max_z, radius, all_types);
                this.map = map;
                this.listener = listener;
+               this.latitude = latitude;
+               this.longitude = longitude;
+               this.min_z = min_z;
+               this.max_z = max_z;
+               this.radius = radius;
+               this.all_types = all_types;
+               start();
        }
 }
index 798270ccfe8828e8d2e85c9303091338a06f9b25..47d7b858b3e18bdabbee2e221d249ded86ebb87f 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public interface AltosMapLoaderListener {
        public abstract void loader_start(int max);
index e87c168d6e114be8c6d293c612ea1282319f7ea7..db714922ece808f740d2d4efbd124d414f9292a5 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.lang.Math;
index 64be49be54fe3ce1f2bb18890b3f8409d520daa8..6f6db4f4149dbbb6e6e6d0689771d725c25e6d0a 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.lang.Math;
index d500a7dbd3627c3251f1c94cd4caf08748245d8e..5b46cb19cb58927f7bae2b10057869f5fdb5abcb 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.lang.Math;
index 9c116b824aec133ca8e748f812e23021f6f619dc..b6294a4e7e31af5a08f09cae72c720c66d5a0e74 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public class AltosMapRectangle {
        AltosLatLon     ul, lr;
index c06384339eaf55f23580809d9528389597f86619..aed365ca175e07ea81abe05b7535b707227887dd 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.net.*;
@@ -35,6 +35,7 @@ public class AltosMapStore {
        public synchronized void add_listener(AltosMapStoreListener listener) {
                if (!listeners.contains(listener))
                        listeners.add(listener);
+               listener.notify_store(this, status);
        }
 
        public synchronized void remove_listener(AltosMapStoreListener listener) {
@@ -110,7 +111,7 @@ public class AltosMapStore {
                                file.delete();
                        return AltosMapTile.bad_request;
                }
-               return AltosMapTile.success;
+               return AltosMapTile.fetched;
        }
 
        static Object   fetch_lock = new Object();
@@ -118,42 +119,42 @@ public class AltosMapStore {
        static final long       forbidden_interval = 60l * 1000l * 1000l * 1000l;
        static final long       google_maps_ratelimit_ms = 1200;
 
-       static Object   loader_lock = new Object();
+       static Object   fetcher_lock = new Object();
 
        static LinkedList<AltosMapStore> waiting = new LinkedList<AltosMapStore>();
        static LinkedList<AltosMapStore> running = new LinkedList<AltosMapStore>();
 
-       static final int concurrent_loaders = 128;
+       static final int concurrent_fetchers = 128;
 
-       static void start_loaders() {
-               while (!waiting.isEmpty() && running.size() < concurrent_loaders) {
+       static void start_fetchers() {
+               while (!waiting.isEmpty() && running.size() < concurrent_fetchers) {
                        AltosMapStore   s = waiting.remove();
                        running.add(s);
-                       Thread lt = s.make_loader_thread();
+                       Thread lt = s.make_fetcher_thread();
                        lt.start();
                }
        }
 
-       void finish_loader() {
-               synchronized(loader_lock) {
+       void finish_fetcher() {
+               synchronized(fetcher_lock) {
                        running.remove(this);
-                       start_loaders();
+                       start_fetchers();
                }
        }
 
-       void add_loader() {
-               synchronized(loader_lock) {
+       void add_fetcher() {
+               synchronized(fetcher_lock) {
                        waiting.add(this);
-                       start_loaders();
+                       start_fetchers();
                }
        }
 
-       class loader implements Runnable {
+       class fetcher implements Runnable {
 
                public void run() {
                        try {
                                if (file.exists()) {
-                                       notify_listeners(AltosMapTile.success);
+                                       notify_listeners(AltosMapTile.fetched);
                                        return;
                                }
 
@@ -170,7 +171,7 @@ public class AltosMapStore {
                                        synchronized (fetch_lock) {
                                                long startTime = System.nanoTime();
                                                new_status = fetch_url();
-                                               if (new_status == AltosMapTile.success) {
+                                               if (new_status == AltosMapTile.fetched) {
                                                        long duration_ms = (System.nanoTime() - startTime) / 1000000;
                                                        if (duration_ms < google_maps_ratelimit_ms) {
                                                                try {
@@ -186,17 +187,17 @@ public class AltosMapStore {
                                }
                                notify_listeners(new_status);
                        } finally {
-                               finish_loader();
+                               finish_fetcher();
                        }
                }
        }
 
-       private Thread make_loader_thread() {
-               return new Thread(new loader());
+       private Thread make_fetcher_thread() {
+               return new Thread(new fetcher());
        }
 
-       private void load() {
-               add_loader();
+       private void fetch() {
+               add_fetcher();
        }
 
        private AltosMapStore (String url, File file) {
@@ -204,10 +205,10 @@ public class AltosMapStore {
                this.file = file;
 
                if (file.exists())
-                       status = AltosMapTile.success;
+                       status = AltosMapTile.fetched;
                else {
-                       status = AltosMapTile.loading;
-                       load();
+                       status = AltosMapTile.fetching;
+                       fetch();
                }
        }
 
index 8912caf7392982d433b88606ad10e89c8c2cf1c0..65bd6ef8480545d6a9273414a2a6981d35cb5e19 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public interface AltosMapStoreListener {
        abstract void notify_store(AltosMapStore store, int status);
index 23ab64e438ca68147e21d80caf8fb86c7738385c..fdc8ff65995ab0752843e88ad3f58b62afd52049 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.util.*;
 
-public abstract class AltosMapTile implements AltosFontListener {
-       AltosMapTileListener    listener;
+public abstract class AltosMapTile implements AltosFontListener, AltosMapStoreListener {
+       LinkedList<AltosMapTileListener>        listeners = new LinkedList<AltosMapTileListener>();
        public AltosLatLon      upper_left, center;
        public int              px_size;
        int             zoom;
        int             maptype;
        int             scale;
+       private AltosMapCache   cache;
        public AltosMapStore    store;
-       public AltosMapCache    cache;
        public int      status;
 
-       static public final int success = 0;
-       static public final int loading = 1;
-       static public final int failed = 2;
-       static public final int bad_request = 3;
-       static public final int forbidden = 4;
+       static public final int loaded = 0;     /* loaded from file */
+       static public final int fetched = 1;    /* downloaded to file */
+       static public final int fetching = 2;   /* downloading from net */
+       static public final int failed = 3;     /* loading from file failed */
+       static public final int bad_request = 4;/* downloading failed */
+       static public final int forbidden = 5;  /* downloading failed */
 
        private File map_file() {
                double lat = center.lat;
@@ -79,33 +80,46 @@ public abstract class AltosMapTile implements AltosFontListener {
        public void font_size_changed(int font_size) {
        }
 
-       public void set_status(int status) {
+       private synchronized void notify_listeners(int status) {
                this.status = status;
-               listener.notify_tile(this, status);
+               for (AltosMapTileListener listener : listeners)
+                       listener.notify_tile(this, status);
        }
 
-       public void notify_image(AltosImage image) {
-               listener.notify_tile(this, status);
+       public void notify_store(AltosMapStore store, int status) {
+//             System.out.printf("AltosMapTile.notify_store %d\n", status);
+               notify_listeners(status);
        }
 
-       public int store_status() {
-               return store.status();
+       public void notify_image(AltosImage image) {
+               if (image == null)
+                       status = failed;
+               else
+                       status = loaded;
+               notify_listeners(status);
        }
 
-       public void add_store_listener(AltosMapStoreListener listener) {
-               store.add_listener(listener);
+       public abstract void paint(AltosMapTransform t);
+
+       public AltosImage get_image() {
+               if (cache == null)
+                       return null;
+               return cache.get(this);
        }
 
-       public void remove_store_listener(AltosMapStoreListener listener) {
-               store.remove_listener(listener);
+       public synchronized void add_listener(AltosMapTileListener listener) {
+               if (!listeners.contains(listener))
+                       listeners.add(listener);
+               listener.notify_tile(this, status);
        }
 
-       public abstract void paint(AltosMapTransform t);
+       public synchronized void remove_listener(AltosMapTileListener listener) {
+               listeners.remove(listener);
+       }
 
-       public AltosMapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size, int scale) {
-               this.listener = listener;
+       public AltosMapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size, int scale) {
+               this.cache = cache;
                this.upper_left = upper_left;
-               this.cache = listener.cache();
 
                while (center.lon < -180.0)
                        center.lon += 360.0;
@@ -118,11 +132,11 @@ public abstract class AltosMapTile implements AltosFontListener {
                this.px_size = px_size;
                this.scale = scale;
 
-               status = AltosMapTile.loading;
                store = AltosMapStore.get(map_url(), map_file());
+               store.add_listener(this);
        }
 
-       public AltosMapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
-               this(listener, upper_left, center, zoom, maptype, px_size, 1);
+       public AltosMapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
+               this(cache, upper_left, center, zoom, maptype, px_size, 1);
        }
 }
index 83c1eaeded0220c5383e1a8414e22e9a948cf0bf..6d78b205207a4cfaf62c2f10af81edb6b60fe542 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public interface AltosMapTileListener {
        abstract public void notify_tile(AltosMapTile tile, int status);
-
-       abstract public AltosMapCache cache();
 }
index ae78befaa2a3f9d7b1290e351c769fca8a8f7eb2..b8901127366a7dc38930e9f173bd00c64bbd7cc0 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.lang.Math;
diff --git a/altoslib/AltosMapTypeListener.java b/altoslib/AltosMapTypeListener.java
new file mode 100644 (file)
index 0000000..b82bda3
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * 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_10;
+
+public interface AltosMapTypeListener {
+       public void map_type_changed(int map_type);
+}
index 5067aaecf0391972c824e7bd55a95166a17c6bda..51f8c3c5e83cf6329607ace9481e67fcb9b8d409 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public interface AltosMapZoomListener {
        abstract public void zoom_changed(int zoom);
index 17aaa3f8c11aecf0cef0e2e8288dd7f415aeba82..b09ec74b250e4a46c2cf377768130f2f15282af2 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.util.concurrent.*;
 
 public class AltosMma655x implements Cloneable {
 
-       int     accel;
+       private int     accel;
 
        public boolean parse_line(String line) throws NumberFormatException {
                if (line.startsWith("MMA655X value")) {
@@ -45,12 +45,18 @@ public class AltosMma655x implements Cloneable {
                return n;
        }
 
-       static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException {
+       static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException, AltosUnknownProduct {
                try {
                        AltosMma655x    mma655x = new AltosMma655x(link);
 
-                       if (mma655x != null)
-                               state.set_accel(mma655x.accel);
+                       if (mma655x != null) {
+                               int accel = mma655x.accel;
+                               if (config_data.mma655x_inverted())
+                                       accel = 4095 - accel;
+                               if (config_data.pad_orientation == 1)
+                                       accel = 4095 - accel;
+                               state.set_accel(accel);
+                       }
                } catch (TimeoutException te) {
                } catch (NumberFormatException ne) {
                }
index aa16e231539e45fd183ccf99555a985df24fd8f2..1277f2672f9e34463e95bbd4752d219dee649872 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.util.concurrent.*;
 import java.io.*;
index 51b48666094204e1eb7d39f3e528053f7ddc5c43..5451047e73b79468d6aa9f2c34329ae55d45a7f7 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public class AltosNoSymbol extends Exception {
        public AltosNoSymbol(String name) {
index a2d501b25680aaaff45355bdbf4fe5ba508b2e5d..8b22c1313f89b221d08abfe02d7b757e5eb0e7be 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public class AltosOrient extends AltosUnits {
 
index 18ef807b9c963d88f4842d52e02090913e309d97..1cbddcf9ef9dfbc4c68cf7c20a6c3a5cb84b30f5 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.util.*;
 import java.text.*;
index a358ea66db118e4ab7b230585c94f7b28386add0..65bad427c779b4e81472f215827758d3c787da8d 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public class AltosPointDouble {
        public double   x, y;
index 5f9591cc624f147dcf19af3d04f0855d6183414a..34eb6fd3a4b07bf5f980cd37d083605164754528 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public class AltosPointInt {
        public int      x, y;
index 91cfc6b6fa76d5a8d0f5c891d7118e1166759a68..fb3026a4c0a55b2b8d5abe1aca145826fa1d4980 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.util.*;
@@ -116,6 +116,7 @@ public class AltosPreferences {
        public final static String      frequency_count = "COUNT";
        public final static String      frequency_format = "FREQUENCY-%d";
        public final static String      description_format = "DESCRIPTION-%d";
+       public final static String      frequenciesPreference = "FREQUENCIES";
 
        /* Units preference */
 
@@ -128,25 +129,33 @@ public class AltosPreferences {
 
        public static int map_cache = 9;
 
+       final static String mapTypePreference = "MAP-TYPE";
+       static int      map_type;
+
        public static AltosFrequency[] load_common_frequencies() {
+
                AltosFrequency[] frequencies = null;
-               boolean existing = false;
-               existing = backend.nodeExists(common_frequencies_node_name);
 
-               if (existing) {
-                       AltosPreferencesBackend node = backend.node(common_frequencies_node_name);
-                       int             count = node.getInt(frequency_count, 0);
+               frequencies = (AltosFrequency[]) backend.getSerializable(frequenciesPreference, null);
+
+               if (frequencies == null) {
+                       if (backend.nodeExists(common_frequencies_node_name)) {
+                               AltosPreferencesBackend node = backend.node(common_frequencies_node_name);
+                               int             count = node.getInt(frequency_count, 0);
 
-                       frequencies = new AltosFrequency[count];
-                       for (int i = 0; i < count; i++) {
-                               double  frequency;
-                               String  description;
+                               frequencies = new AltosFrequency[count];
+                               for (int i = 0; i < count; i++) {
+                                       double  frequency;
+                                       String  description;
 
-                               frequency = node.getDouble(String.format(frequency_format, i), 0.0);
-                               description = node.getString(String.format(description_format, i), null);
-                               frequencies[i] = new AltosFrequency(frequency, description);
+                                       frequency = node.getDouble(String.format(frequency_format, i), 0.0);
+                                       description = node.getString(String.format(description_format, i), null);
+                                       frequencies[i] = new AltosFrequency(frequency, description);
+                               }
                        }
-               } else {
+               }
+
+               if (frequencies == null) {
                        frequencies = new AltosFrequency[10];
                        for (int i = 0; i < 10; i++) {
                                frequencies[i] = new AltosFrequency(434.550 + i * .1,
@@ -156,15 +165,6 @@ public class AltosPreferences {
                return frequencies;
        }
 
-       public static void save_common_frequencies(AltosFrequency[] frequencies) {
-               AltosPreferencesBackend node = backend.node(common_frequencies_node_name);
-
-               node.putInt(frequency_count, frequencies.length);
-               for (int i = 0; i < frequencies.length; i++) {
-                       node.putDouble(String.format(frequency_format, i), frequencies[i].frequency);
-                       node.putString(String.format(description_format, i), frequencies[i].description);
-               }
-       }
        public static int launcher_serial;
 
        public static int launcher_channel;
@@ -221,6 +221,7 @@ public class AltosPreferences {
 
                map_cache = backend.getInt(mapCachePreference, 9);
                map_cache_listeners = new LinkedList<AltosMapCacheListener>();
+               map_type = backend.getInt(mapTypePreference, AltosMap.maptype_hybrid);
        }
 
        public static void flush_preferences() {
@@ -349,24 +350,12 @@ public class AltosPreferences {
                }
        }
 
-       public static void set_state(int serial, AltosState state, AltosListenerState listener_state) {
-
-               ByteArrayOutputStream baos = new ByteArrayOutputStream();
-
-               try {
-                       ObjectOutputStream oos = new ObjectOutputStream(baos);
+       public static void set_state(AltosState state) {
 
-                       AltosSavedState saved_state = new AltosSavedState(state, listener_state);
-                       oos.writeObject(saved_state);
-
-                       byte[] bytes = baos.toByteArray();
-
-                       synchronized(backend) {
-                               backend.putBytes(String.format(statePreferenceFormat, serial), bytes);
-                               backend.putInt(statePreferenceLatest, serial);
-                               flush_preferences();
-                       }
-               } catch (IOException ie) {
+               synchronized(backend) {
+                       backend.putSerializable(String.format(statePreferenceFormat, state.serial), state);
+                       backend.putInt(statePreferenceLatest, state.serial);
+                       flush_preferences();
                }
        }
 
@@ -400,26 +389,14 @@ public class AltosPreferences {
                return latest;
        }
 
-       public static AltosSavedState state(int serial) {
-               byte[] bytes = null;
-
+       public static AltosState state(int serial) {
                synchronized(backend) {
-                       bytes = backend.getBytes(String.format(statePreferenceFormat, serial), null);
-               }
-
-               if (bytes == null)
-                       return null;
-
-               ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
-
-               try {
-                       ObjectInputStream ois = new ObjectInputStream(bais);
-                       AltosSavedState saved_state = (AltosSavedState) ois.readObject();
-                       return saved_state;
-               } catch (IOException ie) {
-               } catch (ClassNotFoundException ce) {
+                       try {
+                               return (AltosState) backend.getSerializable(String.format(statePreferenceFormat, serial), null);
+                       } catch (Exception e) {
+                               return null;
+                       }
                }
-               return null;
        }
 
        public static void set_scanning_telemetry(int new_scanning_telemetry) {
@@ -535,7 +512,7 @@ public class AltosPreferences {
        public static void set_common_frequencies(AltosFrequency[] frequencies) {
                synchronized(backend) {
                        common_frequencies = frequencies;
-                       save_common_frequencies(frequencies);
+                       backend.putSerializable(frequenciesPreference, frequencies);
                        flush_preferences();
                }
        }
@@ -621,4 +598,39 @@ public class AltosPreferences {
                        return map_cache;
                }
        }
+
+       static LinkedList<AltosMapTypeListener> map_type_listeners;
+
+       public static void set_map_type(int map_type) {
+               synchronized(backend) {
+                       AltosPreferences.map_type = map_type;
+                       backend.putInt(mapTypePreference, map_type);
+                       flush_preferences();
+               }
+               if (map_type_listeners != null) {
+                       for (AltosMapTypeListener l : map_type_listeners) {
+                               l.map_type_changed(map_type);
+                       }
+               }
+       }
+
+       public static int map_type() {
+               synchronized(backend) {
+                       return map_type;
+               }
+       }
+
+       public static void register_map_type_listener(AltosMapTypeListener l) {
+               synchronized(backend) {
+                       if (map_type_listeners == null)
+                               map_type_listeners = new LinkedList<AltosMapTypeListener>();
+                       map_type_listeners.add(l);
+               }
+       }
+
+       public static void unregister_map_type_listener(AltosMapTypeListener l) {
+               synchronized(backend) {
+                       map_type_listeners.remove(l);
+               }
+       }
 }
index f43c2ec9d68c269f9a6840d5bf29d6e3c7455100..6e1124e24e5462574c431d841000bf680222cdc6 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
-import java.io.File;
+import java.io.*;
+import java.util.*;
+import java.text.*;
 
-public interface AltosPreferencesBackend {
+public abstract class AltosPreferencesBackend {
 
-       public String  getString(String key, String def);
-       public void    putString(String key, String value);
+       public abstract String  getString(String key, String def);
+       public abstract void    putString(String key, String value);
 
-       public int     getInt(String key, int def);
-       public void    putInt(String key, int value);
+       public abstract int     getInt(String key, int def);
+       public abstract void    putInt(String key, int value);
 
-       public double  getDouble(String key, double def);
-       public void    putDouble(String key, double value);
+       public abstract double  getDouble(String key, double def);
+       public abstract void    putDouble(String key, double value);
 
-       public boolean getBoolean(String key, boolean def);
-       public void    putBoolean(String key, boolean value);
+       public abstract boolean getBoolean(String key, boolean def);
+       public abstract void    putBoolean(String key, boolean value);
 
-       public byte[]  getBytes(String key, byte[] def);
-       public void    putBytes(String key, byte[] value);
+       public abstract byte[]  getBytes(String key, byte[] def);
+       public abstract void    putBytes(String key, byte[] value);
 
-       public boolean nodeExists(String key);
-       public AltosPreferencesBackend node(String key);
+       public Serializable getSerializable(String key, Serializable def) {
+               byte[] bytes = null;
 
-       public String[] keys();
-       public void    remove(String key);
+               bytes = getBytes(key, null);
+               if (bytes == null)
+                       return def;
 
-       public void    flush();
+               ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
 
-       public File homeDirectory();
+               try {
+                       ObjectInputStream ois = new ObjectInputStream(bais);
+                       Serializable object = (Serializable) ois.readObject();
+                       return object;
+               } catch (IOException ie) {
+                       debug("IO exception %s\n", ie.toString());
+               } catch (ClassNotFoundException ce) {
+                       debug("ClassNotFoundException %s\n", ce.toString());
+               }
+               return def;
+       }
+
+       public void putSerializable(String key, Serializable object) {
+               ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+               try {
+                       ObjectOutputStream oos = new ObjectOutputStream(baos);
+
+                       oos.writeObject(object);
+                       byte[] bytes = baos.toByteArray();
+
+                       putBytes(key, bytes);
+               } catch (IOException ie) {
+                       debug("set_state failed %s\n", ie.toString());
+               }
+       }
+
+       public abstract boolean nodeExists(String key);
+       public abstract AltosPreferencesBackend node(String key);
+
+       public abstract String[] keys();
+       public abstract void    remove(String key);
+
+       public abstract void    flush();
+
+       public abstract File homeDirectory();
+
+       public abstract void debug(String format, Object ... arguments);
 }
index 7f9b277d0857b1836b6e89d3e2eb0fbc7299ea98..2f8e3bd0ebad5979d840d0a14b4df09180f78561 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 
index 851e35fb3ba2c84307e31072a81943512cc1b186..28e65bc2f9b52de27de4d0051b1e08d53ec4dc89 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.util.*;
 import java.text.*;
index e96aa7db0fca1c7d90cf462f6ed39a7b3f044018..bc471c9c83149ed778e23542441ff71e74fe8eed 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public class AltosQuaternion {
        double  r;              /* real bit */
index 6933198a3dce73804e70904c4c0140d3b216d95d..4757687d05b28ac949fc463bd8e66f8254392005 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public class AltosRectangle {
        public int      x, y, width, height;
index 5dcb870299fce47a5f4e6008d228b58f7b30fd3c..0f77c979417901e267ec4b7694aa188408950ce5 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.util.*;
index 9c6bb6682c8712ad18d2d444c60d753a9fd237ef..af201939f2d639aa7ae1beff3427beff8dcc0b34 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 
index e3c4dd56b539fb2ed6ec9b56b81765e2265882ea..e53a3a49d46a65e95af505ff90989f2f51fb09ae 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public class AltosRotation {
        private AltosQuaternion         rotation;
index a5a69c9523151984aa77e40ef0933426220239b8..3dbf59a5b98adef2b5c269178366fc41f555d9c0 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 
index 3aa727b3db25db874943db4306b470e3e6c18544..f996d7b121620cb4b4bcd1c90d2e25fabc7afe8f 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 
index 825cbd5d4ff8e39213860f0f655d7ddca852e6a6..884800f87adb004e392bcab82f73a63ce290104e 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.util.concurrent.TimeoutException;
 
index c0a92a18e91bce7ab660236c7b4240063c01fd69..99eca9d87cea4dd9e7352dbf0ba8642602ddcc6a 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.util.concurrent.TimeoutException;
 
index f38d7b4461961cd032a4c1858fa54639927598ab..a4224311d8abbe7be997c9b30a2f2b29c79a4e96 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.util.concurrent.TimeoutException;
 
index fbc10fdd2a980a194291ccf067e2e527ed8cb156..1b09647f60893f0d4d34c2c45a619271967c72f5 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.util.concurrent.TimeoutException;
 
index a2d22e9a1163c569320120a2db4aaaeb59b92e27..9f572eca7bee30cda87e4c79351b96ef0f85a543 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.util.concurrent.TimeoutException;
 
index e044956871a9d1601703887407d22a935a19a632..bb842b52169740aedeed2c7f9109d1bef94b6b4c 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.util.concurrent.TimeoutException;
 
index 74ecacd69a0c4b7c002772ceee42503c16a67ae0..9e01b50c85922188e4ef2cdf9c6c3fd4120ad5d5 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.util.concurrent.TimeoutException;
 
index 45bd4c6a489e56643889dd71af6c95dc02adf5b5..e09bbb7a0754b28ad8ed44fd9ab403fec2c632f1 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public class AltosSpeed extends AltosUnits {
 
        public double value(double v, boolean imperial_units) {
                if (imperial_units)
-                       return AltosConvert.meters_to_mph(v);
+                       return AltosConvert.mps_to_fps(v);
                return v;
        }
 
        public double inverse(double v, boolean imperial_units) {
                if (imperial_units)
-                       return AltosConvert.mph_to_meters(v);
+                       return AltosConvert.fps_to_mps(v);
                return v;
        }
 
        public String show_units(boolean imperial_units) {
                if (imperial_units)
-                       return "mph";
+                       return "fps";
                return "m/s";
        }
 
        public String say_units(boolean imperial_units) {
                if (imperial_units)
-                       return "miles per hour";
+                       return "feet per second";
                return "meters per second";
        }
 
        public int show_fraction(int width, boolean imperial_units) {
                return width / 9;
        }
-}
\ No newline at end of file
+}
index 523f5a70bfe4ff908c19484b20c673c9f280e077..7b41e98dcbe50daea61776a6cc8265ea1545edab 100644 (file)
@@ -19,7 +19,7 @@
  * Track flight state from telemetry or eeprom data stream
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 
index 13b8f4cab0c0d232889d843c38f8de6baaa742b9..a7baa85eae3404978945d7ce529a73b9942ed914 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.util.*;
index 682128468f7351b26469e7556b06da26c87041d1..12d4dd41fad8856bf5b4dc983b35f90526058e6c 100644 (file)
@@ -15,8 +15,8 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public interface AltosStateUpdate {
-       public void     update_state(AltosState state) throws InterruptedException;
-}
\ No newline at end of file
+       public void     update_state(AltosState state) throws InterruptedException, AltosUnknownProduct;
+}
index 0ba9849a6c4c59fd24b0b1cdb3e2207dda82d716..67caa60cd8da0794d36e5c92083b23669c31a17f 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.text.*;
 
index c47f9486ff1f8dc803b0ad15e26fb704fdf37a67..b9d32f4890759c8e916437c4d9a0206d189d0489 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public class AltosTelemetryCompanion extends AltosTelemetryStandard {
        AltosCompanion  companion;
index 20381a53f7cd17125675b47bc3ebd566bc45d4b5..cd2cb8ca3681f467cc7f92b8faabc3012ed1299c 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 
 public class AltosTelemetryConfiguration extends AltosTelemetryStandard {
index a762f615263fe85cd99db5579360ea3958969034..b80c2dc90b094dded90ad99a5af3caa85f491ffb 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.util.*;
index b29881e8ab4ebaea0e9f8336021ec213cc3f1660..ff3958682177974c5d1463cb79e2d3f7ed6cbb16 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.util.*;
index b3071a4bb24e71c00cd96779c8cefded0115047d..6c0fcfeb4ac390a266a1a7837eb5df80dd0863b8 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.text.*;
 
index 6fbed4bc78e5659e33758ae25e02880dea2975bf..33c3644948c58dc86f990b4351e5c1a39ac7db09 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 
 public class AltosTelemetryLocation extends AltosTelemetryStandard {
index 5aa0c41d45bdf989933a50f9cc83c389649167f5..13b5dbeacbbec26892f46c3ada658331b679d297 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 import java.text.*;
 import java.util.HashMap;
 
index 496570517f6ed40430d06c10364dfc319445ed7d..d71f2802d86f582247929c3410df75ad9f69d292 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public class AltosTelemetryMegaData extends AltosTelemetryStandard {
        int     state;
index 2f6256fcc10ec013fb7475370776502c6c26c2e1..f0d16f1925fce78144843d6da8953e3f0429a165 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public class AltosTelemetryMegaSensor extends AltosTelemetryStandard {
        int     accel;
index 4fbb9b86f3ee7fe427d93347d5236058198e070f..a4e9116fa5b21b304ccdd5cc63d1226165747a70 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 
 public class AltosTelemetryMetrumData extends AltosTelemetryStandard {
index 3769c129146cf34cfe1cff7b54d1131b5fdc2d34..1b405f2b509a0bcd96f73f37c21d6efbbd4224ea 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 
 public class AltosTelemetryMetrumSensor extends AltosTelemetryStandard {
index 173fac42353d9f447b37b8ed0e1e269bcd8bea18..8996d66235f2617589b4c8da62a70176aaa33526 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 
 public class AltosTelemetryMini extends AltosTelemetryStandard {
index 7fa12f5e0929ebe0ad7389e0053de915449f9768..8cf023a49378bd6d2bdf5b0eb8d0c1c4020ed7c7 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public class AltosTelemetryRaw extends AltosTelemetryStandard {
        public AltosTelemetryRaw(int[] bytes) {
index 2d76f281b657a1841e4de9adcd33f310b26bba67..2b0a443c3559d08378e2256338cc42c8dbfd729b 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.text.*;
 import java.io.*;
index a3a8abfaeecebe0a8b476c5b4af0164397380f63..de60e63cd70fffcd1c7c3c8c8ead873c60264556 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public class AltosTelemetrySatellite extends AltosTelemetryStandard {
        int             channels;
index 578ac2dae8498fe53ede7f4e2a798e1ed3b21446..74b61d3c919c36363a29872f7d8b4a4f9ac380e3 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 
 public class AltosTelemetrySensor extends AltosTelemetryStandard {
index 5a147b2b1da71a5142962232d3ad7463fe4ae1e0..7086abfc7ffcee3b2bd361d4b7875f74c748bd16 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public abstract class AltosTelemetryStandard extends AltosTelemetry {
        int[]   bytes;
index 19e3393dd78e42fae6a2d381f278627c05079da5..a1e485b399bfe857badbaee04f91d8522f50b4c5 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public class AltosTemperature extends AltosUnits {
 
index c211eb6d2648b5f3bb23cd91bb8cf22ff4b2f2fe..13b9dbe6ab3f21e0afb7adc96e2dfb9ba5982844 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import java.text.*;
 
index f71c42709e7f528c83b904a1573c63eb9f73abe8..bb8451b791170001146d5cb68419762cb6e6d80b 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public interface AltosUnitsListener {
        public void units_changed(boolean imperial_units);
diff --git a/altoslib/AltosUnknownProduct.java b/altoslib/AltosUnknownProduct.java
new file mode 100644 (file)
index 0000000..ff536f5
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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.altoslib_10;
+
+public class AltosUnknownProduct extends Exception {
+       public String product;
+
+       public AltosUnknownProduct (String in_product) {
+               product = in_product;
+       }
+}
index 8c53ef0d267b16c7c218c9c21bb85bbeccb5134d..9ac94dcdec88acee9bf8b5fb67529e5066dacf47 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public class AltosVersion {
        public final static String version = "@VERSION@";
 
-       public final static String google_maps_api_key = @GOOGLEKEY@;
+       public final static String google_maps_api_key = "@GOOGLEKEY@";
 
        public static boolean has_google_maps_api_key() {
                return google_maps_api_key != null && google_maps_api_key.length() > 1;
index 34f4620ed2323335abd7cbbd7586097ebf48b34a..1738dd867b3398a3a79c797f4dbb06449512cd0c 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public class AltosVoltage extends AltosUnits {
 
index b5cc34f081099ee74ab02503363a6b1ba376c707..02b5d669aed9a383fa55ffc40f56c85f3e6ffa48 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 public interface AltosWriter {
 
index d1f8f2652e6329f0cce1db9c44ed8e6c913569d6..dc9da8fdbb9fb00f66102fefb8904019e11b292a 100644 (file)
@@ -39,7 +39,7 @@ altoslib_JAVA = \
        AltosEepromDownload.java \
        AltosEepromFile.java \
        AltosEepromTM.java \
-       AltosEepromTm.java \
+       AltosEepromTMini.java \
        AltosEepromHeader.java \
        AltosEepromIterable.java \
        AltosEepromList.java \
@@ -113,6 +113,7 @@ altoslib_JAVA = \
        AltosTelemetrySatellite.java \
        AltosTelemetryStandard.java \
        AltosUnitsListener.java \
+       AltosUnknownProduct.java \
        AltosMs5607.java \
        AltosIMU.java \
        AltosMag.java \
@@ -157,6 +158,7 @@ altoslib_JAVA = \
        AltosLaunchSites.java \
        AltosMapLoaderListener.java \
        AltosMapLoader.java \
+       AltosMapTypeListener.java \
        AltosVersion.java
 
 JAR=altoslib_$(ALTOSLIB_VERSION).jar
index aae2a79317756e3ac5ff8c55f90199a004862f26..81bc8c28542cc1a797926b4c24a33b711e9f6020 100644 (file)
@@ -20,8 +20,8 @@ package altosui;
 import java.awt.*;
 import libaltosJNI.*;
 
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class Altos extends AltosUILib {
 
index 2fed6e7ced6a8dfded5c797a1cc557d0cec71b20..85260a70c2d9499c3c49bd69e9d4e4f2822964b5 100644 (file)
@@ -21,8 +21,8 @@ import java.util.*;
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class AltosAscent extends AltosUIFlightTab {
        JLabel  cur, max;
index f5080f565f733c7d365e4c728f30b3a45c79cf49..251982ad2778aceb490756dae3d1146906e04127 100644 (file)
@@ -19,8 +19,8 @@ package altosui;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class AltosCompanionInfo extends JTable implements AltosFlightDisplay {
        private AltosFlightInfoTableModel model;
index 50be7f8edf688fe37a4001ce883b92127ed4eb98..e47b0e22e6cd1b0af79192bae9f360a6c822cad0 100644 (file)
@@ -22,8 +22,8 @@ import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
 import java.text.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class AltosConfig implements ActionListener {
 
index 4ad624051a286a3b68789cdbe160bb7b74d7dcfa..e0915a17b898a4d9a3b5bcb090677f8ef451d5bc 100644 (file)
@@ -22,8 +22,8 @@ import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
 import javax.swing.event.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class AltosConfigPyroUI
        extends AltosUIDialog
index 3958a013b948d6a39399996373f7b9f7ceeb436a..eedc18c51715fdca82b4b0c6a0e3c0899e6bac5e 100644 (file)
@@ -21,8 +21,8 @@ import java.awt.event.*;
 import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class AltosConfigTD implements ActionListener {
 
index 94416465258676b4ea32e15c0b47553ba4f201b4..9a76fbe2acb2d42224107f44bd9b03e82add480c 100644 (file)
@@ -21,8 +21,8 @@ import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
 import javax.swing.event.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class AltosConfigTDUI
        extends AltosUIDialog
index a421621299ce364bc11b4ae9f2f1c12df3befe84..24167df36635d058c11284b969512ebbd2488fa6 100644 (file)
@@ -22,8 +22,8 @@ import java.awt.event.*;
 import javax.swing.*;
 import javax.swing.event.*;
 import java.text.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class AltosConfigUI
        extends AltosUIDialog
@@ -63,7 +63,7 @@ public class AltosConfigUI
        JComboBox<String>       apogee_delay_value;
        JComboBox<String>       apogee_lockout_value;
        AltosUIFreqList         radio_frequency_value;
-       JTextField              radio_calibration_value;
+       JLabel                  radio_calibration_value;
        JRadioButton            radio_enable_value;
        AltosUIRateList         rate_value;
        JComboBox<String>       aprs_interval_value;
@@ -191,13 +191,6 @@ public class AltosConfigUI
                return product != null && product.startsWith("TeleMetrum");
        }
 
-       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");
@@ -478,12 +471,8 @@ public class AltosConfigUI
                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);
-               if (remote)
-                       radio_calibration_value.setEnabled(false);
+               radio_calibration_value = new JLabel(String.format("%d", 1186611));
                pane.add(radio_calibration_value, c);
-               set_radio_calibration_tool_tip();
                row++;
 
                /* Radio Enable */
@@ -1087,10 +1076,6 @@ public class AltosConfigUI
                        radio_calibration_value.setText(String.format("%d", new_radio_calibration));
        }
 
-       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) {
                radio_enable_label.setVisible(new_radio_enable >= 0);
                radio_enable_value.setVisible(new_radio_enable >= 0);
index 3d8bb754b0ca3726e969dcafcc9f178b68b64e29..52c503524a13133719eaa0d9011356b10be5cf08 100644 (file)
@@ -22,7 +22,7 @@ import java.awt.event.*;
 import java.beans.*;
 import javax.swing.*;
 import javax.swing.event.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class AltosConfigureUI
        extends AltosUIConfigure
index 9257f069cf09fa5a4e0f7e2f85e460362a2b0e31..eeaed19ebfe4d91a1210d85f38b16434667b42a9 100644 (file)
@@ -21,8 +21,8 @@ import java.util.*;
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class AltosDescent extends AltosUIFlightTab {
 
index cffed41d57d2f81d99afb48bf183fffc29e4f63c..4229e4fcb6730e08c1eefd8168bbb4f414354519 100644 (file)
@@ -19,8 +19,8 @@ package altosui;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class AltosFlightStatus extends JComponent implements AltosFlightDisplay {
        GridBagLayout   layout;
index f8a643fe2fb6ba515e7d223b137f108f4bc0cfc2..7bf2bb781ba5a7611072d48679010397ae0a0842 100644 (file)
@@ -27,7 +27,7 @@ import java.util.*;
 import java.text.*;
 import java.util.prefs.*;
 import java.util.concurrent.LinkedBlockingQueue;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public class AltosFlightStatusTableModel extends AbstractTableModel {
        private String[] columnNames = {
index 9fa813d2912f039739d059c3d783b9fd30033db3..d39366da4291bf152bd20dc90f1347fb0fd360fe 100644 (file)
@@ -18,7 +18,7 @@
 package altosui;
 
 import java.awt.event.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public class AltosFlightStatusUpdate implements ActionListener {
 
index d7646a77fd337442a1c522b7f288f6a0519948fc..a1526cb50751063d0d4456bcc808f93cd09726ef 100644 (file)
@@ -22,8 +22,8 @@ import java.awt.event.*;
 import javax.swing.*;
 import java.util.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay {
        AltosVoice              voice;
index 8e12f229a8cefd710372a80230817af4cc069f12..34d56b24f0d625716d4f69235a2c94efae78de2c 100644 (file)
@@ -23,8 +23,8 @@ import java.util.ArrayList;
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 import org.jfree.chart.ChartPanel;
 import org.jfree.chart.JFreeChart;
index 565ab1b1207c3340472fc6753e383fbb1f28b5ff..d789de77191319de63c00b7a0ac3a346ff516dfc 100644 (file)
@@ -24,8 +24,8 @@ import javax.swing.event.*;
 import java.io.*;
 import java.util.concurrent.*;
 import java.util.Arrays;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDisplay, AltosIdleMonitorListener, DocumentListener {
        AltosDevice             device;
@@ -128,6 +128,19 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl
                SwingUtilities.invokeLater(r);
        }
 
+       public void error(final String reason) {
+               Runnable r = new Runnable() {
+                               public void run() {
+                                       disconnect();
+                                       JOptionPane.showMessageDialog(AltosIdleMonitorUI.this,
+                                                                     reason,
+                                                                     "Error fetching data",
+                                                                     JOptionPane.ERROR_MESSAGE);
+                               }
+                       };
+               SwingUtilities.invokeLater(r);
+       }
+
        Container       bag;
        AltosUIFreqList frequencies;
        JTextField      callsign_value;
index 01d58b5eda1e17c6425fc581d7449ac5701ab989..eca2a66808c301efa62f367bd9efdb155b7502a5 100644 (file)
@@ -24,8 +24,8 @@ import java.io.*;
 import java.text.*;
 import java.util.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class AltosIgniteUI
        extends AltosUIDialog
@@ -48,6 +48,8 @@ public class AltosIgniteUI
        int             time_remaining;
        boolean         timer_running;
 
+       int             poll_remaining;
+
        LinkedBlockingQueue<String>     command_queue;
 
        class Igniter {
@@ -256,6 +258,7 @@ public class AltosIgniteUI
 
        void set_ignite_status() {
                getting_status = false;
+               poll_remaining = 2;
                if (!visible) {
                        visible = true;
                        setVisible(true);
@@ -263,6 +266,10 @@ public class AltosIgniteUI
        }
 
        void poll_ignite_status() {
+               if (poll_remaining > 0) {
+                       --poll_remaining;
+                       return;
+               }
                if (!getting_status) {
                        getting_status = true;
                        send_command("get_status");
index e0f9e92119f806364fe89e04598a5274f5eab227..903da5a91a6637c02f901fbcdd3f832b1961da14 100644 (file)
@@ -20,8 +20,8 @@ package altosui;
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class AltosIgnitor extends AltosUIFlightTab {
 
index 423e0e231f7068a67372576b5a47558ff75f84f3..b704651da53632b0e10fb7de2f7d22410b423efd 100644 (file)
@@ -21,8 +21,8 @@ import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
 import java.io.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class AltosLanded extends AltosUIFlightTab implements ActionListener {
 
index da0dfd928097fea2067604fee2c72853c6838d84..503b062184276f049ac9b53fdd04ef93881392b8 100644 (file)
@@ -20,7 +20,7 @@ package altosui;
 import java.io.*;
 import java.util.concurrent.*;
 import java.awt.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class AltosLaunch {
        AltosDevice     device;
index e6bc7929dca3a36a8e17ba64db09e9d7ff01cd8a..127a33a38da8de9643c39e4170b6f50d1956ded5 100644 (file)
@@ -23,7 +23,7 @@ import javax.swing.*;
 import java.io.*;
 import java.text.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
 
 class FireButton extends JButton {
        protected void processMouseEvent(MouseEvent e) {
index f984e90897fb9e20cbd7ceb48ca8da43e2eb8f17..4f55636db23c706f2ec7a4fafd3894811b6e30ab 100644 (file)
@@ -18,8 +18,8 @@
 package altosui;
 
 import java.util.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class AltosPad extends AltosUIFlightTab {
 
index de6aa34c7025f58ed30fbbaed678e75fd26e9a6c..4a390ee62ee16c16090014941c0cd8bf64463bbc 100644 (file)
@@ -22,8 +22,8 @@ import java.awt.event.*;
 import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class AltosUI extends AltosUIFrame {
        public AltosVoice voice = new AltosVoice();
index d989ddd6693726b5e035d16f813541323ebbac62..8e0e208aea668333b2c70b7bacf04ab474f25d99 100644 (file)
 
 ; Definitions for Java Detection
 
-!define JRE_VERSION "1.6"
-!define JRE32_URL "http://javadl.sun.com/webapps/download/AutoDL?BundleId=52247&/jre-6u27-windows-i586.exe"
-!define JRE64_URL "http://javadl.sun.com/webapps/download/AutoDL?BundleId=52249&/jre-6u27-windows-x64.exe"
-
-Var JavaDownload
-Var JavaBits
+!define JAVA_VERSION "6.0"
+
+Function GetFileVersion
+       !define GetFileVersion `!insertmacro GetFileVersionCall`
+       !macro GetFileVersionCall _FILE _RESULT
+               Push `${_FILE}`
+               Call GetFileVersion
+               Pop ${_RESULT}
+       !macroend
+       Exch $0
+       Push $1
+       Push $2
+       Push $3
+       Push $4
+       Push $5
+       Push $6
+       ClearErrors
+       GetDllVersion '$0' $1 $2
+       IfErrors error
+       IntOp $3 $1 >> 16
+       IntOp $3 $3 & 0x0000FFFF
+       IntOp $4 $1 & 0x0000FFFF
+       IntOp $5 $2 >> 16
+       IntOp $5 $5 & 0x0000FFFF
+       IntOp $6 $2 & 0x0000FFFF
+       StrCpy $0 '$3.$4.$5.$6'
+       goto end
+       error:
+       SetErrors
+       StrCpy $0 ''
+       end:
+       Pop $6
+       Pop $5
+       Pop $4
+       Pop $3
+       Pop $2
+       Pop $1
+       Exch $0
+FunctionEnd
 
-Function GetJRE
-       ${If} ${RunningX64}
-          StrCpy $JavaDownload ${JRE64_URL}
-          StrCpy $JavaBits "64"
-       ${Else}
-          StrCpy $JavaDownload ${JRE32_URL}
-          StrCpy $JavaBits "32"
-       ${EndIf}
-
-        MessageBox MB_OK "This product 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
+Function openLinkNewWindow
+  Push $3
+  Exch
+  Push $2
+  Exch
+  Push $1
+  Exch
+  Push $0
+  Exch
+
+  ReadRegStr $1 HKCU "Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.html\UserChoice" "Progid"
+  IfErrors iexplore
+
+  Goto foundbrowser
+iexplore:
+  StrCpy $1 "IE.AssocFile.HTM"
+
+foundbrowser:  
+
+  StrCpy $2 "\shell\open\command"
+
+  StrCpy $3 $1$2
+
+  ReadRegStr $0 HKCR $3 ""
+
+# Get browser path
+  DetailPrint $0
+  StrCpy $2 '"'
+  StrCpy $1 $0 1
+  StrCmp $1 $2 +2 # if path is not enclosed in " look for space as final char
+  StrCpy $2 ' '
+  StrCpy $3 1
+  loop:
+    StrCpy $1 $0 1 $3
+    DetailPrint $1
+    StrCmp $1 $2 found
+    StrCmp $1 "" found
+    IntOp $3 $3 + 1
+    Goto loop
+  found:
+    StrCpy $1 $0 $3
+    StrCmp $2 " " +2
+      StrCpy $1 '$1"'
+  Pop $0
+  Exec '$1 $0'
+  Pop $0
+  Pop $1
+  Pop $2
+  Pop $3
 FunctionEnd
+!macro _OpenURL URL
+Push "${URL}"
+Call openLinkNewWindow
+!macroend
+!define OpenURL '!insertmacro "_OpenURL"'
 
 Function DoDetectJRE
 
-  DetailPrint "Desired Java version ${JRE_VERSION}"
-
-  ; Check in HKCU for CurrentVersion
-
-  ClearErrors
-  ReadRegStr $2 HKCU "SOFTWARE\JavaSoft\Java Runtime Environment" \
-             "CurrentVersion"
-
-  IfErrors hkcuwow_version
-
-  DetailPrint "HKEY_CURRENT_USER Java version $2"
-
-  ${VersionCompare} $2 ${JRE_VERSION} $3
-
-  IntCmp $3 1 yes yes no
-
-hkcuwow_version:
-
-  ; Check in HKCU Wow6432Node for CurrentVersion
-
-  ClearErrors
-  ReadRegStr $2 HKCU "SOFTWARE\Wow6432Node\JavaSoft\Java Runtime Environment" \
-            "CurrentVersion"
-
-  Iferrors hklm_version
-
-  DetailPrint "HKEY_CURRENT_USER Wow6432Node Java version $2"
+  DetailPrint "Desired Java version ${JAVA_VERSION}"
 
-  ${VersionCompare} $2 ${JRE_VERSION} $3
-
-  IntCmp $3 1 yes yes no
-
-hklm_version:
-
-  ; Check in HKLM for CurrentVersion
-
-  ClearErrors
-  ReadRegStr $2 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment" \
-             "CurrentVersion"
+  SearchPath $0 javaw.exe
+  IfErrors no
   
-  IfErrors hklmwow_version
-
-  DetailPrint "HKEY_LOCAL_MACHINE Java version $2"
-
-  ${VersionCompare} $2 ${JRE_VERSION} $3
-
-  IntCmp $3 1 yes yes no
-
-hklmwow_version:
-
-  ; Check in HKLM Wow6432Node for CurrentVersion
-
-  ClearErrors
-  ReadRegStr $2 HKLM "SOFTWARE\Wow6432Node\JavaSoft\Java Runtime Environment" \
-            "CurrentVersion"
-
-  Iferrors hkcu_any
-
-  DetailPrint "HKEY_LOCAL_MACHINE Wow6432Node Java version $2"
-
-  ${VersionCompare} $2 ${JRE_VERSION} $3
+  DetailPrint "Detected java in $0"
 
-  IntCmp $3 1 yes yes no
+  ${GetFileVersion} "$0" $1
+  IfErrors no
 
-hkcu_any:
+  DetailPrint "Java version $1"
 
-  ; Check in HKCU for any Java install
-
-  StrCpy $0 0
-
-hkcu_any_loop:
-  EnumRegKey $1 HKCU "SOFTWARE\JavaSoft" $0
-
-  StrCmp $1 "Java Runtime Environment" found_hkcu
-
-  StrCmp $1 "" hklm_any
-  
-  IntOp $0 $0 + 1
-
-  Goto hkcu_any_loop
-  
-found_hkcu:
-
-  DetailPrint "HKEY_CURRENT_USER has SOFTWARE\JavaSoft\$1"
-
-  Goto maybe
-
-hklm_any:
-
-  ; Check in HKCU for any Java install
-
-  StrCpy $0 0
-
-hklm_any_loop:
-  EnumRegKey $1 HKLM "SOFTWARE\JavaSoft" $0
-
-  StrCmp $1 "Java Runtime Environment" found_hklm
-
-  StrCmp $1 "" no
-  
-  IntOp $0 $0 + 1
-
-  Goto hklm_any_loop
-  
-found_hklm:
-
-  DetailPrint "HKEY_CURRENT_USER has SOFTWARE\JavaSoft\$1"
-
-  Goto maybe
+  ${VersionCompare} $1 ${JAVA_VERSION} $2
+  IntCmp $2 1 yes yes old
 
 yes:
   StrCpy $0 2
   Goto done
 
-maybe:
+old:
   StrCpy $0 1
   Goto done
 
@@ -168,26 +149,28 @@ var install
 var quit
 var skip
 
+Function GetJRE
+  ${OpenURL} "java.com"
+  MessageBox MB_OK "Click OK to continue after completing the Java Install."
+FunctionEnd
+
 Function DetectJRE
 
   Call DoDetectJRE
 
-  IntCmp $0 1 ask_maybe ask_no yes
+  IntCmp $0 1 ask_old ask_no yes
 
 ask_no:
-  StrCpy $0 "No Java detected. Download and install?"
+  StrCpy $0 "Cannot find Java. Download and install?"
   Goto ask
 
-ask_maybe:
-  StrCpy $0 "Cannot determine installed Java version. Download and install?"
+ask_old:
+  StrCpy $0 "Java version appears to be too old. Download and install?"
   Goto ask
 
 ask:
   MessageBox MB_YESNOCANCEL $0 IDYES do_java IDNO skip_java
 
-bail:
-  Abort
-
 do_java:
   Call GetJRE
 
index 01421071283f20c2e2fa8dcb55e2b360d96b3251..8c2e0d753fecc27f3cea9c67677385803b4ea824 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import libaltosJNI.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public class AltosBTDevice extends altos_bt_device implements AltosDevice {
 
index b8c4c6cf25e3579f47c66dcb396dc77c7e7cf5f5..ea29b0556939402c08445a5e2fdd7d8c4e2c7218 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.util.*;
 import libaltosJNI.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public class AltosBTDeviceIterator implements Iterator<AltosBTDevice> {
        AltosBTDevice   current;
index e444d310fb610a6c739b9638ad5a55279f6b8643..8ae11f679139486e34ce9c5843392cbac2b2fb9d 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.util.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public class AltosBTKnown implements Iterable<AltosBTDevice> {
        LinkedList<AltosBTDevice>       devices = new LinkedList<AltosBTDevice>();
index 65744141283e0a16a8fd10d4d47875ba0a0005bb..e6a1ef6446c464cabcbcd772b95551b201783f55 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -23,7 +23,7 @@ import javax.swing.*;
 import javax.swing.plaf.basic.*;
 import java.util.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public class AltosBTManage extends AltosUIDialog implements ActionListener, Iterable<AltosBTDevice> {
        LinkedBlockingQueue<AltosBTDevice> found_devices;
index d5796cb177fdb84999414581d271612cfef7a764..3846d3fd19ec9c1f119c07b33f97a7e3cf491f37 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
 import java.io.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public class AltosCSVUI
        extends AltosUIDialog
index ccfdc1a387b1726fbc8e6f89fc370921932372fc..5a689a396f3d51a672fa940b9925575cd724eabe 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.awt.*;
 import java.text.*;
 import java.awt.event.*;
 import javax.swing.*;
 import java.util.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 class AltosEditFreqUI extends AltosUIDialog implements ActionListener {
        Frame           frame;
index f7bc516b82ababd61a72f2f802f49bd1699bb605..3dfadfe138f27b4965226bc3520bc17554162b63 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import javax.swing.*;
 import javax.swing.filechooser.FileNameExtensionFilter;
 import java.io.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public class AltosDataChooser extends JFileChooser {
        JFrame  frame;
index f78fc2d0c672e9b4be64f2f174f09c8b36753f8f..dbaf2e36be273f4f2e4f373a5a867bc8dd253054 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import libaltosJNI.*;
 
index 52083b601877492a62bdfa663089a1c3c99607e4..21a8a23f6a28292d76714db0ee3a18fb993aff64 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import javax.swing.*;
 import java.awt.*;
index 908e74e734d7b826bdfe5c524f463cbb88fec1b4..75c3e69142acd09d27309cf63cf66128ae3f9682 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import javax.swing.*;
 import java.awt.*;
index 9aa31aa1d007e9b39bbc40399f92db7ae0bf1f77..968a0b75fbb971d9341401e5ac6958a01f9d0ec3 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.awt.*;
 import javax.swing.*;
 import java.io.*;
 import java.text.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public class AltosDisplayThread extends Thread {
 
index 270b049493946aa40a090d10e6cd70a5c58ad04f..442cee889676917015d8c4b5cc74f89cc6d4a528 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.awt.event.*;
 import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public class AltosEepromDelete implements Runnable {
        AltosEepromList         flights;
index 14cfb127115e518774b134a8af31e942ca97bc17..5f83e6f4b3620dc605b3b6618ea728a04fbcf2ee 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.awt.event.*;
 import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public class AltosEepromManage implements ActionListener {
 
index 41d447bca5dce1cc43d5e63932b4b9837f0ed89c..508e3e3f5938bb16c263c0b2643e8753665c326e 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.awt.*;
 import java.awt.event.*;
index 0c8083cdae86b4d638397c8b5477148925e34117..905780a5bdabb264bfcd00cb52cf52ddbd3098ed 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMonitor {
        JFrame          owner;
index e5c45ca173c1e9cc443febd5eba1bccafc2b02c7..67bff7105189f3d9ddb56223ae70ae7a054afed8 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import javax.swing.*;
 import javax.swing.border.*;
 import java.awt.*;
 import java.awt.event.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 class AltosEepromItem implements ActionListener {
        AltosEepromLog  log;
index 33d432c8930dcc4105343f97c1f846e5b4b660a4..07f04c3e828a091c760f835f836619771dcf6226 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -23,7 +23,7 @@ import javax.swing.*;
 import javax.swing.filechooser.FileNameExtensionFilter;
 import java.io.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public class AltosFlashUI
        extends AltosUIDialog
index 912fc716ad52abc0cbf367c5067e138782bc1ff9..9a4307430cb61637106cb4456d66d5896647121e 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import javax.swing.table.*;
 
index c74614329f3c05bef78f949dcdb8ae42643f4ced..6171f61ac5d3c4ae1b8d8d518146cdc3ff50a85f 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.awt.*;
 import javax.swing.*;
 import java.util.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public class AltosFlightStatsTable extends JComponent implements AltosFontListener {
        GridBagLayout   layout;
@@ -117,18 +117,18 @@ public class AltosFlightStatsTable extends JComponent implements AltosFontListen
                }
                new FlightStat(layout, y++, "Maximum speed",
                               String.format("%5.0f m/s", stats.max_speed),
-                              String.format("%5.0f mph", AltosConvert.meters_to_mph(stats.max_speed)),
+                              String.format("%5.0f fps", AltosConvert.mps_to_fps(stats.max_speed)),
                               String.format("Mach %4.1f", AltosConvert.meters_to_mach(stats.max_speed)));
-               if (stats.max_acceleration != AltosLib.MISSING) {
+               if (stats.max_acceleration != AltosLib.MISSING)
                        new FlightStat(layout, y++, "Maximum boost acceleration",
                                       String.format("%5.0f m/s²", stats.max_acceleration),
                                       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)));
+               if (stats.state_accel[AltosLib.ao_flight_boost] != AltosLib.MISSING)
                        new FlightStat(layout, y++, "Average boost acceleration",
                                       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])));
-               }
                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]),
index ceb730f9cff062f86301835ecbf39655285f965d..a4334cc6b8211553584b7cd09f39dad0a4ff8111 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.io.*;
 import java.util.ArrayList;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 import org.jfree.ui.*;
 import org.jfree.chart.*;
index 6a38f4467dd721305b8911cb784f74f9b4152b38..e4a065c6d000f89ec60fe2cfc65862dd65b0efc8 100644 (file)
@@ -15,9 +15,9 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public class AltosGraphDataPoint implements AltosUIDataPoint {
 
index d7d07c83328e99012db921eabdfef8e4f9bf009d..673d1de929ca5b47238d04932ded82e815d41f66 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.lang.*;
 import java.io.*;
 import java.util.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 class AltosGraphIterator implements Iterator<AltosUIDataPoint> {
        AltosGraphDataSet       dataSet;
index 8e6558b19b5cdead5bfa771c672846dd44a8a15f..3833b37ae38e13e16933894dd1b5c56dd04260bc 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
 import javax.swing.table.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public class AltosInfoTable extends JTable implements AltosFlightDisplay, HierarchyListener {
        private AltosFlightInfoTableModel model;
index fbe6b4ed08f0737f3d0b6bc8671fc418ed93d234..07485cc4a06daf4a4f3b840d9141a058e4f751a0 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import javax.swing.*;
 
index 6ab5054905cdde4b33dd49160dabd702c2ef4680..f445199c7bac5d2f5909951c8cb003ae507f6c75 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.awt.*;
 import javax.swing.*;
index 0c4fb3735fd4709421231a89aba84943145930ff..06ba41886172ef4692be0d786e6b272e58d6c8a2 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 public interface AltosPositionListener {
        public void position_changed(int position);
index 275070ee5ed740dfbe4ab4f142312b65872c6a8a..3a5188f832815723071cedadc106eda746534177 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public class AltosRomconfigUI
        extends AltosUIDialog
index bc647e8f4b6f06bcfe0417e22fbfa1248068a48e..1d176e821e913d6dd334425c9cc8c14b8f8b183b 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -25,7 +25,7 @@ import java.io.*;
 import java.util.*;
 import java.text.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 class AltosScanResult {
        String          callsign;
index a91740c55ec86c81c45a0211229a5bc626392d2b..85ab4654c013922d0cf7d485d66eb5f85e0f20a2 100644 (file)
  * Deal with TeleDongle on a serial port
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.io.*;
 import java.util.*;
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 import libaltosJNI.*;
 
 /*
index d1083098189fe54754142e25e868162e2b4196d8..af7edb65845799e9c35dd7ae9dcc54893f0f4055 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 public class AltosSerialInUseException extends Exception {
        public AltosDevice      device;
index b4024a178a9271899b2310dd9f254c1227308440..e307874a4ade4842ef3a246ae8cc870e4c048df8 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.io.*;
 import java.util.ArrayList;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 import org.jfree.ui.*;
 import org.jfree.chart.*;
index 03967d19a912a8c6213a894ad3f627b940599b49..89114c7eb654423115636a1c2be6f681462baf20 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.awt.*;
 import java.awt.event.*;
 import java.beans.*;
 import javax.swing.*;
 import javax.swing.event.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 class DelegatingRenderer implements ListCellRenderer<Object> {
 
index 1a7e12bf7602264d5379ddcb936192a18e3ed2c1..585289ed63732d4ef27992c661d231da16cbbfc5 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 public class AltosUIDataMissing extends Exception {
        public int      id;
index cf320265150b5eebeb999a83ad7a9001f86abc5e..7feb6d8ee7906a19d2f91ff902f9832d1a1b3a73 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 public interface AltosUIDataPoint {
        public abstract double x() throws AltosUIDataMissing;
index 29648dbf0f9a213965a4a41b1c6c36d8130f3e97..82809aa539cca55fb45e95371d2b81c285906f76 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 public interface AltosUIDataSet {
        public abstract String name();
index 2d0bc3c9da5c68205c541a4f589e8c93e7be9012..a262597517e8953a95f6dca4c7a68e477a5f9329 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.awt.*;
 import java.awt.event.*;
index 42a09acf10b00cceda7d9e8f540c88b6ed0e30da..7bb80bc100d127ead14be817e832ba26197fc651 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 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_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 import org.jfree.ui.*;
 import org.jfree.chart.*;
index 0db1e5da5ad4a3ca89f9ad78c13781020fb8cd89..e098b76f9492a31bba56ed9d2508027d0ec49c6f 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.util.*;
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public abstract class AltosUIFlightTab extends JComponent implements AltosFlightDisplay, HierarchyListener {
        public GridBagLayout    layout;
index b82f07f7cf1c935e32ca6db4f56a9573eb7aa52a..295225d604366ec4a92e871a57a257d51af9e8c0 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.awt.*;
 import java.awt.event.*;
index e0e2ede70dce01141f10f094cd6a6c6a0511d0d0..7d49e6928bf856e1636fc49f6094b3d19a00f87f 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public class AltosUIFreqList extends JComboBox<AltosFrequency> {
 
index 9a669e323f9e545b0a06c226423fb2bbf8ff5d68..dca12854dc2b60b9d070ff7ce9d92a1bb765da58 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.io.*;
 import java.util.ArrayList;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 import org.jfree.ui.*;
 import org.jfree.chart.*;
index 0df5c1a7f68d03b5d02596f672c86ddb8e24ef07..a30609fd5abdc7a4b1dc75e80efcac123fa6c63d 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.io.*;
 import java.util.ArrayList;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 import org.jfree.ui.*;
 import org.jfree.chart.*;
index 8c09b2e7e3854b513a60f4c2fc3e7814fc580c2f..1907e15574b71543c00efd5f3ba2aea781a26a82 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
 
 import javax.swing.*;
 import javax.imageio.ImageIO;
index 9bac992bc062238378c18140bfb565faa0312eab..819123a78f93470fc335aa5b76ca6d341dd72e73 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public abstract class AltosUIIndicator implements AltosFontListener, AltosUnitsListener {
        JLabel          label;
index 1f1ad23b4e748e2750b14901f3d94d39d33c6315..ff9fd72ad378bc4bdbc2192c29d714eaa93aa7cb 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.awt.*;
 import libaltosJNI.*;
 
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public class AltosUILib extends AltosLib {
 
@@ -112,9 +112,8 @@ public class AltosUILib extends AltosLib {
 
                        String OS = System.getProperty("os.name");
 
-                       if (OS.startsWith("Linux")) {
+                       if (OS.startsWith("L") || OS.startsWith("W"))
                                has_bluetooth = true;
-                       }
 
                        initialized = true;
                }
index 8f758300b1bc9a57c0c810fed7a8848c3fadc1c1..98d7452fcbd9b451ba41cd2823088cc917ed67b4 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 public interface AltosUIListener {
        public void ui_changed(String look_and_feel);
index 8de6bea2487fd19074fddfe21ff7f07e4113eda5..a90e8c91ae76f9c9387db39db1a47a2b646956c7 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -27,7 +27,7 @@ import java.awt.geom.*;
 import java.util.*;
 import java.util.concurrent.*;
 import javax.imageio.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public class AltosUIMapNew extends JComponent implements AltosFlightDisplay, AltosMapInterface {
 
@@ -241,8 +241,8 @@ public class AltosUIMapNew extends JComponent implements AltosFlightDisplay, Alt
        }
 
        class MapTile extends AltosMapTile {
-               public MapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
-                       super(listener, upper_left, center, zoom, maptype, px_size);
+               public MapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
+                       super(cache, upper_left, center, zoom, maptype, px_size);
                }
 
                public void paint(AltosMapTransform t) {
@@ -254,11 +254,9 @@ public class AltosUIMapNew extends JComponent implements AltosFlightDisplay, Alt
                        if (!g.hitClip(point.x, point.y, px_size, px_size))
                                return;
 
-                       AltosImage altos_image = cache.get(this, store, px_size, px_size);
-
+                       AltosImage      altos_image = get_image();
                        AltosUIImage    ui_image = (AltosUIImage) altos_image;
-
-                       Image image = null;
+                       Image           image = null;
 
                        if (ui_image != null)
                                image = ui_image.image;
@@ -272,8 +270,8 @@ public class AltosUIMapNew extends JComponent implements AltosFlightDisplay, Alt
                                if (t.has_location()) {
                                        String  message = null;
                                        switch (status) {
-                                       case AltosMapTile.loading:
-                                               message = "Loading...";
+                                       case AltosMapTile.fetching:
+                                               message = "Fetching...";
                                                break;
                                        case AltosMapTile.bad_request:
                                                message = "Internal error";
@@ -334,8 +332,8 @@ public class AltosUIMapNew extends JComponent implements AltosFlightDisplay, Alt
                return new MapMark(lat, lon, state);
        }
 
-       public AltosMapTile new_tile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
-               return new MapTile(listener, upper_left, center, zoom, maptype, px_size);
+       public AltosMapTile new_tile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
+               return new MapTile(cache, upper_left, center, zoom, maptype, px_size);
        }
 
        public int width() {
index c1c3f8bb59d3076719e3e03fb9f435921e1c8683..3269bbddbdeaaa35535483b90dd61978584b0049 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -26,7 +26,7 @@ import java.text.*;
 import java.lang.Math;
 import java.net.URL;
 import java.net.URLConnection;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 class AltosUIMapPos extends Box {
        AltosUIFrame    owner;
@@ -127,8 +127,6 @@ public class AltosUIMapPreloadNew extends AltosUIFrame implements ActionListener
 
        JProgressBar    pbar;
 
-       AltosMapLoader  loader;
-
        JLabel          site_list_label;
        JComboBox<AltosLaunchSite>      site_list;
 
@@ -189,7 +187,8 @@ public class AltosUIMapPreloadNew extends AltosUIFrame implements ActionListener
        }
 
        public void debug(String format, Object ... arguments) {
-               System.out.printf(format, arguments);
+               if (AltosSerial.debug)
+                       System.out.printf(format, arguments);
        }
 
 
@@ -237,7 +236,10 @@ public class AltosUIMapPreloadNew extends AltosUIFrame implements ActionListener
                                                r = r * 1000;
                                        loading = true;
 
-                                       loader.load(latitude, longitude, min_z, max_z, r, all_types());
+                                       new AltosMapLoader(map.map, this,
+                                                          latitude, longitude,
+                                                          min_z, max_z, r, all_types());
+
                                } catch (ParseException pe) {
                                        load_button.setSelected(false);
                                }
@@ -270,8 +272,6 @@ public class AltosUIMapPreloadNew extends AltosUIFrame implements ActionListener
 
                map = new AltosUIMapNew();
 
-               loader = new AltosMapLoader(map.map, this);
-
                c.fill = GridBagConstraints.BOTH;
                c.anchor = GridBagConstraints.CENTER;
                c.insets = i;
index 7c5a91b0daa9a7b9c558aedbcfe10b80ac837094..dc96357a5bf5f4e084ca089617c6fcc3b0cb749a 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.io.*;
 import java.util.ArrayList;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 import org.jfree.ui.*;
 import org.jfree.chart.*;
index 83099fa5fe5d907eea09938c5fed65636591b2ce..5fc5f15e6c07861823272d1bcee829e27aadaa10 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.io.*;
 import java.util.*;
 import java.awt.Component;
 import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public class AltosUIPreferences extends AltosPreferences {
 
index 6d7aa88bd75a09c6258ba90554daf50ff97abd73..d232edf7a373bd496b83467c75dd96f96c15fd57 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.io.File;
 import java.util.prefs.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 import javax.swing.filechooser.FileSystemView;
 
-public class AltosUIPreferencesBackend implements AltosPreferencesBackend {
+public class AltosUIPreferencesBackend extends AltosPreferencesBackend {
 
        private Preferences _preferences = null;
 
@@ -106,4 +106,8 @@ public class AltosUIPreferencesBackend implements AltosPreferencesBackend {
                /* Use the file system view default directory */
                return FileSystemView.getFileSystemView().getDefaultDirectory();
        }
+
+       public void debug(String format, Object ... arguments) {
+               System.out.printf(format, arguments);
+       }
 }
index 8407f31d9b55cd97bf39f3285c7af571e0d413de..5a18b32fe4effae2db52fdbf0232ba823898c51e 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public class AltosUIRateList extends JComboBox<String> {
 
index e2d19e47d0072d139fdc2d0fc1021df5f0e62708..b16f046be51b97fb3e85ae4ba31a0eecef24fb01 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.io.*;
 import java.util.ArrayList;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 import org.jfree.ui.*;
 import org.jfree.chart.*;
index fbbd7c06a3ba8c0018439c1f6524dceaa882c6f2..bba14678be0f6fa08148f73762bd13015e5b52d0 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.util.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 
 public class AltosUITelemetryList extends JComboBox<String> {
index 61e04b3464cf5918af13aa484fe7b2b9da59c08e..a84bd0b2f1cd985fda652f8825e6d257f2feb456 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public abstract class AltosUIUnitsIndicator extends AltosUIIndicator {
 
index 779098ce9cf1456a119140a94191f9f003affe99..d753b759e61d1b2a205f76639ba6cff120322eeb 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public abstract class AltosUIVoltageIndicator extends AltosUIUnitsIndicator {
 
index 6da50deb2df782fddeb91edd2c3ad6e6f5abaf7c..c93a32114cb688bc6a79980b2007aa96ffb7adb9 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.util.*;
 import libaltosJNI.*;
index e68c6d8bed1daab01fd8cf45406eeab9aed77a47..1b65acdc7e335e1a3039adfb5519c60f43f3ffc9 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import com.sun.speech.freetts.Voice;
 import com.sun.speech.freetts.VoiceManager;
index d9f0c7fd321767c3cda17d174d07c193e80d333b..725bbab62a590faef7694321f5fe14fd441df9f7 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.awt.*;
 import java.awt.event.*;
index 69cc3a5535ab7e5598bebdfa953d2deae12ebb70..c2915081e47ec0bac188c587ed0fd02b58ab5d16 100755 (executable)
@@ -55,7 +55,7 @@ Copyright © 2003-2007 Apple, Inc., All Rights Reserved
 
 */
 
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
 
 import java.lang.reflect.*;
 import java.util.HashMap;
index d3d9dc956f859729289f0e48b93d75c91071f303..40c25ce8a5bc7b4c516d871b5bf6893b4dda2e03 100755 (executable)
@@ -10,7 +10,7 @@ case $# in
        ;;
 esac
 
-../ao-tools/ao-cal-freq/ao-cal-freq --dev=$dev
+../ao-tools/ao-cal-freq/ao-cal-freq --tty=$dev
 case $? in
     0)
        calline=`./get-radio-cal $dev`
index b801b20c1fcb72762bce2d62e5f2a387fc03225f..0ac475a30044eb25fc79b0dc8aa6007e71c951ee 100755 (executable)
@@ -60,6 +60,7 @@ ao-list | while read product serial dev; do
            echo""
 
            echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
+           echo "\007"
            ret=0
            ;;
     esac
diff --git a/ao-bringup/turnon_chaoskey b/ao-bringup/turnon_chaoskey
new file mode 100755 (executable)
index 0000000..8c20eba
--- /dev/null
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+if [ -x /usr/bin/dfu-util ]; then
+    DFU_UTIL=/usr/bin/dfu-util
+else
+    echo "Can't find dfu-util! Aborting."
+    exit 1
+fi
+
+if [ -x /usr/bin/ao-usbload ]; then
+       USBLOAD=/usr/bin/ao-usbload
+else
+       echo "Can't find ao-usbload!  Aborting."
+       exit 1
+fi
+
+VERSION=1.0
+PRODUCT=ChaosKey
+
+echo "ChaosKey v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2015 by Keith Packard.  Released under GPL v2"
+echo
+echo "Expectations:"
+echo "\tChaosKey v$VERSION powered from USB"
+echo
+
+$DFU_UTIL -a 0 -s 0x08000000:leave -D ../src/chaoskey-v$VERSION/flash-loader/chaoskey-v$VERSION*.bin || exit 1
+
+sleep 2
+
+$USBLOAD --serial=1 ../src/chaoskey-v$VERSION/chaoskey-v$VERSION*.ihx || exit 1
+
+exit $?
index 66d2560e0faa36b8ce09e8455fe235bf01362067..fb5548576e0fb1a5be5d9e930294d2a6305a6410 100644 (file)
@@ -3,7 +3,7 @@ SUBDIRS=lib ao-rawload ao-dbg ao-bitbang ao-eeprom ao-list \
        ao-dumpflash ao-edit-telem ao-dump-up ao-elftohex \
        ao-flash ao-usbload ao-test-igniter ao-test-baro \
        ao-test-flash ao-cal-accel ao-test-gps ao-usbtrng \
-       ao-cal-freq
+       ao-cal-freq ao-chaosread ao-makebin
 if LIBSTLINK
 SUBDIRS += ao-stmload
 endif
diff --git a/ao-tools/ao-chaosread/.gitignore b/ao-tools/ao-chaosread/.gitignore
new file mode 100644 (file)
index 0000000..b944387
--- /dev/null
@@ -0,0 +1 @@
+ao-chaosread
diff --git a/ao-tools/ao-chaosread/Makefile.am b/ao-tools/ao-chaosread/Makefile.am
new file mode 100644 (file)
index 0000000..581eb2d
--- /dev/null
@@ -0,0 +1,9 @@
+bin_PROGRAMS=ao-chaosread
+
+AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+
+ao_chaosread_LDADD=$(LIBUSB_LIBS)
+
+ao_chaosread_SOURCES = ao-chaosread.c
+
+man_MANS = ao-chaosread.1
diff --git a/ao-tools/ao-chaosread/ao-chaosread.1 b/ao-tools/ao-chaosread/ao-chaosread.1
new file mode 100644 (file)
index 0000000..d8ed6cb
--- /dev/null
@@ -0,0 +1,36 @@
+.\"
+.\" Copyright © 2016 Keith Packard <keithp@keithp.com>
+.\"
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful, but
+.\" WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+.\" General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License along
+.\" with this program; if not, write to the Free Software Foundation, Inc.,
+.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+.\"
+.\"
+.TH AO-LOAD 1 "ao-chaosread" ""
+.SH NAME
+ao-chaosread \- read raw noise source from chaoskey
+.SH SYNOPSIS
+.B "ao-chaosread"
+.SH DESCRIPTION
+.I ao-chaosread
+reads ADC values from the noise source on the attached ChaosKey device.
+.SH OPTIONS
+.TP
+\-s serial | --serial serial
+This selects a ChaosKey by serial number instead of using the first
+one found.
+.SH USAGE
+.I ao-chaosread
+reads noise data.
+.SH AUTHOR
+Keith Packard
diff --git a/ao-tools/ao-chaosread/ao-chaosread.c b/ao-tools/ao-chaosread/ao-chaosread.c
new file mode 100644 (file)
index 0000000..806c2ef
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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 <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <libusb.h>
+#include <getopt.h>
+#include <string.h>
+#include <strings.h>
+
+#define CHAOS_SIZE     64
+
+#define CHAOS_VENDOR   0x1d50
+#define CHAOS_PRODUCT  0x60c6
+
+struct chaoskey {
+       libusb_context          *ctx;
+       libusb_device_handle    *handle;
+       int                     kernel_active;
+};
+
+libusb_device_handle *
+chaoskey_match(libusb_device *dev, char *match_serial)
+{
+       struct libusb_device_descriptor desc;
+       int ret;
+       int match_len;
+       char *device_serial = NULL;
+       libusb_device_handle *handle = NULL;
+
+       ret = libusb_get_device_descriptor(dev, &desc);
+       if (ret < 0) {
+               fprintf(stderr, "failed to get device descriptor: %s\n", libusb_strerror(ret));
+               return 0;
+       }
+
+       if (desc.idVendor != CHAOS_VENDOR)
+               return NULL;
+       if (desc.idProduct != CHAOS_PRODUCT)
+               return NULL;
+
+       ret = libusb_open(dev, &handle);
+
+       if (match_serial == NULL)
+               return handle;
+
+       if (ret < 0) {
+               fprintf(stderr, "failed to open device: %s\n", libusb_strerror(ret));
+               return NULL;
+       }
+
+       match_len = strlen(match_serial);
+       device_serial = malloc(match_len + 2);
+
+       if (!device_serial) {
+               fprintf(stderr, "malloc failed\n");
+               goto out;
+       }
+
+       ret = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, device_serial, match_len + 1);
+
+       if (ret < 0) {
+               fprintf(stderr, "failed to get serial number: %s\n", libusb_strerror(ret));
+               goto out;
+       }
+
+       device_serial[ret] = '\0';
+
+       ret = strcmp(device_serial, match_serial);
+       free(device_serial);
+       if (ret)
+               goto out;
+
+       return handle;
+
+out:
+       free(device_serial);
+       if (handle)
+               libusb_close(handle);
+       return 0;
+}
+
+struct chaoskey *
+chaoskey_open(char *serial)
+{
+       struct chaoskey *ck;
+       int             ret;
+       ssize_t         num;
+       libusb_device   **list;
+       libusb_device   *device = NULL;
+       int             d;
+
+       ck = calloc(sizeof (struct chaoskey), 1);
+       if (!ck)
+               goto out;
+       ret = libusb_init(&ck->ctx);
+       if (ret ) {
+               fprintf(stderr, "libusb_init failed: %s\n", libusb_strerror(ret));
+               goto out;
+       }
+
+       num = libusb_get_device_list(ck->ctx, &list);
+       if (num < 0) {
+               fprintf(stderr, "libusb_get_device_list failed: %s\n", libusb_strerror(num));
+               goto out;
+       }
+
+       for (d = 0; d < num; d++) {
+               libusb_device_handle *handle;
+
+               handle = chaoskey_match(list[d], serial);
+               if (handle) {
+                       ck->handle = handle;
+                       break;
+               }
+       }
+
+       libusb_free_device_list(list, 1);
+
+       if (!ck->handle) {
+               if (serial)
+                       fprintf (stderr, "No chaoskey matching %s\n", serial);
+               else
+                       fprintf (stderr, "No chaoskey\n");
+               goto out;
+       }
+
+       ck->kernel_active = libusb_kernel_driver_active(ck->handle, 0);
+       if (ck->kernel_active) {
+               ret = libusb_detach_kernel_driver(ck->handle, 0);
+               if (ret)
+                       goto out;
+       }
+
+       ret = libusb_claim_interface(ck->handle, 0);
+       if (ret)
+               goto out;
+
+       return ck;
+out:
+       if (ck->kernel_active)
+               libusb_attach_kernel_driver(ck->handle, 0);
+       if (ck->ctx)
+               libusb_exit(ck->ctx);
+       free(ck);
+       return NULL;
+}
+
+void
+chaoskey_close(struct chaoskey *ck)
+{
+       libusb_release_interface(ck->handle, 0);
+       if (ck->kernel_active)
+               libusb_attach_kernel_driver(ck->handle, 0);
+       libusb_close(ck->handle);
+       libusb_exit(ck->ctx);
+       free(ck);
+}
+
+void
+chaoskey_transfer_callback(struct libusb_transfer *transfer)
+{
+       struct chaoskey *ck = transfer->user_data;
+}
+
+#define ENDPOINT       0x86
+
+int
+chaoskey_read(struct chaoskey *ck, uint8_t *buffer, int len)
+{
+       int     total = 0;
+
+       while (len) {
+               int     ret;
+               int     transferred;
+
+               ret = libusb_bulk_transfer(ck->handle, ENDPOINT, buffer, len, &transferred, 10000);
+               if (ret) {
+                       if (total)
+                               return total;
+                       else {
+                               errno = EIO;
+                               return -1;
+                       }
+               }
+               len -= transferred;
+               buffer += transferred;
+       }
+}
+
+static const struct option options[] = {
+       { .name = "serial", .has_arg = 1, .val = 's' },
+       { .name = "length", .has_arg = 1, .val = 'l' },
+       { 0, 0, 0, 0},
+};
+
+static void usage(char *program)
+{
+       fprintf(stderr, "usage: %s [--serial=<serial>] [--length=<length>[kMG]]\n", program);
+       exit(1);
+}
+
+int
+main (int argc, char **argv)
+{
+       struct chaoskey *ck;
+       char    buf[1024];
+       int     got;
+       int     c;
+       char    *serial = NULL;
+       char    *length_string;
+       char    *length_end;
+       unsigned long   length = sizeof(buf);
+       int             this_time;
+
+       while ((c = getopt_long(argc, argv, "s:l:", options, NULL)) != -1) {
+               switch (c) {
+               case 's':
+                       serial = optarg;
+                       break;
+               case 'l':
+                       length_string = optarg;
+                       length = strtoul(length_string, &length_end, 10);
+                       if (!strcasecmp(length_end, "k"))
+                               length *= 1024;
+                       else if (!strcasecmp(length_end, "m"))
+                               length *= 1024 * 1024;
+                       else if (!strcasecmp(length_end, "g"))
+                               length *= 1024 * 1024 * 1024;
+                       else if (strlen(length_end))
+                                usage(argv[0]);
+                       break;
+               default:
+                       usage(argv[0]);
+                       break;
+               }
+       }
+
+       ck = chaoskey_open(serial);
+       if (!ck)
+               exit(1);
+
+       while (length) {
+               this_time = sizeof(buf);
+               if (length < sizeof(buf))
+                       this_time = (int) length;
+               got = chaoskey_read(ck, buf, this_time);
+               if (got < 0) {
+                       perror("read");
+                       exit(1);
+               }
+               write(1, buf, got);
+               length -= got;
+       }
+       exit(0);
+}
index b1f85af63473fe2485bf33780b7f79bd244efdb5..df05088cadaf2e4cb33d0b61482eac66f5210a5e 100644 (file)
@@ -140,20 +140,6 @@ static int find_header(struct cc_usb *cc)
        }
 }
 
-static const char *state_names[] = {
-       "startup",
-       "idle",
-       "pad",
-       "boost",
-       "fast",
-       "coast",
-       "drogue",
-       "main",
-       "landed",
-       "invalid"
-};
-
-
 int
 main (int argc, char **argv)
 {
diff --git a/ao-tools/ao-makebin/Makefile.am b/ao-tools/ao-makebin/Makefile.am
new file mode 100644 (file)
index 0000000..758097a
--- /dev/null
@@ -0,0 +1,12 @@
+bin_PROGRAMS=ao-makebin
+
+AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AO_ELFTOHEX_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
+
+ao_makebin_DEPENDENCIES = $(AO_ELFTOHEX_LIBS)
+
+ao_makebin_LDADD=$(AO_ELFTOHEX_LIBS) -lelf
+
+ao_makebin_SOURCES=ao-makebin.c
+
+man_MANS = ao-makebin.1
diff --git a/ao-tools/ao-makebin/ao-makebin.1 b/ao-tools/ao-makebin/ao-makebin.1
new file mode 100644 (file)
index 0000000..e19ec2c
--- /dev/null
@@ -0,0 +1,47 @@
+.\"
+.\" Copyright © 2013 Keith Packard <keithp@keithp.com>
+.\"
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful, but
+.\" WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+.\" General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License along
+.\" with this program; if not, write to the Free Software Foundation, Inc.,
+.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+.\"
+.\"
+.TH AO-LOAD 1 "ao-makebin" ""
+.SH NAME
+ao-makebin \- construct raw binary file or DFU image from collection of ELF files
+.SH SYNOPSIS
+.B "ao-makebin"
+[\--base=\fIbase-address\fP]
+[\--output=\fIoutput.bin\fP]
+[\--dfu]
+[\--verbose]
+\fIinput.elf ...\fP
+.SH DESCRIPTION
+.I ao-makebin
+reads the specified .elf files and writes out a raw binary flash image
+.SH OPTIONS
+.TP
+\--base=\fIbase-address\fP
+This specifies the target address for the first byte of the file (default is 0)
+.TP
+\--output=\fIoutput.bin\fP
+This specifies the output file (default is stdout)
+.TP
+\--dfu
+Creates a DFU file (as documented by ST's UM0391 user manual) instead
+of a raw binary file.
+.TP
+\--verbose
+Dumps some debug information.
+.SH AUTHOR
+Keith Packard
diff --git a/ao-tools/ao-makebin/ao-makebin.c b/ao-tools/ao-makebin/ao-makebin.c
new file mode 100644 (file)
index 0000000..31ce188
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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 <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include "ao-hex.h"
+#include "ao-elf.h"
+#include "ao-dfu.h"
+
+static const struct option options[] = {
+       { .name = "verbose", .has_arg = 0, .val = 'v' },
+       { .name = "output", .has_arg = 1, .val = 'o' },
+       { .name = "base", .has_arg = 1, .val = 'b' },
+       { .name = "align", .has_arg = 1, .val = 'a' },
+       { .name = "dfu", .has_arg = 0, .val = 'd' },
+       { 0, 0, 0, 0},
+};
+
+static void usage(char *program)
+{
+       fprintf(stderr, "usage: %s [--verbose=<level>] [--output=<output.bin>] [--base=<base-address>] [--align=<align>] [--dfu] <input.elf> ...\n", program);
+       exit(1);
+}
+
+static int
+ends_with(char *whole, char *suffix)
+{
+       int whole_len = strlen(whole);
+       int suffix_len = strlen(suffix);
+
+       if (suffix_len > whole_len)
+               return 0;
+       return strcmp(whole + whole_len - suffix_len, suffix) == 0;
+}
+
+static struct ao_dfu_info dfu_info = {
+       .bcdDevice = 0x0000,
+       .idProduct = 0xdf11,
+       .idVendor = 0x0483,
+};
+
+int
+main (int argc, char **argv)
+{
+       char                    *output = NULL;
+       struct ao_hex_image     *image = NULL;
+       struct ao_sym           *file_symbols;
+       int                     num_file_symbols;
+       FILE                    *file;
+       int                     c;
+       uint32_t                base = 0xffffffff;
+       uint32_t                align = 0;
+       uint32_t                length;
+       int                     verbose = 0;
+       int                     dfu = 0;
+
+       while ((c = getopt_long(argc, argv, "dvo:b:a:", options, NULL)) != -1) {
+               switch (c) {
+               case 'o':
+                       output = optarg;
+                       break;
+               case 'v':
+                       verbose++;
+                       break;
+               case 'b':
+                       base = strtoul(optarg, NULL, 0);
+                       break;
+               case 'a':
+                       align = strtoul(optarg, NULL, 0);
+                       break;
+               case 'd':
+                       dfu = 1;
+                       break;
+               default:
+                       usage(argv[0]);
+                       break;
+               }
+       }
+
+       while (argv[optind]) {
+               char                    *input = argv[optind];
+               struct ao_hex_image     *tmp;
+
+               if (ends_with (input, ".ihx"))
+                       tmp = ao_hex_load(input, &file_symbols, &num_file_symbols);
+               else
+                       tmp = ao_load_elf(input, &file_symbols, &num_file_symbols);
+
+               if (!tmp)
+                       usage(argv[0]);
+
+               if (verbose)
+                       fprintf(stderr, "%s: 0x%x %d\n", input, tmp->address, tmp->length);
+
+               if (image) {
+                       image = ao_hex_image_cat(image, tmp);
+                       if (!image)
+                               usage(argv[0]);
+               } else
+                       image = tmp;
+               optind++;
+       }
+
+       if (base != 0xffffffff && base > image->address) {
+               fprintf(stderr, "requested base 0x%x is after image address 0x%x\n",
+                       base, image->address);
+               usage(argv[0]);
+       }
+
+       if (verbose)
+               fprintf(stderr, "%s: base 0x%x length %d\n", output ? output : "<stdout>", image->address, image->length);
+
+       if (!output)
+               file = stdout;
+       else {
+               file = fopen(output, "w");
+               if (!file) {
+                       perror(output);
+                       exit(1);
+               }
+       }
+
+       if (dfu) {
+               if (!ao_dfu_write(file, &dfu_info, 1, image)) {
+                       fprintf(stderr, "%s: dfu_write failed: %s\n", output, strerror(errno));
+                       if (output)
+                               unlink(output);
+                       exit(1);
+               }
+       } else {
+               while (base < image->address) {
+                       fputc(0xff, file);
+                       base++;
+               }
+
+               if (fwrite(image->data, 1, image->length, file) != image->length) {
+                       fprintf(stderr, "%s: failed to write bin file\n", output ? output : "<stdout>");
+                       if (output)
+                               unlink(output);
+                       exit(1);
+               }
+
+               if (align) {
+                       length = image->length;
+
+                       while (length % align) {
+                               fputc(0xff, file);
+                               length++;
+                       }
+               }
+               fflush(file);
+       }
+
+       exit(0);
+}
index a03a976cd59b3f397790965ee338524975aef925..a33d682d054992018df9e5264b602d0411b8d401 100644 (file)
@@ -46,6 +46,8 @@ libao_tools_a_SOURCES = \
        ao-editaltos.h \
        ao-elf.c \
        ao-elf.h \
+       ao-dfu.c \
+       ao-dfu.h \
        ao-selfload.c \
        ao-selfload.h \
        ao-verbose.c \
diff --git a/ao-tools/lib/ao-dfu.c b/ao-tools/lib/ao-dfu.c
new file mode 100644 (file)
index 0000000..b677849
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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 <stdarg.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+#include "ao-hex.h"
+#include "ao-dfu.h"
+
+static uint32_t        dfu_crc;
+static FILE    *dfu_file;
+static int     dfu_failed;
+static int     dfu_error;
+
+static uint32_t update_crc(uint32_t crc, uint8_t byte)
+{
+       int j;
+       uint32_t mask;
+
+       crc = crc ^ byte;
+       for (j = 0; j < 8; j++) {
+               mask = -(crc & 1);
+               crc = (crc >> 1) ^ (0xEDB88320 & mask);
+       }
+       return crc;
+}
+
+static void dfu_init(FILE *file)
+{
+       dfu_crc = 0xffffffff;
+       dfu_file = file;
+       dfu_failed = 0;
+       dfu_error = 0;
+}
+
+static int dfu_fini(void)
+{
+       if (fflush(dfu_file) == EOF) {
+               if (!dfu_failed) {
+                       dfu_failed = 1;
+                       dfu_error = errno;
+               }
+       }
+       if (dfu_failed)
+               errno = dfu_error;
+       return !dfu_failed;
+}
+
+static void dfu_8(uint8_t byte) {
+       if (putc(byte, dfu_file) == EOF) {
+               if (!dfu_failed) {
+                       dfu_failed = 1;
+                       dfu_error = errno;
+               }
+       }
+       dfu_crc = update_crc(dfu_crc, byte);
+}
+
+static void dfu_pad(int len) {
+       while (len--)
+               dfu_8(0);
+}
+
+static void dfu_string(char *string) {
+       char    c;
+
+       while ((c = *string++))
+               dfu_8((uint8_t) c);
+}
+
+static void dfu_string_pad(char *string, int len) {
+       char    c;
+
+       while ((c = *string++)) {
+               dfu_8((uint8_t) c);
+               len--;
+       }
+       dfu_pad(len);
+}
+
+static void dfu_block(uint8_t *bytes, int len) {
+       while (len--)
+               dfu_8(*bytes++);
+}
+
+static void dfu_lsb16(uint16_t value) {
+       dfu_8(value);
+       dfu_8(value>>8);
+}
+
+static void dfu_lsb32(uint32_t value) {
+       dfu_8(value);
+       dfu_8(value >> 8);
+       dfu_8(value >> 16);
+       dfu_8(value >> 24);
+}
+
+static uint32_t dfu_image_size(struct ao_hex_image *image) {
+       return 8 + image->length;
+}
+
+static uint32_t dfu_images_size(int num_image, struct ao_hex_image images[])
+{
+       uint32_t        size = 0;
+       int             i;
+
+       for (i = 0; i < num_image; i++)
+               size += dfu_image_size(&images[i]);
+       return size;
+}
+
+static void dfu_image(struct ao_hex_image *image)
+{
+       dfu_lsb32(image->address);
+       dfu_lsb32(image->length);
+       dfu_block(image->data, image->length);
+}
+
+static void dfu_target(char *name, int num_image, struct ao_hex_image images[])
+{
+       uint32_t        images_size = dfu_images_size(num_image, images);
+       int             i;
+
+       dfu_string("Target");
+       dfu_8(0);
+       if (name) {
+               dfu_8(1);
+               dfu_pad(3);
+               dfu_string_pad(name, 255);
+       } else {
+               dfu_8(0);
+               dfu_pad(3);
+               dfu_pad(255);
+       }
+       dfu_lsb32(images_size);
+       dfu_lsb32(num_image);
+       for (i = 0; i < num_image; i++)
+               dfu_image(&images[i]);
+}
+
+static uint32_t dfu_target_size(int num_image, struct ao_hex_image images[])
+{
+       return 274 + dfu_images_size(num_image, images);
+}
+
+static uint32_t
+dfu_size(int num_image, struct ao_hex_image images[])
+{
+       uint32_t        size = 0;
+       size += 11;     /* DFU Prefix */
+
+       size += dfu_target_size(num_image, images);
+
+       return size;
+}
+
+int
+ao_dfu_write(FILE *file, struct ao_dfu_info *info, int num_image, struct ao_hex_image images[])
+{
+       uint32_t        total_size;
+
+       total_size = dfu_size(num_image, images);
+
+       dfu_init(file);
+       /* DFU Prefix */
+       dfu_string(DFU_SIGNATURE);
+       dfu_8(0x01);
+       dfu_lsb32(total_size);
+       dfu_8(0x01);
+
+       dfu_target("ST...", num_image, images);
+
+       /* DFU Suffix */
+       dfu_lsb16(info->bcdDevice);
+       dfu_lsb16(info->idProduct);
+       dfu_lsb16(info->idVendor);
+       dfu_lsb16(DFU_SPEC_VERSION);
+       dfu_string("UFD");
+       dfu_8(16);
+       dfu_lsb32(dfu_crc);
+       return dfu_fini();
+}
+
diff --git a/ao-tools/lib/ao-dfu.h b/ao-tools/lib/ao-dfu.h
new file mode 100644 (file)
index 0000000..c3dfc49
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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_DFU_H_
+#define _AO_DFU_H_
+
+struct ao_dfu_info {
+       uint16_t        bcdDevice;
+       uint16_t        idProduct;
+       uint16_t        idVendor;
+};
+
+#define DFU_SIGNATURE          "DfuSe"
+#define DFU_SPEC_VERSION       0x011a
+
+#define DFU_TARGET_SIGNATURE   "Target"
+
+int
+ao_dfu_write(FILE *file, struct ao_dfu_info *info, int num_image, struct ao_hex_image images[]);
+
+#endif /* _AO_DFU_H_ */
index 99b37210781e553094f2e9aa52407392b7da2486..680a80f06098993dc4b5a273b230265cdb51395f 100644 (file)
@@ -206,7 +206,7 @@ get_load(Elf *e)
 #endif
        size_t          nshdr;
        size_t          s;
-       
+
        if (elf_getshdrstrndx(e, &shstrndx) < 0)
                return 0;
 
@@ -238,7 +238,7 @@ get_load(Elf *e)
                         (uint32_t) phdr.p_filesz,
                         (uint32_t) phdr.p_memsz);
 #endif
-               
+
                for (s = 0; s < nshdr; s++) {
                        scn = elf_getscn(e, s);
 
@@ -256,7 +256,7 @@ get_load(Elf *e)
 #endif
 
                        if (phdr.p_offset <= shdr.sh_offset && shdr.sh_offset < phdr.p_offset + phdr.p_filesz) {
-                                       
+
                                if (shdr.sh_size == 0)
                                        continue;
 
index 5cfc63c1347e999e70b7dd2da2e4c497b33925f1..2ceed7ab4f2ba9e1791c3283e23b735e93a2aaea 100644 (file)
@@ -294,7 +294,7 @@ load_symbols(struct ao_hex_file *hex,
        struct ao_sym           *symbol;
        int                     num_symbols = 0;
        int                     size_symbols = 0;
-       
+
        extended_addr = 0;
        for (i = 0; i < hex->nrecord; i++) {
                record = hex->records[i];
@@ -451,6 +451,31 @@ ao_hex_image_free(struct ao_hex_image *image)
        free(image);
 }
 
+uint32_t min(uint32_t a, uint32_t b) { return a < b ? a : b; }
+uint32_t max(uint32_t a, uint32_t b) { return a > b ? a : b; }
+
+struct ao_hex_image *
+ao_hex_image_cat(struct ao_hex_image *a, struct ao_hex_image *b)
+{
+       struct ao_hex_image     *n;
+       uint32_t                base, bound;
+       uint32_t                length;
+
+       base = min(a->address, b->address);
+       bound = max(a->address + a->length, b->address + b->length);
+       length = bound - base;
+
+       n = calloc (sizeof (struct ao_hex_image) + length, 1);
+       if (!n)
+               return NULL;
+       n->address = base;
+       n->length = length;
+       memset(n->data, 0xff, length);
+       memcpy(n->data + a->address - n->address, a->data, a->length);
+       memcpy(n->data + b->address - n->address, b->data, b->length);
+       return n;
+}
+
 int
 ao_hex_image_equal(struct ao_hex_image *a, struct ao_hex_image *b)
 {
@@ -471,7 +496,7 @@ ao_hex_load(char *filename, struct ao_sym **symbols, int *num_symbolsp)
        file = fopen (filename, "r");
        if (!file)
                return NULL;
-       
+
        hex_file = ao_hex_file_read(file, filename);
        fclose(file);
        if (!hex_file)
@@ -549,7 +574,7 @@ ao_hex_file_create(struct ao_hex_image *image, struct ao_sym *symbols, int num_s
        ao_hex_record_set_checksum(record);
 
        hex_file->records[nrecord++] = record;
-       
+
        /* Add the symbols
         */
 
@@ -616,7 +641,7 @@ ao_hex_save(FILE *file, struct ao_hex_image *image,
                        goto write_failed;
        }
        ret = true;
-       
+
        if (fflush(file) != 0)
                ret = false;
 write_failed:
index eb510ba2a18321dc2614f8ac17a3adcb3f14e7b4..a1ab490ceab707c30630241f91fa04cea6b69225 100644 (file)
@@ -71,6 +71,9 @@ ao_hex_image_free(struct ao_hex_image *image);
 struct ao_hex_image *
 ao_hex_load(char *filename, struct ao_sym **symbols, int *num_symbols);
 
+struct ao_hex_image *
+ao_hex_image_cat(struct ao_hex_image *a, struct ao_hex_image *b);
+
 int
 ao_hex_image_equal(struct ao_hex_image *a, struct ao_hex_image *b);
 
index addaad0c61c2e2bb75338f0bd5fd29943baa4b61..ee3d4225f84d85fb58a7876fce82550a34554339 100644 (file)
@@ -18,8 +18,8 @@ dnl
 dnl Process this file with autoconf to create configure.
 
 AC_PREREQ(2.57)
-AC_INIT([altos], 1.6.2)
-ANDROID_VERSION=10
+AC_INIT([altos], 1.6.3)
+ANDROID_VERSION=11
 AC_CONFIG_SRCDIR([src/kernel/ao.h])
 AM_INIT_AUTOMAKE([foreign dist-bzip2])
 AM_MAINTAINER_MODE
@@ -31,8 +31,8 @@ AC_SUBST(ANDROID_VERSION)
 dnl ==========================================================================
 dnl Java library versions
 
-ALTOSUILIB_VERSION=9
-ALTOSLIB_VERSION=9
+ALTOSUILIB_VERSION=10
+ALTOSLIB_VERSION=10
 
 AC_SUBST(ALTOSLIB_VERSION)
 AC_DEFINE(ALTOSLIB_VERSION,$ALTOSLIB_VERSION,[Version of the AltosLib package])
@@ -149,7 +149,7 @@ fi
 ANDROID_RELEASE=no
 if test "x$ANDROID_SDK" != "xno"; then
        HAVE_ANDROID_SDK="yes"
-       if test -f "$HOME/altusmetrumllc/release.keystore" -a -f "$HOME/altusmetrumllc/Passphrase"; then
+       if test -f "$HOME/altusmetrumllc/google-play-release.keystore" -a -f "$HOME/altusmetrumllc/google-play-passphrase"; then
                ANDROID_RELEASE=yes
        fi
 else
@@ -174,7 +174,7 @@ AC_ARG_WITH(google-key, AS_HELP_STRING([--with-google-key=PATH],
            [GOOGLEKEYFILE=$withval], [GOOGLEKEYFILE=$HOME/altusmetrumllc/google-maps-api-key])
 
 if test -r "$GOOGLEKEYFILE" -a -s "$GOOGLEKEYFILE"; then
-       GOOGLEKEY='"'`cat "$GOOGLEKEYFILE"`'"'
+       GOOGLEKEY=`cat "$GOOGLEKEYFILE"`
        HAVE_GOOGLE_KEY="yes"
 else
        GOOGLEKEY='null'
@@ -557,6 +557,8 @@ ao-tools/ao-cal-accel/Makefile
 ao-tools/ao-cal-freq/Makefile
 ao-tools/ao-test-gps/Makefile
 ao-tools/ao-usbtrng/Makefile
+ao-tools/ao-chaosread/Makefile
+ao-tools/ao-makebin/Makefile
 ao-utils/Makefile
 src/Version
 ])
index 6a04a591dd57e458d2e62a7e6838df52b13c26ac..ed06006a1f44d8ffe698423d80798001b06a0233 100644 (file)
@@ -3,6 +3,7 @@
 #
 
 RELNOTES_INC=\
+       release-notes-1.6.3.inc \
        release-notes-1.6.2.inc \
        release-notes-1.6.1.inc \
        release-notes-1.6.inc \
index cdf7b96d71aa67468b267a5060f46bc31851639a..faaa13f9720eb3f2308e5054af4e8dbb1058a3e9 100644 (file)
                doesn't, the most likely reason is that your Android
                device doesn't support USB On-the-go.
       
-       === Configuring AltosDroid
+       === AltosDroid Menu
+
+               The main AltosDroid menu has a selection of operation
+               and configuration options.
+
+               Connect a device::
+
+               Offers a menu of available TeleBT devices, and an
+               option to scan for additional devices.
+
+               Disconnect device::
+
+               Disconnects the current TeleBT or TeleDongle
+               device. You can reconnect TeleBT over bluetooth by
+               using Connect a Device. You can reconnect a USB device
+               by unplugging it and then plugging it back in.
 
-               There are several configuration and operation
-               parameters available in the AltosDroid menu.
-      
                Select radio frequency::
 
                This selects which frequency to listen on by bringing
                up a menu of pre-set radio frequencies. Pick the one
                which matches your altimeter.
        
-               Select data rate::
+               Select Tracker::
+
+               Switches the information displays to show data for a
+               different transmitting device. The map will always
+               show all of the devices in view. Trackers are shown
+               and selected by serial number, so make sure you note
+               the serial number of devices in each airframe.
+
+               Delete Track::
+
+               Deletes all information about a transmitting device.
+       
+               Setup::
+
+               Offers additional configuration operations. See
+               <<_setup>>.
+
+               Idle Mode::
+
+               Communicate with an altimeter in Idle mode. See <<_idle_mode>>
+
+               Quit::
+
+               Shuts down AltosDroid.
+
+       === Setup
+
+               Telemetry Rate::
 
                Altus Metrum transmitters can be configured to operate
                at lower data rates to improve transmission range. If
                you have configured your device to do this, this menu
                item allows you to change the receiver to match.
        
-               Change units::
-
-               This toggles between metric and imperial units.
-       
-               Load maps::
+               Units::
 
-               Brings up a dialog allowing you to download offline
-               map tiles so that you can have maps available even if
-               you have no network connectivity at the launch site.
+               Selects which units used to report values.
        
-               Map type::
+               Map Type::
 
                Displays a menu of map types and lets you select
                one. Hybrid maps include satellite images with a
                includes roads along with shadows indicating changes
                in elevation, and other geographical features.
        
-               Toggle Online/Offline maps::
+               Map Source::
 
-               Switches between online and offline maps. Online maps
+               Select between online and offline maps. Online maps
                will show a 'move to current position' icon in the
                upper right corner, while offline maps will have
                copyright information all over the map. Otherwise,
                they're pretty similar.
        
-               Select Tracker::
+               Preload Maps::
 
-               Switches the information displays to show data for a
-               different transmitting device. The map will always
-               show all of the devices in view. Trackers are shown
-               and selected by serial number, so make sure you note
-               the serial number of devices in each airframe.
+               Brings up a dialog allowing you to download offline
+               map tiles so that you can have maps available even if
+               you have no network connectivity at the launch site.
+       
+               Manage Frequencies::
 
-               Delete Track::
+               This presents a dialog containing the current list of
+               frequencies that will be show in the 'Select radio
+               frequency' menu. You can change the label for existing
+               frequencies, delete or add new frequencies.
+
+       === Idle Mode
+
+               Callsign::
+
+               Lets you configure the callsign used by AltosDroid to
+               communicate with the flight computer. The callsign on
+               the two devices must match or the communication will
+               fail. This provides a modest amount of protection
+               against accidentally controlling another persons
+               flight computer.
+
+               Monitor::
+
+               This provides similar information to monitoring the
+               telemetry stream from a flight computer in flight
+               mode. The title of the application will change to
+               include (idle) so you can tell this mode is active.
+
+               Reboot::
+
+               Remotely reboots the flight computer. This is useful
+               when the flight computers turned on while the airframe
+               is horizontal and you want to restart the flight
+               computers in pad mode after raising the airframe to
+               vertical.
+
+               Fire Igniters::
+
+               Remotely control igniters for ground testing recovery
+               systems.
 
-               Deletes all information about a transmitting device.
-       
        === AltosDroid Flight Monitoring
 
                AltosDroid is designed to mimic the AltosUI flight
 
                Bearing::
 
-               This is the aziumuth from true north for the rocket
+               This is the azimuth from true north for the rocket
                from the android device. Use this in combination with
                the Elevation value to help locate the rocket in the
                sky, or at least to help point the antenna in the
        
                Bearing::
            
-               This is the aziumuth from true north for the rocket
+               This is the azimuth from true north for the rocket
                from the android device. Use this in combination with
                the Elevation value to help locate the rocket in the
                sky, or at least to help point the antenna in the
              
                Max Height::
 
-               Shows the maximum height above launch pad.
+               Shows the maximum height above launch pad seen during
+               the flight.
              
                Max Speed::
 
index 63c1e0355d0c0d3483946518f5650f343114d53c..5473dd66f9779c2ec5ef1dacea747b7a9e474c25 100644 (file)
 </legalnotice>
 <revhistory>
   <?dbhtml filename="altusmetrum-revhistory.html"?>
+  <revision>
+    <revnumber>1.6.3</revnumber>
+    <date>21 April 2016</date>
+    <revremark>
+      Minor release adding idle mode to AltosDroid and fixing various
+      host software bugs.
+    </revremark>
+  </revision>
   <revision>
     <revnumber>1.6.2</revnumber>
     <date>10 January 2016</date>
index 7789d2f3e2ec89e7363d864a9f91e0c71e00872d..cf3f27d2c270869ec6edc9da43af5856d8ab9eda 100644 (file)
 </legalnotice>
 <revhistory>
   <?dbhtml filename="easymini-revhistory.html"?>
+  <revision>
+    <revnumber>1.6.3</revnumber>
+    <date>21 April 2016</date>
+    <revremark>
+      Minor release fixing various host software bugs.
+    </revremark>
+  </revision>
   <revision>
     <revnumber>1.6.2</revnumber>
     <date>10 January 2016</date>
index 352a989b7ddb09e0fcb835c4ad7a74b80e11e4e2..7f578f71af87cc90c8983b576cc2f77cb07e9774 100644 (file)
@@ -1,6 +1,10 @@
 [appendix]
 == Release Notes
 
+       :leveloffset: 2
+       include::release-notes-1.6.3.raw[]
+
+       <<<<
        :leveloffset: 2
        include::release-notes-1.6.2.raw[]
 
diff --git a/doc/release-notes-1.6.3.inc b/doc/release-notes-1.6.3.inc
new file mode 100644 (file)
index 0000000..6aa7704
--- /dev/null
@@ -0,0 +1,92 @@
+= Release Notes for Version 1.6.3
+:toc!:
+:doctype: article
+
+       Version 1.6.3 adds idle mode to AltosDroid and has bug fixes
+       for our host software on desktops, laptops an android devices
+       along with BlueTooth support for Windows.
+
+       == AltOS
+
+       AltOS fixes:
+
+       * Fix hardware flow control on TeleBT v3.0. RTS/CTS is
+         wired backwards on this board, switch from using the
+         hardware to driving these pins with software.
+
+       == AltosUI and TeleGPS Applications
+
+       AltosUI and TeleGPS New Features:
+
+       * Add BlueTooth support for Windows operating system. This
+          supports connections to TeleBT over BlueTooth rather than
+          just USB.
+
+       AltosUI and TeleGPS Fixes:
+
+       * Change Java detection and install on Windows. Detection is
+          now done by looking for the 'javaw.exe' program, and
+          installation by opening a browser on the java.com web site.
+
+       * Delay polling while the Fire Igniters is visible to allow
+          for TeleMega to report back complete status over the radio.
+
+       * Disallow changing RF calibration numbers in the
+          configuration UI. There's no good reason to change this from
+          the field, and recovering is really hard if you haven't
+          written down the right number.
+
+       * Fix USB device discovery on Mac OS X El Capitan. This makes
+          the connected Altus Metrum USB devices appear again.
+
+       * Fix acceleration data presented in MonitorIdle mode for
+         TeleMetrum v2.0 flight computers.
+
+       == AltosDroid
+
+       AltosDroid new features:
+
+       * Monitor Idle mode. Check state of flight computer while in
+          idle mode over the radio link
+
+       * Fire Igniters. Remotely fire ignires for recovery system
+          ground tests.
+
+       * Remote reboot. Cause the flight computer to reboot over the
+          radio link. This provides a method for switching the flight
+          computer from idle to flight mode without needing to reach
+          the power switch.
+
+       * Configurable frequency menu. Change the set of available
+          frequencies and provide more descriptive names.
+
+       AltosDroid bug fixes:
+
+       * Don't set target location if GPS hasn't locked yet.
+
+       * Fix saving target states so they can be reloaded when the
+          application restarts. When the application is shut down and
+          restarted, all previous target state information will be
+          restored (including GPS position if available).
+
+       * Fix crash on some Android devices for offline maps when
+          changing the map scale or location.
+
+       * Don't require USB OTG support. This kept the latest
+         AltosDroid from being offered on devices without USB device
+         support, although it can work without that just fine using
+         BlueTooth.
+
+       * Don't require bluetooth to be enabled. This allows the
+          application to operate with USB devices or just show old
+          data without turning on the bluetooth radio.
+
+       * Recover old tracker positions when restarting
+          application. This finally allows you to safely stop and
+          restart the application without losing the last known
+          location of any tracker.
+
+       == Documentation
+
+       * Document TeleMega and EasyMega additional pyro channel
+          continuity audio alert pattern.
index a6240d4370957b19c2f761d077ea1bc70bcc3b1c..35ffa0d1ecda1376af707ee4c064bdb6dcb75168 100644 (file)
@@ -1,6 +1,10 @@
 [appendix]
 == Release Notes
 
+       :leveloffset: 2
+       include::release-notes-1.6.3.raw[]
+
+       <<<<
        :leveloffset: 2
        include::release-notes-1.6.2.raw[]
 
index dcdabc0581fede82cacfdc1b086cd0bedff9fd32..4123c783a2bafd192b63e60d350b02f3d879e51f 100644 (file)
@@ -1,6 +1,10 @@
 [appendix]
 == Release Notes
 
+       :leveloffset: 2
+       include::release-notes-1.6.3.raw[]
+
+       <<<<
        :leveloffset: 2
        include::release-notes-1.6.2.raw[]
 
index 8349f86c52f3d7287661e1b0ed601c6eb2f59c1a..25fdd6d32899af59e183f941e7a892e2bfdc3eb9 100644 (file)
                 controlling the flight or transmitting telemetry
                 signals, but no record of the flight will be
                 stored in on-board flash.
+
+               |Additional Igniters
+               |four very short beeps
+               |Continuity indication for the four additional pyro
+               |channels on TeleMega and EasyMega. One high tone for
+               |no continuity, one low tone for continuity. These are
+               |produced after the continuity indicators for the two
+               |primary igniter channels.
+
                |====
 
                ifdef::radio[]
index a1f9f5bc27d5568f76bc9aff7079ca52b15e10d0..1430aacb2fb07cdd65d1be3a56ececd3096edb8e 100644 (file)
@@ -5,9 +5,11 @@ OS:=$(shell uname)
 #
 ifeq ($(OS),Linux)
 
-JAVA_CFLAGS=-I/usr/lib/jvm/java-6-openjdk/include
+OS_SRCS=libaltos_posix.c libaltos_linux.c
 
-OS_LIB_CFLAGS=-DLINUX -DPOSIX_TTY $(JAVA_CFLAGS)
+JAVA_CFLAGS=-I/usr/lib/jvm/default-java/include -I/usr/lib/jvm/default-java/include/linux
+
+OS_LIB_CFLAGS=-DLINUX -DPOSIX_TTY $(JAVA_CFLAGS) -shared -fPIC
 
 OS_APP_CFLAGS=$(OS_LIB_CFLAGS)
 
@@ -22,6 +24,8 @@ endif
 #
 ifeq ($(OS),Darwin)
 
+OS_SRCS=libaltos_posix.c libaltos_darwin.c
+
 #OS_LIB_CFLAGS=\
 #      -DDARWIN -DPOSIX_TTY -arch i386 -arch x86_64 \
 #      --sysroot=/Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.5 \
@@ -29,8 +33,8 @@ ifeq ($(OS),Darwin)
 #      -iwithsysroot /System/Library/Frameworks/IOKit.framework/Headers \
 #      -iwithsysroot /System/Library/Frameworks/CoreFoundation.framework/Headers
 
-XCODE=/Applications/Xcode.app
-SDK=$(XCODE)/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk
+XCODE=/Applications/Xcode-beta.app
+SDK=$(XCODE)/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk
 MINVERSION=10.5
 
 OS_LIB_CFLAGS=\
@@ -39,7 +43,7 @@ OS_LIB_CFLAGS=\
        -iwithsysroot /System/Library/Frameworks/JavaVM.framework/Headers \
        -iwithsysroot /System/Library/Frameworks/IOKit.framework/Headers \
        -iwithsysroot /System/Library/Frameworks/CoreFoundation.framework/Headers
-OS_APP_CFLAGS=$(OS_LIB_CFLAGS)
+OS_APP_CFLAGS=$(OS_LIB_CFLAGS) -O0 -g
 
 OS_LDFLAGS =\
        -framework IOKit -framework CoreFoundation
@@ -54,6 +58,8 @@ endif
 #
 ifneq (,$(findstring MINGW,$(OS)))
 
+OS_SRCS=libaltos_windows.c
+
 CC=gcc
 
 OS_LIB_CFLAGS = -DWINDOWS -mconsole -DBUILD_DLL
@@ -103,7 +109,7 @@ CFLAGS=$(OS_LIB_CFLAGS) -O -I.
 LDFLAGS=$(OS_LDFLAGS)
 
 HEADERS=libaltos.h
-SRCS = libaltos.c $(SWIG_WRAP)
+SRCS = libaltos_common.c $(OS_SRCS) $(SWIG_WRAP)
 OBJS = $(SRCS:%.c=%.o)
 LIBS = $(DARWIN_LIBS)
 
@@ -111,7 +117,7 @@ $(CJNITEST): cjnitest.c $(LIBNAME)
        $(CC) -o $@ $(OS_APP_CFLAGS) cjnitest.c $(LIBNAME) $(LIBS) $(LDFLAGS)
 
 $(LIBNAME): $(OBJS)
-       $(CC) -shared $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(LDFLAGS)
+       $(CC) -shared -fPIC $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(LDFLAGS)
 
 clean:
        rm -f $(CLASSFILES) $(OBJS) $(LIBNAME) $(CJNITEST) cjnitest.o
index 1db2d486d2173adf26c6639bbd529e0c79f47b32..8f69c1ad9661df9b95290c007d89467a8ca8ec9a 100644 (file)
@@ -1,5 +1,5 @@
 JAVAC=javac
-AM_CFLAGS=-DLINUX -DPOSIX_TTY -I$(JVM_INCLUDE)
+AM_CFLAGS=-DLINUX -DPOSIX_TTY -I$(JVM_INCLUDE) -I$(JVM_INCLUDE)/linux
 AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -source 6
 
 altoslibdir=$(libdir)/altos
@@ -8,9 +8,22 @@ altoslib_LTLIBRARIES=libaltos.la
 libaltos_la_LDFLAGS=-version-info 1:0:1 -Wl,-znoexecstack
 
 libaltos_la_SOURCES=\
-       libaltos.c \
+       libaltos_common.c \
+       libaltos_posix.c \
+       libaltos_linux.c \
+       libaltos_wrap.c \
+       libaltos.h \
+       libaltos_posix.h \
+       libaltos_private.h
+
+WINDOWS_SRC=\
+       libaltos_common.c\
+       libaltos_windows.c\
        libaltos_wrap.c
 
+WINDOWS_H=\
+       libaltos.h
+
 noinst_PROGRAMS=cjnitest
 
 cjnitest_SOURCES=cjnitest.c
@@ -64,16 +77,16 @@ classlibaltos.stamp: $(SWIG_FILE)
 
 MINGCC32=i686-w64-mingw32-gcc
 MINGCC64=x86_64-w64-mingw32-gcc
-MINGFLAGS=-Wall -DWINDOWS -DBUILD_DLL -I$(JVM_INCLUDE)
-MINGLIBS=-lsetupapi
+MINGFLAGS=-Wall -Wextra -DWINDOWS -DBUILD_DLL -mconsole -I$(JVM_INCLUDE) -I$(JVM_INCLUDE)/linux
+MINGLIBS=-lsetupapi -lws2_32
 
 fat: all altos.dll altos64.dll
 
-altos.dll: $(libaltos_la_SOURCES)
-       $(MINGCC32) -o $@ $(MINGFLAGS) -shared $(libaltos_la_SOURCES) $(MINGLIBS)
+altos.dll: $(WINDOWS_SRC) $(WINDOWS_H)
+       $(MINGCC32) -o $@ $(MINGFLAGS) -shared $(WINDOWS_SRC) $(MINGLIBS)
 
-altos64.dll: $(libaltos_la_SOURCES)
-       $(MINGCC64) -o $@ $(MINGFLAGS) -shared $(libaltos_la_SOURCES) $(MINGLIBS)
+altos64.dll: $(WINDOWS_SRC) $(WINDOWS_H)
+       $(MINGCC64) -o $@ $(MINGFLAGS) -shared $(WINDOWS_SRC) $(MINGLIBS)
 
 clean-local:
        -rm -rf libaltosJNI *.class *.java classlibaltos.stamp $(SWIG_FILE) libaltos_wrap.c altos.dll altos64.dll
diff --git a/libaltos/libaltos.c b/libaltos/libaltos.c
deleted file mode 100644 (file)
index 97b7b3f..0000000
+++ /dev/null
@@ -1,1535 +0,0 @@
-/*
- * 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.
- */
-
-#include "libaltos.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define BLUETOOTH_PRODUCT_TELEBT       "TeleBT"
-
-#define USE_POLL
-
-PUBLIC int
-altos_init(void)
-{
-       return LIBALTOS_SUCCESS;
-}
-
-PUBLIC void
-altos_fini(void)
-{
-}
-
-static struct altos_error last_error;
-
-static void
-altos_set_last_error(int code, char *string)
-{
-       last_error.code = code;
-       strncpy(last_error.string, string, sizeof (last_error.string) -1);
-       last_error.string[sizeof(last_error.string)-1] = '\0';
-}
-
-PUBLIC void
-altos_get_last_error(struct altos_error *error)
-{
-       *error = last_error;
-}
-
-#ifdef DARWIN
-
-#include <unistd.h>
-
-#undef USE_POLL
-
-/* Mac OS X don't have strndup even if _GNU_SOURCE is defined */
-static char *
-altos_strndup (const char *s, size_t n)
-{
-    size_t len = strlen (s);
-    char *ret;
-
-    if (len <= n)
-       return strdup (s);
-    ret = malloc(n + 1);
-    strncpy(ret, s, n);
-    ret[n] = '\0';
-    return ret;
-}
-
-#else
-#define altos_strndup strndup
-#endif
-
-#ifdef POSIX_TTY
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <termios.h>
-#include <errno.h>
-
-#define USB_BUF_SIZE   64
-
-struct altos_file {
-       int                             fd;
-#ifdef USE_POLL
-       int                             pipe[2];
-#else
-       int                             out_fd;
-#endif
-       unsigned char                   out_data[USB_BUF_SIZE];
-       int                             out_used;
-       unsigned char                   in_data[USB_BUF_SIZE];
-       int                             in_used;
-       int                             in_read;
-};
-
-static void
-altos_set_last_posix_error(void)
-{
-       altos_set_last_error(errno, strerror(errno));
-}
-
-PUBLIC struct altos_file *
-altos_open(struct altos_device *device)
-{
-       struct altos_file       *file = calloc (sizeof (struct altos_file), 1);
-       int                     ret;
-       struct termios          term;
-
-       if (!file) {
-               altos_set_last_posix_error();
-               return NULL;
-       }
-
-//     altos_set_last_error(12, "yeah yeah, failed again");
-//     free(file);
-//     return NULL;
-
-       file->fd = open(device->path, O_RDWR | O_NOCTTY);
-       if (file->fd < 0) {
-               altos_set_last_posix_error();
-               free(file);
-               return NULL;
-       }
-#ifdef USE_POLL
-       pipe(file->pipe);
-#else
-       file->out_fd = open(device->path, O_RDWR | O_NOCTTY);
-       if (file->out_fd < 0) {
-               altos_set_last_posix_error();
-               close(file->fd);
-               free(file);
-               return NULL;
-       }
-#endif
-       ret = tcgetattr(file->fd, &term);
-       if (ret < 0) {
-               altos_set_last_posix_error();
-               close(file->fd);
-#ifndef USE_POLL
-               close(file->out_fd);
-#endif
-               free(file);
-               return NULL;
-       }
-       cfmakeraw(&term);
-       cfsetospeed(&term, B9600);
-       cfsetispeed(&term, B9600);
-#ifdef USE_POLL
-       term.c_cc[VMIN] = 1;
-       term.c_cc[VTIME] = 0;
-#else
-       term.c_cc[VMIN] = 0;
-       term.c_cc[VTIME] = 1;
-#endif
-       ret = tcsetattr(file->fd, TCSAFLUSH, &term);
-       if (ret < 0) {
-               altos_set_last_posix_error();
-               close(file->fd);
-#ifndef USE_POLL
-               close(file->out_fd);
-#endif
-               free(file);
-               return NULL;
-       }
-       return file;
-}
-
-PUBLIC void
-altos_close(struct altos_file *file)
-{
-       if (file->fd != -1) {
-               int     fd = file->fd;
-               file->fd = -1;
-#ifdef USE_POLL
-               write(file->pipe[1], "\r", 1);
-#else
-               close(file->out_fd);
-               file->out_fd = -1;
-#endif
-               close(fd);
-       }
-}
-
-PUBLIC void
-altos_free(struct altos_file *file)
-{
-       altos_close(file);
-       free(file);
-}
-
-PUBLIC int
-altos_flush(struct altos_file *file)
-{
-       if (file->out_used && 0) {
-               printf ("flush \"");
-               fwrite(file->out_data, 1, file->out_used, stdout);
-               printf ("\"\n");
-       }
-       while (file->out_used) {
-               int     ret;
-
-               if (file->fd < 0)
-                       return -EBADF;
-#ifdef USE_POLL
-               ret = write (file->fd, file->out_data, file->out_used);
-#else
-               ret = write (file->out_fd, file->out_data, file->out_used);
-#endif
-               if (ret < 0) {
-                       altos_set_last_posix_error();
-                       return -last_error.code;
-               }
-               if (ret) {
-                       memmove(file->out_data, file->out_data + ret,
-                               file->out_used - ret);
-                       file->out_used -= ret;
-               }
-       }
-       return 0;
-}
-
-PUBLIC int
-altos_putchar(struct altos_file *file, char c)
-{
-       int     ret;
-
-       if (file->out_used == USB_BUF_SIZE) {
-               ret = altos_flush(file);
-               if (ret) {
-                       return ret;
-               }
-       }
-       file->out_data[file->out_used++] = c;
-       ret = 0;
-       if (file->out_used == USB_BUF_SIZE)
-               ret = altos_flush(file);
-       return ret;
-}
-
-#ifdef USE_POLL
-#include <poll.h>
-#endif
-
-static int
-altos_fill(struct altos_file *file, int timeout)
-{
-       int             ret;
-#ifdef USE_POLL
-       struct pollfd   fd[2];
-#endif
-
-       if (timeout == 0)
-               timeout = -1;
-       while (file->in_read == file->in_used) {
-               if (file->fd < 0)
-                       return LIBALTOS_ERROR;
-#ifdef USE_POLL
-               fd[0].fd = file->fd;
-               fd[0].events = POLLIN|POLLERR|POLLHUP|POLLNVAL;
-               fd[1].fd = file->pipe[0];
-               fd[1].events = POLLIN;
-               ret = poll(fd, 2, timeout);
-               if (ret < 0) {
-                       altos_set_last_posix_error();
-                       return LIBALTOS_ERROR;
-               }
-               if (ret == 0)
-                       return LIBALTOS_TIMEOUT;
-
-               if (fd[0].revents & (POLLHUP|POLLERR|POLLNVAL))
-                       return LIBALTOS_ERROR;
-               if (fd[0].revents & POLLIN)
-#endif
-               {
-                       ret = read(file->fd, file->in_data, USB_BUF_SIZE);
-                       if (ret < 0) {
-                               altos_set_last_posix_error();
-                               return LIBALTOS_ERROR;
-                       }
-                       file->in_read = 0;
-                       file->in_used = ret;
-#ifndef USE_POLL
-                       if (ret == 0 && timeout > 0)
-                               return LIBALTOS_TIMEOUT;
-#endif
-               }
-       }
-       if (file->in_used && 0) {
-               printf ("fill \"");
-               fwrite(file->in_data, 1, file->in_used, stdout);
-               printf ("\"\n");
-       }
-       return 0;
-}
-
-PUBLIC int
-altos_getchar(struct altos_file *file, int timeout)
-{
-       int     ret;
-       while (file->in_read == file->in_used) {
-               if (file->fd < 0)
-                       return LIBALTOS_ERROR;
-               ret = altos_fill(file, timeout);
-               if (ret)
-                       return ret;
-       }
-       return file->in_data[file->in_read++];
-}
-
-#endif /* POSIX_TTY */
-
-/*
- * Scan for Altus Metrum devices by looking through /sys
- */
-
-#ifdef LINUX
-
-#define _GNU_SOURCE
-#include <ctype.h>
-#include <dirent.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/hci.h>
-#include <bluetooth/hci_lib.h>
-#include <bluetooth/rfcomm.h>
-
-static char *
-cc_fullname (char *dir, char *file)
-{
-       char    *new;
-       int     dlen = strlen (dir);
-       int     flen = strlen (file);
-       int     slen = 0;
-
-       if (dir[dlen-1] != '/')
-               slen = 1;
-       new = malloc (dlen + slen + flen + 1);
-       if (!new)
-               return 0;
-       strcpy(new, dir);
-       if (slen)
-               strcat (new, "/");
-       strcat(new, file);
-       return new;
-}
-
-static char *
-cc_basename(char *file)
-{
-       char *b;
-
-       b = strrchr(file, '/');
-       if (!b)
-               return file;
-       return b + 1;
-}
-
-static char *
-load_string(char *dir, char *file)
-{
-       char    *full = cc_fullname(dir, file);
-       char    line[4096];
-       char    *r;
-       FILE    *f;
-       int     rlen;
-
-       f = fopen(full, "r");
-       free(full);
-       if (!f)
-               return NULL;
-       r = fgets(line, sizeof (line), f);
-       fclose(f);
-       if (!r)
-               return NULL;
-       rlen = strlen(r);
-       if (r[rlen-1] == '\n')
-               r[rlen-1] = '\0';
-       return strdup(r);
-}
-
-static int
-load_hex(char *dir, char *file)
-{
-       char    *line;
-       char    *end;
-       long    i;
-
-       line = load_string(dir, file);
-       if (!line)
-               return -1;
-       i = strtol(line, &end, 16);
-       free(line);
-       if (end == line)
-               return -1;
-       return i;
-}
-
-static int
-load_dec(char *dir, char *file)
-{
-       char    *line;
-       char    *end;
-       long    i;
-
-       line = load_string(dir, file);
-       if (!line)
-               return -1;
-       i = strtol(line, &end, 10);
-       free(line);
-       if (end == line)
-               return -1;
-       return i;
-}
-
-static int
-dir_filter_tty_colon(const struct dirent *d)
-{
-       return strncmp(d->d_name, "tty:", 4) == 0;
-}
-
-static int
-dir_filter_tty(const struct dirent *d)
-{
-       return strncmp(d->d_name, "tty", 3) == 0;
-}
-
-struct altos_usbdev {
-       char    *sys;
-       char    *tty;
-       char    *manufacturer;
-       char    *product_name;
-       int     serial; /* AltOS always uses simple integer serial numbers */
-       int     idProduct;
-       int     idVendor;
-};
-
-static char *
-usb_tty(char *sys)
-{
-       char *base;
-       int num_configs;
-       int config;
-       struct dirent **namelist;
-       int interface;
-       int num_interfaces;
-       char endpoint_base[20];
-       char *endpoint_full;
-       char *tty_dir;
-       int ntty;
-       char *tty;
-
-       base = cc_basename(sys);
-       num_configs = load_hex(sys, "bNumConfigurations");
-       num_interfaces = load_hex(sys, "bNumInterfaces");
-       for (config = 1; config <= num_configs; config++) {
-               for (interface = 0; interface < num_interfaces; interface++) {
-                       sprintf(endpoint_base, "%s:%d.%d",
-                               base, config, interface);
-                       endpoint_full = cc_fullname(sys, endpoint_base);
-
-
-                       /* Check for tty:ttyACMx style names
-                        */
-                       ntty = scandir(endpoint_full, &namelist,
-                                      dir_filter_tty_colon,
-                                      alphasort);
-                       if (ntty > 0) {
-                               free(endpoint_full);
-                               tty = cc_fullname("/dev", namelist[0]->d_name + 4);
-                               free(namelist);
-                               return tty;
-                       }
-
-                       /* Check for tty/ttyACMx style names
-                        */
-                       tty_dir = cc_fullname(endpoint_full, "tty");
-                       ntty = scandir(tty_dir, &namelist,
-                                      dir_filter_tty,
-                                      alphasort);
-                       free (tty_dir);
-                       if (ntty > 0) {
-                               tty = cc_fullname("/dev", namelist[0]->d_name);
-                               free(endpoint_full);
-                               free(namelist);
-                               return tty;
-                       }
-
-                       /* Check for ttyACMx style names
-                        */
-                       ntty = scandir(endpoint_full, &namelist,
-                                      dir_filter_tty,
-                                      alphasort);
-                       free(endpoint_full);
-                       if (ntty > 0) {
-                               tty = cc_fullname("/dev", namelist[0]->d_name);
-                               free(namelist);
-                               return tty;
-                       }
-
-               }
-       }
-       return NULL;
-}
-
-static struct altos_usbdev *
-usb_scan_device(char *sys)
-{
-       struct altos_usbdev *usbdev;
-       char *tty;
-
-       tty = usb_tty(sys);
-       if (!tty)
-               return NULL;
-       usbdev = calloc(1, sizeof (struct altos_usbdev));
-       if (!usbdev)
-               return NULL;
-       usbdev->sys = strdup(sys);
-       usbdev->manufacturer = load_string(sys, "manufacturer");
-       usbdev->product_name = load_string(sys, "product");
-       usbdev->serial = load_dec(sys, "serial");
-       usbdev->idProduct = load_hex(sys, "idProduct");
-       usbdev->idVendor = load_hex(sys, "idVendor");
-       usbdev->tty = tty;
-       return usbdev;
-}
-
-static void
-usbdev_free(struct altos_usbdev *usbdev)
-{
-       free(usbdev->sys);
-       free(usbdev->manufacturer);
-       free(usbdev->product_name);
-       /* this can get used as a return value */
-       if (usbdev->tty)
-               free(usbdev->tty);
-       free(usbdev);
-}
-
-#define USB_DEVICES    "/sys/bus/usb/devices"
-
-static int
-dir_filter_dev(const struct dirent *d)
-{
-       const char      *n = d->d_name;
-       char    c;
-
-       while ((c = *n++)) {
-               if (isdigit(c))
-                       continue;
-               if (c == '-')
-                       continue;
-               if (c == '.' && n != d->d_name + 1)
-                       continue;
-               return 0;
-       }
-       return 1;
-}
-
-struct altos_list {
-       struct altos_usbdev     **dev;
-       int                     current;
-       int                     ndev;
-};
-
-struct altos_list *
-altos_list_start(void)
-{
-       int                     e;
-       struct dirent           **ents;
-       char                    *dir;
-       struct altos_usbdev     *dev;
-       struct altos_list       *devs;
-       int                     n;
-
-       devs = calloc(1, sizeof (struct altos_list));
-       if (!devs)
-               return NULL;
-
-       n = scandir (USB_DEVICES, &ents,
-                    dir_filter_dev,
-                    alphasort);
-       if (!n)
-               return 0;
-       for (e = 0; e < n; e++) {
-               dir = cc_fullname(USB_DEVICES, ents[e]->d_name);
-               dev = usb_scan_device(dir);
-               if (!dev)
-                       continue;
-               free(dir);
-               if (devs->dev)
-                       devs->dev = realloc(devs->dev,
-                                           (devs->ndev + 1) * sizeof (struct usbdev *));
-               else
-                       devs->dev = malloc (sizeof (struct usbdev *));
-               devs->dev[devs->ndev++] = dev;
-       }
-       free(ents);
-       devs->current = 0;
-       return devs;
-}
-
-PUBLIC struct altos_list *
-altos_ftdi_list_start(void)
-{
-       return altos_list_start();
-}
-
-int
-altos_list_next(struct altos_list *list, struct altos_device *device)
-{
-       struct altos_usbdev *dev;
-       if (list->current >= list->ndev) {
-               return 0;
-       }
-       dev = list->dev[list->current];
-       strcpy(device->name, dev->product_name);
-       device->vendor = dev->idVendor;
-       device->product = dev->idProduct;
-       strcpy(device->path, dev->tty);
-       device->serial = dev->serial;
-       list->current++;
-       return 1;
-}
-
-void
-altos_list_finish(struct altos_list *usbdevs)
-{
-       int     i;
-
-       if (!usbdevs)
-               return;
-       for (i = 0; i < usbdevs->ndev; i++)
-               usbdev_free(usbdevs->dev[i]);
-       free(usbdevs);
-}
-
-#include <dlfcn.h>
-
-static void *libbt;
-static int bt_initialized;
-
-static int init_bt(void) {
-       if (!bt_initialized) {
-               bt_initialized = 1;
-               libbt = dlopen("libbluetooth.so.3", RTLD_LAZY);
-               if (!libbt)
-                       printf("failed to find bluetooth library\n");
-       }
-       return libbt != NULL;
-}
-
-#define join(a,b)      a ## b
-#define bt_func(name, ret, fail, formals, actuals)                     \
-       static ret join(altos_, name) formals {                         \
-                                     static ret (*name) formals;       \
-                                     if (!init_bt()) return fail;      \
-                                     name = dlsym(libbt, #name);       \
-                                     if (!name) return fail;           \
-                                     return name actuals;              \
-                                     }
-
-bt_func(ba2str, int, -1, (const bdaddr_t *ba, char *str), (ba, str))
-#define ba2str altos_ba2str
-
-bt_func(str2ba, int, -1, (const char *str, bdaddr_t *ba), (str, ba))
-#define str2ba altos_str2ba
-
-bt_func(hci_read_remote_name, int, -1, (int sock, const bdaddr_t *ba, int len, char *name, int timeout), (sock, ba, len, name, timeout))
-#define hci_read_remote_name altos_hci_read_remote_name
-
-bt_func(hci_open_dev, int, -1, (int dev_id), (dev_id))
-#define hci_open_dev altos_hci_open_dev
-
-bt_func(hci_get_route, int, -1, (bdaddr_t *bdaddr), (bdaddr))
-#define hci_get_route altos_hci_get_route
-
-bt_func(hci_inquiry, int, -1, (int adapter_id, int len, int max_rsp, const uint8_t *lap, inquiry_info **devs, long flags), (adapter_id, len, max_rsp, lap, devs, flags))
-#define hci_inquiry altos_hci_inquiry
-
-struct altos_bt_list {
-       inquiry_info    *ii;
-       int             sock;
-       int             dev_id;
-       int             rsp;
-       int             num_rsp;
-};
-
-#define INQUIRY_MAX_RSP        255
-
-struct altos_bt_list *
-altos_bt_list_start(int inquiry_time)
-{
-       struct altos_bt_list    *bt_list;
-
-       bt_list = calloc(1, sizeof (struct altos_bt_list));
-       if (!bt_list)
-               goto no_bt_list;
-
-       bt_list->ii = calloc(INQUIRY_MAX_RSP, sizeof (inquiry_info));
-       if (!bt_list->ii)
-               goto no_ii;
-       bt_list->dev_id = hci_get_route(NULL);
-       if (bt_list->dev_id < 0)
-               goto no_dev_id;
-
-       bt_list->sock = hci_open_dev(bt_list->dev_id);
-       if (bt_list->sock < 0)
-               goto no_sock;
-
-       bt_list->num_rsp = hci_inquiry(bt_list->dev_id,
-                                      inquiry_time,
-                                      INQUIRY_MAX_RSP,
-                                      NULL,
-                                      &bt_list->ii,
-                                      IREQ_CACHE_FLUSH);
-       if (bt_list->num_rsp < 0)
-               goto no_rsp;
-
-       bt_list->rsp = 0;
-       return bt_list;
-
-no_rsp:
-       close(bt_list->sock);
-no_sock:
-no_dev_id:
-       free(bt_list->ii);
-no_ii:
-       free(bt_list);
-no_bt_list:
-       return NULL;
-}
-
-int
-altos_bt_list_next(struct altos_bt_list *bt_list,
-                  struct altos_bt_device *device)
-{
-       inquiry_info    *ii;
-
-       if (bt_list->rsp >= bt_list->num_rsp)
-               return 0;
-
-       ii = &bt_list->ii[bt_list->rsp];
-       if (ba2str(&ii->bdaddr, device->addr) < 0)
-               return 0;
-       memset(&device->name, '\0', sizeof (device->name));
-       if (hci_read_remote_name(bt_list->sock, &ii->bdaddr,
-                                sizeof (device->name),
-                                device->name, 0) < 0) {
-               strcpy(device->name, "[unknown]");
-       }
-       bt_list->rsp++;
-       return 1;
-}
-
-void
-altos_bt_list_finish(struct altos_bt_list *bt_list)
-{
-       close(bt_list->sock);
-       free(bt_list->ii);
-       free(bt_list);
-}
-
-void
-altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device)
-{
-       strncpy(device->name, name, sizeof (device->name));
-       device->name[sizeof(device->name)-1] = '\0';
-       strncpy(device->addr, addr, sizeof (device->addr));
-       device->addr[sizeof(device->addr)-1] = '\0';
-}
-
-struct altos_file *
-altos_bt_open(struct altos_bt_device *device)
-{
-       struct sockaddr_rc addr = { 0 };
-       int     status, i;
-       struct altos_file *file;
-
-       file = calloc(1, sizeof (struct altos_file));
-       if (!file) {
-               errno = ENOMEM;
-               altos_set_last_posix_error();
-               goto no_file;
-       }
-       addr.rc_family = AF_BLUETOOTH;
-       addr.rc_channel = 1;
-       if (str2ba(device->addr, &addr.rc_bdaddr) < 0) {
-               altos_set_last_posix_error();
-               goto no_sock;
-       }
-
-       for (i = 0; i < 5; i++) {
-               file->fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
-               if (file->fd < 0) {
-                       altos_set_last_posix_error();
-                       goto no_sock;
-               }
-
-               status = connect(file->fd,
-                                (struct sockaddr *)&addr,
-                                sizeof(addr));
-               if (status >= 0 || errno != EBUSY)
-                       break;
-               close(file->fd);
-               usleep(100 * 1000);
-       }
-       if (status < 0) {
-               altos_set_last_posix_error();
-               goto no_link;
-       }
-       usleep(100 * 1000);
-
-#ifdef USE_POLL
-       pipe(file->pipe);
-#else
-       file->out_fd = dup(file->fd);
-#endif
-       return file;
-no_link:
-       close(file->fd);
-no_sock:
-       free(file);
-no_file:
-       return NULL;
-}
-
-#endif
-
-#ifdef DARWIN
-
-#include <IOKitLib.h>
-#include <IOKit/usb/USBspec.h>
-#include <sys/param.h>
-#include <paths.h>
-#include <CFNumber.h>
-#include <IOBSD.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-struct altos_list {
-       io_iterator_t iterator;
-       int ftdi;
-};
-
-static int
-get_string(io_object_t object, CFStringRef entry, char *result, int result_len)
-{
-       CFTypeRef entry_as_string;
-       Boolean got_string;
-
-       entry_as_string = IORegistryEntrySearchCFProperty (object,
-                                                          kIOServicePlane,
-                                                          entry,
-                                                          kCFAllocatorDefault,
-                                                          kIORegistryIterateRecursively);
-       if (entry_as_string) {
-               got_string = CFStringGetCString(entry_as_string,
-                                               result, result_len,
-                                               kCFStringEncodingASCII);
-
-               CFRelease(entry_as_string);
-               if (got_string)
-                       return 1;
-       }
-       return 0;
-}
-
-static int
-get_number(io_object_t object, CFStringRef entry, int *result)
-{
-       CFTypeRef entry_as_number;
-       Boolean got_number;
-
-       entry_as_number = IORegistryEntrySearchCFProperty (object,
-                                                          kIOServicePlane,
-                                                          entry,
-                                                          kCFAllocatorDefault,
-                                                          kIORegistryIterateRecursively);
-       if (entry_as_number) {
-               got_number = CFNumberGetValue(entry_as_number,
-                                             kCFNumberIntType,
-                                             result);
-               if (got_number)
-                       return 1;
-       }
-       return 0;
-}
-
-PUBLIC struct altos_list *
-altos_list_start(void)
-{
-       struct altos_list *list = calloc (sizeof (struct altos_list), 1);
-       CFMutableDictionaryRef matching_dictionary = IOServiceMatching("IOUSBDevice");
-       io_iterator_t tdIterator;
-       io_object_t tdObject;
-       kern_return_t ret;
-       int i;
-
-       ret = IOServiceGetMatchingServices(kIOMasterPortDefault, matching_dictionary, &list->iterator);
-       if (ret != kIOReturnSuccess) {
-               free(list);
-               return NULL;
-       }
-       list->ftdi = 0;
-       return list;
-}
-
-PUBLIC struct altos_list *
-altos_ftdi_list_start(void)
-{
-       struct altos_list *list = altos_list_start();
-
-       if (list)
-               list->ftdi = 1;
-       return list;
-}
-
-PUBLIC int
-altos_list_next(struct altos_list *list, struct altos_device *device)
-{
-       io_object_t object;
-       char serial_string[128];
-
-       for (;;) {
-               object = IOIteratorNext(list->iterator);
-               if (!object)
-                       return 0;
-
-               if (!get_number (object, CFSTR(kUSBVendorID), &device->vendor) ||
-                   !get_number (object, CFSTR(kUSBProductID), &device->product))
-                       continue;
-               if (get_string (object, CFSTR("IOCalloutDevice"), device->path, sizeof (device->path)) &&
-                   get_string (object, CFSTR("USB Product Name"), device->name, sizeof (device->name)) &&
-                   get_string (object, CFSTR("USB Serial Number"), serial_string, sizeof (serial_string))) {
-                       device->serial = atoi(serial_string);
-                       return 1;
-               }
-       }
-}
-
-PUBLIC void
-altos_list_finish(struct altos_list *list)
-{
-       IOObjectRelease (list->iterator);
-       free(list);
-}
-
-struct altos_bt_list {
-       int             sock;
-       int             dev_id;
-       int             rsp;
-       int             num_rsp;
-};
-
-#define INQUIRY_MAX_RSP        255
-
-struct altos_bt_list *
-altos_bt_list_start(int inquiry_time)
-{
-       return NULL;
-}
-
-int
-altos_bt_list_next(struct altos_bt_list *bt_list,
-                  struct altos_bt_device *device)
-{
-       return 0;
-}
-
-void
-altos_bt_list_finish(struct altos_bt_list *bt_list)
-{
-}
-
-void
-altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device)
-{
-       strncpy(device->name, name, sizeof (device->name));
-       device->name[sizeof(device->name)-1] = '\0';
-       strncpy(device->addr, addr, sizeof (device->addr));
-       device->addr[sizeof(device->addr)-1] = '\0';
-}
-
-struct altos_file *
-altos_bt_open(struct altos_bt_device *device)
-{
-       return NULL;
-}
-
-#endif
-
-
-#ifdef WINDOWS
-
-#include <stdlib.h>
-#include <windows.h>
-#include <setupapi.h>
-
-struct altos_list {
-       HDEVINFO        dev_info;
-       int             index;
-       int             ftdi;
-};
-
-#define USB_BUF_SIZE   64
-
-struct altos_file {
-       HANDLE                          handle;
-       unsigned char                   out_data[USB_BUF_SIZE];
-       int                             out_used;
-       unsigned char                   in_data[USB_BUF_SIZE];
-       int                             in_used;
-       int                             in_read;
-       OVERLAPPED                      ov_read;
-       BOOL                            pend_read;
-       OVERLAPPED                      ov_write;
-};
-
-#include <stdarg.h>
-
-static void
-log_message(char *fmt, ...)
-{
-       static  FILE *log = NULL;
-       va_list a;
-
-       if (!log)
-               log = fopen("\\temp\\altos.txt", "w");
-       if (log) {
-               SYSTEMTIME time;
-               GetLocalTime(&time);
-               fprintf (log, "%4d-%02d-%02d %2d:%02d:%02d. ",
-                        time.wYear, time.wMonth, time.wDay,
-                        time.wHour, time.wMinute, time.wSecond);
-               va_start(a, fmt);
-               vfprintf(log, fmt, a);
-               va_end(a);
-               fflush(log);
-       }
-}
-
-static void
-_altos_set_last_windows_error(char *file, int line)
-{
-       DWORD   error = GetLastError();
-       TCHAR   message[1024];
-       FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
-                     0,
-                     error,
-                     0,
-                     message,
-                     sizeof (message) / sizeof (TCHAR),
-                     NULL);
-       if (error != ERROR_SUCCESS)
-               log_message ("%s:%d %s\n", file, line, message);
-       altos_set_last_error(error, message);
-}
-
-#define altos_set_last_windows_error() _altos_set_last_windows_error(__FILE__, __LINE__)
-
-PUBLIC struct altos_list *
-altos_list_start(void)
-{
-       struct altos_list       *list = calloc(1, sizeof (struct altos_list));
-
-       if (!list)
-               return NULL;
-       list->dev_info = SetupDiGetClassDevs(NULL, "USB", NULL,
-                                            DIGCF_ALLCLASSES|DIGCF_PRESENT);
-       if (list->dev_info == INVALID_HANDLE_VALUE) {
-               altos_set_last_windows_error();
-               free(list);
-               return NULL;
-       }
-       list->index = 0;
-       list->ftdi = 0;
-       return list;
-}
-
-PUBLIC struct altos_list *
-altos_ftdi_list_start(void)
-{
-       struct altos_list       *list = calloc(1, sizeof (struct altos_list));
-
-       if (!list)
-               return NULL;
-       list->dev_info = SetupDiGetClassDevs(NULL, "FTDIBUS", NULL,
-                                            DIGCF_ALLCLASSES|DIGCF_PRESENT);
-       if (list->dev_info == INVALID_HANDLE_VALUE) {
-               altos_set_last_windows_error();
-               free(list);
-               return NULL;
-       }
-       list->index = 0;
-       list->ftdi = 1;
-       return list;
-}
-
-PUBLIC int
-altos_list_next(struct altos_list *list, struct altos_device *device)
-{
-       SP_DEVINFO_DATA dev_info_data;
-       BYTE            port[128];
-       DWORD           port_len;
-       char            friendlyname[256];
-       BYTE            symbolic[256];
-       DWORD           symbolic_len;
-       HKEY            dev_key;
-       unsigned int    vid, pid;
-       int             serial;
-       HRESULT         result;
-       DWORD           friendlyname_type;
-       DWORD           friendlyname_len;
-       char            instanceid[1024];
-       DWORD           instanceid_len;
-
-       dev_info_data.cbSize = sizeof (SP_DEVINFO_DATA);
-       while(SetupDiEnumDeviceInfo(list->dev_info, list->index,
-                                   &dev_info_data))
-       {
-               list->index++;
-
-               dev_key = SetupDiOpenDevRegKey(list->dev_info, &dev_info_data,
-                                              DICS_FLAG_GLOBAL, 0, DIREG_DEV,
-                                              KEY_READ);
-               if (dev_key == INVALID_HANDLE_VALUE) {
-                       altos_set_last_windows_error();
-                       continue;
-               }
-
-               if (list->ftdi) {
-                       vid = 0x0403;
-                       pid = 0x6015;
-                       serial = 0;
-               } else {
-                       vid = pid = serial = 0;
-                       /* Fetch symbolic name for this device and parse out
-                        * the vid/pid/serial info */
-                       symbolic_len = sizeof(symbolic);
-                       result = RegQueryValueEx(dev_key, "SymbolicName", NULL, NULL,
-                                                symbolic, &symbolic_len);
-                       if (result != 0) {
-                               altos_set_last_windows_error();
-                       } else {
-                               sscanf((char *) symbolic + sizeof("\\??\\USB#VID_") - 1,
-                                      "%04X", &vid);
-                               sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_") - 1,
-                                      "%04X", &pid);
-                               sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_XXXX#") - 1,
-                                      "%d", &serial);
-                       }
-                       if (vid == 0 || pid == 0 || serial == 0) {
-                               if (SetupDiGetDeviceInstanceId(list->dev_info,
-                                                              &dev_info_data,
-                                                              instanceid,
-                                                              sizeof (instanceid),
-                                                              &instanceid_len)) {
-                                       sscanf((char *) instanceid + sizeof("USB\\VID_") - 1,
-                                              "%04X", &vid);
-                                       sscanf((char *) instanceid + sizeof("USB\\VID_XXXX&PID_") - 1,
-                                              "%04X", &pid);
-                                       sscanf((char *) instanceid + sizeof("USB\\VID_XXXX&PID_XXXX\\") - 1,
-                                              "%d", &serial);
-                               } else {
-                                       altos_set_last_windows_error();
-                               }
-                       }
-                       if (vid == 0 || pid == 0 || serial == 0) {
-                               RegCloseKey(dev_key);
-                               continue;
-                       }
-               }
-
-               /* Fetch the com port name */
-               port_len = sizeof (port);
-               result = RegQueryValueEx(dev_key, "PortName", NULL, NULL,
-                                        port, &port_len);
-               RegCloseKey(dev_key);
-               if (result != 0) {
-                       altos_set_last_windows_error();
-                       continue;
-               }
-
-               /* Fetch the device description which is the device name,
-                * with firmware that has unique USB ids */
-               friendlyname_len = sizeof (friendlyname);
-               if(!SetupDiGetDeviceRegistryProperty(list->dev_info,
-                                                    &dev_info_data,
-                                                    SPDRP_FRIENDLYNAME,
-                                                    &friendlyname_type,
-                                                    (BYTE *)friendlyname,
-                                                    sizeof(friendlyname),
-                                                    &friendlyname_len))
-               {
-                       altos_set_last_windows_error();
-                       continue;
-               }
-               device->vendor = vid;
-               device->product = pid;
-               device->serial = serial;
-               strcpy(device->name, friendlyname);
-
-               strcpy(device->path, (char *) port);
-               return 1;
-       }
-       result = GetLastError();
-       if (result != ERROR_NO_MORE_ITEMS)
-               altos_set_last_windows_error();
-       return 0;
-}
-
-PUBLIC void
-altos_list_finish(struct altos_list *list)
-{
-       SetupDiDestroyDeviceInfoList(list->dev_info);
-       free(list);
-}
-
-static int
-altos_queue_read(struct altos_file *file)
-{
-       DWORD   got;
-       if (file->pend_read)
-               return LIBALTOS_SUCCESS;
-
-       if (!ReadFile(file->handle, file->in_data, USB_BUF_SIZE, &got, &file->ov_read)) {
-               if (GetLastError() != ERROR_IO_PENDING) {
-                       altos_set_last_windows_error();
-                       return LIBALTOS_ERROR;
-               }
-               file->pend_read = TRUE;
-       } else {
-               file->pend_read = FALSE;
-               file->in_read = 0;
-               file->in_used = got;
-       }
-       return LIBALTOS_SUCCESS;
-}
-
-static int
-altos_wait_read(struct altos_file *file, int timeout)
-{
-       DWORD   ret;
-       DWORD   got;
-
-       if (!file->pend_read)
-               return LIBALTOS_SUCCESS;
-
-       if (!timeout)
-               timeout = INFINITE;
-
-       ret = WaitForSingleObject(file->ov_read.hEvent, timeout);
-       switch (ret) {
-       case WAIT_OBJECT_0:
-               if (!GetOverlappedResult(file->handle, &file->ov_read, &got, FALSE)) {
-                       altos_set_last_windows_error();
-                       return LIBALTOS_ERROR;
-               }
-               file->pend_read = FALSE;
-               file->in_read = 0;
-               file->in_used = got;
-               break;
-       case WAIT_TIMEOUT:
-               return LIBALTOS_TIMEOUT;
-               break;
-       default:
-               altos_set_last_windows_error();
-               return LIBALTOS_ERROR;
-       }
-       return LIBALTOS_SUCCESS;
-}
-
-static int
-altos_fill(struct altos_file *file, int timeout)
-{
-       int     ret;
-
-       if (file->in_read < file->in_used)
-               return LIBALTOS_SUCCESS;
-
-       file->in_read = file->in_used = 0;
-
-       ret = altos_queue_read(file);
-       if (ret)
-               return ret;
-       ret = altos_wait_read(file, timeout);
-       if (ret)
-               return ret;
-
-       return LIBALTOS_SUCCESS;
-}
-
-PUBLIC int
-altos_flush(struct altos_file *file)
-{
-       DWORD           put;
-       unsigned char   *data = file->out_data;
-       int             used = file->out_used;
-       DWORD           ret;
-
-       while (used) {
-               if (!WriteFile(file->handle, data, used, &put, &file->ov_write)) {
-                       if (GetLastError() != ERROR_IO_PENDING) {
-                               altos_set_last_windows_error();
-                               return LIBALTOS_ERROR;
-                       }
-                       ret = WaitForSingleObject(file->ov_write.hEvent, INFINITE);
-                       switch (ret) {
-                       case WAIT_OBJECT_0:
-                               if (!GetOverlappedResult(file->handle, &file->ov_write, &put, FALSE)) {
-                                       altos_set_last_windows_error();
-                                       return LIBALTOS_ERROR;
-                               }
-                               break;
-                       default:
-                               altos_set_last_windows_error();
-                               return LIBALTOS_ERROR;
-                       }
-               }
-               data += put;
-               used -= put;
-       }
-       file->out_used = 0;
-       return LIBALTOS_SUCCESS;
-}
-
-static HANDLE
-open_serial(char *full_name)
-{
-       HANDLE  handle;
-       DCB     dcb;
-
-       handle = CreateFile(full_name, GENERIC_READ|GENERIC_WRITE,
-                           0, NULL, OPEN_EXISTING,
-                           FILE_FLAG_OVERLAPPED, NULL);
-
-       if (handle == INVALID_HANDLE_VALUE) {
-               altos_set_last_windows_error();
-               return INVALID_HANDLE_VALUE;
-       }
-
-       if (!GetCommState(handle, &dcb)) {
-               altos_set_last_windows_error();
-               CloseHandle(handle);
-               return INVALID_HANDLE_VALUE;
-       }
-       dcb.BaudRate = CBR_9600;
-       dcb.fBinary = TRUE;
-       dcb.fParity = FALSE;
-       dcb.fOutxCtsFlow = FALSE;
-       dcb.fOutxDsrFlow = FALSE;
-       dcb.fDtrControl = DTR_CONTROL_ENABLE;
-       dcb.fDsrSensitivity = FALSE;
-       dcb.fTXContinueOnXoff = FALSE;
-       dcb.fOutX = FALSE;
-       dcb.fInX = FALSE;
-       dcb.fErrorChar = FALSE;
-       dcb.fNull = FALSE;
-       dcb.fRtsControl = RTS_CONTROL_ENABLE;
-       dcb.fAbortOnError = FALSE;
-       dcb.XonLim = 10;
-       dcb.XoffLim = 10;
-       dcb.ByteSize = 8;
-       dcb.Parity = NOPARITY;
-       dcb.StopBits = ONESTOPBIT;
-       dcb.XonChar = 17;
-       dcb.XoffChar = 19;
-#if 0
-       dcb.ErrorChar = 0;
-       dcb.EofChar = 0;
-       dcb.EvtChar = 0;
-#endif
-       if (!SetCommState(handle, &dcb)) {
-               altos_set_last_windows_error();
-               CloseHandle(handle);
-               return INVALID_HANDLE_VALUE;
-       }
-       return handle;
-}
-
-PUBLIC struct altos_file *
-altos_open(struct altos_device *device)
-{
-       struct altos_file       *file = calloc (1, sizeof (struct altos_file));
-       char    full_name[64];
-       COMMTIMEOUTS timeouts;
-       int i;
-
-       if (!file)
-               return NULL;
-
-       strcpy(full_name, "\\\\.\\");
-       strcat(full_name, device->path);
-
-       file->handle = INVALID_HANDLE_VALUE;
-
-       for (i = 0; i < 5; i++) {
-               file->handle = open_serial(full_name);
-               if (file->handle != INVALID_HANDLE_VALUE)
-                       break;
-               altos_set_last_windows_error();
-               Sleep(100);
-       }
-
-       if (file->handle == INVALID_HANDLE_VALUE) {
-               free(file);
-               return NULL;
-       }
-
-       /* The FTDI driver doesn't appear to work right unless you open it twice */
-       if (device->vendor == 0x0403) {
-               CloseHandle(file->handle);
-               file->handle = open_serial(full_name);
-               if (file->handle == INVALID_HANDLE_VALUE) {
-                       free(file);
-                       return NULL;
-               }
-       }
-
-       timeouts.ReadIntervalTimeout = MAXDWORD;
-       timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
-       timeouts.ReadTotalTimeoutConstant = 1 << 30;    /* almost forever */
-       timeouts.WriteTotalTimeoutMultiplier = 0;
-       timeouts.WriteTotalTimeoutConstant = 0;
-       SetCommTimeouts(file->handle, &timeouts);
-
-       file->ov_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
-       file->ov_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
-
-       return file;
-}
-
-PUBLIC void
-altos_close(struct altos_file *file)
-{
-       HANDLE  handle = file->handle;
-       if (handle != INVALID_HANDLE_VALUE) {
-               HANDLE  ov_read = file->ov_read.hEvent;
-               HANDLE  ov_write = file->ov_write.hEvent;
-               file->handle = INVALID_HANDLE_VALUE;
-               file->ov_read.hEvent = INVALID_HANDLE_VALUE;
-               file->ov_write.hEvent = INVALID_HANDLE_VALUE;
-               PurgeComm(handle, PURGE_RXABORT|PURGE_RXCLEAR|PURGE_TXABORT|PURGE_TXCLEAR);
-               Sleep(100);
-               CloseHandle(handle);
-               file->handle = INVALID_HANDLE_VALUE;
-               CloseHandle(ov_read);
-               CloseHandle(ov_write);
-       }
-}
-
-PUBLIC void
-altos_free(struct altos_file *file)
-{
-       altos_close(file);
-       free(file);
-}
-
-PUBLIC int
-altos_putchar(struct altos_file *file, char c)
-{
-       int     ret;
-
-       if (file->out_used == USB_BUF_SIZE) {
-               ret = altos_flush(file);
-               if (ret)
-                       return ret;
-       }
-       file->out_data[file->out_used++] = c;
-       if (file->out_used == USB_BUF_SIZE)
-               return altos_flush(file);
-       return LIBALTOS_SUCCESS;
-}
-
-PUBLIC int
-altos_getchar(struct altos_file *file, int timeout)
-{
-       int     ret;
-       while (file->in_read == file->in_used) {
-               if (file->handle == INVALID_HANDLE_VALUE) {
-                       altos_set_last_windows_error();
-                       return LIBALTOS_ERROR;
-               }
-               ret = altos_fill(file, timeout);
-               if (ret)
-                       return ret;
-       }
-       return file->in_data[file->in_read++];
-}
-
-struct altos_bt_list *
-altos_bt_list_start(int inquiry_time)
-{
-       return NULL;
-}
-
-int
-altos_bt_list_next(struct altos_bt_list *bt_list,
-                  struct altos_bt_device *device)
-{
-       return 0;
-}
-
-void
-altos_bt_list_finish(struct altos_bt_list *bt_list)
-{
-       free(bt_list);
-}
-
-void
-altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device)
-{
-       strncpy(device->name, name, sizeof (device->name));
-       device->name[sizeof(device->name)-1] = '\0';
-       strncpy(device->addr, addr, sizeof (device->addr));
-       device->addr[sizeof(device->addr)-1] = '\0';
-}
-
-struct altos_file *
-altos_bt_open(struct altos_bt_device *device)
-{
-       return NULL;
-}
-
-#endif
index 8b491c580c9c06e913b9438e083ae7274734f5d8..c18493ea7836aca971c0f9ebe8b3b04b1b8d85de 100755 (executable)
Binary files a/libaltos/libaltos.dylib and b/libaltos/libaltos.dylib differ
diff --git a/libaltos/libaltos_common.c b/libaltos/libaltos_common.c
new file mode 100644 (file)
index 0000000..090f03a
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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 "libaltos_private.h"
+
+PUBLIC int
+altos_init(void)
+{
+       return LIBALTOS_SUCCESS;
+}
+
+PUBLIC void
+altos_fini(void)
+{
+}
+
+struct altos_error altos_last_error;
+
+void
+altos_set_last_error(int code, char *string)
+{
+       altos_last_error.code = code;
+       strncpy(altos_last_error.string, string, sizeof (altos_last_error.string) -1);
+       altos_last_error.string[sizeof(altos_last_error.string)-1] = '\0';
+}
+
+PUBLIC void
+altos_get_last_error(struct altos_error *error)
+{
+       *error = altos_last_error;
+}
+
+PUBLIC int
+altos_getchar(struct altos_file *file, int timeout)
+{
+       int     ret;
+       while (file->in_read == file->in_used) {
+               ret = altos_fill(file, timeout);
+               if (ret)
+                       return ret;
+       }
+       return file->in_data[file->in_read++];
+}
+
+PUBLIC int
+altos_putchar(struct altos_file *file, char c)
+{
+       int     ret;
+
+       if (file->out_used == USB_BUF_SIZE) {
+               ret = altos_flush(file);
+               if (ret) {
+                       return ret;
+               }
+       }
+       file->out_data[file->out_used++] = c;
+       ret = 0;
+       if (file->out_used == USB_BUF_SIZE)
+               ret = altos_flush(file);
+       return ret;
+}
+
+
+PUBLIC void
+altos_free(struct altos_file *file)
+{
+       altos_close(file);
+       free(file);
+}
diff --git a/libaltos/libaltos_darwin.c b/libaltos/libaltos_darwin.c
new file mode 100644 (file)
index 0000000..04194d9
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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 "libaltos_private.h"
+#include "libaltos_posix.h"
+
+#include <IOKitLib.h>
+#include <IOKit/usb/USBspec.h>
+#include <IOKit/serial/IOSerialKeys.h>
+#include <usb/IOUSBLib.h>
+#include <usb/USBSpec.h>
+#include <sys/param.h>
+#include <paths.h>
+#include <CFNumber.h>
+#include <IOBSD.h>
+
+/* Mac OS X don't have strndup even if _GNU_SOURCE is defined */
+char *
+altos_strndup (const char *s, size_t n)
+{
+    size_t len = strlen (s);
+    char *ret;
+
+    if (len <= n)
+       return strdup (s);
+    ret = malloc(n + 1);
+    strncpy(ret, s, n);
+    ret[n] = '\0';
+    return ret;
+}
+
+struct altos_list {
+       io_iterator_t iterator;
+       int ftdi;
+};
+
+static char *
+get_cfstring(CFTypeRef string, char result[512])
+{
+       Boolean         got_string;
+
+       got_string = CFStringGetCString(string, result, 512, kCFStringEncodingASCII);
+       if (!got_string)
+               strcpy(result, "CFStringGetCString failed");
+       return result;
+}
+
+static int
+get_string(io_object_t object, CFStringRef entry, char *result, int result_len)
+{
+       CFTypeRef entry_as_string;
+       Boolean got_string;
+       char entry_string[512];
+
+       entry_as_string = IORegistryEntrySearchCFProperty (object,
+                                                          kIOServicePlane,
+                                                          entry,
+                                                          kCFAllocatorDefault,
+                                                          kIORegistryIterateRecursively);
+       if (entry_as_string) {
+               got_string = CFStringGetCString(entry_as_string,
+                                               result, result_len,
+                                               kCFStringEncodingASCII);
+
+               CFRelease(entry_as_string);
+               if (got_string) {
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+static int
+get_number(io_object_t object, CFStringRef entry, int *result)
+{
+       CFTypeRef entry_as_number;
+       Boolean got_number;
+       char entry_string[512];
+
+       entry_as_number = IORegistryEntrySearchCFProperty (object,
+                                                          kIOServicePlane,
+                                                          entry,
+                                                          kCFAllocatorDefault,
+                                                          kIORegistryIterateRecursively);
+       if (entry_as_number) {
+               got_number = CFNumberGetValue(entry_as_number,
+                                             kCFNumberIntType,
+                                             result);
+               if (got_number) {
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+PUBLIC struct altos_list *
+altos_list_start(void)
+{
+       struct altos_list *list = calloc (sizeof (struct altos_list), 1);
+       CFMutableDictionaryRef matching_dictionary;
+       io_iterator_t tdIterator;
+       io_object_t tdObject;
+       kern_return_t ret;
+       int i;
+
+       matching_dictionary = IOServiceMatching(kIOSerialBSDServiceValue);
+       if (matching_dictionary) {
+               CFDictionarySetValue(matching_dictionary,
+                                    CFSTR(kIOSerialBSDTypeKey),
+                                    CFSTR(kIOSerialBSDAllTypes));
+       }
+
+       ret = IOServiceGetMatchingServices(kIOMasterPortDefault, matching_dictionary, &list->iterator);
+       if (ret != kIOReturnSuccess) {
+               free(list);
+               return NULL;
+       }
+       list->ftdi = 0;
+       return list;
+}
+
+PUBLIC struct altos_list *
+altos_ftdi_list_start(void)
+{
+       struct altos_list *list = altos_list_start();
+
+       if (list)
+               list->ftdi = 1;
+       return list;
+}
+
+static io_service_t get_usb_object(io_object_t serial_device)
+{
+       io_iterator_t iterator;
+       io_service_t usb_device;
+       io_service_t service;
+       IOReturn status;
+
+       status = IORegistryEntryCreateIterator(serial_device,
+                                     kIOServicePlane,
+                                     kIORegistryIterateParents | kIORegistryIterateRecursively,
+                                     &iterator);
+
+       if (status != kIOReturnSuccess)
+               return 0;
+
+       while((service = IOIteratorNext(iterator))) {
+               io_name_t servicename;
+               status = IORegistryEntryGetNameInPlane(service, kIOServicePlane, servicename);
+
+               if (status == kIOReturnSuccess && IOObjectConformsTo(service, kIOUSBDeviceClassName)) {
+                       IOObjectRelease(iterator);
+                       return service;
+               }
+               IOObjectRelease(service);
+       }
+       IOObjectRelease(iterator);
+       return 0;
+}
+
+PUBLIC int
+altos_list_next(struct altos_list *list, struct altos_device *device)
+{
+
+       io_object_t object;
+       io_service_t usb_device;
+       char serial_string[128];
+
+       for (;;) {
+               object = IOIteratorNext(list->iterator);
+               if (!object) {
+                       return 0;
+               }
+
+               usb_device = get_usb_object(object);
+
+               if (get_number (usb_device, CFSTR(kUSBVendorID), &device->vendor) &&
+                   get_number (usb_device, CFSTR(kUSBProductID), &device->product) &&
+                   get_string (object, CFSTR(kIOCalloutDeviceKey), device->path, sizeof (device->path)) &&
+                   get_string (usb_device, CFSTR(kUSBProductString), device->name, sizeof (device->name)) &&
+                   get_string (usb_device, CFSTR(kUSBSerialNumberString), serial_string, sizeof (serial_string))) {
+                       device->serial = atoi(serial_string);
+                       IOObjectRelease(object);
+                       IOObjectRelease(usb_device);
+                       return 1;
+               }
+               IOObjectRelease(object);
+               IOObjectRelease(usb_device);
+       }
+}
+
+PUBLIC void
+altos_list_finish(struct altos_list *list)
+{
+       IOObjectRelease (list->iterator);
+       free(list);
+}
+
+struct altos_bt_list {
+       int             sock;
+       int             dev_id;
+       int             rsp;
+       int             num_rsp;
+};
+
+#define INQUIRY_MAX_RSP        255
+
+struct altos_bt_list *
+altos_bt_list_start(int inquiry_time)
+{
+       return NULL;
+}
+
+int
+altos_bt_list_next(struct altos_bt_list *bt_list,
+                  struct altos_bt_device *device)
+{
+       return 0;
+}
+
+void
+altos_bt_list_finish(struct altos_bt_list *bt_list)
+{
+}
+
+void
+altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device)
+{
+       strncpy(device->name, name, sizeof (device->name));
+       device->name[sizeof(device->name)-1] = '\0';
+       strncpy(device->addr, addr, sizeof (device->addr));
+       device->addr[sizeof(device->addr)-1] = '\0';
+}
+
+struct altos_file *
+altos_bt_open(struct altos_bt_device *device)
+{
+       return NULL;
+}
diff --git a/libaltos/libaltos_linux.c b/libaltos/libaltos_linux.c
new file mode 100644 (file)
index 0000000..2065d74
--- /dev/null
@@ -0,0 +1,528 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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 _GNU_SOURCE
+#include "libaltos_private.h"
+#include "libaltos_posix.h"
+
+#include <ctype.h>
+#include <dirent.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_lib.h>
+#include <bluetooth/rfcomm.h>
+
+static char *
+cc_fullname (char *dir, char *file)
+{
+       char    *new;
+       int     dlen = strlen (dir);
+       int     flen = strlen (file);
+       int     slen = 0;
+
+       if (dir[dlen-1] != '/')
+               slen = 1;
+       new = malloc (dlen + slen + flen + 1);
+       if (!new)
+               return 0;
+       strcpy(new, dir);
+       if (slen)
+               strcat (new, "/");
+       strcat(new, file);
+       return new;
+}
+
+static char *
+cc_basename(char *file)
+{
+       char *b;
+
+       b = strrchr(file, '/');
+       if (!b)
+               return file;
+       return b + 1;
+}
+
+static char *
+load_string(char *dir, char *file)
+{
+       char    *full = cc_fullname(dir, file);
+       char    line[4096];
+       char    *r;
+       FILE    *f;
+       int     rlen;
+
+       f = fopen(full, "r");
+       free(full);
+       if (!f)
+               return NULL;
+       r = fgets(line, sizeof (line), f);
+       fclose(f);
+       if (!r)
+               return NULL;
+       rlen = strlen(r);
+       if (r[rlen-1] == '\n')
+               r[rlen-1] = '\0';
+       return strdup(r);
+}
+
+static int
+load_hex(char *dir, char *file)
+{
+       char    *line;
+       char    *end;
+       long    i;
+
+       line = load_string(dir, file);
+       if (!line)
+               return -1;
+       i = strtol(line, &end, 16);
+       free(line);
+       if (end == line)
+               return -1;
+       return i;
+}
+
+static int
+load_dec(char *dir, char *file)
+{
+       char    *line;
+       char    *end;
+       long    i;
+
+       line = load_string(dir, file);
+       if (!line)
+               return -1;
+       i = strtol(line, &end, 10);
+       free(line);
+       if (end == line)
+               return -1;
+       return i;
+}
+
+static int
+dir_filter_tty_colon(const struct dirent *d)
+{
+       return strncmp(d->d_name, "tty:", 4) == 0;
+}
+
+static int
+dir_filter_tty(const struct dirent *d)
+{
+       return strncmp(d->d_name, "tty", 3) == 0;
+}
+
+struct altos_usbdev {
+       char    *sys;
+       char    *tty;
+       char    *manufacturer;
+       char    *product_name;
+       int     serial; /* AltOS always uses simple integer serial numbers */
+       int     idProduct;
+       int     idVendor;
+};
+
+static char *
+usb_tty(char *sys)
+{
+       char *base;
+       int num_configs;
+       int config;
+       struct dirent **namelist;
+       int interface;
+       int num_interfaces;
+       char endpoint_base[20];
+       char *endpoint_full;
+       char *tty_dir;
+       int ntty;
+       char *tty;
+
+       base = cc_basename(sys);
+       num_configs = load_hex(sys, "bNumConfigurations");
+       num_interfaces = load_hex(sys, "bNumInterfaces");
+       for (config = 1; config <= num_configs; config++) {
+               for (interface = 0; interface < num_interfaces; interface++) {
+                       sprintf(endpoint_base, "%s:%d.%d",
+                               base, config, interface);
+                       endpoint_full = cc_fullname(sys, endpoint_base);
+
+
+                       /* Check for tty:ttyACMx style names
+                        */
+                       ntty = scandir(endpoint_full, &namelist,
+                                      dir_filter_tty_colon,
+                                      alphasort);
+                       if (ntty > 0) {
+                               free(endpoint_full);
+                               tty = cc_fullname("/dev", namelist[0]->d_name + 4);
+                               free(namelist);
+                               return tty;
+                       }
+
+                       /* Check for tty/ttyACMx style names
+                        */
+                       tty_dir = cc_fullname(endpoint_full, "tty");
+                       ntty = scandir(tty_dir, &namelist,
+                                      dir_filter_tty,
+                                      alphasort);
+                       free (tty_dir);
+                       if (ntty > 0) {
+                               tty = cc_fullname("/dev", namelist[0]->d_name);
+                               free(endpoint_full);
+                               free(namelist);
+                               return tty;
+                       }
+
+                       /* Check for ttyACMx style names
+                        */
+                       ntty = scandir(endpoint_full, &namelist,
+                                      dir_filter_tty,
+                                      alphasort);
+                       free(endpoint_full);
+                       if (ntty > 0) {
+                               tty = cc_fullname("/dev", namelist[0]->d_name);
+                               free(namelist);
+                               return tty;
+                       }
+
+               }
+       }
+       return NULL;
+}
+
+static struct altos_usbdev *
+usb_scan_device(char *sys)
+{
+       struct altos_usbdev *usbdev;
+       char *tty;
+
+       tty = usb_tty(sys);
+       if (!tty)
+               return NULL;
+       usbdev = calloc(1, sizeof (struct altos_usbdev));
+       if (!usbdev)
+               return NULL;
+       usbdev->sys = strdup(sys);
+       usbdev->manufacturer = load_string(sys, "manufacturer");
+       usbdev->product_name = load_string(sys, "product");
+       usbdev->serial = load_dec(sys, "serial");
+       usbdev->idProduct = load_hex(sys, "idProduct");
+       usbdev->idVendor = load_hex(sys, "idVendor");
+       usbdev->tty = tty;
+       return usbdev;
+}
+
+static void
+usbdev_free(struct altos_usbdev *usbdev)
+{
+       free(usbdev->sys);
+       free(usbdev->manufacturer);
+       free(usbdev->product_name);
+       /* this can get used as a return value */
+       if (usbdev->tty)
+               free(usbdev->tty);
+       free(usbdev);
+}
+
+#define USB_DEVICES    "/sys/bus/usb/devices"
+
+static int
+dir_filter_dev(const struct dirent *d)
+{
+       const char      *n = d->d_name;
+       char    c;
+
+       while ((c = *n++)) {
+               if (isdigit(c))
+                       continue;
+               if (c == '-')
+                       continue;
+               if (c == '.' && n != d->d_name + 1)
+                       continue;
+               return 0;
+       }
+       return 1;
+}
+
+struct altos_list {
+       struct altos_usbdev     **dev;
+       int                     current;
+       int                     ndev;
+};
+
+struct altos_list *
+altos_list_start(void)
+{
+       int                     e;
+       struct dirent           **ents;
+       char                    *dir;
+       struct altos_usbdev     *dev;
+       struct altos_list       *devs;
+       int                     n;
+
+       devs = calloc(1, sizeof (struct altos_list));
+       if (!devs)
+               return NULL;
+
+       n = scandir (USB_DEVICES, &ents,
+                    dir_filter_dev,
+                    alphasort);
+       if (!n)
+               return 0;
+       for (e = 0; e < n; e++) {
+               dir = cc_fullname(USB_DEVICES, ents[e]->d_name);
+               dev = usb_scan_device(dir);
+               if (!dev)
+                       continue;
+               free(dir);
+               if (devs->dev)
+                       devs->dev = realloc(devs->dev,
+                                           (devs->ndev + 1) * sizeof (struct usbdev *));
+               else
+                       devs->dev = malloc (sizeof (struct usbdev *));
+               devs->dev[devs->ndev++] = dev;
+       }
+       free(ents);
+       devs->current = 0;
+       return devs;
+}
+
+PUBLIC struct altos_list *
+altos_ftdi_list_start(void)
+{
+       return altos_list_start();
+}
+
+int
+altos_list_next(struct altos_list *list, struct altos_device *device)
+{
+       struct altos_usbdev *dev;
+       if (list->current >= list->ndev) {
+               return 0;
+       }
+       dev = list->dev[list->current];
+       strcpy(device->name, dev->product_name);
+       device->vendor = dev->idVendor;
+       device->product = dev->idProduct;
+       strcpy(device->path, dev->tty);
+       device->serial = dev->serial;
+       list->current++;
+       return 1;
+}
+
+void
+altos_list_finish(struct altos_list *usbdevs)
+{
+       int     i;
+
+       if (!usbdevs)
+               return;
+       for (i = 0; i < usbdevs->ndev; i++)
+               usbdev_free(usbdevs->dev[i]);
+       free(usbdevs);
+}
+
+#include <dlfcn.h>
+
+static void *libbt;
+static int bt_initialized;
+
+static int init_bt(void) {
+       if (!bt_initialized) {
+               bt_initialized = 1;
+               libbt = dlopen("libbluetooth.so.3", RTLD_LAZY);
+               if (!libbt)
+                       printf("failed to find bluetooth library\n");
+       }
+       return libbt != NULL;
+}
+
+#define join(a,b)      a ## b
+#define bt_func(name, ret, fail, formals, actuals)                     \
+       static ret join(altos_, name) formals {                         \
+                                     static ret (*name) formals;       \
+                                     if (!init_bt()) return fail;      \
+                                     name = dlsym(libbt, #name);       \
+                                     if (!name) return fail;           \
+                                     return name actuals;              \
+                                     }
+
+bt_func(ba2str, int, -1, (const bdaddr_t *ba, char *str), (ba, str))
+#define ba2str altos_ba2str
+
+bt_func(str2ba, int, -1, (const char *str, bdaddr_t *ba), (str, ba))
+#define str2ba altos_str2ba
+
+bt_func(hci_read_remote_name, int, -1, (int sock, const bdaddr_t *ba, int len, char *name, int timeout), (sock, ba, len, name, timeout))
+#define hci_read_remote_name altos_hci_read_remote_name
+
+bt_func(hci_open_dev, int, -1, (int dev_id), (dev_id))
+#define hci_open_dev altos_hci_open_dev
+
+bt_func(hci_get_route, int, -1, (bdaddr_t *bdaddr), (bdaddr))
+#define hci_get_route altos_hci_get_route
+
+bt_func(hci_inquiry, int, -1, (int adapter_id, int len, int max_rsp, const uint8_t *lap, inquiry_info **devs, long flags), (adapter_id, len, max_rsp, lap, devs, flags))
+#define hci_inquiry altos_hci_inquiry
+
+struct altos_bt_list {
+       inquiry_info    *ii;
+       int             sock;
+       int             dev_id;
+       int             rsp;
+       int             num_rsp;
+};
+
+#define INQUIRY_MAX_RSP        255
+
+struct altos_bt_list *
+altos_bt_list_start(int inquiry_time)
+{
+       struct altos_bt_list    *bt_list;
+
+       bt_list = calloc(1, sizeof (struct altos_bt_list));
+       if (!bt_list)
+               goto no_bt_list;
+
+       bt_list->ii = calloc(INQUIRY_MAX_RSP, sizeof (inquiry_info));
+       if (!bt_list->ii)
+               goto no_ii;
+       bt_list->dev_id = hci_get_route(NULL);
+       if (bt_list->dev_id < 0)
+               goto no_dev_id;
+
+       bt_list->sock = hci_open_dev(bt_list->dev_id);
+       if (bt_list->sock < 0)
+               goto no_sock;
+
+       bt_list->num_rsp = hci_inquiry(bt_list->dev_id,
+                                      inquiry_time,
+                                      INQUIRY_MAX_RSP,
+                                      NULL,
+                                      &bt_list->ii,
+                                      IREQ_CACHE_FLUSH);
+       if (bt_list->num_rsp < 0)
+               goto no_rsp;
+
+       bt_list->rsp = 0;
+       return bt_list;
+
+no_rsp:
+       close(bt_list->sock);
+no_sock:
+no_dev_id:
+       free(bt_list->ii);
+no_ii:
+       free(bt_list);
+no_bt_list:
+       return NULL;
+}
+
+int
+altos_bt_list_next(struct altos_bt_list *bt_list,
+                  struct altos_bt_device *device)
+{
+       inquiry_info    *ii;
+
+       if (bt_list->rsp >= bt_list->num_rsp)
+               return 0;
+
+       ii = &bt_list->ii[bt_list->rsp];
+       if (ba2str(&ii->bdaddr, device->addr) < 0)
+               return 0;
+       memset(&device->name, '\0', sizeof (device->name));
+       if (hci_read_remote_name(bt_list->sock, &ii->bdaddr,
+                                sizeof (device->name),
+                                device->name, 0) < 0) {
+               strcpy(device->name, "[unknown]");
+       }
+       bt_list->rsp++;
+       return 1;
+}
+
+void
+altos_bt_list_finish(struct altos_bt_list *bt_list)
+{
+       close(bt_list->sock);
+       free(bt_list->ii);
+       free(bt_list);
+}
+
+void
+altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device)
+{
+       strncpy(device->name, name, sizeof (device->name));
+       device->name[sizeof(device->name)-1] = '\0';
+       strncpy(device->addr, addr, sizeof (device->addr));
+       device->addr[sizeof(device->addr)-1] = '\0';
+}
+
+struct altos_file *
+altos_bt_open(struct altos_bt_device *device)
+{
+       struct sockaddr_rc      addr = { 0 };
+       int                     status, i;
+       struct altos_file_posix *file;
+
+       file = calloc(1, sizeof (struct altos_file_posix));
+       if (!file) {
+               errno = ENOMEM;
+               altos_set_last_posix_error();
+               goto no_file;
+       }
+       addr.rc_family = AF_BLUETOOTH;
+       addr.rc_channel = 1;
+       if (str2ba(device->addr, &addr.rc_bdaddr) < 0) {
+               altos_set_last_posix_error();
+               goto no_sock;
+       }
+
+       for (i = 0; i < 5; i++) {
+               file->fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
+               if (file->fd < 0) {
+                       altos_set_last_posix_error();
+                       goto no_sock;
+               }
+
+               status = connect(file->fd,
+                                (struct sockaddr *)&addr,
+                                sizeof(addr));
+               if (status >= 0 || errno != EBUSY)
+                       break;
+               close(file->fd);
+               usleep(100 * 1000);
+       }
+       if (status < 0) {
+               altos_set_last_posix_error();
+               goto no_link;
+       }
+       usleep(100 * 1000);
+
+#ifdef USE_POLL
+       pipe(file->pipe);
+#else
+       file->out_fd = dup(file->fd);
+#endif
+       return &file->file;
+no_link:
+       close(file->fd);
+no_sock:
+       free(file);
+no_file:
+       return NULL;
+}
+
diff --git a/libaltos/libaltos_posix.c b/libaltos/libaltos_posix.c
new file mode 100644 (file)
index 0000000..731e9aa
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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 "libaltos_private.h"
+#include "libaltos_posix.h"
+
+void
+altos_set_last_posix_error(void)
+{
+       altos_set_last_error(errno, strerror(errno));
+}
+
+PUBLIC struct altos_file *
+altos_open(struct altos_device *device)
+{
+       struct altos_file_posix *file = calloc (sizeof (struct altos_file_posix), 1);
+       int                     ret;
+       struct termios          term;
+
+       if (!file) {
+               altos_set_last_posix_error();
+               return NULL;
+       }
+
+//     altos_set_last_error(12, "yeah yeah, failed again");
+//     free(file);
+//     return NULL;
+
+       file->fd = open(device->path, O_RDWR | O_NOCTTY);
+       if (file->fd < 0) {
+               altos_set_last_posix_error();
+               free(file);
+               return NULL;
+       }
+#ifdef USE_POLL
+       pipe(file->pipe);
+#else
+       file->out_fd = open(device->path, O_RDWR | O_NOCTTY);
+       if (file->out_fd < 0) {
+               altos_set_last_posix_error();
+               close(file->fd);
+               free(file);
+               return NULL;
+       }
+#endif
+       ret = tcgetattr(file->fd, &term);
+       if (ret < 0) {
+               altos_set_last_posix_error();
+               close(file->fd);
+#ifndef USE_POLL
+               close(file->out_fd);
+#endif
+               free(file);
+               return NULL;
+       }
+       cfmakeraw(&term);
+       cfsetospeed(&term, B9600);
+       cfsetispeed(&term, B9600);
+#ifdef USE_POLL
+       term.c_cc[VMIN] = 1;
+       term.c_cc[VTIME] = 0;
+#else
+       term.c_cc[VMIN] = 0;
+       term.c_cc[VTIME] = 1;
+#endif
+       ret = tcsetattr(file->fd, TCSAFLUSH, &term);
+       if (ret < 0) {
+               altos_set_last_posix_error();
+               close(file->fd);
+#ifndef USE_POLL
+               close(file->out_fd);
+#endif
+               free(file);
+               return NULL;
+       }
+       return &file->file;
+}
+
+PUBLIC void
+altos_close(struct altos_file *file_common)
+{
+       struct altos_file_posix *file = (struct altos_file_posix *) file_common;
+
+       if (file->fd != -1) {
+               int     fd = file->fd;
+               file->fd = -1;
+#ifdef USE_POLL
+               write(file->pipe[1], "\r", 1);
+#else
+               close(file->out_fd);
+               file->out_fd = -1;
+#endif
+               close(fd);
+       }
+}
+
+PUBLIC int
+altos_flush(struct altos_file *file_common)
+{
+       struct altos_file_posix *file = (struct altos_file_posix *) file_common;
+
+       if (file->file.out_used && 0) {
+               printf ("flush \"");
+               fwrite(file->file.out_data, 1, file->file.out_used, stdout);
+               printf ("\"\n");
+       }
+       while (file->file.out_used) {
+               int     ret;
+
+               if (file->fd < 0)
+                       return -EBADF;
+#ifdef USE_POLL
+               ret = write (file->fd, file->file.out_data, file->file.out_used);
+#else
+               ret = write (file->out_fd, file->file.out_data, file->file.out_used);
+#endif
+               if (ret < 0) {
+                       altos_set_last_posix_error();
+                       return -altos_last_error.code;
+               }
+               if (ret) {
+                       memmove(file->file.out_data, file->file.out_data + ret,
+                               file->file.out_used - ret);
+                       file->file.out_used -= ret;
+               }
+       }
+       return 0;
+}
+
+
+#ifdef USE_POLL
+#include <poll.h>
+#endif
+
+int
+altos_fill(struct altos_file *file_common, int timeout)
+{
+       struct altos_file_posix *file = (struct altos_file_posix *) file_common;
+
+       int             ret;
+#ifdef USE_POLL
+       struct pollfd   fd[2];
+#endif
+       if (timeout == 0)
+               timeout = -1;
+       while (file->file.in_read == file->file.in_used) {
+               if (file->fd < 0)
+                       return LIBALTOS_ERROR;
+#ifdef USE_POLL
+               fd[0].fd = file->fd;
+               fd[0].events = POLLIN|POLLERR|POLLHUP|POLLNVAL;
+               fd[1].fd = file->pipe[0];
+               fd[1].events = POLLIN;
+               ret = poll(fd, 2, timeout);
+               if (ret < 0) {
+                       altos_set_last_posix_error();
+                       return LIBALTOS_ERROR;
+               }
+               if (ret == 0)
+                       return LIBALTOS_TIMEOUT;
+
+               if (fd[0].revents & (POLLHUP|POLLERR|POLLNVAL))
+                       return LIBALTOS_ERROR;
+               if (fd[0].revents & POLLIN)
+#endif
+               {
+                       ret = read(file->fd, file->file.in_data, USB_BUF_SIZE);
+                       if (ret < 0) {
+                               altos_set_last_posix_error();
+                               return LIBALTOS_ERROR;
+                       }
+                       file->file.in_read = 0;
+                       file->file.in_used = ret;
+#ifndef USE_POLL
+                       if (ret == 0 && timeout > 0)
+                               return LIBALTOS_TIMEOUT;
+#endif
+               }
+       }
+       if (file->file.in_used && 0) {
+               printf ("fill \"");
+               fwrite(file->file.in_data, 1, file->file.in_used, stdout);
+               printf ("\"\n");
+       }
+       return 0;
+}
+
diff --git a/libaltos/libaltos_posix.h b/libaltos/libaltos_posix.h
new file mode 100644 (file)
index 0000000..dc9bfb6
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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 _LIBALTOS_POSIX_H_
+#define _LIBALTOS_POSIX_H_
+
+#include <fcntl.h>
+#include <termios.h>
+#include <errno.h>
+#include <unistd.h>
+
+struct altos_file_posix {
+       struct altos_file               file;
+
+       int                             fd;
+#ifdef USE_POLL
+       int                             pipe[2];
+#else
+       int                             out_fd;
+#endif
+};
+
+void
+altos_set_last_posix_error(void);
+
+#endif /* _LIBALTOS_POSIX_H_ */
diff --git a/libaltos/libaltos_private.h b/libaltos/libaltos_private.h
new file mode 100644 (file)
index 0000000..56f6335
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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 _LIBALTOS_PRIVATE_H_
+#define _LIBALTOS_PRIVATE_H_
+
+#include "libaltos.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define BLUETOOTH_PRODUCT_TELEBT       "TeleBT"
+
+#define USB_BUF_SIZE   64
+
+struct altos_file {
+       /* Shared data */
+       unsigned char                   out_data[USB_BUF_SIZE];
+       int                             out_used;
+       unsigned char                   in_data[USB_BUF_SIZE];
+       int                             in_used;
+       int                             in_read;
+};
+
+#ifdef LINUX
+#define USE_POLL
+#endif
+
+#ifdef DARWIN
+#include <unistd.h>
+
+#define strndup(s,n) altos_strndup(s,n)
+
+char *altos_strndup(const char *s, size_t n);
+
+#endif
+
+void
+altos_set_last_error(int code, char *string);
+
+extern struct altos_error altos_last_error;
+
+PUBLIC int
+altos_flush(struct altos_file *file);
+
+int
+altos_fill(struct altos_file *file, int timeout);
+
+#endif /* _LIBALTOS_PRIVATE_H_ */
diff --git a/libaltos/libaltos_windows.c b/libaltos/libaltos_windows.c
new file mode 100644 (file)
index 0000000..2c3f41e
--- /dev/null
@@ -0,0 +1,761 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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 "libaltos_private.h"
+
+#include <winsock2.h>
+#include <windows.h>
+#include <setupapi.h>
+
+struct altos_list {
+       HDEVINFO        dev_info;
+       int             index;
+       int             ftdi;
+};
+
+#define USB_BUF_SIZE   64
+
+struct altos_file_windows {
+       struct altos_file               file;
+
+       BOOL                            is_winsock;
+       /* Data used by the regular I/O */
+       HANDLE                          handle;
+       OVERLAPPED                      ov_read;
+       BOOL                            pend_read;
+       OVERLAPPED                      ov_write;
+
+       /* Data used by winsock */
+       SOCKET                          socket;
+};
+
+#include <stdarg.h>
+
+static void
+log_message(char *fmt, ...)
+{
+       static FILE *log = NULL;
+       va_list a;
+
+       if (!log)
+               log = fopen("\\temp\\altos.txt", "w");
+       if (log) {
+               SYSTEMTIME time;
+               char    buffer[4096];
+
+               GetLocalTime(&time);
+               sprintf (buffer, "%4d-%02d-%02d %2d:%02d:%02d. ",
+                        time.wYear, time.wMonth, time.wDay,
+                        time.wHour, time.wMinute, time.wSecond);
+               va_start(a, fmt);
+
+               vsprintf(buffer + strlen(buffer), fmt, a);
+               va_end(a);
+
+               fputs(buffer, log);
+               fflush(log);
+               fputs(buffer, stdout);
+               fflush(stdout);
+       }
+}
+
+static void
+_altos_set_last_windows_error(char *file, int line, DWORD error)
+{
+       TCHAR   message[1024];
+       FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
+                     0,
+                     error,
+                     0,
+                     message,
+                     sizeof (message) / sizeof (TCHAR),
+                     NULL);
+       if (error != ERROR_SUCCESS)
+               log_message ("%s:%d (%d) %s\n", file, line, error, message);
+       altos_set_last_error(error, message);
+}
+
+#define altos_set_last_windows_error() _altos_set_last_windows_error(__FILE__, __LINE__, GetLastError())
+#define altos_set_last_winsock_error() _altos_set_last_windows_error(__FILE__, __LINE__, WSAGetLastError())
+
+PUBLIC struct altos_list *
+altos_list_start(void)
+{
+       struct altos_list       *list = calloc(1, sizeof (struct altos_list));
+
+       if (!list)
+               return NULL;
+       list->dev_info = SetupDiGetClassDevs(NULL, "USB", NULL,
+                                            DIGCF_ALLCLASSES|DIGCF_PRESENT);
+       if (list->dev_info == INVALID_HANDLE_VALUE) {
+               altos_set_last_windows_error();
+               free(list);
+               return NULL;
+       }
+       list->index = 0;
+       list->ftdi = 0;
+       return list;
+}
+
+PUBLIC struct altos_list *
+altos_ftdi_list_start(void)
+{
+       struct altos_list       *list = calloc(1, sizeof (struct altos_list));
+
+       if (!list)
+               return NULL;
+       list->dev_info = SetupDiGetClassDevs(NULL, "FTDIBUS", NULL,
+                                            DIGCF_ALLCLASSES|DIGCF_PRESENT);
+       if (list->dev_info == INVALID_HANDLE_VALUE) {
+               altos_set_last_windows_error();
+               free(list);
+               return NULL;
+       }
+       list->index = 0;
+       list->ftdi = 1;
+       return list;
+}
+
+PUBLIC int
+altos_list_next(struct altos_list *list, struct altos_device *device)
+{
+       SP_DEVINFO_DATA dev_info_data;
+       BYTE            port[128];
+       DWORD           port_len;
+       char            friendlyname[256];
+       BYTE            symbolic[256];
+       DWORD           symbolic_len;
+       HKEY            dev_key;
+       unsigned int    vid, pid;
+       int             serial;
+       HRESULT         result;
+       DWORD           friendlyname_type;
+       DWORD           friendlyname_len;
+       char            instanceid[1024];
+       DWORD           instanceid_len;
+
+       dev_info_data.cbSize = sizeof (SP_DEVINFO_DATA);
+       while(SetupDiEnumDeviceInfo(list->dev_info, list->index,
+                                   &dev_info_data))
+       {
+               list->index++;
+
+               dev_key = SetupDiOpenDevRegKey(list->dev_info, &dev_info_data,
+                                              DICS_FLAG_GLOBAL, 0, DIREG_DEV,
+                                              KEY_READ);
+               if (dev_key == INVALID_HANDLE_VALUE) {
+                       altos_set_last_windows_error();
+                       continue;
+               }
+
+               if (list->ftdi) {
+                       vid = 0x0403;
+                       pid = 0x6015;
+                       serial = 0;
+               } else {
+                       vid = pid = serial = 0;
+                       /* Fetch symbolic name for this device and parse out
+                        * the vid/pid/serial info */
+                       symbolic_len = sizeof(symbolic);
+                       result = RegQueryValueEx(dev_key, "SymbolicName", NULL, NULL,
+                                                symbolic, &symbolic_len);
+                       if (result != 0) {
+                               altos_set_last_windows_error();
+                       } else {
+                               sscanf((char *) symbolic + sizeof("\\??\\USB#VID_") - 1,
+                                      "%04X", &vid);
+                               sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_") - 1,
+                                      "%04X", &pid);
+                               sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_XXXX#") - 1,
+                                      "%d", &serial);
+                       }
+                       if (vid == 0 || pid == 0 || serial == 0) {
+                               if (SetupDiGetDeviceInstanceId(list->dev_info,
+                                                              &dev_info_data,
+                                                              instanceid,
+                                                              sizeof (instanceid),
+                                                              &instanceid_len)) {
+                                       sscanf((char *) instanceid + sizeof("USB\\VID_") - 1,
+                                              "%04X", &vid);
+                                       sscanf((char *) instanceid + sizeof("USB\\VID_XXXX&PID_") - 1,
+                                              "%04X", &pid);
+                                       sscanf((char *) instanceid + sizeof("USB\\VID_XXXX&PID_XXXX\\") - 1,
+                                              "%d", &serial);
+                               } else {
+                                       altos_set_last_windows_error();
+                               }
+                       }
+                       if (vid == 0 || pid == 0 || serial == 0) {
+                               RegCloseKey(dev_key);
+                               continue;
+                       }
+               }
+
+               /* Fetch the com port name */
+               port_len = sizeof (port);
+               result = RegQueryValueEx(dev_key, "PortName", NULL, NULL,
+                                        port, &port_len);
+               RegCloseKey(dev_key);
+               if (result != 0) {
+                       altos_set_last_windows_error();
+                       continue;
+               }
+
+               /* Fetch the device description which is the device name,
+                * with firmware that has unique USB ids */
+               friendlyname_len = sizeof (friendlyname);
+               if(!SetupDiGetDeviceRegistryProperty(list->dev_info,
+                                                    &dev_info_data,
+                                                    SPDRP_FRIENDLYNAME,
+                                                    &friendlyname_type,
+                                                    (BYTE *)friendlyname,
+                                                    sizeof(friendlyname),
+                                                    &friendlyname_len))
+               {
+                       altos_set_last_windows_error();
+                       continue;
+               }
+               device->vendor = vid;
+               device->product = pid;
+               device->serial = serial;
+               strcpy(device->name, friendlyname);
+
+               strcpy(device->path, (char *) port);
+               return 1;
+       }
+       result = GetLastError();
+       if (result != ERROR_NO_MORE_ITEMS)
+               altos_set_last_windows_error();
+       return 0;
+}
+
+PUBLIC void
+altos_list_finish(struct altos_list *list)
+{
+       SetupDiDestroyDeviceInfoList(list->dev_info);
+       free(list);
+}
+
+static int
+altos_queue_read(struct altos_file_windows *file)
+{
+       DWORD   got;
+       if (file->pend_read)
+               return LIBALTOS_SUCCESS;
+
+       if (!ReadFile(file->handle, file->file.in_data, USB_BUF_SIZE, &got, &file->ov_read)) {
+               if (GetLastError() != ERROR_IO_PENDING) {
+                       altos_set_last_windows_error();
+                       return LIBALTOS_ERROR;
+               }
+               file->pend_read = TRUE;
+       } else {
+               file->pend_read = FALSE;
+               file->file.in_read = 0;
+               file->file.in_used = got;
+       }
+       return LIBALTOS_SUCCESS;
+}
+
+static int
+altos_wait_read(struct altos_file_windows *file, int timeout)
+{
+       DWORD   ret;
+       DWORD   got;
+
+       if (!file->pend_read)
+               return LIBALTOS_SUCCESS;
+
+       if (!timeout)
+               timeout = INFINITE;
+
+       ret = WaitForSingleObject(file->ov_read.hEvent, timeout);
+       switch (ret) {
+       case WAIT_OBJECT_0:
+               if (!GetOverlappedResult(file->handle, &file->ov_read, &got, FALSE)) {
+                       if (GetLastError () != ERROR_OPERATION_ABORTED)
+                               altos_set_last_windows_error();
+                       return LIBALTOS_ERROR;
+               }
+               file->pend_read = FALSE;
+               file->file.in_read = 0;
+               file->file.in_used = got;
+               break;
+       case WAIT_TIMEOUT:
+               return LIBALTOS_TIMEOUT;
+               break;
+       default:
+               altos_set_last_windows_error();
+               return LIBALTOS_ERROR;
+       }
+       return LIBALTOS_SUCCESS;
+}
+
+int
+altos_fill(struct altos_file *file_common, int timeout)
+{
+       struct altos_file_windows       *file = (struct altos_file_windows *) file_common;
+
+       int     ret;
+
+       if (file->file.in_read < file->file.in_used)
+               return LIBALTOS_SUCCESS;
+
+       file->file.in_read = file->file.in_used = 0;
+
+       if (file->is_winsock) {
+
+               for (;;) {
+                       fd_set  readfds;
+                       TIMEVAL timeval;
+                       int     thistimeout;
+
+                       /* Check to see if the socket has been closed */
+                       if (file->socket == INVALID_SOCKET)
+                               return LIBALTOS_ERROR;
+
+#define POLL_TIMEOUT   10000
+
+                       /* Poll to see if the socket has been closed
+                        * as select doesn't abort when that happens
+                        */
+                       if (timeout) {
+                               thistimeout = timeout;
+                               if (thistimeout > POLL_TIMEOUT)
+                                       thistimeout = POLL_TIMEOUT;
+                       } else {
+                               thistimeout = POLL_TIMEOUT;
+                       }
+
+                       timeval.tv_sec = thistimeout / 1000;
+                       timeval.tv_usec = (thistimeout % 1000) * 1000;
+
+                       FD_ZERO(&readfds);
+                       FD_SET(file->socket, &readfds);
+
+                       ret = select(1, &readfds, NULL, NULL, &timeval);
+
+                       if (ret == 0) {
+                               if (timeout) {
+                                       timeout -= thistimeout;
+                                       if (timeout == 0)
+                                               return LIBALTOS_TIMEOUT;
+                               }
+                       } else {
+                               if (ret > 0)
+                                       break;
+
+                               if (ret < 0) {
+                                       altos_set_last_winsock_error();
+                                       return LIBALTOS_ERROR;
+                               }
+                       }
+               }
+
+               if (file->socket == INVALID_SOCKET) {
+                       altos_set_last_winsock_error();
+                       return LIBALTOS_ERROR;
+               }
+
+               ret = recv(file->socket, (char *) file->file.in_data, USB_BUF_SIZE, 0);
+
+               if (ret <= 0) {
+                       altos_set_last_winsock_error();
+                       return LIBALTOS_ERROR;
+               }
+               file->file.in_read = 0;
+               file->file.in_used = ret;
+       } else {
+               if (file->handle == INVALID_HANDLE_VALUE) {
+                       altos_set_last_windows_error();
+                       return LIBALTOS_ERROR;
+               }
+
+               ret = altos_queue_read(file);
+               if (ret)
+                       return ret;
+               ret = altos_wait_read(file, timeout);
+               if (ret)
+                       return ret;
+       }
+
+       return LIBALTOS_SUCCESS;
+}
+
+PUBLIC int
+altos_flush(struct altos_file *file_common)
+{
+       struct altos_file_windows       *file = (struct altos_file_windows *) file_common;
+
+       unsigned char   *data = file->file.out_data;
+       int             used = file->file.out_used;
+
+       while (used) {
+               if (file->is_winsock) {
+                       int     put;
+
+                       put = send(file->socket, (char *) data, used, 0);
+                       if (put <= 0) {
+                               altos_set_last_winsock_error();
+                               return LIBALTOS_ERROR;
+                       }
+                       data += put;
+                       used -= put;
+               } else {
+                       DWORD           put;
+                       DWORD           ret;
+                       if (!WriteFile(file->handle, data, used, &put, &file->ov_write)) {
+                               if (GetLastError() != ERROR_IO_PENDING) {
+                                       altos_set_last_windows_error();
+                                       return LIBALTOS_ERROR;
+                               }
+                               ret = WaitForSingleObject(file->ov_write.hEvent, INFINITE);
+                               switch (ret) {
+                               case WAIT_OBJECT_0:
+                                       if (!GetOverlappedResult(file->handle, &file->ov_write, &put, FALSE)) {
+                                               altos_set_last_windows_error();
+                                               return LIBALTOS_ERROR;
+                                       }
+                                       break;
+                               default:
+                                       altos_set_last_windows_error();
+                                       return LIBALTOS_ERROR;
+                               }
+                       }
+                       data += put;
+                       used -= put;
+               }
+       }
+       file->file.out_used = 0;
+       return LIBALTOS_SUCCESS;
+}
+
+static HANDLE
+open_serial(char *full_name)
+{
+       HANDLE  handle;
+       DCB     dcb;
+
+       handle = CreateFile(full_name, GENERIC_READ|GENERIC_WRITE,
+                           0, NULL, OPEN_EXISTING,
+                           FILE_FLAG_OVERLAPPED, NULL);
+
+       if (handle == INVALID_HANDLE_VALUE) {
+               altos_set_last_windows_error();
+               return INVALID_HANDLE_VALUE;
+       }
+
+       if (!GetCommState(handle, &dcb)) {
+               altos_set_last_windows_error();
+               CloseHandle(handle);
+               return INVALID_HANDLE_VALUE;
+       }
+       dcb.BaudRate = CBR_9600;
+       dcb.fBinary = TRUE;
+       dcb.fParity = FALSE;
+       dcb.fOutxCtsFlow = FALSE;
+       dcb.fOutxDsrFlow = FALSE;
+       dcb.fDtrControl = DTR_CONTROL_ENABLE;
+       dcb.fDsrSensitivity = FALSE;
+       dcb.fTXContinueOnXoff = FALSE;
+       dcb.fOutX = FALSE;
+       dcb.fInX = FALSE;
+       dcb.fErrorChar = FALSE;
+       dcb.fNull = FALSE;
+       dcb.fRtsControl = RTS_CONTROL_ENABLE;
+       dcb.fAbortOnError = FALSE;
+       dcb.XonLim = 10;
+       dcb.XoffLim = 10;
+       dcb.ByteSize = 8;
+       dcb.Parity = NOPARITY;
+       dcb.StopBits = ONESTOPBIT;
+       dcb.XonChar = 17;
+       dcb.XoffChar = 19;
+#if 0
+       dcb.ErrorChar = 0;
+       dcb.EofChar = 0;
+       dcb.EvtChar = 0;
+#endif
+       if (!SetCommState(handle, &dcb)) {
+               altos_set_last_windows_error();
+               CloseHandle(handle);
+               return INVALID_HANDLE_VALUE;
+       }
+       return handle;
+}
+
+PUBLIC struct altos_file *
+altos_open(struct altos_device *device)
+{
+       struct altos_file_windows       *file = calloc (1, sizeof (struct altos_file_windows));
+       char    full_name[64];
+       COMMTIMEOUTS timeouts;
+       int i;
+
+       if (!file)
+               return NULL;
+
+       strcpy(full_name, "\\\\.\\");
+       strcat(full_name, device->path);
+
+       file->handle = INVALID_HANDLE_VALUE;
+
+       for (i = 0; i < 5; i++) {
+               file->handle = open_serial(full_name);
+               if (file->handle != INVALID_HANDLE_VALUE)
+                       break;
+               altos_set_last_windows_error();
+               Sleep(100);
+       }
+
+       if (file->handle == INVALID_HANDLE_VALUE) {
+               free(file);
+               return NULL;
+       }
+
+       /* The FTDI driver doesn't appear to work right unless you open it twice */
+       if (device->vendor == 0x0403) {
+               CloseHandle(file->handle);
+               file->handle = open_serial(full_name);
+               if (file->handle == INVALID_HANDLE_VALUE) {
+                       free(file);
+                       return NULL;
+               }
+       }
+
+       timeouts.ReadIntervalTimeout = MAXDWORD;
+       timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
+       timeouts.ReadTotalTimeoutConstant = 1 << 30;    /* almost forever */
+       timeouts.WriteTotalTimeoutMultiplier = 0;
+       timeouts.WriteTotalTimeoutConstant = 0;
+       SetCommTimeouts(file->handle, &timeouts);
+
+       file->ov_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+       file->ov_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+       return &file->file;
+}
+
+PUBLIC void
+altos_close(struct altos_file *file_common)
+{
+       struct altos_file_windows       *file = (struct altos_file_windows *) file_common;
+
+       if (file->is_winsock) {
+               SOCKET  socket = file->socket;
+               if (socket != INVALID_SOCKET) {
+                       file->socket = INVALID_SOCKET;
+                       closesocket(socket);
+               }
+       } else {
+               HANDLE  handle = file->handle;
+               if (handle != INVALID_HANDLE_VALUE) {
+                       HANDLE  ov_read = file->ov_read.hEvent;
+                       HANDLE  ov_write = file->ov_write.hEvent;
+                       file->handle = INVALID_HANDLE_VALUE;
+                       file->ov_read.hEvent = INVALID_HANDLE_VALUE;
+                       file->ov_write.hEvent = INVALID_HANDLE_VALUE;
+                       PurgeComm(handle, PURGE_RXABORT|PURGE_RXCLEAR|PURGE_TXABORT|PURGE_TXCLEAR);
+                       Sleep(100);
+                       CloseHandle(handle);
+                       file->handle = INVALID_HANDLE_VALUE;
+                       CloseHandle(ov_read);
+                       CloseHandle(ov_write);
+               }
+       }
+}
+
+#include <ws2bth.h>
+
+#define LUP_SET        (LUP_RETURN_NAME| LUP_CONTAINERS | LUP_RETURN_ADDR | LUP_FLUSHCACHE |\
+                LUP_RETURN_TYPE | LUP_RETURN_BLOB | LUP_RES_SERVICE)
+
+struct altos_bt_list {
+       WSADATA WSAData;
+       HANDLE  lookup;
+};
+
+struct altos_bt_list *
+altos_bt_list_start(int inquiry_time)
+{
+       struct altos_bt_list    *bt_list;
+       WSAQUERYSET             query_set;
+       int                     retCode;
+
+       /* Windows provides no way to set the time */
+       (void) inquiry_time;
+       bt_list = calloc(1, sizeof (struct altos_bt_list));
+       if (!bt_list) {
+               altos_set_last_windows_error();
+               return NULL;
+       }
+
+       if ((retCode = WSAStartup(MAKEWORD(2,2),&bt_list->WSAData)) != 0) {
+               altos_set_last_winsock_error();
+               free(bt_list);
+               return NULL;
+       }
+
+       memset(&query_set, '\0', sizeof (query_set));
+       query_set.dwSize = sizeof(WSAQUERYSET);
+       query_set.dwNameSpace = NS_BTH;
+
+       retCode = WSALookupServiceBegin(&query_set, LUP_SET, &bt_list->lookup);
+
+       if (retCode != 0) {
+               altos_set_last_winsock_error();
+               free(bt_list);
+               return NULL;
+       }
+       return bt_list;
+}
+
+static unsigned char get_byte(BTH_ADDR ba, int shift)
+{
+       return (ba >> ((5 - shift) << 3)) & 0xff;
+}
+
+static BTH_ADDR put_byte(unsigned char c, int shift)
+{
+       return ((BTH_ADDR) c) << ((5 - shift) << 3);
+}
+
+static void
+ba2str(BTH_ADDR ba, char *str)
+{
+
+       sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
+               get_byte(ba, 0),
+               get_byte(ba, 1),
+               get_byte(ba, 2),
+               get_byte(ba, 3),
+               get_byte(ba, 4),
+               get_byte(ba, 5));
+}
+
+static BTH_ADDR
+str2ba(char *str)
+{
+       unsigned int    bytes[6];
+
+       sscanf(str,  "%02x:%02x:%02x:%02x:%02x:%02x",
+              &bytes[0],
+              &bytes[1],
+              &bytes[2],
+              &bytes[3],
+              &bytes[4],
+              &bytes[5]);
+       return (put_byte(bytes[0], 0) |
+               put_byte(bytes[1], 1) |
+               put_byte(bytes[2], 2) |
+               put_byte(bytes[3], 3) |
+               put_byte(bytes[4], 4) |
+               put_byte(bytes[5], 5));
+}
+
+int
+altos_bt_list_next(struct altos_bt_list *bt_list,
+                  struct altos_bt_device *device)
+{
+       for (;;) {
+               BYTE            buffer[4096];
+               DWORD           length = sizeof (buffer);;
+               WSAQUERYSET     *results = (WSAQUERYSET *)buffer;
+               CSADDR_INFO     *addr_info;
+               int             retCode;
+               SOCKADDR_BTH    *sockaddr_bth;
+
+               memset(buffer, '\0', sizeof(buffer));
+
+               retCode = WSALookupServiceNext(bt_list->lookup, LUP_SET, &length, results);
+
+               if (retCode != 0) {
+                       int error = WSAGetLastError();
+                       if (error != WSAENOMORE && error != WSA_E_NO_MORE)
+                               altos_set_last_winsock_error();
+                       return 0;
+               }
+
+               if (results->dwNumberOfCsAddrs > 0) {
+
+                       addr_info = results->lpcsaBuffer;
+
+                       strncpy(device->name, results->lpszServiceInstanceName, sizeof(device->name));
+                       device->name[sizeof(device->name)-1] = '\0';
+
+                       sockaddr_bth = (SOCKADDR_BTH *) addr_info->RemoteAddr.lpSockaddr;
+
+                       ba2str(sockaddr_bth->btAddr, device->addr);
+
+                       return 1;
+               }
+       }
+}
+
+void
+altos_bt_list_finish(struct altos_bt_list *bt_list)
+{
+       WSALookupServiceEnd(bt_list->lookup);
+       free(bt_list);
+}
+
+void
+altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device)
+{
+       strncpy(device->name, name, sizeof (device->name));
+       device->name[sizeof(device->name)-1] = '\0';
+       strncpy(device->addr, addr, sizeof (device->addr));
+       device->addr[sizeof(device->addr)-1] = '\0';
+}
+
+struct altos_file *
+altos_bt_open(struct altos_bt_device *device)
+{
+       struct altos_file_windows       *file;
+       SOCKADDR_BTH            sockaddr_bth;
+       int                     ret;
+
+       file = calloc(1, sizeof (struct altos_file_windows));
+       if (!file) {
+               return NULL;
+       }
+
+       file->is_winsock = TRUE;
+       file->socket = WSASocket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM, NULL, 0, WSA_FLAG_OVERLAPPED);
+
+       if (file->socket == INVALID_SOCKET) {
+               altos_set_last_winsock_error();
+               free(file);
+               return NULL;
+       }
+
+       memset(&sockaddr_bth, '\0', sizeof (sockaddr_bth));
+       sockaddr_bth.addressFamily = AF_BTH;
+       sockaddr_bth.btAddr = str2ba(device->addr);
+       sockaddr_bth.port = 1;
+
+       ret = connect(file->socket, (SOCKADDR *) &sockaddr_bth, sizeof (sockaddr_bth));
+
+       if (ret != 0) {
+               altos_set_last_winsock_error();
+               closesocket(file->socket);
+               free(file);
+               return NULL;
+       }
+       return &file->file;
+}
+
index 085b01314db07ed9cd327cc315de60a95bc01257..60bf8ad7f52bd61ee1110b8879082a0f91d4900a 100644 (file)
@@ -20,8 +20,8 @@ package org.altusmetrum.micropeak;
 import java.lang.*;
 import java.io.*;
 import java.util.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 class MicroIterator implements Iterator<MicroDataPoint> {
        int             i;
index 0157f05daf7f6f398331a5e9fd800719ccf820bc..2775165f690bab88634f293dc7fda5b375715df2 100644 (file)
@@ -17,7 +17,7 @@
 
 package org.altusmetrum.micropeak;
 
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class MicroDataPoint implements AltosUIDataPoint {
        public double           time;
index 6e45359b7878239a83ac2357e9d30ce828edc877..005e154e08a505c20570e9adf742b03e70146cb8 100644 (file)
@@ -21,7 +21,7 @@ import javax.swing.*;
 import java.awt.*;
 import java.awt.event.*;
 import java.util.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class MicroDeviceDialog extends AltosDeviceDialog {
 
index 53d70b1b18b0d7c21027fc472e6c886a0c62f0f8..49bcaf54e4ef994b034f30c8348208efa384fa28 100644 (file)
@@ -23,8 +23,8 @@ import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
 import java.util.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class MicroDownload extends AltosUIDialog implements Runnable, ActionListener, MicroSerialLog, WindowListener {
        MicroPeak       owner;
index c5b5d3d6641d5e2fdde6da9e848419acafb664f1..1c48a0d3dfd48a8f0035ecfffeb46311db7cc549 100644 (file)
@@ -23,8 +23,8 @@ import java.util.ArrayList;
 import java.awt.*;
 import javax.swing.*;
 import javax.swing.filechooser.FileNameExtensionFilter;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class MicroExport extends JFileChooser {
 
index 5712d6b66b31827c37d26a0380e63cbde53794ce..0ef021a1de38f415d09b49d36af3a364e9a61143 100644 (file)
@@ -19,8 +19,8 @@ package org.altusmetrum.micropeak;
 
 import java.io.*;
 import java.util.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class MicroFile {
 
index 01ce284b1086e6b02d1dcb23f01d928255b1a0a1..013d1128c784b838e019e1e60e24c15cb32d2f60 100644 (file)
@@ -20,8 +20,8 @@ package org.altusmetrum.micropeak;
 import javax.swing.*;
 import javax.swing.filechooser.FileNameExtensionFilter;
 import java.io.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class MicroFileChooser extends JFileChooser {
        JFrame  frame;
index 21f839b64f816d13f6bfa0fbbe6e433eb8988b5a..9f3c0426597bb96120cb3aca96f233f7f1a2cfe1 100644 (file)
@@ -21,7 +21,7 @@ import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
 import java.util.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class MicroFrame extends AltosUIFrame {
        static String[] micro_icon_names = {
index c4dcb29c973e8a2f72518c460f27df2213fc5b76..4941070cc1e860089cfe88891766e4796383d660 100644 (file)
@@ -22,8 +22,8 @@ import java.util.ArrayList;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 import org.jfree.ui.*;
 import org.jfree.chart.*;
index 1b7327e4ef161249baf139c89fb07709d7f6309d..fb4fe1cb721a797b49a325be07c1ba0f26d13f80 100644 (file)
@@ -23,8 +23,8 @@ import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
 import java.util.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class MicroPeak extends MicroFrame implements ActionListener, ItemListener {
 
index c35048345373fb27fc3be9c2cd3475ad0dbf1279..767ff9e133dd7f82a46dad6a5afe108f59802d57 100644 (file)
@@ -20,8 +20,8 @@ package org.altusmetrum.micropeak;
 import java.awt.*;
 import java.io.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class MicroRaw extends JTextArea {
 
index e964ee9e52bd5e1da4c4ca936f0d6b9bfc049793..a38e2b46710a6bb8bad88eca0760fe7a452b085f 100644 (file)
@@ -24,8 +24,8 @@ import javax.swing.filechooser.FileNameExtensionFilter;
 import java.io.*;
 import java.util.concurrent.*;
 import java.util.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class MicroSave extends JFileChooser {
 
index f5a98929ca01681609124a2f549a11b816cce072..ea68aa1ad1441072b4b6b9867186788925052e0b 100644 (file)
@@ -20,7 +20,7 @@ package org.altusmetrum.micropeak;
 import java.util.*;
 import java.io.*;
 import libaltosJNI.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class MicroSerial extends InputStream {
        SWIGTYPE_p_altos_file   file;
index e808dee24b81fcb6676da6d7acd7bbbacba67337..e8accaeb81d9e8835af42ea8b3fa5d00a1eebef5 100644 (file)
@@ -20,7 +20,7 @@ package org.altusmetrum.micropeak;
 import java.util.*;
 import java.io.*;
 import libaltosJNI.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public interface MicroSerialLog {
 
index 9e8f193815bbbdd924340824ed8c7081bf144aae..d2f80a8f561c904d904e14ccc91e93871b2042a0 100644 (file)
@@ -18,8 +18,8 @@
 package org.altusmetrum.micropeak;
 
 import java.io.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class MicroStats {
        double          coast_height;
index ad7b206c3a8f0876480187980bcffd366d4824f7..1adef54aba3b089697227bf1e72fde1fa2b03412 100644 (file)
@@ -19,8 +19,8 @@ package org.altusmetrum.micropeak;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class MicroStatsTable extends JComponent implements AltosFontListener {
        GridBagLayout   layout;
index f6568d3663b50308c32aefd292d4deb10806fbcd..9ceae1cb2dd47599ed18381bd00f9385ba854c49 100644 (file)
@@ -19,8 +19,8 @@ package org.altusmetrum.micropeak;
 
 import java.util.*;
 import libaltosJNI.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class MicroUSB extends altos_device implements AltosDevice {
 
index c3b63f7b31d6b3215764a4a601973178a8d02225..34f5908d38a15c1c9eb79bf6a909dc38e74ee44d 100644 (file)
@@ -62,15 +62,6 @@ UninstPage instfiles
 
 ; And the stuff to install
 
-Section "FTDI USB Driver"
-       SetOutPath $INSTDIR
-
-       File "CDM_v2.12.00_WHQL_Certified.exe"
-
-       StrCpy $2 "$INSTDIR\CDM_v2.12.00_WHQL_Certified.exe"
-       ExecWait $2
-SectionEnd
-
 Section "Install Driver" InstDriver
 
        InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} AltusMetrumSerial
@@ -117,6 +108,15 @@ Section "${REG_NAME} Desktop Shortcut"
        CreateShortCut "$DESKTOP\${REG_NAME}.lnk" "$INSTDIR\${WIN_APP_EXE}"  "" "$INSTDIR\${WIN_APP_ICON}"
 SectionEnd
 
+Section "FTDI USB Driver"
+       SetOutPath $INSTDIR
+
+       File "CDM_v2.12.00_WHQL_Certified.exe"
+
+       StrCpy $2 "$INSTDIR\CDM_v2.12.00_WHQL_Certified.exe"
+       ExecWait $2
+SectionEnd
+
 Section "Documentation"
 
        SetOutPath $INSTDIR
index ebe1df9c18285f1a999f309844fc70fb6103b352..ecba2fbd7740e5b67f8935b4ec4b38d183c4ef64 100644 (file)
@@ -39,11 +39,14 @@ ARMM3DIRS=\
        telescience-v0.2 telescience-v0.2/flash-loader \
        teledongle-v3.0 teledongle-v3.0/flash-loader \
        teleballoon-v2.0 \
-       telebt-v3.0 telebt-v3.0/flash-loader
+       telebt-v3.0 telebt-v3.0/flash-loader \
+       telelcotwo-v0.1 telelcotwo-v0.1/flash-loader \
+       telefiretwo-v0.1 telefiretwo-v0.1/flash-loader \
 
 ARMM0DIRS=\
        easymini-v1.0 easymini-v1.0/flash-loader \
-       chaoskey-v0.1 chaoskey-v0.1/flash-loader
+       chaoskey-v0.1 chaoskey-v0.1/flash-loader \
+       chaoskey-v1.0 chaoskey-v1.0/flash-loader
 
 AVRDIRS=\
        telescience-v0.1 telescience-pwm micropeak nanopeak-v0.1 microkite
index ea340dfd56901194b9534a600fb146fbbdef1be4..1eb506cdcb1d02000e238609284e091dc4dc05c9 100644 (file)
@@ -146,4 +146,6 @@ ao_spi_init(void);
 #define ao_enable_output(port,bit,pin,v) cc1111_enable_output(port,token_evaluator(port,DIR), token_evaluator(port,SEL), pin, bit, v)
 #define ao_gpio_set(port, bit, pin, v) ((pin) = (v))
 #define ao_gpio_get(port, bit, pin) (pin)
-
+#define ao_gpio_get_bits(port) (port)
+#define ao_gpio_set_bits(port, bits) ((port) |= bits)
+#define ao_gpio_clr_bits(port, bits) ((port) &= ~bits)
index ac4a6788c221fcf8b6c0d65c30c97a43bceda7d1..853922804b839fa31b967b238057f8cc23c130bc 100644 (file)
@@ -13,6 +13,7 @@ INC = \
        ao_product.h \
        ao_task.h \
        ao_adc_fast.h \
+       ao_power.h \
        stm32f0.h
 
 #
@@ -33,9 +34,11 @@ ALTOS_SRC = \
        ao_usb_stm.c \
        ao_trng_send.c \
        ao_task.c \
+       ao_power.c \
+       ao_gpio.c \
        ao_product.c
 
-PRODUCT=ChaosKey-v0.1
+PRODUCT=ChaosKey-hw-0.3-sw-$(VERSION)
 PRODUCT_DEF=-DCHAOSKEY_V_0_1
 IDVENDOR=0x1d50
 IDPRODUCT=0x60c6
index 72963dbab9eb955832107d2ff296a94b0379744d..73f763071df5ae1c04059bf89372211159155401 100644 (file)
@@ -27,6 +27,9 @@
 
 #define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN)
 
+#define AO_POWER_MANAGEMENT    1
+#define AO_LED_POWER           AO_LED_RED
+
 #define HAS_BEEP       0
 
 /* 48MHz clock based on USB */
 #define AO_APB_PRESCALER       1
 #define AO_RCC_CFGR_PPRE_DIV   STM_RCC_CFGR_PPRE_DIV_1
 
-#define HAS_USB                        1
-#define AO_USB_DIRECTIO                1
-#define AO_PA11_PA12_RMP       0
-#define AO_USB_INTERFACE_CLASS 0xff
+#define HAS_USB                                1
+#define AO_USB_DIRECTIO                        1
+#define AO_PA11_PA12_RMP               0
+#define AO_USB_DEVICE_CLASS            0xff
+#define AO_USB_INTERFACE_CLASS_DATA    0xff
+#define AO_USB_HAS_OUT                 0
+#define AO_USB_HAS_IN                  1
+#define AO_USB_HAS_IN2                 1
+#define AO_USB_HAS_INT                 0
+#define USE_USB_STDIO                  0
+#define AO_USB_SELF_POWER              0
+#define AO_USB_DEVICE_ID_SERIAL                1
 
 #define IS_FLASH_LOADER        0
 
 
 #define AO_NUM_ADC             1
 
+/* TRNG enable */
+
+#define AO_TRNG_ENABLE_PORT    (&stm_gpioa)
+#define AO_TRNG_ENABLE_BIT     8
+
 /* CRC */
 #define AO_CRC_WIDTH   32
 #define AO_CRC_INIT    0xffffffff
 
 /* TRNG */
-#define AO_LED_TRNG_ACTIVE     AO_LED_GREEN
+#define AO_LED_TRNG_COOKED     AO_LED_GREEN
+#define AO_LED_TRNG_RAW                AO_LED_GREEN
+
+/* Mode pin */
+#define AO_RAW_PORT            (&stm_gpioa)
+#define AO_RAW_BIT             15
 
 #endif /* _AO_PINS_H_ */
diff --git a/src/chaoskey-v1.0/.gitignore b/src/chaoskey-v1.0/.gitignore
new file mode 100644 (file)
index 0000000..b0adba2
--- /dev/null
@@ -0,0 +1,2 @@
+ao_product.h
+chaoskey-*
diff --git a/src/chaoskey-v1.0/Makefile b/src/chaoskey-v1.0/Makefile
new file mode 100644 (file)
index 0000000..d9944a1
--- /dev/null
@@ -0,0 +1,73 @@
+#
+# AltOS build
+#
+#
+
+include ../stmf0/Makefile.defs
+
+INC = \
+       ao.h \
+       ao_arch.h \
+       ao_arch_funcs.h \
+       ao_pins.h \
+       ao_product.h \
+       ao_task.h \
+       ao_adc_fast.h \
+       ao_power.h \
+       stm32f0.h
+
+#
+# Common AltOS sources
+#
+ALTOS_SRC = \
+       ao_interrupt.c \
+       ao_timer.c \
+       ao_panic.c \
+       ao_mutex.c \
+       ao_dma_stm.c \
+       ao_adc_fast.c \
+       ao_crc_stm.c \
+       ao_stdio.c \
+       ao_led.c \
+       ao_romconfig.c \
+       ao_boot_chain.c \
+       ao_usb_stm.c \
+       ao_trng_send.c \
+       ao_task.c \
+       ao_power.c \
+       ao_gpio.c \
+       ao_product.c
+
+PRODUCT=ChaosKey-hw-1.0-sw-$(VERSION)
+PRODUCT_DEF=-DCHAOSKEY_V_1_0
+IDVENDOR=0x1d50
+IDPRODUCT=0x60c6
+
+CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -g -Os
+
+PROGNAME=chaoskey-v1.0
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_chaoskey.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 -V $(IDVENDOR) -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) -o $@
+
+$(OBJ): $(INC)
+
+distclean:     clean
+
+clean:
+       rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+       rm -f ao_product.h
+
+install:
+
+uninstall:
diff --git a/src/chaoskey-v1.0/ao_chaoskey.c b/src/chaoskey-v1.0/ao_chaoskey.c
new file mode 100644 (file)
index 0000000..f887e60
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * 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_adc_fast.h>
+#include <ao_crc.h>
+#include <ao_trng_send.h>
+
+void main(void)
+{
+       ao_led_init(LEDS_AVAILABLE);
+       ao_clock_init();
+       ao_task_init();
+       ao_timer_init();
+       ao_dma_init();
+       ao_adc_init();
+       ao_crc_init();
+
+       ao_usb_init();
+
+       ao_trng_send_init();
+
+       ao_start_scheduler();
+}
diff --git a/src/chaoskey-v1.0/ao_pins.h b/src/chaoskey-v1.0/ao_pins.h
new file mode 100644 (file)
index 0000000..89a2cb0
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright © 2015 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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 LED_PORT_ENABLE        STM_RCC_AHBENR_IOPBEN
+#define LED_PORT       (&stm_gpiob)
+#define LED_PIN_RED    4
+#define AO_LED_RED     (1 << LED_PIN_RED)
+
+#define LEDS_AVAILABLE (AO_LED_RED)
+
+#define AO_POWER_MANAGEMENT    1
+#define AO_LED_POWER           AO_LED_RED
+
+#define HAS_BEEP       0
+
+/* 48MHz clock based on USB */
+#define AO_HSI48       1
+
+/* HCLK = 48MHz */
+#define AO_AHB_PRESCALER       1
+#define AO_RCC_CFGR_HPRE_DIV   STM_RCC_CFGR_HPRE_DIV_1
+
+/* APB = 48MHz */
+#define AO_APB_PRESCALER       1
+#define AO_RCC_CFGR_PPRE_DIV   STM_RCC_CFGR_PPRE_DIV_1
+
+#define HAS_USB                                1
+#define AO_USB_DIRECTIO                        1
+#define AO_PA11_PA12_RMP               1
+#define AO_USB_DEVICE_CLASS            0xff
+#define AO_USB_INTERFACE_CLASS_DATA    0xff
+#define AO_USB_HAS_OUT                 0
+#define AO_USB_HAS_IN                  1
+#define AO_USB_HAS_IN2                 1
+#define AO_USB_HAS_INT                 0
+#define AO_USB_SELF_POWER              0
+#define AO_USB_DEVICE_ID_SERIAL                1
+#define AO_USB_START_DISABLED          1
+#define USE_USB_STDIO                  0
+
+#define IS_FLASH_LOADER        0
+
+/* ADC */
+
+#define AO_ADC_PIN0_PORT       (&stm_gpioa)
+#define AO_ADC_PIN0_PIN                0
+#define AO_ADC_PIN0_CH         0
+
+#define AO_ADC_RCC_AHBENR      ((1 << STM_RCC_AHBENR_IOPAEN))
+
+#define AO_NUM_ADC             1
+
+/* TRNG enable */
+
+#define AO_TRNG_ENABLE_PORT    (&stm_gpioa)
+#define AO_TRNG_ENABLE_BIT     1
+
+/* CRC */
+#define AO_CRC_WIDTH   32
+#define AO_CRC_INIT    0xffffffff
+
+/* Mode pin */
+#define AO_RAW_PORT            (&stm_gpioa)
+#define AO_RAW_BIT             15
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/chaoskey-v1.0/flash-loader/.gitignore b/src/chaoskey-v1.0/flash-loader/.gitignore
new file mode 100644 (file)
index 0000000..a60a494
--- /dev/null
@@ -0,0 +1,2 @@
+ao_product.h
+chaoskey*
diff --git a/src/chaoskey-v1.0/flash-loader/Makefile b/src/chaoskey-v1.0/flash-loader/Makefile
new file mode 100644 (file)
index 0000000..4f84014
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=chaoskey-v1.0
+include $(TOPDIR)/stmf0/Makefile-flash.defs
diff --git a/src/chaoskey-v1.0/flash-loader/ao_pins.h b/src/chaoskey-v1.0/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..570800c
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * 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_stm_pins.h>
+
+/* Pin 5 on debug connector */
+
+#define AO_BOOT_PIN                    1
+#define AO_BOOT_APPLICATION_GPIO       stm_gpioa
+#define AO_BOOT_APPLICATION_PIN                15
+#define AO_BOOT_APPLICATION_VALUE      1
+#define AO_BOOT_APPLICATION_MODE       AO_EXTI_MODE_PULL_UP
+
+/* USB */
+#define HAS_USB                        1
+#define AO_USB_DIRECTIO                0
+#define AO_PA11_PA12_RMP       1
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/detherm/.gitignore b/src/detherm/.gitignore
new file mode 100644 (file)
index 0000000..4f11d9a
--- /dev/null
@@ -0,0 +1,2 @@
+ao_product.h
+detherm-*
diff --git a/src/detherm/Makefile b/src/detherm/Makefile
new file mode 100644 (file)
index 0000000..6b0e0bf
--- /dev/null
@@ -0,0 +1,82 @@
+#
+# AltOS build
+#
+#
+
+include ../stmf0/Makefile.defs
+
+INC = \
+       ao.h \
+       ao_arch.h \
+       ao_arch_funcs.h \
+       ao_pins.h \
+       ao_product.h \
+       ao_task.h \
+       stm32f0.h
+
+#
+# Common AltOS sources
+#
+ALTOS_SRC = \
+       ao_interrupt.c \
+       ao_timer.c \
+       ao_panic.c \
+       ao_mutex.c \
+       ao_dma_stm.c \
+       ao_usb_stm.c \
+       ao_spi_stm.c \
+       ao_exti_stm.c \
+       ao_stdio.c \
+       ao_led.c \
+       ao_log.c \
+       ao_log_mini.c \
+       ao_sample.c \
+       ao_data.c \
+       ao_kalman.c \
+       ao_flight.c \
+       ao_report.c \
+       ao_storage.c \
+       ao_m25.c \
+       ao_romconfig.c \
+       ao_boot_chain.c \
+       ao_ms5607.c \
+       ao_convert_pa.c \
+       ao_pwm.c \
+       ao_servo.c \
+       ao_task.c \
+       ao_config.c \
+       ao_cmd.c \
+       ao_product.c
+
+PRODUCT=Detherm-v1.0
+PRODUCT_DEF=-DDETHERM_V_1_0
+IDPRODUCT=0x0013
+
+CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -g -Os
+
+PROGNAME=detherm-v1.0
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_detherm.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) -o $@
+
+$(OBJ): $(INC)
+
+distclean:     clean
+
+clean:
+       rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+       rm -f ao_product.h
+
+install:
+
+uninstall:
diff --git a/src/detherm/ao_detherm.c b/src/detherm/ao_detherm.c
new file mode 100644 (file)
index 0000000..fba9195
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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_exti.h>
+#include <ao_pwm.h>
+#include <ao_servo.h>
+
+void main(void)
+{
+       ao_led_init(LEDS_AVAILABLE);
+
+       ao_led_on(AO_LED_RED);
+
+       ao_clock_init();
+       ao_task_init();
+       ao_timer_init();
+       ao_exti_init();
+
+       ao_dma_init();
+       ao_spi_init();
+       ao_usb_init();
+
+       ao_storage_init();
+       ao_ms5607_init();
+//     ao_flight_init();
+       ao_pwm_init();
+       ao_servo_init();
+       ao_log_init();
+       ao_report_init();
+       ao_config_init();
+
+       ao_cmd_init();
+
+       ao_start_scheduler();
+}
diff --git a/src/detherm/ao_pins.h b/src/detherm/ao_pins.h
new file mode 100644 (file)
index 0000000..1c577b6
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright © 2015 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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 LED_PORT_ENABLE        STM_RCC_AHBENR_IOPAEN
+#define LED_PORT       (&stm_gpioa)
+#define LED_PIN_RED    3
+#define AO_LED_RED     (1 << LED_PIN_RED)
+
+#define LEDS_AVAILABLE (AO_LED_RED)
+
+#define HAS_BEEP       0
+
+/* 48MHz clock based on USB */
+//#define AO_HSI48     1
+#define AO_HSE                 16000000
+#define AO_RCC_CFGR_PLLMUL     STM_RCC_CFGR_PLLMUL_3
+#define AO_PLLMUL              3
+#define AO_PLLDIV              1
+
+/* HCLK = 48MHz */
+#define AO_AHB_PRESCALER       1
+#define AO_RCC_CFGR_HPRE_DIV   STM_RCC_CFGR_HPRE_DIV_1
+
+/* APB = 48MHz */
+#define AO_APB_PRESCALER       1
+#define AO_RCC_CFGR_PPRE_DIV   STM_RCC_CFGR_PPRE_DIV_1
+
+#define HAS_USB                                1
+#define AO_USB_DIRECTIO                        0
+#define AO_PA11_PA12_RMP               1
+
+#define IS_FLASH_LOADER        0
+
+#define AO_DATA_RING   16
+
+#define HAS_ADC                0
+#define HAS_ACCEL      0
+#define HAS_GPS                0
+#define HAS_RADIO      0
+#define HAS_FLIGHT     1
+#define HAS_EEPROM     1
+#define HAS_LOG                1
+
+#define AO_LOG_FORMAT          AO_LOG_FORMAT_DETHERM
+
+#define USE_INTERNAL_FLASH     0
+
+/* SPI */
+#define HAS_SPI_1              1
+#define HAS_SPI_2              0
+#define SPI_1_PA5_PA6_PA7      1
+#define SPI_1_PB3_PB4_PB5      1
+#define SPI_1_OSPEEDR          STM_OSPEEDR_HIGH
+
+/* MS5607 */
+#define HAS_MS5607             1
+
+#define AO_MS5607_CS_PORT      (&stm_gpioa)
+#define AO_MS5607_CS_PIN       0
+#define AO_MS5607_SPI_INDEX    AO_SPI_1_PB3_PB4_PB5
+#define AO_MS5607_MISO_PORT    (&stm_gpiob)
+#define AO_MS5607_MISO_PIN     4
+#define AO_MS5607_PRIVATE_PINS 1
+#define AO_MS5607_SPI_SPEED    AO_SPI_SPEED_6MHz
+
+/* Flash */
+
+#define M25_MAX_CHIPS          1
+#define AO_M25_SPI_CS_PORT     (&stm_gpioa)
+#define AO_M25_SPI_CS_MASK     (1 << 4)
+#define AO_M25_SPI_BUS         AO_SPI_1_PA5_PA6_PA7
+
+/* PWM */
+
+#define NUM_PWM                        1
+#define AO_PWM_TIMER           (&stm_tim3)
+#define AO_PWM_0_GPIO          (&stm_gpiob)
+#define AO_PWM_0_PIN           1
+#define AO_PWM_0_CH            4
+#define PWM_MAX                        20000
+#define AO_PWM_TIMER_ENABLE    STM_RCC_APB1ENR_TIM3EN
+#define AO_PWM_TIMER_SCALE     32
+
+/* Servo */
+
+#define AO_SERVO_DIR_PORT      (&stm_gpiob)
+#define AO_SERVO_DIR_BIT       0
+#define AO_SERVO_SPEED_PWM     0
+
+/* limit 2 */
+#define AO_SERVO_LIMIT_FORE_PORT       (&stm_gpiob)
+#define AO_SERVO_LIMIT_FORE_BIT                6
+
+/* limit 1 */
+#define AO_SERVO_LIMIT_BACK_PORT       (&stm_gpiob)
+#define AO_SERVO_LIMIT_BACK_BIT                7
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/detherm/flash-loader/.gitignore b/src/detherm/flash-loader/.gitignore
new file mode 100644 (file)
index 0000000..d0d4657
--- /dev/null
@@ -0,0 +1,2 @@
+ao_product.h
+detherm*
diff --git a/src/detherm/flash-loader/Makefile b/src/detherm/flash-loader/Makefile
new file mode 100644 (file)
index 0000000..5210aa0
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=detherm-v1.0
+include $(TOPDIR)/stmf0/Makefile-flash.defs
diff --git a/src/detherm/flash-loader/ao_pins.h b/src/detherm/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..570800c
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * 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_stm_pins.h>
+
+/* Pin 5 on debug connector */
+
+#define AO_BOOT_PIN                    1
+#define AO_BOOT_APPLICATION_GPIO       stm_gpioa
+#define AO_BOOT_APPLICATION_PIN                15
+#define AO_BOOT_APPLICATION_VALUE      1
+#define AO_BOOT_APPLICATION_MODE       AO_EXTI_MODE_PULL_UP
+
+/* USB */
+#define HAS_USB                        1
+#define AO_USB_DIRECTIO                0
+#define AO_PA11_PA12_RMP       1
+
+#endif /* _AO_PINS_H_ */
index cdf073524e1e8f4ffb5f232f255c5ef854de28fe..8e7dead71df6d075014a233c0d43c77f973a59a9 100644 (file)
@@ -18,7 +18,6 @@
 #include <ao.h>
 #include <ao_button.h>
 #include <ao_exti.h>
-#include <ao_debounce.h>
 #if AO_EVENT
 #include <ao_event.h>
 #define ao_button_queue(b,v)   ao_event_put_isr(AO_EVENT_BUTTON, b, v)
 #define ao_button_queue(b,v)
 #endif
 
-#define AO_BUTTON_DEBOUNCE_HOLD        10
+#define AO_BUTTON_DEBOUNCE_INTERVAL    AO_MS_TO_TICKS(50)
 
-static struct ao_debounce      ao_button_debounce[AO_BUTTON_COUNT];
+struct ao_button_state {
+       AO_TICK_TYPE    time;
+       uint8_t         value;
+};
+
+static struct ao_button_state  ao_button_state[AO_BUTTON_COUNT];
 
 #define port(q)        AO_BUTTON_ ## q ## _PORT
 #define bit(q) AO_BUTTON_ ## q
@@ -38,10 +42,8 @@ static struct ao_debounce    ao_button_debounce[AO_BUTTON_COUNT];
 #define ao_button_value(b)     !ao_gpio_get(port(b), bit(b), pin(b))
 
 static uint8_t
-_ao_button_get(struct ao_debounce *debounce)
+_ao_button_get(uint8_t b)
 {
-       uint8_t b = debounce - ao_button_debounce;
-
        switch (b) {
 #if AO_BUTTON_COUNT > 0
        case 0: return ao_button_value(0);
@@ -63,22 +65,31 @@ _ao_button_get(struct ao_debounce *debounce)
 }
 
 static void
-_ao_button_set(struct ao_debounce *debounce, uint8_t value)
+_ao_button_check(uint8_t b)
 {
-       uint8_t b = debounce - ao_button_debounce;
-
-       ao_button_queue(b, value);
-}
+       uint8_t value = _ao_button_get(b);
 
+       if (value != ao_button_state[b].value) {
+               AO_TICK_TYPE    now = ao_time();
 
-#define ao_button_update(b)    ao_button_do(b, ao_gpio_get(port(b), bit(b), pin(b)))
+               if ((now - ao_button_state[b].time) >= AO_BUTTON_DEBOUNCE_INTERVAL) {
+                       ao_button_state[b].value = value;
+                       ao_button_queue(b, value);
+               }
+               ao_button_state[b].time = now;
+       }
+}
 
 static void
-ao_button_debounce_init(struct ao_debounce *debounce) {
-       ao_debounce_config(debounce,
-                          _ao_button_get,
-                          _ao_button_set,
-                          AO_BUTTON_DEBOUNCE_HOLD);
+_ao_button_init(uint8_t b)
+{
+       uint8_t m = ao_arch_irqsave();
+       uint8_t value = _ao_button_get(b);
+       ao_button_state[b].value = value;
+       ao_button_state[b].time = ao_time();
+       ao_button_queue(b, value);
+       ao_arch_irqrestore(m);
+
 }
 
 static void
@@ -87,17 +98,17 @@ ao_button_isr(void)
        uint8_t b;
 
        for (b = 0; b < AO_BUTTON_COUNT; b++)
-               _ao_debounce_start(&ao_button_debounce[b]);
+               _ao_button_check(b);
 }
 
 #define init(b) do {                                                   \
-               ao_button_debounce_init(&ao_button_debounce[b]);        \
                ao_enable_port(port(b));                                \
                                                                        \
                ao_exti_setup(port(b), bit(b),                          \
                              AO_BUTTON_MODE|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, \
-                             ao_button_isr);                   \
+                             ao_button_isr);                           \
                ao_exti_enable(port(b), bit(b));                        \
+               _ao_button_init(b);                                     \
        } while (0)
 
 void
@@ -118,5 +129,4 @@ ao_button_init(void)
 #if AO_BUTTON_COUNT > 4
        init(4);
 #endif
-       ao_debounce_init();
 }
index 6547be3963d910055a8628aeb11b52b029cbc376..6bccb18863f9439ac0f4ed46f76dc7bd90adabcd 100644 (file)
@@ -20,6 +20,9 @@
 #include <ao_exti.h>
 #include <ao_fec.h>
 #include <ao_packet.h>
+#if HAS_PAD
+#include <ao_pad.h>
+#endif
 
 static uint8_t ao_radio_mutex;
 
@@ -812,6 +815,9 @@ ao_radio_test_cmd(void)
 #endif
 #if PACKET_HAS_SLAVE
                ao_packet_slave_stop();
+#endif
+#if HAS_PAD
+               ao_pad_disable();
 #endif
                ao_radio_get(0xff);
                ao_radio_set_mode(AO_RADIO_MODE_TEST);
@@ -837,6 +843,9 @@ ao_radio_test_cmd(void)
                radio_on = 0;
 #if HAS_MONITOR
                ao_monitor_enable();
+#endif
+#if HAS_PAD
+               ao_pad_enable();
 #endif
        }
 }
index 5c0d286310f2460f1638227f8ddb8bd87303d083..8f88d77866c391cc91645de7633ab28fe1390779 100644 (file)
@@ -41,6 +41,22 @@ ao_event_get(struct ao_event *ev)
                );
 }
 
+uint8_t
+ao_event_get_for(struct ao_event *ev, uint16_t timeout)
+{
+       uint8_t empty = 1;
+       ao_arch_critical(
+               while ((empty = ao_event_queue_empty()))
+                       if (ao_sleep_for(&ao_event_queue, timeout))
+                               break;
+               if (!empty) {
+                       *ev = ao_event_queue[ao_event_queue_remove];
+                       ao_event_queue_remove = ao_event_queue_next(ao_event_queue_remove);
+               }
+               );
+       return empty;
+}
+
 /* called with interrupts disabled */
 void
 ao_event_put_isr(uint8_t type, uint8_t unit, int32_t value)
index 584a845a3e14d8103ab67720d5fc754865ace603..ea89da23c07cef3598c4159c5792fae4d376cbda 100644 (file)
@@ -32,6 +32,9 @@ struct ao_event {
 void
 ao_event_get(struct ao_event *ev);
 
+uint8_t
+ao_event_get_for(struct ao_event *ev, uint16_t timeout);
+
 void
 ao_event_put_isr(uint8_t type, uint8_t unit, int32_t value);
 
diff --git a/src/drivers/ao_lco_two.c b/src/drivers/ao_lco_two.c
new file mode 100644 (file)
index 0000000..f53fef7
--- /dev/null
@@ -0,0 +1,314 @@
+/*
+ * 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.
+ */
+
+#include <ao.h>
+#include <ao_lco.h>
+#include <ao_event.h>
+#include <ao_lco_func.h>
+#include <ao_radio_cmac.h>
+
+#define DEBUG  1
+
+#if DEBUG
+static uint8_t ao_lco_debug;
+#define DEBUG_EVENT    1
+#define DEBUG_STATUS   2
+#define PRINTD(l, ...) do { if (!(ao_lco_debug & l)) break; printf ("\r%5u %s: ", ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } while(0)
+#else
+#define PRINTD(l,...)
+#endif
+
+#define AO_LCO_VALID_LAST      1
+#define AO_LCO_VALID_EVER      2
+
+static uint8_t ao_lco_suspended;
+static uint8_t ao_lco_selected;
+static uint8_t ao_lco_valid;
+static uint8_t ao_lco_channels;
+static uint16_t        ao_lco_tick_offset;
+
+/* UI values */
+static uint8_t ao_lco_armed;
+static uint8_t ao_lco_firing;
+
+#define ao_lco_box     (ao_config.pad_box)
+
+static struct ao_pad_query     ao_pad_query;
+
+#define MASK_SIZE(n)   (((n) + 7) >> 3)
+#define MASK_ID(n)     ((n) >> 3)
+#define MASK_SHIFT(n)  ((n) & 7)
+
+static void
+ao_lco_set_armed(int pad, int armed)
+{
+       uint8_t bit = (1 << pad);
+
+       if (armed) {
+               ao_lco_selected |= bit;
+               ao_lco_armed |= bit;
+       } else {
+               ao_lco_selected &= ~bit;
+               ao_lco_armed &= ~bit;
+       }
+       PRINTD(DEBUG_EVENT, "pad %d bit 0x%x armed %d ao_lco_selected 0x%x ao_lco_armed 0x%x\n",
+              pad, bit, armed, ao_lco_selected, ao_lco_armed);
+       ao_wakeup(&ao_lco_armed);
+}
+
+static void
+ao_lco_suspend(void)
+{
+       if (!ao_lco_suspended) {
+               PRINTD(DEBUG_EVENT, "suspend\n");
+               ao_lco_suspended = 1;
+               ao_lco_selected = 0;
+               ao_lco_armed = 0;
+               ao_wakeup(&ao_pad_query);
+       }
+}
+
+static void
+ao_lco_wakeup(void)
+{
+       if (ao_lco_suspended) {
+               ao_lco_suspended = 0;
+               ao_wakeup(&ao_lco_suspended);
+       }
+}
+
+static void
+ao_lco_input(void)
+{
+       static struct ao_event  event;
+       uint8_t timeout;
+
+       ao_config_get();
+       for (;;) {
+               if (ao_config.pad_idle && !ao_lco_suspended) {
+                       timeout = ao_event_get_for(&event, AO_SEC_TO_TICKS(ao_config.pad_idle));
+                       if (timeout) {
+                               ao_lco_suspend();
+                               continue;
+                       }
+               } else {
+                       ao_event_get(&event);
+               }
+               ao_lco_wakeup();
+               PRINTD(DEBUG_EVENT, "event type %d unit %d value %d\n",
+                      event.type, event.unit, event.value);
+               switch (event.type) {
+               case AO_EVENT_BUTTON:
+                       switch (event.unit) {
+                       case AO_BUTTON_ARM_0:
+                               ao_lco_set_armed(0, event.value);
+                               break;
+#if AO_BUTTON_ARM_NUM > 1
+                       case AO_BUTTON_ARM_1:
+                               ao_lco_set_armed(1, event.value);
+                               break;
+#endif
+                       case AO_BUTTON_FIRE:
+                               if (ao_lco_armed) {
+                                       ao_lco_firing = event.value;
+                                       PRINTD(DEBUG_EVENT, "Firing %d\n", ao_lco_firing);
+                                       ao_wakeup(&ao_lco_armed);
+                               }
+                               break;
+                       }
+                       break;
+               }
+       }
+}
+
+static AO_LED_TYPE     continuity_led[AO_LED_CONTINUITY_NUM] = {
+#ifdef AO_LED_CONTINUITY_0
+       AO_LED_CONTINUITY_0,
+#endif
+#ifdef AO_LED_CONTINUITY_1
+       AO_LED_CONTINUITY_1,
+#endif
+#ifdef AO_LED_CONTINUITY_2
+       AO_LED_CONTINUITY_2,
+#endif
+#ifdef AO_LED_CONTINUITY_3
+       AO_LED_CONTINUITY_3,
+#endif
+#ifdef AO_LED_CONTINUITY_4
+       AO_LED_CONTINUITY_4,
+#endif
+#ifdef AO_LED_CONTINUITY_5
+       AO_LED_CONTINUITY_5,
+#endif
+#ifdef AO_LED_CONTINUITY_6
+       AO_LED_CONTINUITY_6,
+#endif
+#ifdef AO_LED_CONTINUITY_7
+       AO_LED_CONTINUITY_7,
+#endif
+};
+
+static uint8_t
+ao_lco_get_channels(void)
+{
+       int8_t                  r;
+
+       r = ao_lco_query(ao_lco_box, &ao_pad_query, &ao_lco_tick_offset);
+       if (r == AO_RADIO_CMAC_OK) {
+               ao_lco_channels = ao_pad_query.channels;
+               ao_lco_valid = AO_LCO_VALID_LAST | AO_LCO_VALID_EVER;
+       } else
+               ao_lco_valid &= ~AO_LCO_VALID_LAST;
+       PRINTD(DEBUG_STATUS, "ao_lco_get_channels() rssi %d valid %d ret %d offset %d\n", ao_radio_cmac_rssi, ao_lco_valid, r, ao_lco_tick_offset);
+       ao_wakeup(&ao_pad_query);
+       return ao_lco_valid;
+}
+
+static void
+ao_lco_igniter_status(void)
+{
+       uint8_t         c;
+       uint8_t         t = 0;
+
+       for (;;) {
+               ao_sleep(&ao_pad_query);
+               while (ao_lco_suspended) {
+                       ao_led_off(AO_LED_GREEN|AO_LED_AMBER|AO_LED_RED|AO_LED_REMOTE_ARM);
+                       for (c = 0; c < AO_LED_CONTINUITY_NUM; c++)
+                               ao_led_off(continuity_led[c]);
+                       ao_sleep(&ao_lco_suspended);
+               }
+               PRINTD(DEBUG_STATUS, "RSSI %d VALID %d\n", ao_radio_cmac_rssi, ao_lco_valid);
+               if (!(ao_lco_valid & AO_LCO_VALID_LAST)) {
+                       ao_led_on(AO_LED_RED);
+                       ao_led_off(AO_LED_GREEN|AO_LED_AMBER);
+                       continue;
+               }
+               if (ao_radio_cmac_rssi < -90) {
+                       ao_led_on(AO_LED_AMBER);
+                       ao_led_off(AO_LED_RED|AO_LED_GREEN);
+               } else {
+                       ao_led_on(AO_LED_GREEN);
+                       ao_led_off(AO_LED_RED|AO_LED_AMBER);
+               }
+               if (ao_pad_query.arm_status)
+                       ao_led_on(AO_LED_REMOTE_ARM);
+               else
+                       ao_led_off(AO_LED_REMOTE_ARM);
+
+               for (c = 0; c < AO_LED_CONTINUITY_NUM; c++) {
+                       uint8_t status;
+
+                       if (ao_pad_query.channels & (1 << c))
+                               status = ao_pad_query.igniter_status[c];
+                       else
+                               status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN;
+                       PRINTD(DEBUG_STATUS, "\tchannel %d status %d\n", c, status);
+                       if (status == AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN)
+                               ao_led_on(continuity_led[c]);
+                       else
+                               ao_led_off(continuity_led[c]);
+               }
+               t = 1-t;
+       }
+}
+
+static void
+ao_lco_arm_warn(void)
+{
+       int     i;
+       for (;;) {
+               while (ao_lco_suspended)
+                       ao_sleep(&ao_lco_suspended);
+               while (!ao_lco_armed)
+                       ao_sleep(&ao_lco_armed);
+               for (i = 0; i < ao_lco_armed; i++) {
+                       ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(100));
+                       ao_delay(AO_MS_TO_TICKS(100));
+               }
+               ao_delay(AO_MS_TO_TICKS(300));
+       }
+}
+
+static struct ao_task ao_lco_input_task;
+static struct ao_task ao_lco_monitor_task;
+static struct ao_task ao_lco_arm_warn_task;
+static struct ao_task ao_lco_igniter_status_task;
+
+static void
+ao_lco_monitor(void)
+{
+       uint16_t                delay;
+
+       ao_add_task(&ao_lco_input_task, ao_lco_input, "lco input");
+       ao_add_task(&ao_lco_arm_warn_task, ao_lco_arm_warn, "lco arm warn");
+       ao_add_task(&ao_lco_igniter_status_task, ao_lco_igniter_status, "lco igniter status");
+       ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200));
+       for (;;) {
+               while (ao_lco_suspended)
+                       ao_sleep(&ao_lco_suspended);
+
+               PRINTD(DEBUG_STATUS, "monitor armed %d firing %d\n",
+                      ao_lco_armed, ao_lco_firing);
+
+               if (ao_lco_armed && ao_lco_firing) {
+                       ao_lco_ignite();
+               } else {
+                       ao_lco_get_channels();
+                       if (ao_lco_armed) {
+                               if (ao_lco_selected) {
+                                       PRINTD(DEBUG_STATUS, "Arming pads %x\n",
+                                              ao_lco_selected);
+                                       if (ao_lco_valid & AO_LCO_VALID_EVER) {
+                                               ao_lco_arm(ao_lco_box, ao_lco_selected, ao_lco_tick_offset);
+                                               ao_delay(AO_MS_TO_TICKS(10));
+                                       }
+                               }
+                       }
+               }
+               if (ao_lco_armed && ao_lco_firing)
+                       delay = AO_MS_TO_TICKS(100);
+               else {
+                       delay = AO_SEC_TO_TICKS(1);
+               }
+               ao_sleep_for(&ao_lco_armed, delay);
+       }
+}
+
+#if DEBUG
+void
+ao_lco_set_debug(void)
+{
+       ao_cmd_decimal();
+       if (ao_cmd_status == ao_cmd_success)
+               ao_lco_debug = ao_cmd_lex_i;
+}
+
+__code struct ao_cmds ao_lco_cmds[] = {
+       { ao_lco_set_debug,     "D <0 off, 1 on>\0Debug" },
+       { 0, NULL }
+};
+#endif
+
+void
+ao_lco_init(void)
+{
+       ao_add_task(&ao_lco_monitor_task, ao_lco_monitor, "lco monitor");
+#if DEBUG
+       ao_cmd_register(&ao_lco_cmds[0]);
+#endif
+}
index 6098699edf4b1735a8a0ede41fd163722ba809aa..ef31882ef4ff818628f27e66c458922fdf536140 100644 (file)
 __xdata struct ao_ms5607_prom  ao_ms5607_prom;
 static __xdata uint8_t         ms5607_configured;
 
+#ifndef AO_MS5607_SPI_SPEED
+#define AO_MS5607_SPI_SPEED    AO_SPI_SPEED_FAST
+#endif
+
 static void
 ao_ms5607_start(void) {
-       ao_spi_get_bit(AO_MS5607_CS_PORT, AO_MS5607_CS_PIN, AO_MS5607_CS, AO_MS5607_SPI_INDEX, AO_SPI_SPEED_FAST);
+       ao_spi_get_bit(AO_MS5607_CS_PORT, AO_MS5607_CS_PIN, AO_MS5607_CS, AO_MS5607_SPI_INDEX, AO_MS5607_SPI_SPEED);
 }
 
 static void
index 5e440db04776442dc0c516bdcdadb69f4ed8ce12..2beda4cbad865f066b047be61f912a4c3c19bd97 100644 (file)
@@ -117,6 +117,7 @@ ao_packet_forward(void) __reentrant
 {
        char c;
        ao_packet_enable = 1;
+       ao_packet_tx_used = 0;
        ao_cmd_white();
 
        flush();
index 419ea8d34c58e4b5a5281e80f1aff0b4e883eeff..99a90e7739970d3954f460c28e7d3c2924801c79 100644 (file)
@@ -50,7 +50,11 @@ ao_siren(uint8_t v)
 #ifdef AO_SIREN
        ao_gpio_set(AO_SIREN_PORT, AO_SIREN_PIN, AO_SIREN, v);
 #else
+#if HAS_BEEP
        ao_beep(v ? AO_BEEP_MID : 0);
+#else
+       (void) v;
+#endif
 #endif
 }
 
@@ -59,13 +63,15 @@ ao_strobe(uint8_t v)
 {
 #ifdef AO_STROBE
        ao_gpio_set(AO_STROBE_PORT, AO_STROBE_PIN, AO_STROBE, v);
+#else
+       (void) v;
 #endif
 }
 
 static void
 ao_pad_run(void)
 {
-       uint8_t pins;
+       AO_PORT_TYPE    pins;
 
        for (;;) {
                while (!ao_pad_ignite)
@@ -90,18 +96,28 @@ ao_pad_run(void)
                if (ao_pad_ignite & (1 << 3))
                        pins |= (1 << AO_PAD_PIN_3);
 #endif
-               AO_PAD_PORT = (AO_PAD_PORT & (~AO_PAD_ALL_PINS)) | pins;
+               PRINTD("ignite pins 0x%x\n", pins);
+               ao_gpio_set_bits(AO_PAD_PORT, pins);
                while (ao_pad_ignite) {
                        ao_pad_ignite = 0;
 
                        ao_delay(AO_PAD_FIRE_TIME);
                }
-               AO_PAD_PORT &= ~(AO_PAD_ALL_PINS);
+               ao_gpio_clr_bits(AO_PAD_PORT, pins);
+               PRINTD("turn off pins 0x%x\n", pins);
        }
 }
 
 #define AO_PAD_ARM_SIREN_INTERVAL      200
 
+#ifndef AO_PYRO_R_PYRO_SENSE
+#define AO_PYRO_R_PYRO_SENSE   100
+#define AO_PYRO_R_SENSE_GND    27
+#define AO_FIRE_R_POWER_FET    100
+#define AO_FIRE_R_FET_SENSE    100
+#define AO_FIRE_R_SENSE_GND    27
+#endif
+
 static void
 ao_pad_monitor(void)
 {
@@ -109,7 +125,7 @@ ao_pad_monitor(void)
        uint8_t                 sample;
        __pdata uint8_t         prev = 0, cur = 0;
        __pdata uint8_t         beeping = 0;
-       __xdata struct ao_data  *packet;
+       __xdata volatile struct ao_data *packet;
        __pdata uint16_t        arm_beep_time = 0;
 
        sample = ao_data_head;
@@ -120,12 +136,18 @@ ao_pad_monitor(void)
                                ao_sleep((void *) DATA_TO_XDATA(&ao_data_head));
                        );
 
+
                packet = &ao_data_ring[sample];
                sample = ao_data_ring_next(sample);
 
                pyro = packet->adc.pyro;
 
-#define VOLTS_TO_PYRO(x) ((int16_t) ((x) * 27.0 / 127.0 / 3.3 * 32767.0))
+#define VOLTS_TO_PYRO(x) ((int16_t) ((x) * ((1.0 * AO_PYRO_R_SENSE_GND) / \
+                                           (1.0 * (AO_PYRO_R_SENSE_GND + AO_PYRO_R_PYRO_SENSE)) / 3.3 * AO_ADC_MAX)))
+
+
+#define VOLTS_TO_FIRE(x) ((int16_t) ((x) * ((1.0 * AO_FIRE_R_SENSE_GND) / \
+                                           (1.0 * (AO_FIRE_R_SENSE_GND + AO_FIRE_R_FET_SENSE)) / 3.3 * AO_ADC_MAX)))
 
                /* convert ADC value to voltage in tenths, then add .2 for the diode drop */
                query.battery = (packet->adc.batt + 96) / 192 + 2;
@@ -133,14 +155,16 @@ ao_pad_monitor(void)
                if (pyro > VOLTS_TO_PYRO(10)) {
                        query.arm_status = AO_PAD_ARM_STATUS_ARMED;
                        cur |= AO_LED_ARMED;
-               } else if (pyro < VOLTS_TO_PYRO(5)) {
-                       query.arm_status = AO_PAD_ARM_STATUS_DISARMED;
-                       arm_beep_time = 0;
-               } else {
+#if AO_FIRE_R_POWER_FET
+               } else if (pyro > VOLTS_TO_PYRO(5)) {
                        if ((ao_time() % 100) < 50)
                                cur |= AO_LED_ARMED;
                        query.arm_status = AO_PAD_ARM_STATUS_UNKNOWN;
                        arm_beep_time = 0;
+#endif
+               } else {
+                       query.arm_status = AO_PAD_ARM_STATUS_DISARMED;
+                       arm_beep_time = 0;
                }
                if ((ao_time() - ao_pad_packet_time) > AO_SEC_TO_TICKS(2))
                        cur |= AO_LED_RED;
@@ -165,22 +189,39 @@ ao_pad_monitor(void)
                         *      27k            /
                         *              gnd ---
                         *
+                        *              v_pyro \
+                        *      200k            igniter
+                        *              output /
+                        *      200k           \
+                        *              sense   relay
+                        *      22k            /
+                        *              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
                         *      If igniter is present, then sense will be v_pyro * 27k/127k ~= v_pyro / 20 = pyro
                         */
 
+#if AO_FIRE_R_POWER_FET
                        if (sense <= pyro / 8) {
                                status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED;
                                if ((ao_time() % 100) < 50)
                                        cur |= AO_LED_CONTINUITY(c);
-                       }
-                       else if (pyro / 8 * 3 <= sense && sense <= pyro / 8 * 5)
+                       } else
+                       if (pyro / 8 * 3 <= sense && sense <= pyro / 8 * 5)
                                status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN;
                        else if (pyro / 8 * 7 <= sense) {
                                status = AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN;
                                cur |= AO_LED_CONTINUITY(c);
                        }
+#else
+                       if (sense >= pyro / 8 * 5) {
+                               status = AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN;
+                               cur |= AO_LED_CONTINUITY(c);
+                       } else {
+                               status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN;
+                       }
+#endif
                        query.igniter_status[c] = status;
                }
                if (cur != prev) {
@@ -240,8 +281,14 @@ ao_pad_read_box(void)
        l = byte & 0xf;
        return h * 10 + l;
 }
-#else
-#define ao_pad_read_box()      0
+#endif
+
+#if HAS_FIXED_PAD_BOX
+#define ao_pad_read_box()      ao_config.pad_box
+#endif
+
+#ifdef PAD_BOX
+#define ao_pad_read_box()      PAD_BOX
 #endif
 
 static void
diff --git a/src/drivers/ao_servo.c b/src/drivers/ao_servo.c
new file mode 100644 (file)
index 0000000..b48a411
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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_servo.h"
+#include "ao_pwm.h"
+#include "ao_exti.h"
+
+static uint8_t limit_wakeup;
+
+static void
+ao_limit_isr(void)
+{
+       ao_wakeup(&limit_wakeup);
+}
+
+static void
+ao_limit_enable(uint8_t dir)
+{
+       if (dir == AO_SERVO_FORE)
+               ao_exti_enable(AO_SERVO_LIMIT_FORE_PORT, AO_SERVO_LIMIT_FORE_BIT);
+       else
+               ao_exti_enable(AO_SERVO_LIMIT_BACK_PORT, AO_SERVO_LIMIT_BACK_BIT);
+}
+
+static void
+ao_limit_disable(uint8_t dir)
+{
+       if (dir == AO_SERVO_FORE)
+               ao_exti_disable(AO_SERVO_LIMIT_FORE_PORT, AO_SERVO_LIMIT_FORE_BIT);
+       else
+               ao_exti_disable(AO_SERVO_LIMIT_BACK_PORT, AO_SERVO_LIMIT_BACK_BIT);
+}
+
+static uint8_t
+ao_limit_get(uint8_t dir)
+{
+       if (dir == AO_SERVO_FORE)
+               return !ao_gpio_get(AO_SERVO_LIMIT_FORE_PORT, AO_SERVO_LIMIT_FORE_BIT, PIN);
+       else
+               return !ao_gpio_get(AO_SERVO_LIMIT_BACK_PORT, AO_SERVO_LIMIT_BACK_BIT, PIN);
+}
+
+void
+ao_servo_run(uint16_t speed, uint8_t dir, uint16_t timeout)
+{
+       printf ("speed %d dir %d\n", speed, dir);
+
+       /* Turn on the motor */
+       ao_gpio_set(AO_SERVO_DIR_PORT, AO_SERVO_DIR_BIT, AO_SERVO_DIR_PIN, dir);
+       ao_pwm_set(AO_SERVO_SPEED_PWM, speed);
+
+       /* Wait until the limit sensor is triggered */
+       ao_arch_block_interrupts();
+       ao_limit_enable(dir);
+       while (!ao_limit_get(dir))
+               if (ao_sleep_for(&limit_wakeup, timeout))
+                       break;
+       ao_limit_disable(dir);
+       ao_arch_release_interrupts();
+
+       /* Turn off the motor */
+       ao_pwm_set(AO_SERVO_SPEED_PWM, 0);
+}
+
+#define init_limit(p,b) do {                                           \
+               ao_enable_port(p);                                      \
+               ao_exti_setup(p, b,                                     \
+                             AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED, \
+                             ao_limit_isr);                            \
+       } while (0)
+
+
+static void
+ao_servo_cmd(void)
+{
+       uint8_t dir;
+       uint16_t speed;
+
+       ao_cmd_decimal();
+       dir = ao_cmd_lex_u32;
+       ao_cmd_decimal();
+       speed = ao_cmd_lex_u32;
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+
+       printf("Run servo %d\n", dir);
+       ao_servo_run(speed, dir, AO_MS_TO_TICKS(200));
+}
+
+static const struct ao_cmds ao_servo_cmds[] = {
+       { ao_servo_cmd, "S <dir> <speed>\0Run servo in indicated direction" },
+       { 0, NULL },
+};
+
+
+void
+ao_servo_init(void)
+{
+       init_limit(AO_SERVO_LIMIT_FORE_PORT, AO_SERVO_LIMIT_FORE_BIT);
+       init_limit(AO_SERVO_LIMIT_BACK_PORT, AO_SERVO_LIMIT_BACK_BIT);
+       ao_enable_output(AO_SERVO_DIR_PORT, AO_SERVO_DIR_BIT, AO_SERVO_DIR_PIN, 0);
+       ao_cmd_register(&ao_servo_cmds[0]);
+}
diff --git a/src/drivers/ao_servo.h b/src/drivers/ao_servo.h
new file mode 100644 (file)
index 0000000..e1df347
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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_SERVO_H_
+#define _AO_SERVO_H_
+
+void
+ao_servo_run(uint16_t speed, uint8_t dir, uint16_t timeout);
+
+void
+ao_servo_init(void);
+
+#define AO_SERVO_FORE  0
+#define AO_SERVO_BACK  1
+
+/* To configure the servo:
+ *
+ *     #define AO_SERVO_PWM                    <pwm index>
+ *     #define AO_SERVO_DIR_PORT               <gpio>
+ *     #define AO_SERVO_DIR_PIN                <pin>
+ *     #define AO_SERVO_LIMIT_FORE_PORT        <gpio>
+ *     #define AO_SERVO_LIMIT_FORE_PIN         <pin>
+ *     #define AO_SERVO_LIMIT_BACK_PORT        <gpio>
+ *     #define AO_SERVO_LIMIT_BACK_PIN         <pin>
+ */
+
+#endif /* _AO_SERVO_H_ */
index bac6035cd8dbde1b09fdb929debc5fc4b67a8c80..171a345fbe2db047feebaab19c25a55ba03410e9 100644 (file)
 #include <ao_adc_fast.h>
 #include <ao_crc.h>
 #include <ao_trng_send.h>
+#include <ao_exti.h>
+#include <ao_power.h>
+
+static struct ao_task  ao_trng_send_task, ao_trng_send_raw_task;
+static uint8_t         trng_running;
+static AO_TICK_TYPE    trng_power_time;
+
+#define TRNG_ENABLE_DELAY      AO_MS_TO_TICKS(100)
+
+static uint8_t         random_mutex;
 
 static void
-ao_trng_send(void)
+ao_trng_get_raw(uint16_t *buf)
+{
+       uint16_t        i;
+       uint16_t        t;
+       uint16_t        v;
+
+       t = ao_adc_get(AO_USB_IN_SIZE>>1);      /* one 16-bit value per two output bytes */
+       for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) {
+               v = ao_adc_ring[t];
+               *buf++ = v;
+               t = (t + 1) & (AO_ADC_RING_SIZE - 1);
+       }
+       ao_adc_ack(AO_USB_IN_SIZE>>1);
+}
+
+static void
+ao_trng_send_raw(void)
 {
        static uint16_t *buffer[2];
        int             usb_buf_id;
+
+       if (!buffer[0]) {
+               buffer[0] = ao_usb_alloc();
+               buffer[1] = ao_usb_alloc();
+               if (!buffer[0])
+                       ao_exit();
+       }
+
+       usb_buf_id = 0;
+
+       for (;;) {
+               ao_mutex_get(&random_mutex);
+               if (!trng_running) {
+                       AO_TICK_TYPE    delay;
+
+                       delay = trng_power_time + TRNG_ENABLE_DELAY - ao_time();
+                       if (delay > TRNG_ENABLE_DELAY)
+                               delay = TRNG_ENABLE_DELAY;
+
+                       /* Delay long enough for the HV power supply
+                        * to stabilize so that the first bits we read
+                        * aren't of poor quality
+                        */
+                       ao_delay(delay);
+                       trng_running = TRUE;
+               }
+#ifdef AO_LED_TRNG_RAW
+               ao_led_on(AO_LED_TRNG_RAW);
+#endif
+               ao_trng_get_raw(buffer[usb_buf_id]);
+#ifdef AO_LED_TRNG_RAW
+               ao_led_off(AO_LED_TRNG_RAW);
+#endif
+               ao_mutex_put(&random_mutex);
+               ao_usb_write2(buffer[usb_buf_id], AO_USB_IN_SIZE);
+               usb_buf_id = 1-usb_buf_id;
+       }
+}
+
+/* Make sure there's at least 8 bits of variance in the samples */
+#define MIN_VARIANCE           (128 * 128)
+
+/* Make sure the signal is spread around a bit */
+#define MAX_VARIANCE           (512 * 512)
+
+#define ADD_STATS(value) do {                  \
+               sum += (value);                 \
+               sum2 += (value) * (value);      \
+       } while(0)
+
+#define VARIANCE(n)    ((sum2 - (sum / (n) * sum)) / (n))
+
+static int
+ao_trng_get_cooked(uint16_t *buf)
+{
        uint16_t        i;
-       uint16_t        *buf;
        uint16_t        t;
        uint32_t        *rnd = (uint32_t *) ao_adc_ring;
+       int32_t         sum, sum2, var;
+
+       sum = sum2 = 0;
+       t = ao_adc_get(AO_USB_IN_SIZE) >> 1;            /* one 16-bit value per output byte */
+       for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) {
+               uint32_t        v;
+               uint16_t        v1, v2;
+
+               /* Fetch two values in one operation */
+               v = rnd[t];
+               t = (t + 1) & ((AO_ADC_RING_SIZE >> 1) - 1);
+
+               *buf++ = ao_crc_in_32_out_16(v);
+
+               v1 = v;
+               v2 = v >> 16;
+
+               ADD_STATS(v1);
+               ADD_STATS(v2);
+       }
+       ao_adc_ack(AO_USB_IN_SIZE);
+       var = VARIANCE(2 * AO_USB_IN_SIZE / sizeof (uint16_t));
+       return var >= MIN_VARIANCE && var <= MAX_VARIANCE;
+}
+
+#define AO_TRNG_START_WAIT     1024
+#define AO_TRNG_START_CHECK    32
+
+static void
+ao_trng_send(void)
+{
+       static uint16_t *buffer[2];
+       int     usb_buf_id;
+       int     good_bits;
+       int     failed;
+       int     s;
 
        if (!buffer[0]) {
                buffer[0] = ao_usb_alloc();
                buffer[1] = ao_usb_alloc();
                if (!buffer[0])
-                       return;
+                       ao_exit();
        }
 
        usb_buf_id = 0;
 
+#ifdef AO_TRNG_ENABLE_PORT
+       ao_gpio_set(AO_TRNG_ENABLE_PORT, AO_TRNG_ENABLE_BIT, AO_TRNG_ENABLE_PIN, 1);
+#endif
+       trng_power_time = ao_time();
+
        ao_crc_reset();
 
+       ao_delay(TRNG_ENABLE_DELAY);
+
+       for (s = 0; s < AO_TRNG_START_WAIT; s++) {
+               if (ao_trng_get_cooked(buffer[0]))
+                       break;
+               ao_delay(AO_MS_TO_TICKS(10));
+       }
+
+       /* Validate the hardware before enabling USB */
+       failed = 0;
+       for (s = 0; s < AO_TRNG_START_CHECK; s++) {
+               if (!ao_trng_get_cooked(buffer[0])) {
+                       failed++;
+                       ao_delay(AO_MS_TO_TICKS(10));
+               }
+       }
+       if (failed > AO_TRNG_START_CHECK / 4)
+               ao_panic(AO_PANIC_DMA);
+
+       ao_add_task(&ao_trng_send_raw_task, ao_trng_send_raw, "trng_send_raw");
+
+#ifdef AO_USB_START_DISABLED
+       ao_usb_enable();
+#endif
+
        for (;;) {
-               ao_led_on(AO_LED_TRNG_ACTIVE);
-               t = ao_adc_get(AO_USB_IN_SIZE) >> 1;    /* one 16-bit value per output byte */
-               buf = buffer[usb_buf_id];
-               for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) {
-                       *buf++ = ao_crc_in_32_out_16(rnd[t]);
-                       t = (t + 1) & ((AO_ADC_RING_SIZE>>1) - 1);
+               ao_mutex_get(&random_mutex);
+               if (!trng_running) {
+                       AO_TICK_TYPE    delay;
+
+                       delay = trng_power_time + TRNG_ENABLE_DELAY - ao_time();
+                       if (delay > TRNG_ENABLE_DELAY)
+                               delay = TRNG_ENABLE_DELAY;
+
+                       /* Delay long enough for the HV power supply
+                        * to stabilize so that the first bits we read
+                        * aren't of poor quality
+                        */
+                       ao_delay(delay);
+                       trng_running = TRUE;
+               }
+#ifdef AO_LED_TRNG_COOKED
+               ao_led_on(AO_LED_TRNG_COOKED);
+#endif
+               good_bits = ao_trng_get_cooked(buffer[usb_buf_id]);
+#ifdef AO_LED_TRNG_COOKED
+               ao_led_off(AO_LED_TRNG_COOKED);
+#endif
+               ao_mutex_put(&random_mutex);
+               if (good_bits) {
+                       ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE);
+                       usb_buf_id = 1-usb_buf_id;
+                       failed = 0;
+               } else {
+                       failed++;
+                       ao_delay(AO_MS_TO_TICKS(10));
+                       if (failed > 10) {
+                               ao_usb_disable();
+                               ao_panic(AO_PANIC_DMA);
+                       }
                }
-               ao_adc_ack(AO_USB_IN_SIZE);
-               ao_led_off(AO_LED_TRNG_ACTIVE);
-               ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE);
-               usb_buf_id = 1-usb_buf_id;
        }
 }
 
-static struct ao_task ao_trng_send_task;
+#if AO_POWER_MANAGEMENT
+
+static void ao_trng_suspend(void *arg)
+{
+       (void) arg;
+#ifdef AO_TRNG_ENABLE_PORT
+       ao_gpio_set(AO_TRNG_ENABLE_PORT, AO_TRNG_ENABLE_BIT, AO_TRNG_ENABLE_PIN, 0);
+#endif
+       trng_running = FALSE;
+}
+
+static void ao_trng_resume(void *arg)
+{
+       (void) arg;
+#ifdef AO_TRNG_ENABLE_PORT
+       ao_gpio_set(AO_TRNG_ENABLE_PORT, AO_TRNG_ENABLE_BIT, AO_TRNG_ENABLE_PIN, 1);
+#endif
+       trng_power_time = ao_time();
+}
+
+static struct ao_power ao_trng_power = {
+       .suspend = ao_trng_suspend,
+       .resume = ao_trng_resume
+};
+
+#endif
 
 void
 ao_trng_send_init(void)
 {
+#ifdef AO_TRNG_ENABLE_PORT
+       ao_enable_output(AO_TRNG_ENABLE_PORT, AO_TRNG_ENABLE_BIT, AO_TRNG_ENABLE_PIN, 0);
+       ao_power_register(&ao_trng_power);
+#endif
+       ao_enable_input(AO_RAW_PORT, AO_RAW_BIT, AO_EXTI_MODE_PULL_UP);
        ao_add_task(&ao_trng_send_task, ao_trng_send, "trng_send");
 }
index a5e556384615a6e6a52b2b4b615de5302c119b66..773e58d9709cdff034b5e7632bbbe2bec8afd4fb 100644 (file)
@@ -321,6 +321,7 @@ struct ao_adc {
  */
 
 #define HAS_MMA655X            1
+#define AO_MMA655X_INVERT      0
 #define AO_MMA655X_SPI_INDEX   AO_SPI_1_PB3_PB4_PB5
 #define AO_MMA655X_CS_PORT     (&stm_gpioc)
 #define AO_MMA655X_CS_PIN      12
index 59a469ae4fc41742f779da7628b2d372b30b9bb3..6ed0299e2d707baa607a515394ab4f4eccb7988b 100644 (file)
@@ -124,6 +124,16 @@ ao_timer_init(void);
 void
 ao_clock_init(void);
 
+#if AO_POWER_MANAGEMENT
+/* Go to low power clock */
+void
+ao_clock_suspend(void);
+
+/* Restart full-speed clock */
+void
+ao_clock_resume(void);
+#endif
+
 /*
  * ao_mutex.c
  */
@@ -810,6 +820,8 @@ struct ao_fifo {
 } while(0)
 
 #define ao_fifo_full(f)                ((((f).insert + 1) & (AO_FIFO_SIZE-1)) == (f).remove)
+#define ao_fifo_mostly(f)      ((((f).insert - (f).remove) & (AO_FIFO_SIZE-1)) >= (AO_FIFO_SIZE * 3 / 4))
+#define ao_fifo_barely(f)      ((((f).insert - (f).remove) & (AO_FIFO_SIZE-1)) >= (AO_FIFO_SIZE * 1 / 4))
 #define ao_fifo_empty(f)       ((f).insert == (f).remove)
 
 #if PACKET_HAS_MASTER || PACKET_HAS_SLAVE
index b0d3e5417533ccf32e79e8fd905fc5b386d1d7b7..f95ca8933cc3f526c15a9c7d2acf2d7efea4f9c4 100644 (file)
@@ -223,6 +223,12 @@ _ao_config_get(void)
 #if HAS_APRS
                if (minor < 22)
                        ao_config.aprs_format = AO_CONFIG_DEFAULT_APRS_FORMAT;
+#endif
+#if HAS_FIXED_PAD_BOX
+               if (minor < 22)
+                       ao_config.pad_box = 1;
+               if (minor < 23)
+                       ao_config.pad_idle = 120;
 #endif
                ao_config.minor = AO_CONFIG_MINOR;
                ao_config_dirty = 1;
@@ -899,6 +905,42 @@ ao_config_aprs_format_show(void)
 }
 #endif /* HAS_APRS */
 
+#if HAS_FIXED_PAD_BOX
+void
+ao_config_pad_box_show(void)
+{
+       printf ("Pad box: %d\n", ao_config.pad_box);
+}
+
+void
+ao_config_pad_box_set(void)
+{
+       ao_cmd_decimal();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       _ao_config_edit_start();
+       ao_config.pad_box = ao_cmd_lex_i;
+       _ao_config_edit_finish();
+}
+
+void
+ao_config_pad_idle_show(void)
+{
+       printf ("Idle timeout: %d\n", ao_config.pad_idle);
+}
+
+void
+ao_config_pad_idle_set(void)
+{
+       ao_cmd_decimal();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       _ao_config_edit_start();
+       ao_config.pad_idle = ao_cmd_lex_i;
+       _ao_config_edit_finish();
+}
+#endif
+
 struct ao_config_var {
        __code char     *str;
        void            (*set)(void) __reentrant;
@@ -992,6 +1034,12 @@ __code struct ao_config_var ao_config_vars[] = {
          ao_config_aprs_ssid_set, ao_config_aprs_ssid_show },
        { "C <0 compressed, 1 uncompressed>\0APRS format",
          ao_config_aprs_format_set, ao_config_aprs_format_show },
+#endif
+#if HAS_FIXED_PAD_BOX
+       { "B <box>\0Set pad box (1-99)",
+         ao_config_pad_box_set, ao_config_pad_box_show },
+       { "i <seconds>\0Set idle timeout (0 disable)",
+         ao_config_pad_idle_set, ao_config_pad_idle_show },
 #endif
        { "s\0Show",
          ao_config_show,               0 },
index cfe8555c0387af784c747f9b57dd0df499f76294..3c73ea4948d6264f82c6d7079df5c2706dcaa912 100644 (file)
@@ -57,7 +57,7 @@
 #endif
 
 #define AO_CONFIG_MAJOR        1
-#define AO_CONFIG_MINOR        22
+#define AO_CONFIG_MINOR        23
 
 #define AO_AES_LEN 16
 
@@ -118,6 +118,10 @@ struct ao_config {
 #if HAS_APRS
        uint8_t         aprs_format;            /* minor version 22 */
 #endif
+#if HAS_FIXED_PAD_BOX
+       uint8_t         pad_box;                /* minor version 22 */
+       uint8_t         pad_idle;               /* minor version 23 */
+#endif
 };
 
 #define AO_APRS_FORMAT_COMPRESSED      0
index 8f75ad876b612e3cc1480e1fc9aa9fc8024908bd..6ee0965d4e732ed4ce25adec78ac11231942356e 100644 (file)
@@ -269,6 +269,10 @@ typedef int16_t accel_t;
 
 #define AO_ACCEL_INVERT                4095
 
+#ifndef AO_MMA655X_INVERT
+#error AO_MMA655X_INVERT not defined
+#endif
+
 #define ao_data_accel(packet)                  ((packet)->mma655x)
 #if AO_MMA655X_INVERT
 #define ao_data_accel_cook(packet)             (AO_ACCEL_INVERT - (packet)->mma655x)
diff --git a/src/kernel/ao_fast_timer.h b/src/kernel/ao_fast_timer.h
new file mode 100644 (file)
index 0000000..90fb393
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_FAST_TIMER_H_
+#define _AO_FAST_TIMER_H_
+
+void
+ao_fast_timer_init(void);
+
+#ifndef AO_FAST_TIMER_MAX
+#define AO_FAST_TIMER_MAX      2
+#endif
+
+void
+ao_fast_timer_on(void (*callback)(void));
+
+void
+ao_fast_timer_off(void (*callback)(void));
+
+#endif /* _AO_FAST_TIMER_H_ */
index 251dbc02a7f35eaa7994c1541af5be3800205f84..9ba02bb8b24e8cc9b872e3e84a205daf1bba96db 100644 (file)
@@ -370,8 +370,10 @@ ao_flight(void)
                                {
                                        ao_flight_state = ao_flight_landed;
 
+#if HAS_ADC
                                        /* turn off the ADC capture */
                                        ao_timer_set_adc_interval(0);
+#endif
 
                                        ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
                                }
index f86fb35998f8cfcf58af6134589fcd5f08882e5c..fdd428c223eb84c1ee13615243d09cfa6563fc82 100644 (file)
@@ -49,6 +49,7 @@ extern __pdata enum ao_flight_state ao_log_state;
 #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_TELEMEGA         10      /* 32 byte typed telemega records with 32 bit gyro cal */
+#define AO_LOG_FORMAT_DETHERM          11      /* 16-byte MS5607 baro only, no ADC */
 #define AO_LOG_FORMAT_NONE             127     /* No log at all */
 
 extern __code uint8_t ao_log_format;
index 0ca3ed06266352cabd99a81195c3ea7f0d962c0e..844f38aa6929a6e0946206aaa6cc5a13fc04bfc9 100644 (file)
@@ -110,9 +110,11 @@ ao_log(void)
                                              ao_data_ring[ao_log_data_pos].ms5607_raw.pres);
                                ao_log_pack24(log.u.sensor.temp,
                                              ao_data_ring[ao_log_data_pos].ms5607_raw.temp);
+#if AO_LOG_FORMAT != AO_LOG_FORMAT_DETHERM
                                log.u.sensor.sense_a = ao_data_ring[ao_log_data_pos].adc.sense_a;
                                log.u.sensor.sense_m = ao_data_ring[ao_log_data_pos].adc.sense_m;
                                log.u.sensor.v_batt = ao_data_ring[ao_log_data_pos].adc.v_batt;
+#endif
                                ao_log_mini(&log);
                                if (ao_log_state <= ao_flight_coast)
                                        next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT;
index c29cd8feb279d605e06ffafa50ff3a53f7864dbd..e280f98c57a77253d692e968ded0450cb56e3091 100644 (file)
@@ -38,10 +38,15 @@ ao_panic_delay(uint8_t n)
 {
        uint8_t i = 0, j = 0;
 
-       while (n--)
+       while (n--) {
+#ifdef AO_PANIC_DELAY_SCALE
+       uint8_t s = AO_PANIC_DELAY_SCALE;
+       while (s--)
+#endif
                while (--j)
                        while (--i)
                                ao_arch_nop();
+       }
 }
 
 void
@@ -56,16 +61,16 @@ ao_panic(uint8_t reason)
        ao_arch_block_interrupts();
        for (;;) {
                ao_panic_delay(20);
+#if HAS_BEEP
                for (n = 0; n < 5; n++) {
-                       ao_led_on(AO_LED_PANIC);
                        ao_beep(AO_BEEP_HIGH);
                        ao_panic_delay(1);
-                       ao_led_off(AO_LED_PANIC);
                        ao_beep(AO_BEEP_LOW);
                        ao_panic_delay(1);
                }
                ao_beep(AO_BEEP_OFF);
                ao_panic_delay(2);
+#endif
 
 #ifdef SDCC
 #pragma disable_warning 126
diff --git a/src/kernel/ao_power.c b/src/kernel/ao_power.c
new file mode 100644 (file)
index 0000000..bead594
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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_power.h>
+
+static struct ao_power *head, *tail;
+
+void
+ao_power_register(struct ao_power *power)
+{
+       if (power->registered)
+               return;
+       power->registered = TRUE;
+       if (tail) {
+               tail->next = power;
+               power->prev = tail;
+               tail = power;
+       } else {
+               head = tail = power;
+       }
+#ifdef AO_LED_POWER
+       ao_led_on(AO_LED_POWER);
+#endif
+}
+
+void
+ao_power_unregister(struct ao_power *power)
+{
+       if (!power->registered)
+               return;
+       power->registered = FALSE;
+       if (power->prev)
+               power->prev->next = power->next;
+       else
+               head = power->next;
+       if (power->next)
+               power->next->prev = power->prev;
+       else
+               tail = power->prev;
+}
+
+void
+ao_power_suspend(void)
+{
+       struct ao_power *p;
+
+#ifdef AO_LED_POWER
+       ao_led_off(AO_LED_POWER);
+#endif
+       for (p = tail; p; p = p->prev)
+               p->suspend(p->arg);
+}
+
+void
+ao_power_resume(void)
+{
+       struct ao_power *p;
+
+       for (p = head; p; p = p->next)
+               p->resume(p->arg);
+#ifdef AO_LED_POWER
+       ao_led_on(AO_LED_POWER);
+#endif
+}
+
diff --git a/src/kernel/ao_power.h b/src/kernel/ao_power.h
new file mode 100644 (file)
index 0000000..98a8c1c
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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_POWER_H_
+#define _AO_POWER_H_
+
+#if AO_POWER_MANAGEMENT
+
+struct ao_power {
+       struct ao_power *prev, *next;
+
+       void (*suspend)(void *arg);
+       void (*resume)(void *arg);
+       void *arg;
+       uint8_t registered;
+};
+
+void
+ao_power_register(struct ao_power *power);
+
+void
+ao_power_unregister(struct ao_power *power);
+
+void
+ao_power_suspend(void);
+
+void
+ao_power_resume(void);
+
+#else /* AO_POWER_MANAGEMENT */
+
+#define ao_power_register(power)
+#define ao_power_unregister(power)
+#define ao_power_suspend()
+#define ao_power_resume()
+
+#endif /* else AO_POWER_MANAGEMENT */
+
+#endif /* _AO_POWER_H_ */
index c711a4d261bec9685fc210579a129e7f6bb77668..3a829b3a654736e58539a7b57d22f7cc7239ed4d 100644 (file)
@@ -33,11 +33,32 @@ const char ao_product[] = AO_iProduct_STRING;
 #define AO_USB_MAX_POWER       100
 #endif
 
-#ifndef AO_USB_INTERFACE_CLASS
-#define AO_USB_INTERFACE_CLASS 0x02
+#ifndef AO_USB_SELF_POWER
+#define AO_USB_SELF_POWER      1
+#endif
+
+#define AO_USB_DEVICE_CLASS_COMMUNICATION      0x02
+#define AO_USB_INTERFACE_CLASS_CONTROL_CDC     0x02
+#define AO_USB_INTERFACE_CLASS_DATA_CDC                0x0A
+
+#ifndef AO_USB_DEVICE_CLASS
+#define AO_USB_DEVICE_CLASS            AO_USB_DEVICE_CLASS_COMMUNICATION
+#endif
+
+#ifndef AO_USB_INTERFACE_CLASS_DATA
+#define AO_USB_INTERFACE_CLASS_CONTROL AO_USB_INTERFACE_CLASS_CONTROL_CDC
+#define AO_USB_INTERFACE_CLASS_DATA    AO_USB_INTERFACE_CLASS_DATA_CDC
 #endif
 
 #include "ao_usb.h"
+
+#define HEADER_LEN             9
+#define CONTROL_CLASS_LEN      35
+#define DATA_LEN               (9 + 7 * AO_USB_HAS_OUT + 7 * AO_USB_HAS_IN + 7 * AO_USB_HAS_IN2)
+
+#define TOTAL_LENGTH           (HEADER_LEN + AO_USB_HAS_INT * CONTROL_CLASS_LEN + DATA_LEN)
+#define NUM_INTERFACES         (AO_USB_HAS_INT + 1)
+
 /* USB descriptors in one giant block of bytes */
 AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] =
 {
@@ -45,7 +66,7 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] =
        0x12,
        AO_USB_DESC_DEVICE,
        LE_WORD(0x0110),        /*  bcdUSB */
-       0x02,                   /*  bDeviceClass */
+       AO_USB_DEVICE_CLASS,    /*  bDeviceClass */
        0x00,                   /*  bDeviceSubClass */
        0x00,                   /*  bDeviceProtocol */
        AO_USB_CONTROL_SIZE,    /*  bMaxPacketSize */
@@ -60,20 +81,21 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] =
        /* Configuration descriptor */
        0x09,
        AO_USB_DESC_CONFIGURATION,
-       LE_WORD(67),            /*  wTotalLength */
-       0x02,                   /*  bNumInterfaces */
+       LE_WORD(TOTAL_LENGTH),  /*  wTotalLength */
+       NUM_INTERFACES,         /*  bNumInterfaces */
        0x01,                   /*  bConfigurationValue */
        0x00,                   /*  iConfiguration */
-       0xC0,                   /*  bmAttributes */
+       0x80 | (AO_USB_SELF_POWER << 6),        /*  bmAttributes */
        AO_USB_MAX_POWER >> 1,  /*  bMaxPower, 2mA units */
 
+#if AO_USB_HAS_INT
        /* Control class interface */
        0x09,
        AO_USB_DESC_INTERFACE,
        0x00,                   /*  bInterfaceNumber */
        0x00,                   /*  bAlternateSetting */
        0x01,                   /*  bNumEndPoints */
-       AO_USB_INTERFACE_CLASS, /*  bInterfaceClass */
+       AO_USB_INTERFACE_CLASS_CONTROL, /*  bInterfaceClass */
        0x02,                   /*  bInterfaceSubClass */
        0x01,                   /*  bInterfaceProtocol, linux requires value of 1 for the cdc_acm module */
        0x00,                   /*  iInterface */
@@ -111,18 +133,20 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] =
        0x03,                   /* bmAttributes = intr */
        LE_WORD(8),             /* wMaxPacketSize */
        0xff,                   /* bInterval */
+#endif
 
        /* Data class interface descriptor */
        0x09,
        AO_USB_DESC_INTERFACE,
-       0x01,                   /* bInterfaceNumber */
-       0x00,                   /* bAlternateSetting */
-       0x02,                   /* bNumEndPoints */
-       0x0A,                   /* bInterfaceClass = data */
-       0x00,                   /* bInterfaceSubClass */
-       0x00,                   /* bInterfaceProtocol */
-       0x00,                   /* iInterface */
-
+       AO_USB_HAS_INT,                 /* bInterfaceNumber */
+       0x00,                           /* bAlternateSetting */
+       AO_USB_HAS_OUT + AO_USB_HAS_IN + AO_USB_HAS_IN2,        /* bNumEndPoints */
+       AO_USB_INTERFACE_CLASS_DATA,    /* bInterfaceClass = data */
+       0x00,                           /* bInterfaceSubClass */
+       0x00,                           /* bInterfaceProtocol */
+       0x00,                           /* iInterface */
+
+#if AO_USB_HAS_OUT
        /* Data EP OUT */
        0x07,
        AO_USB_DESC_ENDPOINT,
@@ -130,7 +154,9 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] =
        0x02,                   /* bmAttributes = bulk */
        LE_WORD(AO_USB_OUT_SIZE),/* wMaxPacketSize */
        0x00,                   /* bInterval */
+#endif
 
+#if AO_USB_HAS_IN
        /* Data EP in */
        0x07,
        AO_USB_DESC_ENDPOINT,
@@ -138,6 +164,17 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] =
        0x02,                   /* bmAttributes = bulk */
        LE_WORD(AO_USB_IN_SIZE),/* wMaxPacketSize */
        0x00,                   /* bInterval */
+#endif
+
+#if AO_USB_HAS_IN2
+       /* Data EP in 2 */
+       0x07,
+       AO_USB_DESC_ENDPOINT,
+       AO_USB_IN2_EP|0x80,     /* bEndpointAddress */
+       0x02,                   /* bmAttributes = bulk */
+       LE_WORD(AO_USB_IN_SIZE),/* wMaxPacketSize */
+       0x00,                   /* bInterval */
+#endif
 
        /* String descriptors */
        0x04,
index 55e423bb90bae9589f926ddbb3aeae690e2ad48a..e430edc6c02f3e5854b5163ebd18afc26d6c0e0e 100644 (file)
@@ -355,7 +355,6 @@ ao_yield(void) ao_arch_naked_define
         */
        if (ao_cur_task->wchan == NULL)
                ao_task_to_run_queue(ao_cur_task);
-       ao_cur_task = NULL;
        for (;;) {
                ao_arch_memory_barrier();
                if (!ao_list_is_empty(&run_queue))
@@ -425,6 +424,7 @@ ao_sleep(__xdata void *wchan)
 void
 ao_wakeup(__xdata void *wchan) __reentrant
 {
+       ao_validate_cur_stack();
 #if HAS_TASK_QUEUE
        struct ao_task  *sleep, *next;
        struct ao_list  *sleep_queue;
@@ -442,10 +442,12 @@ ao_wakeup(__xdata void *wchan) __reentrant
        }
        ao_arch_irqrestore(flags);
 #else
+       {
        uint8_t i;
        for (i = 0; i < ao_num_tasks; i++)
                if (ao_tasks[i]->wchan == wchan)
                        ao_tasks[i]->wchan = NULL;
+       }
 #endif
        ao_check_stack();
 }
index c6bec0e397dccba3f1625160330ff4af049f27fa..0e353fe83a9998fcebffd52e0eb207d8c9002814 100644 (file)
@@ -56,6 +56,10 @@ extern __data uint8_t ao_num_tasks;
 extern __xdata struct ao_task *__data ao_cur_task;
 extern __data uint8_t ao_task_minimize_latency;        /* Reduce IRQ latency */
 
+#ifndef HAS_ARCH_VALIDATE_CUR_STACK
+#define ao_validate_cur_stack()
+#endif
+
 /*
  ao_task.c
  */
index 1ce4f82f2a1066d24f6276c0149501a47e569a3a..8f3e7813f4ed308b2f0ef937d8f8f0aec0af72cd 100644 (file)
@@ -105,6 +105,23 @@ extern __code __at (0x00aa) uint8_t ao_usb_descriptors [];
 #ifndef AO_USB_OUT_EP
 #define AO_USB_OUT_EP          4
 #define AO_USB_IN_EP           5
+#define AO_USB_IN2_EP          6
+#endif
+
+#ifndef AO_USB_HAS_OUT
+#define AO_USB_HAS_OUT 1
+#endif
+
+#ifndef AO_USB_HAS_IN
+#define AO_USB_HAS_IN  1
+#endif
+
+#ifndef AO_USB_HAS_INT
+#define AO_USB_HAS_INT 1
+#endif
+
+#ifndef AO_USB_HAS_IN2
+#define AO_USB_HAS_IN2 0
 #endif
 
 /*
index fbe641d87b9ee7ca53c16934e70a8ce6b35bc660..dbb415381ce28c980cf78f31da38ada52fad1f55 100644 (file)
@@ -227,6 +227,28 @@ ao_spi_duplex(const void *out, void *in, uint16_t len, uint8_t spi_index);
 void
 ao_spi_init(void);
 
+static inline void
+ao_spi_send_sync(const void *block, uint16_t len, uint8_t spi_index)
+{
+       ao_spi_send(block, len, spi_index);
+}
+
+static inline void ao_spi_send_byte(uint8_t byte, uint8_t spi_index)
+{
+       struct lpc_ssp  *lpc_ssp;
+       switch (spi_index) {
+       case 0:
+               lpc_ssp = &lpc_ssp0;
+               break;
+       case 1:
+               lpc_ssp = &lpc_ssp1;
+               break;
+       }
+       lpc_ssp->dr = byte;
+       while ((lpc_ssp->sr & (1 << LPC_SSP_SR_RNE)) == 0);
+       (void) lpc_ssp->dr;
+}
+
 #define ao_spi_init_cs(port, mask) do {                                        \
                uint8_t __bit__;                                        \
                for (__bit__ = 0; __bit__ < 32; __bit__++) {            \
diff --git a/src/lpc/ao_fast_timer_lpc.c b/src/lpc/ao_fast_timer_lpc.c
new file mode 100644 (file)
index 0000000..c4f26fc
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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_fast_timer.h>
+
+static void (*ao_fast_timer_callback[AO_FAST_TIMER_MAX])(void);
+static uint8_t ao_fast_timer_count;
+static uint8_t ao_fast_timer_users;
+
+static void
+ao_fast_timer_enable(void)
+{
+       lpc_ct16b0.tcr = ((1 << LPC_CT16B_TCR_CEN) |
+                         (1 << LPC_CT16B_TCR_CRST));
+}
+
+static void
+ao_fast_timer_disable(void)
+{
+       lpc_ct16b0.tcr = ((0 << LPC_CT16B_TCR_CEN) |
+                         (0 << LPC_CT16B_TCR_CRST));
+}
+
+void
+ao_fast_timer_on(void (*callback)(void))
+{
+       ao_fast_timer_callback[ao_fast_timer_count] = callback;
+       if (!ao_fast_timer_count++)
+               ao_fast_timer_enable();
+}
+
+void
+ao_fast_timer_off(void (*callback)(void))
+{
+       uint8_t n;
+
+       for (n = 0; n < ao_fast_timer_count; n++)
+               if (ao_fast_timer_callback[n] == callback) {
+                       for (; n < ao_fast_timer_count-1; n++) {
+                               ao_fast_timer_callback[n] = ao_fast_timer_callback[n+1];
+                       }
+                       if (!--ao_fast_timer_count)
+                               ao_fast_timer_disable();
+                       break;
+               }
+}
+
+void lpc_ct16b0_isr(void)
+{
+       uint32_t        v = lpc_ct16b0.ir;
+       int             i;
+
+       lpc_ct16b0.ir = v;
+       if (v & (1 << LPC_CT16B_IR_MR0INT)) {
+               for (i = 0; i < ao_fast_timer_count; i++)
+                       (*ao_fast_timer_callback[i])();
+       }
+}
+
+#ifndef FAST_TIMER_FREQ
+#define FAST_TIMER_FREQ        10000
+#endif
+
+#define TIMER_FAST     (AO_LPC_SYSCLK / FAST_TIMER_FREQ)
+
+void
+ao_fast_timer_init(void)
+{
+       if (!ao_fast_timer_users) {
+
+               lpc_nvic_set_enable(LPC_ISR_CT16B0_POS);
+               lpc_nvic_set_priority(LPC_ISR_CT16B0_POS, AO_LPC_NVIC_CLOCK_PRIORITY);
+               /* Turn on 16-bit timer CT16B0 */
+
+               lpc_scb.sysahbclkctrl |= 1 << LPC_SCB_SYSAHBCLKCTRL_CT16B0;
+
+               /* Disable timer */
+               lpc_ct16b0.tcr = 0;
+
+               /* scale factor 1 */
+               lpc_ct16b0.pr = 0;
+               lpc_ct16b0.pc = 0;
+
+               lpc_ct16b0.mcr = ((1 << LPC_CT16B_MCR_MR0I) |
+                                 (1 << LPC_CT16B_MCR_MR0R));
+
+               lpc_ct16b0.mr[0] = TIMER_FAST;
+
+               ao_fast_timer_disable();
+       }
+       if (ao_fast_timer_users == AO_FAST_TIMER_MAX)
+               ao_panic(AO_PANIC_FAST_TIMER);
+       ao_fast_timer_users++;
+}
+
index 44fb410e7f522b642d1a68f965f46681690a3d74..623559ebe14c4c69127a62c381d8a1161085a945 100644 (file)
@@ -99,7 +99,7 @@ ao_clock_init(void)
                                 (1 << LPC_SCB_SYSAHBCLKCTRL_FLASHARRAY) |
                                 (1 << LPC_SCB_SYSAHBCLKCTRL_GPIO) |
                                 (1 << LPC_SCB_SYSAHBCLKCTRL_IOCON));
-                                
+
        /* Enable the brown-out detection at the highest voltage to
         * make sure the flash part remains happy
         */
@@ -112,21 +112,21 @@ ao_clock_init(void)
        /* Turn the IRC clock back on */
        lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_IRC_PD);
        ao_clock_delay();
-       
+
        /* Switch to the IRC clock */
        lpc_scb.mainclksel = LPC_SCB_MAINCLKSEL_SEL_IRC << LPC_SCB_MAINCLKSEL_SEL;
        lpc_scb.mainclkuen = (0 << LPC_SCB_MAINCLKUEN_ENA);
        lpc_scb.mainclkuen = (1 << LPC_SCB_MAINCLKUEN_ENA);
        while (!(lpc_scb.mainclkuen & (1 << LPC_SCB_MAINCLKUEN_ENA)))
                ;
-       
+
        /* Switch USB to the main clock */
        lpc_scb.usbclksel = (LPC_SCB_USBCLKSEL_SEL_MAIN_CLOCK << LPC_SCB_USBCLKSEL_SEL);
        lpc_scb.usbclkuen = (0 << LPC_SCB_USBCLKUEN_ENA);
        lpc_scb.usbclkuen = (1 << LPC_SCB_USBCLKUEN_ENA);
        while (!(lpc_scb.usbclkuen & (1 << LPC_SCB_USBCLKUEN_ENA)))
                ;
-       
+
        /* Find a PLL post divider ratio that gets the FCCO in range */
        for (p = 0; p < 4; p++)
                if (AO_LPC_CLKOUT << (1 + p) >= AO_LPC_FCCO_MIN)
@@ -163,12 +163,12 @@ ao_clock_init(void)
        lpc_scb.syspllclkuen = (1 << LPC_SCB_SYSPLLCLKUEN_ENA);
        while (!(lpc_scb.syspllclkuen & (1 << LPC_SCB_SYSPLLCLKUEN_ENA)))
                ;
-       
+
        /* Turn on the PLL */
        lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_SYSPLL_PD);
 
        /* Wait for it to lock */
-       
+
        for (i = 0; i < 20000; i++)
                if (lpc_scb.syspllstat & (1 << LPC_SCB_SYSPLLSTAT_LOCK))
                        break;
@@ -199,7 +199,7 @@ ao_clock_init(void)
        lpc_scb.usbpllclkuen = (1 << LPC_SCB_USBPLLCLKUEN_ENA);
        while (!(lpc_scb.usbpllclkuen & (1 << LPC_SCB_USBPLLCLKUEN_ENA)))
                ;
-       
+
        /* Power down everything we don't need */
        lpc_scb.pdruncfg = ((1 << LPC_SCB_PDRUNCFG_IRCOUT_PD) |
                            (1 << LPC_SCB_PDRUNCFG_IRC_PD) |
index 9408ceab1ab7d76ab71037f3c009f7b3ab53d716..40d412d01f90b6fabed6fc57e4aa44e1fc348d4c 100644 (file)
@@ -411,7 +411,7 @@ struct lpc_scb {
        vuint32_t       mainclksel;     /* 0x70 */
        vuint32_t       mainclkuen;
        vuint32_t       sysahbclkdiv;
-       uint32_t        r7c;            
+       uint32_t        r7c;
 
        vuint32_t       sysahbclkctrl;  /* 0x80 */
        uint32_t        r84[3];
@@ -429,14 +429,14 @@ struct lpc_scb {
        uint32_t        rcc;
 
        uint32_t        rd0[4];
-       
+
        vuint32_t       clkoutsel;      /* 0xe0 */
        vuint32_t       clkoutuen;
        vuint32_t       clkoutdiv;
        uint32_t        rec;
-       
+
        uint32_t        rf0[4];         /* 0xf0 */
-       
+
        vuint32_t       pioporcap0;     /* 0x100 */
        vuint32_t       pioporcap1;
        uint32_t        r102[2];
@@ -445,7 +445,7 @@ struct lpc_scb {
        uint32_t        r120[4];        /* 0x120 */
        uint32_t        r130[4];        /* 0x130 */
        uint32_t        r140[4];        /* 0x140 */
-       
+
        vuint32_t       bodctrl;        /* 0x150 */
        vuint32_t       systckcal;
        uint32_t        r158[2];
@@ -479,7 +479,7 @@ struct lpc_scb {
        uint32_t        r240[12 * 4];   /* 0x240 */
 
        uint32_t        r300[15 * 4];   /* 0x300 */
-                            
+
        uint32_t        r3f0;           /* 0x3f0 */
        vuint32_t       device_id;
 };
@@ -680,7 +680,7 @@ struct lpc_gpio {
        vuint32_t       word[0x40];     /* 0x1000 */
 
        uint8_t         r1100[0x2000 - 0x1100];
-       
+
        vuint32_t       dir[2];         /* 0x2000 */
 
        uint8_t         r2008[0x2080 - 0x2008];
@@ -1032,7 +1032,7 @@ lpc_nvic_enabled(int irq) {
        return (lpc_nvic.iser >> irq) & 1;
 }
 
-       
+
 static inline void
 lpc_nvic_set_pending(int irq) {
        lpc_nvic.ispr = (1 << irq);
@@ -1201,18 +1201,118 @@ extern struct lpc_adc lpc_adc;
 #define LPC_ADC_STAT_OVERRUN   8
 #define LPC_ADC_STAT_ADINT     16
 
+struct lpc_ct16b {
+       vuint32_t       ir;     /* 0x00 */
+       vuint32_t       tcr;
+       vuint32_t       tc;
+       vuint32_t       pr;
+
+       vuint32_t       pc;     /* 0x10 */
+       vuint32_t       mcr;
+       vuint32_t       mr[4];  /* 0x18 */
+       vuint32_t       ccr;    /* 0x28 */
+       vuint32_t       cr0;
+
+       vuint32_t       cr1_0;  /* 0x30 (only for ct16b0 */
+       vuint32_t       cr1_1;  /* 0x34 (only for ct16b1 */
+       uint32_t        r38;
+       vuint32_t       emr;
+
+       uint8_t         r40[0x70 - 0x40];
+
+       vuint32_t       ctcr;   /* 0x70 */
+       vuint32_t       pwmc;
+};
+
+extern struct lpc_ct16b        lpc_ct16b0, lpc_ct16b1;
+
+#define lpc_ct16b0     (*(struct lpc_ct16b *) 0x4000c000)
+#define lpc_ct16b1     (*(struct lpc_ct16b *) 0x40010000)
+
+#define LPC_CT16B_IR_MR0INT    0
+#define LPC_CT16B_IR_MR1INT    1
+#define LPC_CT16B_IR_MR2INT    2
+#define LPC_CT16B_IR_MR3INT    3
+#define LPC_CT16B_IR_CR0INT    4
+#define LPC_CT16B0_IR_CR1INT   6
+#define LPC_CT16B1_IR_CR1INT   5
+
+#define LPC_CT16B_TCR_CEN      0
+#define LPC_CT16B_TCR_CRST     1
+
+#define LPC_CT16B_MCR_MR0I     0
+#define LPC_CT16B_MCR_MR0R     1
+#define LPC_CT16B_MCR_MR0S     2
+#define LPC_CT16B_MCR_MR1I     3
+#define LPC_CT16B_MCR_MR1R     4
+#define LPC_CT16B_MCR_MR1S     5
+#define LPC_CT16B_MCR_MR2I     6
+#define LPC_CT16B_MCR_MR2R     7
+#define LPC_CT16B_MCR_MR2S     8
+#define LPC_CT16B_MCR_MR3I     9
+#define LPC_CT16B_MCR_MR3R     10
+#define LPC_CT16B_MCR_MR3S     11
+
+#define LPC_CT16B_CCR_CAP0RE   0
+#define LPC_CT16B_CCR_CAP0FE   1
+#define LPC_CT16B_CCR_CAP0I    2
+#define LPC_CT16B0_CCR_CAP1RE  6
+#define LPC_CT16B0_CCR_CAP1FE  7
+#define LPC_CT16B0_CCR_CAP1I   8
+#define LPC_CT16B1_CCR_CAP1RE  3
+#define LPC_CT16B1_CCR_CAP1FE  4
+#define LPC_CT16B1_CCR_CAP1I   5
+
+#define LPC_CT16B_EMR_EM0      0
+#define LPC_CT16B_EMR_EM1      1
+#define LPC_CT16B_EMR_EM2      2
+#define LPC_CT16B_EMR_EM3      3
+#define LPC_CT16B_EMR_EMC0     4
+#define LPC_CT16B_EMR_EMC1     6
+#define LPC_CT16B_EMR_EMC2     8
+#define LPC_CT16B_EMR_EMC3     10
+
+#define LPC_CT16B_EMR_EMC_NOTHING      0
+#define LPC_CT16B_EMR_EMC_CLEAR                1
+#define LPC_CT16B_EMR_EMC_SET          2
+#define LPC_CT16B_EMR_EMC_TOGGLE       3
+
+#define LPC_CT16B_CCR_CTM      0
+#define  LPC_CT16B_CCR_CTM_TIMER               0
+#define  LPC_CT16B_CCR_CTM_COUNTER_RISING      1
+#define  LPC_CT16B_CCR_CTM_COUNTER_FALLING     2
+#define  LPC_CT16B_CCR_CTM_COUNTER_BOTH                3
+#define LPC_CT16B_CCR_CIS      2
+#define  LPC_CT16B_CCR_CIS_CAP0                        0
+#define  LPC_CT16B0_CCR_CIS_CAP1               2
+#define  LPC_CT16B1_CCR_CIS_CAP1               1
+#define LPC_CT16B_CCR_ENCC     4
+#define LPC_CT16B_CCR_SELCC    5
+#define  LPC_CT16B_CCR_SELCC_RISING_CAP0       0
+#define  LPC_CT16B_CCR_SELCC_FALLING_CAP0      1
+#define  LPC_CT16B0_CCR_SELCC_RISING_CAP1      4
+#define  LPC_CT16B0_CCR_SELCC_FALLING_CAP1     5
+#define  LPC_CT16B1_CCR_SELCC_RISING_CAP1      2
+#define  LPC_CT16B1_CCR_SELCC_FALLING_CAP1     3
+#define LPC_CT16B_CCR_
+
+#define LPC_CT16B_PWMC_PWMEN0  0
+#define LPC_CT16B_PWMC_PWMEN1  1
+#define LPC_CT16B_PWMC_PWMEN2  2
+#define LPC_CT16B_PWMC_PWMEN3  3
+
 struct lpc_ct32b {
        vuint32_t       ir;     /* 0x00 */
        vuint32_t       tcr;
        vuint32_t       tc;
        vuint32_t       pr;
-       
+
        vuint32_t       pc;     /* 0x10 */
        vuint32_t       mcr;
        vuint32_t       mr[4];  /* 0x18 */
        vuint32_t       ccr;    /* 0x28 */
        vuint32_t       cr0;
-       
+
        vuint32_t       cr1_0;  /* 0x30 (only for ct32b0 */
        vuint32_t       cr1_1;  /* 0x34 (only for ct32b1 */
        uint32_t        r38;
index a523c39c9afb1910f6d844b0ef3d81005e3da336..61dd9e7076c0dca5130badee0868fcd2a3e4fe1e 100644 (file)
@@ -1,6 +1,8 @@
 lpc_usb_sram   = 0x20004000;
 lpc_usb_endpoint = 0x20004700;
 lpc_usart      = 0x40008000;
+lpc_ct16b0     = 0x4000c000;
+lpc_ct16b1     = 0x40010000;
 lpc_ct32b0     = 0x40014000;
 lpc_ct32b1     = 0x40018000;
 lpc_adc                = 0x4001c000;
index a6276c5ae306963e8ac76fc0e86b02ca9e76b2fa..f9508b8f2f4c92401c196e702720a74f70f50e70 100644 (file)
@@ -25,7 +25,9 @@
  * STM32L definitions and code fragments for AltOS
  */
 
+#ifndef AO_STACK_SIZE
 #define AO_STACK_SIZE  512
+#endif
 
 #define AO_LED_TYPE    uint16_t
 
index 42f1a2e5d75c5aeb4680dbf12c7c9b0f039e9ebb..2c017c79f0191b5b5395f66f508a26748cb048db 100644 (file)
@@ -82,6 +82,34 @@ ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index);
 void
 ao_spi_send_sync(void *block, uint16_t len, uint8_t spi_index);
 
+static inline void
+ao_spi_send_byte(uint8_t byte, uint8_t spi_index)
+{
+       struct stm_spi  *stm_spi;
+
+       switch (AO_SPI_INDEX(spi_index)) {
+       case 0:
+               stm_spi = &stm_spi1;
+               break;
+       case 1:
+               stm_spi = &stm_spi2;
+               break;
+       }
+
+       stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
+                       (0 << STM_SPI_CR2_RXNEIE) |
+                       (0 << STM_SPI_CR2_ERRIE) |
+                       (0 << STM_SPI_CR2_SSOE) |
+                       (0 << STM_SPI_CR2_TXDMAEN) |
+                       (0 << STM_SPI_CR2_RXDMAEN));
+
+       /* Clear RXNE */
+       (void) stm_spi->dr;
+
+       while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE)));
+       stm_spi->dr = byte;
+}
+
 void
 ao_spi_recv(void *block, uint16_t len, uint8_t spi_index);
 
@@ -149,6 +177,11 @@ ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t s
 
 #define ao_gpio_get(port, bit, pin) stm_gpio_get(port, bit)
 
+#define ao_gpio_set_bits(port, bits) stm_gpio_set_bits(port, bits)
+
+#define ao_gpio_clr_bits(port, bits) stm_gpio_clr_bits(port, bits);
+
+
 #define ao_enable_output(port,bit,pin,v) do {                  \
                ao_enable_port(port);                           \
                ao_gpio_set(port, bit, pin, v);                 \
@@ -245,12 +278,35 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t i2c_index, uint8_t stop);
 void
 ao_i2c_init(void);
 
+#if USE_SERIAL_1_SW_FLOW || USE_SERIAL_2_SW_FLOW || USE_SERIAL_3_SW_FLOW
+#define HAS_SERIAL_SW_FLOW 1
+#else
+#define HAS_SERIAL_SW_FLOW 0
+#endif
+
+#if USE_SERIAL_1_FLOW && !USE_SERIAL_1_SW_FLOW || USE_SERIAL_2_FLOW && !USE_SERIAL_2_SW_FLOW || USE_SERIAL_3_FLOW && !USE_SERIAL_3_SW_FLOW
+#define HAS_SERIAL_HW_FLOW 1
+#else
+#define HAS_SERIAL_HW_FLOW 0
+#endif
+
 /* ao_serial_stm.c */
 struct ao_stm_usart {
        struct ao_fifo          rx_fifo;
        struct ao_fifo          tx_fifo;
        struct stm_usart        *reg;
-       uint8_t                 tx_started;
+       uint8_t                 tx_running;
+       uint8_t                 draining;
+#if HAS_SERIAL_SW_FLOW
+       /* RTS - 0 if we have FIFO space, 1 if not
+        * CTS - 0 if we can send, 0 if not
+        */
+       struct stm_gpio         *gpio_rts;
+       struct stm_gpio         *gpio_cts;
+       uint8_t                 pin_rts;
+       uint8_t                 pin_cts;
+       uint8_t                 rts;
+#endif
 };
 
 #if HAS_SERIAL_1
@@ -359,6 +415,22 @@ static inline void ao_arch_restore_stack(void) {
 #define HAS_SAMPLE_PROFILE 0
 #endif
 
+#if DEBUG
+#define HAS_ARCH_VALIDATE_CUR_STACK    1
+
+static inline void
+ao_validate_cur_stack(void)
+{
+       uint8_t         *psp;
+
+       asm("mrs %0,psp" : "=&r" (psp));
+       if (ao_cur_task &&
+           psp <= ao_cur_task->stack &&
+           psp >= ao_cur_task->stack - 256)
+               ao_panic(AO_PANIC_STACK);
+}
+#endif
+
 #if !HAS_SAMPLE_PROFILE
 #define HAS_ARCH_START_SCHEDULER       1
 
diff --git a/src/stm/ao_fast_timer.h b/src/stm/ao_fast_timer.h
deleted file mode 100644 (file)
index 90fb393..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright © 2013 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef _AO_FAST_TIMER_H_
-#define _AO_FAST_TIMER_H_
-
-void
-ao_fast_timer_init(void);
-
-#ifndef AO_FAST_TIMER_MAX
-#define AO_FAST_TIMER_MAX      2
-#endif
-
-void
-ao_fast_timer_on(void (*callback)(void));
-
-void
-ao_fast_timer_off(void (*callback)(void));
-
-#endif /* _AO_FAST_TIMER_H_ */
index 88f2d0299ecf65f1b350dde44e0ede1d744c7c1f..bf07906016387c870213b0ae02316f0deb06b280 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include <ao.h>
+#include <ao_exti.h>
 
 void
 ao_debug_out(char c)
@@ -26,40 +27,80 @@ ao_debug_out(char c)
        stm_usart1.dr = c;
 }
 
-static void
+static int
 _ao_usart_tx_start(struct ao_stm_usart *usart)
 {
-       if (!ao_fifo_empty(usart->tx_fifo) && !usart->tx_started)
-       {
-               usart->tx_started = 1;
-               ao_fifo_remove(usart->tx_fifo, usart->reg->dr);
+       if (!ao_fifo_empty(usart->tx_fifo)) {
+#if HAS_SERIAL_SW_FLOW
+               if (usart->gpio_cts && ao_gpio_get(usart->gpio_cts, usart->pin_cts, foo) == 1) {
+                       ao_exti_enable(usart->gpio_cts, usart->pin_cts);
+                       return 0;
+               }
+#endif
+               if (usart->reg->sr & (1 << STM_USART_SR_TXE))
+               {
+                       usart->tx_running = 1;
+                       usart->reg->cr1 |= (1 << STM_USART_CR1_TXEIE) | (1 << STM_USART_CR1_TCIE);
+                       ao_fifo_remove(usart->tx_fifo, usart->reg->dr);
+                       ao_wakeup(&usart->tx_fifo);
+                       return 1;
+               }
        }
+       return 0;
 }
 
+#if HAS_SERIAL_SW_FLOW
 static void
-ao_usart_isr(struct ao_stm_usart *usart, int stdin)
+_ao_usart_cts(struct ao_stm_usart *usart)
 {
-       uint32_t        sr;
-
-       sr = usart->reg->sr;
-       usart->reg->sr = 0;
+       if (_ao_usart_tx_start(usart))
+               ao_exti_disable(usart->gpio_cts, usart->pin_cts);
+}
+#endif
 
-       if (sr & (1 << STM_USART_SR_RXNE)) {
-               char c = usart->reg->dr;
-               if (!ao_fifo_full(usart->rx_fifo))
-                       ao_fifo_insert(usart->rx_fifo, c);
-               ao_wakeup(&usart->rx_fifo);
-               if (stdin)
-                       ao_wakeup(&ao_stdin_ready);
+static void
+_ao_usart_rx(struct ao_stm_usart *usart, int stdin)
+{
+       if (usart->reg->sr & (1 << STM_USART_SR_RXNE)) {
+               if (!ao_fifo_full(usart->rx_fifo)) {
+                       ao_fifo_insert(usart->rx_fifo, usart->reg->dr);
+                       ao_wakeup(&usart->rx_fifo);
+                       if (stdin)
+                               ao_wakeup(&ao_stdin_ready);
+#if HAS_SERIAL_SW_FLOW
+                       /* If the fifo is nearly full, turn off RTS and wait
+                        * for it to drain a bunch
+                        */
+                       if (usart->gpio_rts && ao_fifo_mostly(usart->rx_fifo)) {
+                               ao_gpio_set(usart->gpio_rts, usart->pin_rts, usart->pin_rts, 1);
+                               usart->rts = 0;
+                       }
+#endif
+               } else {
+                       usart->reg->cr1 &= ~(1 << STM_USART_CR1_RXNEIE);
+               }
        }
-       if (sr & (1 << STM_USART_SR_TC)) {
-               usart->tx_started = 0;
-               _ao_usart_tx_start(usart);
-               ao_wakeup(&usart->tx_fifo);
+}
+
+static void
+ao_usart_isr(struct ao_stm_usart *usart, int stdin)
+{
+       _ao_usart_rx(usart, stdin);
+
+       if (!_ao_usart_tx_start(usart))
+               usart->reg->cr1 &= ~(1<< STM_USART_CR1_TXEIE);
+
+       if (usart->reg->sr & (1 << STM_USART_SR_TC)) {
+               usart->tx_running = 0;
+               usart->reg->cr1 &= ~(1 << STM_USART_CR1_TCIE);
+               if (usart->draining) {
+                       usart->draining = 0;
+                       ao_wakeup(&usart->tx_fifo);
+               }
        }
 }
 
-int
+static int
 _ao_usart_pollchar(struct ao_stm_usart *usart)
 {
        int     c;
@@ -69,12 +110,23 @@ _ao_usart_pollchar(struct ao_stm_usart *usart)
        else {
                uint8_t u;
                ao_fifo_remove(usart->rx_fifo,u);
+               if ((usart->reg->cr1 & (1 << STM_USART_CR1_RXNEIE)) == 0) {
+                       if (ao_fifo_barely(usart->rx_fifo))
+                               usart->reg->cr1 |= (1 << STM_USART_CR1_RXNEIE);
+               }
+#if HAS_SERIAL_SW_FLOW
+               /* If we've cleared RTS, check if there's space now and turn it back on */
+               if (usart->gpio_rts && usart->rts == 0 && ao_fifo_barely(usart->rx_fifo)) {
+                       ao_gpio_set(usart->gpio_rts, usart->pin_rts, foo, 0);
+                       usart->rts = 1;
+               }
+#endif
                c = u;
        }
        return c;
 }
 
-char
+static char
 ao_usart_getchar(struct ao_stm_usart *usart)
 {
        int c;
@@ -91,7 +143,7 @@ _ao_usart_sleep_for(struct ao_stm_usart *usart, uint16_t timeout)
        return ao_sleep_for(&usart->rx_fifo, timeout);
 }
 
-void
+static void
 ao_usart_putchar(struct ao_stm_usart *usart, char c)
 {
        ao_arch_block_interrupts();
@@ -102,12 +154,14 @@ ao_usart_putchar(struct ao_stm_usart *usart, char c)
        ao_arch_release_interrupts();
 }
 
-void
+static void
 ao_usart_drain(struct ao_stm_usart *usart)
 {
        ao_arch_block_interrupts();
-       while (!ao_fifo_empty(usart->tx_fifo))
+       while (!ao_fifo_empty(usart->tx_fifo) || usart->tx_running) {
+               usart->draining = 1;
                ao_sleep(&usart->tx_fifo);
+       }
        ao_arch_release_interrupts();
 }
 
@@ -131,7 +185,7 @@ static const struct {
        },
 };
 
-void
+static void
 ao_usart_set_speed(struct ao_stm_usart *usart, uint8_t speed)
 {
        if (speed > AO_SERIAL_SPEED_115200)
@@ -139,7 +193,7 @@ ao_usart_set_speed(struct ao_stm_usart *usart, uint8_t speed)
        usart->reg->brr = ao_usart_speeds[speed].brr;
 }
 
-void
+static void
 ao_usart_init(struct ao_stm_usart *usart)
 {
        usart->reg->cr1 = ((0 << STM_USART_CR1_OVER8) |
@@ -150,7 +204,7 @@ ao_usart_init(struct ao_stm_usart *usart)
                          (0 << STM_USART_CR1_PS) |
                          (0 << STM_USART_CR1_PEIE) |
                          (0 << STM_USART_CR1_TXEIE) |
-                         (1 << STM_USART_CR1_TCIE) |
+                         (0 << STM_USART_CR1_TCIE) |
                          (1 << STM_USART_CR1_RXNEIE) |
                          (0 << STM_USART_CR1_IDLEIE) |
                          (1 << STM_USART_CR1_TE) |
@@ -185,12 +239,14 @@ ao_usart_init(struct ao_stm_usart *usart)
        ao_usart_set_speed(usart, AO_SERIAL_SPEED_9600);
 }
 
-void
+#if HAS_SERIAL_HW_FLOW
+static void
 ao_usart_set_flow(struct ao_stm_usart *usart)
 {
        usart->reg->cr3 |= ((1 << STM_USART_CR3_CTSE) |
                            (1 << STM_USART_CR3_RTSE));
 }
+#endif
 
 #if HAS_SERIAL_1
 
@@ -231,6 +287,7 @@ ao_serial1_drain(void)
 void
 ao_serial1_set_speed(uint8_t speed)
 {
+       ao_usart_drain(&ao_stm_usart1);
        ao_usart_set_speed(&ao_stm_usart1, speed);
 }
 #endif /* HAS_SERIAL_1 */
@@ -274,15 +331,25 @@ ao_serial2_drain(void)
 void
 ao_serial2_set_speed(uint8_t speed)
 {
+       ao_usart_drain(&ao_stm_usart2);
        ao_usart_set_speed(&ao_stm_usart2, speed);
 }
+
+#if HAS_SERIAL_SW_FLOW
+void
+ao_serial2_cts(void)
+{
+       _ao_usart_cts(&ao_stm_usart2);
+}
+#endif
+
 #endif /* HAS_SERIAL_2 */
 
 #if HAS_SERIAL_3
 
 struct ao_stm_usart ao_stm_usart3;
 
-void stm_usart3_isr(void) { ao_usart_isr(&ao_stm_usart3, USE_SERIAL_2_STDIN); }
+void stm_usart3_isr(void) { ao_usart_isr(&ao_stm_usart3, USE_SERIAL_3_STDIN); }
 
 char
 ao_serial3_getchar(void)
@@ -311,10 +378,39 @@ _ao_serial3_sleep_for(uint16_t timeout)
 void
 ao_serial3_set_speed(uint8_t speed)
 {
+       ao_usart_drain(&ao_stm_usart3);
        ao_usart_set_speed(&ao_stm_usart3, speed);
 }
+
+void
+ao_serial3_drain(void)
+{
+       ao_usart_drain(&ao_stm_usart3);
+}
 #endif /* HAS_SERIAL_3 */
 
+#if HAS_SERIAL_SW_FLOW
+static void
+ao_serial_set_sw_rts_cts(struct ao_stm_usart *usart,
+                        void (*isr)(void),
+                        struct stm_gpio *port_rts,
+                        int pin_rts,
+                        struct stm_gpio *port_cts,
+                        int pin_cts)
+{
+       /* Pull RTS low to note that there's space in the FIFO
+        */
+       ao_enable_output(port_rts, pin_rts, foo, 0);
+       usart->gpio_rts = port_rts;
+       usart->pin_rts = pin_rts;
+       usart->rts = 1;
+
+       ao_exti_setup(port_cts, pin_cts, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED, isr);
+       usart->gpio_cts = port_cts;
+       usart->pin_cts = pin_cts;
+}
+#endif
+
 void
 ao_serial_init(void)
 {
@@ -367,10 +463,19 @@ ao_serial_init(void)
 
        stm_afr_set(&stm_gpioa, 2, STM_AFR_AF7);
        stm_afr_set(&stm_gpioa, 3, STM_AFR_AF7);
-#if USE_SERIAL_2_FLOW
+# if USE_SERIAL_2_FLOW
+#  if USE_SERIAL_2_SW_FLOW
+       ao_serial_set_sw_rts_cts(&ao_stm_usart2,
+                                ao_serial2_cts,
+                                SERIAL_2_PORT_RTS,
+                                SERIAL_2_PIN_RTS,
+                                SERIAL_2_PORT_CTS,
+                                SERIAL_2_PIN_CTS);
+#  else
        stm_afr_set(&stm_gpioa, 0, STM_AFR_AF7);
        stm_afr_set(&stm_gpioa, 1, STM_AFR_AF7);
-#endif
+#  endif
+# endif
 #else
 #if SERIAL_2_PD5_PD6
        stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN);
@@ -389,7 +494,7 @@ ao_serial_init(void)
 
        ao_stm_usart2.reg = &stm_usart2;
        ao_usart_init(&ao_stm_usart2);
-#if USE_SERIAL_2_FLOW
+#if USE_SERIAL_2_FLOW && !USE_SERIAL_2_SW_FLOW
        ao_usart_set_flow(&ao_stm_usart2);
 #endif
 
index 8db62e76a806b6ff51e49ecb3e23d0cc087aab72..91ede84bcc5ee7f4e015fb46b6188412c35b6746 100644 (file)
@@ -41,6 +41,7 @@ volatile __data uint8_t       ao_data_count;
 
 void stm_systick_isr(void)
 {
+       ao_validate_cur_stack();
        if (stm_systick.csr & (1 << STM_SYSTICK_CSR_COUNTFLAG)) {
                ++ao_tick_count;
 #if HAS_TASK_QUEUE
index 01afedc625bc0b66fe4c07798237903019e5f2a9..0b6b27983d6a3633d891be36bfdd0f0ecb3063fe 100644 (file)
@@ -166,6 +166,16 @@ stm_gpio_set(struct stm_gpio *gpio, int pin, uint8_t value) {
        gpio->bsrr = ((uint32_t) (value ^ 1) << (pin + 16)) | ((uint32_t) value << pin);
 }
 
+static inline void
+stm_gpio_set_bits(struct stm_gpio *gpio, uint16_t bits) {
+       gpio->bsrr = bits;
+}
+
+static inline void
+stm_gpio_clr_bits(struct stm_gpio *gpio, uint16_t bits) {
+       gpio->bsrr = ((uint32_t) bits) << 16;
+}
+
 static inline uint8_t
 stm_gpio_get(struct stm_gpio *gpio, int pin) {
        return (gpio->idr >> pin) & 1;
index 706b93eebaeb0e28372c2599c79175413887d8ca..29d6ae45b2eee46453e7444f91d6c5c6ad835a24 100644 (file)
@@ -39,17 +39,24 @@ LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stmf0 -Wl,-Taltos-loader.ld
 
 PROGNAME=altos-flash
 PROG=$(HARDWARE)-$(PROGNAME)-$(VERSION).elf
+BIN=$(HARDWARE)-$(PROGNAME)-$(VERSION).bin
+
+MAKEBIN=$(TOPDIR)/../ao-tools/ao-makebin/ao-makebin
+FLASH_ADDR=0x08000000
+
+all: $(PROG) $(BIN)
 
 $(PROG): Makefile $(OBJ) altos-loader.ld
        $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
 
+$(BIN): $(PROG)
+       $(MAKEBIN) --output=$@ --base=$(FLASH_ADDR) $(PROG)
+       
 ao_product.h: ao-make-product.5c $(TOPDIR)/Version
        $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
 
 $(OBJ): $(INC)
 
-all: $(PROG)
-
 distclean:     clean
 
 clean:
index 26e6691c914c87169d72905dbcdfe06ea393cca1..0a2e2c5c7b13f952ec5e20ede18132381862d2be 100644 (file)
@@ -72,7 +72,9 @@ _ao_adc_start(void)
                            (1 << STM_DMA_CCR_MINC) |
                            (0 << STM_DMA_CCR_PINC) |
                            (0 << STM_DMA_CCR_CIRC) |
-                           (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR));
+                           (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR) |
+                           (1 << STM_DMA_CCR_TCIE));
+
        ao_dma_set_isr(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1), ao_adc_dma_done);
        ao_dma_start(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1));
 
@@ -83,7 +85,6 @@ void
 ao_adc_init(void)
 {
        uint32_t        chselr;
-       int             i;
 
        /* Reset ADC */
        stm_rcc.apb2rstr |= (1 << STM_RCC_APB2RSTR_ADCRST);
@@ -157,12 +158,13 @@ ao_adc_init(void)
        /* Shortest sample time */
        stm_adc.smpr = STM_ADC_SMPR_SMP_1_5 << STM_ADC_SMPR_SMP;
 
+       /* Turn off enable and start */
+       stm_adc.cr &= ~((1 << STM_ADC_CR_ADEN) | (1 << STM_ADC_CR_ADSTART));
+
        /* Calibrate */
        stm_adc.cr |= (1 << STM_ADC_CR_ADCAL);
-       for (i = 0; i < 0xf000; i++) {
-               if ((stm_adc.cr & (1 << STM_ADC_CR_ADCAL)) == 0)
-                       break;
-       }
+       while ((stm_adc.cr & (1 << STM_ADC_CR_ADCAL)) != 0)
+               ;
 
        /* Enable */
        stm_adc.cr |= (1 << STM_ADC_CR_ADEN);
index 6ee71ef9caeec029f4cdd2042c62e817fc50ce0b..2597cadc735e8accb7285536d735386fa8069a76 100644 (file)
@@ -25,7 +25,9 @@
  * STM32F0 definitions and code fragments for AltOS
  */
 
+#ifndef AO_STACK_SIZE
 #define AO_STACK_SIZE  512
+#endif
 
 #define AO_LED_TYPE    uint16_t
 
@@ -115,6 +117,7 @@ extern const uint32_t ao_radio_cal;
 #define AO_PCLK1       (AO_HCLK / AO_APB1_PRESCALER)
 #define AO_PCLK2       (AO_HCLK / AO_APB2_PRESCALER)
 #define AO_SYSTICK     (AO_HCLK)
+#define AO_PANIC_DELAY_SCALE  (AO_SYSCLK / 12000000)
 
 #if AO_APB1_PRESCALER == 1
 #define AO_TIM23467_CLK                AO_PCLK1
@@ -128,10 +131,10 @@ extern const uint32_t ao_radio_cal;
 #define AO_TIM91011_CLK                (2 * AO_PCLK2)
 #endif
 
-#define AO_STM_NVIC_HIGH_PRIORITY      4
-#define AO_STM_NVIC_CLOCK_PRIORITY     6
-#define AO_STM_NVIC_MED_PRIORITY       8
-#define AO_STM_NVIC_LOW_PRIORITY       10
+#define AO_STM_NVIC_HIGH_PRIORITY      (0 << 6)
+#define AO_STM_NVIC_CLOCK_PRIORITY     (1 << 6)
+#define AO_STM_NVIC_MED_PRIORITY       (2 << 6)
+#define AO_STM_NVIC_LOW_PRIORITY       (3 << 6)
 
 void ao_lcd_stm_init(void);
 
index 3db96be238c1c63586fbe75916fbf60fe9f29d7b..ccfa3fc78d5dc4905a3e640d4058dbd11534bc7f 100644 (file)
 #ifndef _AO_ARCH_FUNCS_H_
 #define _AO_ARCH_FUNCS_H_
 
+#include <ao_power.h>
+
 /* ao_spi_stm.c
  */
 
-/* PCLK is set to 16MHz (HCLK 32MHz, APB prescaler 2) */
+/* PCLK is set to 48MHz (HCLK 48MHz, HPRE 1, PPRE 1) */
 
-#define AO_SPI_SPEED_8MHz      STM_SPI_CR1_BR_PCLK_2
-#define AO_SPI_SPEED_4MHz      STM_SPI_CR1_BR_PCLK_4
-#define AO_SPI_SPEED_2MHz      STM_SPI_CR1_BR_PCLK_8
-#define AO_SPI_SPEED_1MHz      STM_SPI_CR1_BR_PCLK_16
-#define AO_SPI_SPEED_500kHz    STM_SPI_CR1_BR_PCLK_32
-#define AO_SPI_SPEED_250kHz    STM_SPI_CR1_BR_PCLK_64
-#define AO_SPI_SPEED_125kHz    STM_SPI_CR1_BR_PCLK_128
-#define AO_SPI_SPEED_62500Hz   STM_SPI_CR1_BR_PCLK_256
+#define AO_SPI_SPEED_24MHz     STM_SPI_CR1_BR_PCLK_2
+#define AO_SPI_SPEED_12MHz     STM_SPI_CR1_BR_PCLK_4
+#define AO_SPI_SPEED_6MHz      STM_SPI_CR1_BR_PCLK_8
+#define AO_SPI_SPEED_3MHz      STM_SPI_CR1_BR_PCLK_16
+#define AO_SPI_SPEED_1500kHz   STM_SPI_CR1_BR_PCLK_32
+#define AO_SPI_SPEED_750kHz    STM_SPI_CR1_BR_PCLK_64
+#define AO_SPI_SPEED_375kHz    STM_SPI_CR1_BR_PCLK_128
+#define AO_SPI_SPEED_187500Hz  STM_SPI_CR1_BR_PCLK_256
 
-#define AO_SPI_SPEED_FAST      AO_SPI_SPEED_8MHz
+#define AO_SPI_SPEED_FAST      AO_SPI_SPEED_24MHz
 
 /* Companion bus wants something no faster than 200kHz */
 
-#define AO_SPI_SPEED_200kHz    AO_SPI_SPEED_125kHz
+#define AO_SPI_SPEED_200kHz    AO_SPI_SPEED_187500Hz
 
 #define AO_SPI_CONFIG_1                0x00
 #define AO_SPI_1_CONFIG_PA5_PA6_PA7    AO_SPI_CONFIG_1
@@ -118,27 +120,44 @@ ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t s
 #define ao_spi_get_bit(reg,bit,pin,bus,speed) ao_spi_get_mask(reg,(1<<bit),bus,speed)
 #define ao_spi_put_bit(reg,bit,pin,bus) ao_spi_put_mask(reg,(1<<bit),bus)
 
-#define ao_enable_port(port) do {                                      \
-               if ((port) == &stm_gpioa)                               \
-                       stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN); \
-               else if ((port) == &stm_gpiob)                          \
-                       stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN); \
-               else if ((port) == &stm_gpioc)                          \
-                       stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPCEN); \
-               else if ((port) == &stm_gpiof)                          \
-                       stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPFEN); \
-       } while (0)
+extern struct ao_power ao_power_gpioa;
+extern struct ao_power ao_power_gpiob;
+extern struct ao_power ao_power_gpioc;
+extern struct ao_power ao_power_gpiof;
 
-#define ao_disable_port(port) do {                                     \
-               if ((port) == &stm_gpioa)                               \
-                       stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPAEN); \
-               else if ((port) == &stm_gpiob)                          \
-                       stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPBEN); \
-               else if ((port) == &stm_gpioc)                          \
-                       stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPCEN); \
-               else if ((port) == &stm_gpiof)                          \
-                       stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPFEN); \
-       } while (0)
+static inline void ao_enable_port(struct stm_gpio *port)
+{
+       if ((port) == &stm_gpioa) {
+               stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN);
+               ao_power_register(&ao_power_gpioa);
+       } else if ((port) == &stm_gpiob) {
+               stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN);
+               ao_power_register(&ao_power_gpiob);
+       } else if ((port) == &stm_gpioc) {
+               stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPCEN);
+               ao_power_register(&ao_power_gpioc);
+       } else if ((port) == &stm_gpiof) {
+               stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPFEN);
+               ao_power_register(&ao_power_gpiof);
+       }
+}
+
+static inline void ao_disable_port(struct stm_gpio *port)
+{
+       if ((port) == &stm_gpioa) {
+               stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPAEN);
+               ao_power_unregister(&ao_power_gpioa);
+       } else if ((port) == &stm_gpiob) {
+               stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPBEN);
+               ao_power_unregister(&ao_power_gpiob);
+       } else if ((port) == &stm_gpioc) {
+               stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPCEN);
+               ao_power_unregister(&ao_power_gpioc);
+       } else if ((port) == &stm_gpiof) {
+               stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPFEN);
+               ao_power_unregister(&ao_power_gpiof);
+       }
+}
 
 #define ao_gpio_set(port, bit, pin, v) stm_gpio_set(port, bit, v)
 
@@ -166,8 +185,7 @@ ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t s
        } while (0)
 
 #define ao_enable_cs(port,bit) do {                            \
-               stm_gpio_set((port), bit, 1);                   \
-               stm_moder_set((port), bit, STM_MODER_OUTPUT);   \
+               ao_enable_output(port, bit, pin, 1);            \
        } while (0)
 
 #define ao_spi_init_cs(port, mask) do {                                \
@@ -395,6 +413,9 @@ ao_usb_free(uint16_t *buffer);
 
 void
 ao_usb_write(uint16_t *buffer, uint16_t len);
+
+void
+ao_usb_write2(uint16_t *buffer, uint16_t len);
 #endif /* AO_USB_DIRECTIO */
 
 #endif /* _AO_ARCH_FUNCS_H_ */
index 78fabe18558ea84d43c5ddfe23a3328b9070f766..e90c6bf838b11f4cca1e77df85560f7fe4c344e8 100644 (file)
@@ -28,9 +28,7 @@ static uint8_t ao_dma_allocated[STM_NUM_DMA];
 static uint8_t ao_dma_mutex[STM_NUM_DMA];
 static uint8_t ao_dma_active;
 
-#define id(ch)         STM_DMA_INDEX(ch)
-#define id_mask(id)    (STM_DMA_ISR_MASK << (id))
-#define ch_mask(ch)    id_mask(id(ch))
+#define ch_mask(id)    (STM_DMA_ISR_MASK << STM_DMA_ISR(id))
 
 static void
 ao_dma_isr(uint8_t low_index, uint8_t high_index, uint32_t mask) {
@@ -41,7 +39,7 @@ ao_dma_isr(uint8_t low_index, uint8_t high_index, uint32_t mask) {
        /* Ack them */
        stm_dma.ifcr = isr;
        for (index = low_index; index <= high_index; index++) {
-               if (isr & id_mask(index)) {
+               if (isr & ch_mask(index)) {
                        if (ao_dma_config[index].isr)
                                (*ao_dma_config[index].isr)(index);
                        else {
@@ -52,9 +50,25 @@ ao_dma_isr(uint8_t low_index, uint8_t high_index, uint32_t mask) {
        }
 }
 
-void stm_dma_ch1_isr(void) { ao_dma_isr(id(1), id(1), ch_mask(1)); }
-void stm_dma_ch2_3_isr(void) { ao_dma_isr(id(2), id(3), ch_mask(2) | ch_mask(3)); }
-void stm_dma1_ch4_5_6_isr(void) { ao_dma_isr(id(4), id(6), ch_mask(4) | ch_mask(5) | ch_mask(6)); }
+void stm_dma_ch1_isr(void) {
+       ao_dma_isr(STM_DMA_INDEX(1),
+                  STM_DMA_INDEX(1),
+                  ch_mask(STM_DMA_INDEX(1)));
+}
+
+void stm_dma_ch2_3_isr(void) {
+       ao_dma_isr(STM_DMA_INDEX(2),
+                  STM_DMA_INDEX(3),
+                  ch_mask(STM_DMA_INDEX(2)) |
+                  ch_mask(STM_DMA_INDEX(3)));
+}
+
+void stm_dma1_ch4_5_6_isr(void) {
+       ao_dma_isr(STM_DMA_INDEX(4), STM_DMA_INDEX(6),
+                  ch_mask(STM_DMA_INDEX(4)) |
+                  ch_mask(STM_DMA_INDEX(5)) |
+                  ch_mask(STM_DMA_INDEX(6)));
+}
 
 void
 ao_dma_set_transfer(uint8_t            index,
@@ -73,11 +87,12 @@ ao_dma_set_transfer(uint8_t                 index,
                if (ao_dma_active++ == 0)
                        stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMAEN);
                );
-       stm_dma.channel[index].ccr = ccr | (1 << STM_DMA_CCR_TCIE);
+       ao_dma_config[index].isr = NULL;
+       ao_dma_done[index] = 0;
        stm_dma.channel[index].cndtr = count;
        stm_dma.channel[index].cpar = peripheral;
        stm_dma.channel[index].cmar = memory;
-       ao_dma_config[index].isr = NULL;
+       stm_dma.channel[index].ccr = ccr;
 }
 
 void
@@ -89,7 +104,6 @@ ao_dma_set_isr(uint8_t index, void (*isr)(int))
 void
 ao_dma_start(uint8_t index)
 {
-       ao_dma_done[index] = 0;
        stm_dma.channel[index].ccr |= (1 << STM_DMA_CCR_EN);
 }
 
index ebea224d03d48934507e3673d5d049ba9bc2324e..192611bd501f01759dae1fefd8509b0a98675042 100644 (file)
@@ -28,7 +28,7 @@
 #define AO_EXTI_PIN_NOCONFIGURE        64
 
 void
-ao_exti_setup(struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)());
+ao_exti_setup(struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)(void));
 
 void
 ao_exti_set_mode(struct stm_gpio *gpio, uint8_t pin, uint8_t mode);
diff --git a/src/stmf0/ao_exti_stm.c b/src/stmf0/ao_exti_stm.c
new file mode 100644 (file)
index 0000000..910afcf
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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>
+
+static void    (*ao_exti_callback[16])(void);
+
+uint32_t       ao_last_exti;
+
+static void ao_exti_range_isr(uint8_t first, uint8_t last, uint16_t mask) {
+       uint16_t        pending = (ao_last_exti = stm_exti.pr) & mask;
+       uint8_t         pin;
+       static uint16_t last_mask;
+       static uint8_t  last_pin;
+
+       if (pending == last_mask) {
+               stm_exti.pr = last_mask;
+               (*ao_exti_callback[last_pin])();
+               return;
+       }
+       stm_exti.pr = pending;
+       for (pin = first; pin <= last; pin++)
+               if ((pending & ((uint32_t) 1 << pin)) && ao_exti_callback[pin]) {
+                       last_mask = (1 << pin);
+                       last_pin = pin;
+                       (*ao_exti_callback[pin])();
+               }
+}
+
+void stm_exti0_1_isr(void) { ao_exti_range_isr(0, 1, 0x0003); }
+void stm_exti2_3_isr(void) { ao_exti_range_isr(2, 3, 0x000c); }
+void stm_exti4_15_isr(void) { ao_exti_range_isr(4, 15, 0xfff0); }
+
+void
+ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)(void)) {
+       uint32_t        mask = 1 << pin;
+       uint32_t        pupdr;
+       uint8_t         irq;
+       uint8_t         prio;
+
+       ao_exti_callback[pin] = callback;
+
+       /* configure gpio to interrupt routing */
+       stm_exticr_set(gpio, pin);
+
+       if (!(mode & AO_EXTI_PIN_NOCONFIGURE)) {
+               /* configure pin as input, setting selected pull-up/down mode */
+               stm_moder_set(gpio, pin, STM_MODER_INPUT);
+               switch (mode & (AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_PULL_DOWN)) {
+               case 0:
+               default:
+                       pupdr  = STM_PUPDR_NONE;
+                       break;
+               case AO_EXTI_MODE_PULL_UP:
+                       pupdr = STM_PUPDR_PULL_UP;
+                       break;
+               case AO_EXTI_MODE_PULL_DOWN:
+                       pupdr = STM_PUPDR_PULL_DOWN;
+                       break;
+               }
+               stm_pupdr_set(gpio, pin, pupdr);
+       }
+
+       /* Set interrupt mask and rising/falling mode */
+       stm_exti.imr &= ~mask;
+       if (mode & AO_EXTI_MODE_RISING)
+               stm_exti.rtsr |= mask;
+       else
+               stm_exti.rtsr &= ~mask;
+       if (mode & AO_EXTI_MODE_FALLING)
+               stm_exti.ftsr |= mask;
+       else
+               stm_exti.ftsr &= ~mask;
+
+       if (pin <= 1)
+               irq = STM_ISR_EXTI0_1_POS;
+       else if (pin <= 3)
+               irq = STM_ISR_EXTI2_3_POS;
+       else
+               irq = STM_ISR_EXTI4_15_POS;
+
+       /* Set priority */
+       prio = AO_STM_NVIC_MED_PRIORITY;
+       if (mode & AO_EXTI_PRIORITY_LOW)
+               prio = AO_STM_NVIC_LOW_PRIORITY;
+       else if (mode & AO_EXTI_PRIORITY_HIGH)
+               prio = AO_STM_NVIC_HIGH_PRIORITY;
+
+       stm_nvic_set_priority(irq, prio);
+       stm_nvic_set_enable(irq);
+}
+
+void
+ao_exti_set_mode(struct stm_gpio *gpio, uint8_t pin, uint8_t mode) {
+       (void) gpio;
+
+       uint32_t        mask = 1 << pin;
+
+       if (mode & AO_EXTI_MODE_RISING)
+               stm_exti.rtsr |= mask;
+       else
+               stm_exti.rtsr &= ~mask;
+       if (mode & AO_EXTI_MODE_FALLING)
+               stm_exti.ftsr |= mask;
+       else
+               stm_exti.ftsr &= ~mask;
+}
+
+void
+ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)()) {
+       (void) gpio;
+       ao_exti_callback[pin] = callback;
+}
+
+void
+ao_exti_enable(struct stm_gpio *gpio, uint8_t pin) {
+       uint32_t        mask = (1 << pin);
+       (void) gpio;
+       stm_exti.pr = mask;
+       stm_exti.imr |= (1 << pin);
+}
+
+void
+ao_exti_disable(struct stm_gpio *gpio, uint8_t pin) {
+       uint32_t        mask = (1 << pin);
+       (void) gpio;
+       stm_exti.imr &= ~mask;
+       stm_exti.pr = mask;
+}
+
+void
+ao_exti_init(void)
+{
+}
diff --git a/src/stmf0/ao_gpio.c b/src/stmf0/ao_gpio.c
new file mode 100644 (file)
index 0000000..c7bf079
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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>
+
+static void
+ao_gpio_suspend(void *arg)
+{
+       struct stm_gpio *port = arg;
+       if (port == &stm_gpioa)
+               stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPAEN);
+       else if ((port) == &stm_gpiob)
+               stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPBEN);
+       else if ((port) == &stm_gpioc)
+               stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPCEN);
+       else if ((port) == &stm_gpiof)
+               stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPFEN);
+}
+
+static void
+ao_gpio_resume(void *arg)
+{
+       struct stm_gpio *port = arg;
+       if (port == &stm_gpioa)
+               stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN);
+       else if ((port) == &stm_gpiob)
+               stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN);
+       else if ((port) == &stm_gpioc)
+               stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPCEN);
+       else if ((port) == &stm_gpiof)
+               stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPFEN);
+}
+
+struct ao_power        ao_power_gpioa = {
+       .suspend = ao_gpio_suspend,
+       .resume = ao_gpio_resume,
+       .arg = &stm_gpioa
+};
+
+struct ao_power        ao_power_gpiob = {
+       .suspend = ao_gpio_suspend,
+       .resume = ao_gpio_resume,
+       .arg = &stm_gpiob
+};
+
+struct ao_power        ao_power_gpioc = {
+       .suspend = ao_gpio_suspend,
+       .resume = ao_gpio_resume,
+       .arg = &stm_gpioc
+};
+
+struct ao_power        ao_power_gpiof = {
+       .suspend = ao_gpio_suspend,
+       .resume = ao_gpio_resume,
+       .arg = &stm_gpiof
+};
+
diff --git a/src/stmf0/ao_pwm.c b/src/stmf0/ao_pwm.c
new file mode 100644 (file)
index 0000000..c1e157f
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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_pwm.h"
+
+static uint8_t pwm_running;
+
+static uint16_t        pwm_value[NUM_PWM];
+
+static void
+ao_pwm_up(void)
+{
+       if (pwm_running++ == 0) {
+               struct stm_tim23        *tim = AO_PWM_TIMER;
+
+               tim->ccr1 = 0;
+               tim->ccr2 = 0;
+               tim->ccr3 = 0;
+               tim->ccr4 = 0;
+               tim->arr = PWM_MAX - 1; /* turn on the timer */
+               tim->cr1 = ((STM_TIM23_CR1_CKD_1 << STM_TIM23_CR1_CKD) |
+                           (0 << STM_TIM23_CR1_ARPE) |
+                           (STM_TIM23_CR1_CMS_EDGE << STM_TIM23_CR1_CMS) |
+                           (STM_TIM23_CR1_DIR_UP << STM_TIM23_CR1_DIR) |
+                           (0 << STM_TIM23_CR1_OPM) |
+                           (0 << STM_TIM23_CR1_URS) |
+                           (0 << STM_TIM23_CR1_UDIS) |
+                           (1 << STM_TIM23_CR1_CEN));
+
+               /* Set the timer running */
+               tim->egr = (1 << STM_TIM23_EGR_UG);
+       }
+}
+
+static void
+ao_pwm_down(void)
+{
+       if (--pwm_running == 0) {
+               struct stm_tim23        *tim = AO_PWM_TIMER;
+
+               tim->arr = 0;
+               tim->cr1 = ((STM_TIM23_CR1_CKD_1 << STM_TIM23_CR1_CKD) |
+                           (0 << STM_TIM23_CR1_ARPE) |
+                           (STM_TIM23_CR1_CMS_EDGE << STM_TIM23_CR1_CMS) |
+                           (STM_TIM23_CR1_DIR_UP << STM_TIM23_CR1_DIR) |
+                           (0 << STM_TIM23_CR1_OPM) |
+                           (0 << STM_TIM23_CR1_URS) |
+                           (0 << STM_TIM23_CR1_UDIS) |
+                           (0 << STM_TIM23_CR1_CEN));
+
+               /* Stop the timer */
+               tim->egr = (1 << STM_TIM23_EGR_UG);
+       }
+}
+
+void
+ao_pwm_set(uint8_t pwm, uint16_t value)
+{
+       struct stm_tim23        *tim = AO_PWM_TIMER;
+       uint8_t                 ch = AO_PWM_0_CH;
+
+       if (value > PWM_MAX)
+               value = PWM_MAX;
+       if (value != 0) {
+               if (pwm_value[pwm] == 0)
+                       ao_pwm_up();
+       }
+#if NUM_PWM > 1
+       switch (pwm) {
+       case 0:
+               ch = AO_PWM_0_CH;
+               break;
+       case 1:
+               ch = AO_PWM_0_CH;
+               break;
+#if NUM_PWM > 2
+       case 2:
+               ch = AO_PWM_0_CH;
+               break;
+#endif
+#if NUM_PWM > 3
+       case 3:
+               ch = AO_PWM_0_CH;
+               break;
+#endif
+       }
+#endif
+
+       switch (ch) {
+       case 1:
+               tim->ccr1 = value;
+               break;
+       case 2:
+               tim->ccr2 = value;
+               break;
+       case 3:
+               tim->ccr3 = value;
+               break;
+       case 4:
+               tim->ccr4 = value;
+               break;
+       }
+       if (value == 0) {
+               if (pwm_value[pwm] != 0)
+                       ao_pwm_down();
+       }
+       pwm_value[pwm] = value;
+}
+
+static void
+ao_pwm_cmd(void)
+{
+       uint8_t ch;
+       uint16_t val;
+
+       ao_cmd_decimal();
+       ch = ao_cmd_lex_u32;
+       ao_cmd_decimal();
+       val = ao_cmd_lex_u32;
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+
+       printf("Set channel %d to %d\n", ch, val);
+       ao_pwm_set(ch, val);
+}
+
+static const struct ao_cmds ao_pwm_cmds[] = {
+       { ao_pwm_cmd,   "P <ch> <val>\0Set PWM ch to val" },
+       { 0, NULL },
+};
+
+void
+ao_pwm_init(void)
+{
+       struct stm_tim23        *tim = AO_PWM_TIMER;
+
+       stm_rcc.apb1enr |= (1 << AO_PWM_TIMER_ENABLE);
+
+       tim->cr1 = 0;
+       tim->psc = AO_PWM_TIMER_SCALE - 1;
+       tim->cnt = 0;
+       tim->ccer = ((1 << STM_TIM23_CCER_CC1E) |
+                    (0 << STM_TIM23_CCER_CC1P) |
+                    (1 << STM_TIM23_CCER_CC2E) |
+                    (0 << STM_TIM23_CCER_CC2P) |
+                    (1 << STM_TIM23_CCER_CC3E) |
+                    (0 << STM_TIM23_CCER_CC3P) |
+                    (1 << STM_TIM23_CCER_CC4E) |
+                    (0 << STM_TIM23_CCER_CC4P));
+
+       tim->ccmr1 = ((0 << STM_TIM23_CCMR1_OC2CE) |
+                     (STM_TIM23_CCMR1_OC2M_PWM_MODE_1 << STM_TIM23_CCMR1_OC2M) |
+                     (0 << STM_TIM23_CCMR1_OC2PE) |
+                     (0 << STM_TIM23_CCMR1_OC2FE) |
+                     (STM_TIM23_CCMR1_CC2S_OUTPUT << STM_TIM23_CCMR1_CC2S) |
+
+                     (0 << STM_TIM23_CCMR1_OC1CE) |
+                     (STM_TIM23_CCMR1_OC1M_PWM_MODE_1 << STM_TIM23_CCMR1_OC1M) |
+                     (0 << STM_TIM23_CCMR1_OC1PE) |
+                     (0 << STM_TIM23_CCMR1_OC1FE) |
+                     (STM_TIM23_CCMR1_CC1S_OUTPUT << STM_TIM23_CCMR1_CC1S));
+
+
+       tim->ccmr2 = ((0 << STM_TIM23_CCMR2_OC4CE) |
+                     (STM_TIM23_CCMR2_OC4M_PWM_MODE_1 << STM_TIM23_CCMR2_OC4M) |
+                     (0 << STM_TIM23_CCMR2_OC4PE) |
+                     (0 << STM_TIM23_CCMR2_OC4FE) |
+                     (STM_TIM23_CCMR2_CC4S_OUTPUT << STM_TIM23_CCMR2_CC4S) |
+
+                     (0 << STM_TIM23_CCMR2_OC3CE) |
+                     (STM_TIM23_CCMR2_OC3M_PWM_MODE_1 << STM_TIM23_CCMR2_OC3M) |
+                     (0 << STM_TIM23_CCMR2_OC3PE) |
+                     (0 << STM_TIM23_CCMR2_OC3FE) |
+                     (STM_TIM23_CCMR2_CC3S_OUTPUT << STM_TIM23_CCMR2_CC3S));
+       tim->egr = 0;
+
+       tim->sr = 0;
+       tim->dier = 0;
+       tim->smcr = 0;
+       tim->cr2 = ((0 << STM_TIM23_CR2_TI1S) |
+                   (STM_TIM23_CR2_MMS_RESET<< STM_TIM23_CR2_MMS) |
+                   (0 << STM_TIM23_CR2_CCDS));
+
+       stm_afr_set(AO_PWM_0_GPIO, AO_PWM_0_PIN, STM_AFR_AF1);
+       stm_ospeedr_set(AO_PWM_0_GPIO, AO_PWM_0_PIN, STM_OSPEEDR_MEDIUM);
+#if NUM_PWM > 1
+       stm_afr_set(AO_PWM_1_GPIO, AO_PWM_1_PIN, STM_AFR_AF1);
+       stm_ospeedr_set(AO_PWM_1_GPIO, AO_PWM_1_PIN, STM_OSPEEDR_MEDIUM);
+#endif
+#if NUM_PWM > 2
+       stm_afr_set(AO_PWM_2_GPIO, AO_PWM_2_PIN, STM_AFR_AF1);
+       stm_ospeedr_set(AO_PWM_2_GPIO, AO_PWM_2_PIN, STM_OSPEEDR_MEDIUM);
+#endif
+#if NUM_PWM > 3
+       stm_afr_set(AO_PWM_3_GPIO, AO_PWM_3_PIN, STM_AFR_AF1);
+       stm_ospeedr_set(AO_PWM_3_GPIO, AO_PWM_3_PIN, STM_OSPEEDR_MEDIUM);
+#endif
+       ao_cmd_register(&ao_pwm_cmds[0]);
+}
diff --git a/src/stmf0/ao_spi_stm.c b/src/stmf0/ao_spi_stm.c
new file mode 100644 (file)
index 0000000..55bf59d
--- /dev/null
@@ -0,0 +1,478 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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>
+
+struct ao_spi_stm_info {
+       uint8_t miso_dma_index;
+       uint8_t mosi_dma_index;
+       struct stm_spi *stm_spi;
+};
+
+static uint8_t         ao_spi_mutex[STM_NUM_SPI];
+static uint8_t         ao_spi_index[STM_NUM_SPI];
+
+static const struct ao_spi_stm_info ao_spi_stm_info[STM_NUM_SPI] = {
+       {
+               .miso_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI1_RX),
+               .mosi_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI1_TX),
+               &stm_spi1
+       },
+       {
+               .miso_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI2_RX),
+               .mosi_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI2_TX),
+               &stm_spi2
+       }
+};
+
+static uint8_t spi_dev_null;
+
+
+
+#define SPI_CR2        ((0 << STM_SPI_CR2_LDMA_TX) |                           \
+                (0 << STM_SPI_CR2_LDMA_RX) |                           \
+                (1 << STM_SPI_CR2_FRXTH) |                             \
+                (STM_SPI_CR2_DS_8 << STM_SPI_CR2_DS) |                 \
+                (0 << STM_SPI_CR2_TXEIE) |                             \
+                (0 << STM_SPI_CR2_RXNEIE) |                            \
+                (0 << STM_SPI_CR2_ERRIE) |                             \
+                (STM_SPI_CR2_FRF_MOTOROLA << STM_SPI_CR2_FRF) |        \
+                (0 << STM_SPI_CR2_NSSP) |                              \
+                (0 << STM_SPI_CR2_SSOE))
+
+#define SPI_CR2_DMA    (SPI_CR2 |                      \
+                        (1 << STM_SPI_CR2_TXDMAEN) |   \
+                        (1 << STM_SPI_CR2_RXDMAEN))
+
+#define SPI_CR2_SYNC   (SPI_CR2 |                      \
+                        (0 << STM_SPI_CR2_TXDMAEN) |   \
+                        (0 << STM_SPI_CR2_RXDMAEN))
+
+void
+ao_spi_send(const void *block, uint16_t len, uint8_t spi_index)
+{
+       struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
+       uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index;
+       uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index;
+
+       /* Set up the transmit DMA to deliver data */
+       ao_dma_set_transfer(mosi_dma_index,
+                           &stm_spi->dr,
+                           (void *) block,
+                           len,
+                           (0 << STM_DMA_CCR_MEM2MEM) |
+                           (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+                           (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+                           (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+                           (1 << STM_DMA_CCR_MINC) |
+                           (0 << STM_DMA_CCR_PINC) |
+                           (0 << STM_DMA_CCR_CIRC) |
+                           (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR) |
+                           (0 << STM_DMA_CCR_TCIE));
+
+       /* Clear RXNE */
+       (void) stm_spi->dr;
+
+       /* Set up the receive DMA -- when this is done, we know the SPI unit
+        * is idle. Without this, we'd have to poll waiting for the BSY bit to
+        * be cleared
+        */
+       ao_dma_set_transfer(miso_dma_index,
+                           &stm_spi->dr,
+                           &spi_dev_null,
+                           len,
+                           (0 << STM_DMA_CCR_MEM2MEM) |
+                           (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+                           (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+                           (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+                           (0 << STM_DMA_CCR_MINC) |
+                           (0 << STM_DMA_CCR_PINC) |
+                           (0 << STM_DMA_CCR_CIRC) |
+                           (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR) |
+                           (1 << STM_DMA_CCR_TCIE));
+
+       stm_spi->cr2 = SPI_CR2_DMA;
+
+       ao_dma_start(miso_dma_index);
+       ao_dma_start(mosi_dma_index);
+       ao_arch_critical(
+               while (!ao_dma_done[miso_dma_index])
+                       ao_sleep(&ao_dma_done[miso_dma_index]);
+               );
+       ao_dma_done_transfer(mosi_dma_index);
+       ao_dma_done_transfer(miso_dma_index);
+}
+
+void
+ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index)
+{
+       struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
+       uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index;
+       uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index;
+
+       /* Set up the transmit DMA to deliver data */
+       ao_dma_set_transfer(mosi_dma_index,
+                           &stm_spi->dr,
+                           &value,
+                           len,
+                           (0 << STM_DMA_CCR_MEM2MEM) |
+                           (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+                           (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+                           (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+                           (0 << STM_DMA_CCR_MINC) |
+                           (0 << STM_DMA_CCR_PINC) |
+                           (0 << STM_DMA_CCR_CIRC) |
+                           (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR) |
+                           (0 << STM_DMA_CCR_TCIE));
+
+       /* Clear RXNE */
+       (void) stm_spi->dr;
+
+       /* Set up the receive DMA -- when this is done, we know the SPI unit
+        * is idle. Without this, we'd have to poll waiting for the BSY bit to
+        * be cleared
+        */
+       ao_dma_set_transfer(miso_dma_index,
+                           &stm_spi->dr,
+                           &spi_dev_null,
+                           len,
+                           (0 << STM_DMA_CCR_MEM2MEM) |
+                           (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+                           (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+                           (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+                           (0 << STM_DMA_CCR_MINC) |
+                           (0 << STM_DMA_CCR_PINC) |
+                           (0 << STM_DMA_CCR_CIRC) |
+                           (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR) |
+                           (1 << STM_DMA_CCR_TCIE));
+
+       stm_spi->cr2 = SPI_CR2_DMA;
+       ao_dma_start(miso_dma_index);
+       ao_dma_start(mosi_dma_index);
+       ao_arch_critical(
+               while (!ao_dma_done[miso_dma_index])
+                       ao_sleep(&ao_dma_done[miso_dma_index]);
+               );
+       ao_dma_done_transfer(mosi_dma_index);
+       ao_dma_done_transfer(miso_dma_index);
+}
+
+void
+ao_spi_send_sync(void *block, uint16_t len, uint8_t spi_index)
+{
+       uint8_t         *b = block;
+       struct stm_spi  *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
+
+       stm_spi->cr2 = SPI_CR2_SYNC;
+
+       /* Clear RXNE */
+       (void) stm_spi->dr;
+
+       while (len--) {
+               while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE)));
+               stm_spi->dr = *b++;
+       }
+}
+
+void
+ao_spi_recv(void *block, uint16_t len, uint8_t spi_index)
+{
+       struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
+       uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index;
+       uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index;
+
+       spi_dev_null = 0xff;
+
+       /* Set up transmit DMA to make the SPI hardware actually run */
+       ao_dma_set_transfer(mosi_dma_index,
+                           &stm_spi->dr,
+                           &spi_dev_null,
+                           len,
+                           (0 << STM_DMA_CCR_MEM2MEM) |
+                           (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+                           (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+                           (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+                           (0 << STM_DMA_CCR_MINC) |
+                           (0 << STM_DMA_CCR_PINC) |
+                           (0 << STM_DMA_CCR_CIRC) |
+                           (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR) |
+                           (0 << STM_DMA_CCR_TCIE));
+
+       /* Clear RXNE */
+       (void) stm_spi->dr;
+
+       /* Set up the receive DMA to capture data */
+       ao_dma_set_transfer(miso_dma_index,
+                           &stm_spi->dr,
+                           block,
+                           len,
+                           (0 << STM_DMA_CCR_MEM2MEM) |
+                           (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+                           (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+                           (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+                           (1 << STM_DMA_CCR_MINC) |
+                           (0 << STM_DMA_CCR_PINC) |
+                           (0 << STM_DMA_CCR_CIRC) |
+                           (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR) |
+                           (1 << STM_DMA_CCR_TCIE));
+
+       stm_spi->cr2 = SPI_CR2_DMA;
+       ao_dma_start(miso_dma_index);
+       ao_dma_start(mosi_dma_index);
+
+       /* Wait until the SPI unit is done */
+       ao_arch_critical(
+               while (!ao_dma_done[miso_dma_index])
+                       ao_sleep(&ao_dma_done[miso_dma_index]);
+               );
+
+       ao_dma_done_transfer(mosi_dma_index);
+       ao_dma_done_transfer(miso_dma_index);
+}
+
+void
+ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index)
+{
+       struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
+       uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index;
+       uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index;
+
+       /* Set up transmit DMA to send data */
+       ao_dma_set_transfer(mosi_dma_index,
+                           &stm_spi->dr,
+                           out,
+                           len,
+                           (0 << STM_DMA_CCR_MEM2MEM) |
+                           (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+                           (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+                           (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+                           (1 << STM_DMA_CCR_MINC) |
+                           (0 << STM_DMA_CCR_PINC) |
+                           (0 << STM_DMA_CCR_CIRC) |
+                           (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR) |
+                           (0 << STM_DMA_CCR_TCIE));
+
+       /* Clear RXNE */
+       (void) stm_spi->dr;
+
+       /* Set up the receive DMA to capture data */
+       ao_dma_set_transfer(miso_dma_index,
+                           &stm_spi->dr,
+                           in,
+                           len,
+                           (0 << STM_DMA_CCR_MEM2MEM) |
+                           (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+                           (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+                           (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+                           (1 << STM_DMA_CCR_MINC) |
+                           (0 << STM_DMA_CCR_PINC) |
+                           (0 << STM_DMA_CCR_CIRC) |
+                           (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR) |
+                           (1 << STM_DMA_CCR_TCIE));
+
+       stm_spi->cr2 = SPI_CR2_DMA;
+       ao_dma_start(miso_dma_index);
+       ao_dma_start(mosi_dma_index);
+
+       /* Wait until the SPI unit is done */
+       ao_arch_critical(
+               while (!ao_dma_done[miso_dma_index])
+                       ao_sleep(&ao_dma_done[miso_dma_index]);
+               );
+
+       ao_dma_done_transfer(mosi_dma_index);
+       ao_dma_done_transfer(miso_dma_index);
+}
+
+static void
+ao_spi_disable_index(uint8_t spi_index)
+{
+       /* Disable current config
+        */
+       switch (AO_SPI_INDEX(spi_index)) {
+       case STM_SPI_INDEX(1):
+               switch (spi_index) {
+               case AO_SPI_1_PA5_PA6_PA7:
+                       stm_gpio_set(&stm_gpioa, 5, 1);
+                       stm_moder_set(&stm_gpioa, 5, STM_MODER_OUTPUT);
+                       stm_moder_set(&stm_gpioa, 6, STM_MODER_INPUT);
+                       stm_moder_set(&stm_gpioa, 7, STM_MODER_OUTPUT);
+                       break;
+               case AO_SPI_1_PB3_PB4_PB5:
+                       stm_gpio_set(&stm_gpiob, 3, 1);
+                       stm_moder_set(&stm_gpiob, 3, STM_MODER_OUTPUT);
+                       stm_moder_set(&stm_gpiob, 4, STM_MODER_INPUT);
+                       stm_moder_set(&stm_gpiob, 5, STM_MODER_OUTPUT);
+                       break;
+               }
+               break;
+       case STM_SPI_INDEX(2):
+               switch (spi_index) {
+               case AO_SPI_2_PB13_PB14_PB15:
+                       stm_gpio_set(&stm_gpiob, 13, 1);
+                       stm_moder_set(&stm_gpiob, 13, STM_MODER_OUTPUT);
+                       stm_moder_set(&stm_gpiob, 14, STM_MODER_INPUT);
+                       stm_moder_set(&stm_gpiob, 15, STM_MODER_OUTPUT);
+                       break;
+               }
+               break;
+       }
+}
+
+static void
+ao_spi_enable_index(uint8_t spi_index)
+{
+       switch (AO_SPI_INDEX(spi_index)) {
+       case STM_SPI_INDEX(1):
+               switch (spi_index) {
+               case AO_SPI_1_PA5_PA6_PA7:
+                       stm_afr_set(&stm_gpioa, 5, STM_AFR_AF0);
+                       stm_afr_set(&stm_gpioa, 6, STM_AFR_AF0);
+                       stm_afr_set(&stm_gpioa, 7, STM_AFR_AF0);
+                       break;
+               case AO_SPI_1_PB3_PB4_PB5:
+                       stm_afr_set(&stm_gpiob, 3, STM_AFR_AF0);
+                       stm_afr_set(&stm_gpiob, 4, STM_AFR_AF0);
+                       stm_afr_set(&stm_gpiob, 5, STM_AFR_AF0);
+                       break;
+               }
+               break;
+       case STM_SPI_INDEX(2):
+               switch (spi_index) {
+               case AO_SPI_2_PB13_PB14_PB15:
+                       stm_afr_set(&stm_gpiob, 13, STM_AFR_AF0);
+                       stm_afr_set(&stm_gpiob, 14, STM_AFR_AF0);
+                       stm_afr_set(&stm_gpiob, 15, STM_AFR_AF0);
+                       break;
+               }
+               break;
+       }
+}
+
+static void
+ao_spi_config(uint8_t spi_index, uint32_t speed)
+{
+       uint8_t         id = AO_SPI_INDEX(spi_index);
+       struct stm_spi  *stm_spi = ao_spi_stm_info[id].stm_spi;
+
+       stm_spi->cr2 = SPI_CR2;
+       stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) |                   /* Three wire mode */
+                       (0 << STM_SPI_CR1_BIDIOE) |
+                       (0 << STM_SPI_CR1_CRCEN) |                      /* CRC disabled */
+                       (0 << STM_SPI_CR1_CRCNEXT) |
+                       (0 << STM_SPI_CR1_CRCL) |
+                       (0 << STM_SPI_CR1_RXONLY) |
+                       (1 << STM_SPI_CR1_SSM) |                        /* Software SS handling */
+                       (1 << STM_SPI_CR1_SSI) |                        /*  ... */
+                       (0 << STM_SPI_CR1_LSBFIRST) |                   /* Big endian */
+                       (1 << STM_SPI_CR1_SPE) |                        /* Enable SPI unit */
+                       (speed << STM_SPI_CR1_BR) |                     /* baud rate to pclk/4 */
+                       (1 << STM_SPI_CR1_MSTR) |
+                       (0 << STM_SPI_CR1_CPOL) |                       /* Format 0 */
+                       (0 << STM_SPI_CR1_CPHA));
+
+       if (spi_index != ao_spi_index[id]) {
+
+               /* Disable old config
+                */
+               ao_spi_disable_index(ao_spi_index[id]);
+
+               /* Enable new config
+                */
+               ao_spi_enable_index(spi_index);
+
+               /* Remember current config
+                */
+               ao_spi_index[id] = spi_index;
+       }
+}
+
+uint8_t
+ao_spi_try_get(uint8_t spi_index, uint32_t speed, uint8_t task_id)
+{
+       uint8_t         id = AO_SPI_INDEX(spi_index);
+
+       if (!ao_mutex_try(&ao_spi_mutex[id], task_id))
+               return 0;
+       ao_spi_config(spi_index, speed);
+       return 1;
+}
+
+void
+ao_spi_get(uint8_t spi_index, uint32_t speed)
+{
+       uint8_t         id = AO_SPI_INDEX(spi_index);
+       ao_mutex_get(&ao_spi_mutex[id]);
+       ao_spi_config(spi_index, speed);
+}
+
+void
+ao_spi_put(uint8_t spi_index)
+{
+       uint8_t         id = AO_SPI_INDEX(spi_index);
+       struct stm_spi  *stm_spi = ao_spi_stm_info[id].stm_spi;
+
+       stm_spi->cr1 = 0;
+       ao_mutex_put(&ao_spi_mutex[id]);
+}
+
+static void
+ao_spi_channel_init(uint8_t spi_index)
+{
+       uint8_t         id = AO_SPI_INDEX(spi_index);
+       struct stm_spi  *stm_spi = ao_spi_stm_info[id].stm_spi;
+
+       ao_spi_disable_index(spi_index);
+
+       stm_spi->cr1 = 0;
+       (void) stm_spi->sr;
+       stm_spi->cr2 = SPI_CR2_SYNC;
+}
+
+void
+ao_spi_init(void)
+{
+#if HAS_SPI_1
+# if SPI_1_PA5_PA6_PA7
+       stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN);
+       stm_ospeedr_set(&stm_gpioa, 5, SPI_1_OSPEEDR);
+       stm_ospeedr_set(&stm_gpioa, 6, SPI_1_OSPEEDR);
+       stm_ospeedr_set(&stm_gpioa, 7, SPI_1_OSPEEDR);
+# endif
+# if SPI_1_PB3_PB4_PB5
+       stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN);
+       stm_ospeedr_set(&stm_gpiob, 3, SPI_1_OSPEEDR);
+       stm_ospeedr_set(&stm_gpiob, 4, SPI_1_OSPEEDR);
+       stm_ospeedr_set(&stm_gpiob, 5, SPI_1_OSPEEDR);
+# endif
+       stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SPI1EN);
+       ao_spi_index[0] = AO_SPI_CONFIG_NONE;
+       ao_spi_channel_init(STM_SPI_INDEX(1));
+#endif
+
+#if HAS_SPI_2
+# if SPI_2_PB10_PB13_PB14
+       stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN);
+       stm_ospeedr_set(&stm_gpiob, 13, SPI_2_OSPEEDR);
+       stm_ospeedr_set(&stm_gpiob, 14, SPI_2_OSPEEDR);
+       stm_ospeedr_set(&stm_gpiob, 15, SPI_2_OSPEEDR);
+# endif
+       stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_SPI2EN);
+       ao_spi_index[1] = AO_SPI_CONFIG_NONE;
+       ao_spi_channel_init(STM_SPI_INDEX(2));
+#endif
+}
index 3aae7e550ba8168babb23668f9da7d6bcdfb012d..e5bf04a3ccb8eecfe56593ad446b177d57fb2af6 100644 (file)
@@ -50,12 +50,14 @@ void stm_systick_isr(void)
 #if AO_DATA_ALL
                if (++ao_data_count == ao_data_interval) {
                        ao_data_count = 0;
+#if HAS_ADC
 #if HAS_FAKE_FLIGHT
                        if (ao_fake_flight_active)
                                ao_fake_flight_poll();
                        else
 #endif
                                ao_adc_poll();
+#endif
 #if (AO_DATA_ALL & ~(AO_DATA_ADC))
                        ao_wakeup((void *) &ao_data_count);
 #endif
@@ -92,6 +94,7 @@ ao_timer_init(void)
 
 #endif
 
+#if AO_HSI48
 static void
 ao_clock_enable_crs(void)
 {
@@ -127,15 +130,12 @@ ao_clock_enable_crs(void)
                      (0 << STM_CRS_CR_ERRIE) |
                      (0 << STM_CRS_CR_SYNCWARNIE) |
                      (0 << STM_CRS_CR_SYNCOKIE));
-
 }
+#endif
 
-void
-ao_clock_init(void)
+static void
+ao_clock_hsi(void)
 {
-       uint32_t        cfgr;
-
-       /* Switch to HSI while messing about */
        stm_rcc.cr |= (1 << STM_RCC_CR_HSION);
        while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY)))
                ao_arch_nop();
@@ -153,15 +153,17 @@ ao_clock_init(void)
 
        /* reset PLLON, CSSON, HSEBYP, HSEON */
        stm_rcc.cr &= 0x0000ffff;
+}
 
-       /* Disable all interrupts */
-       stm_rcc.cir = 0;
-
+static void
+ao_clock_normal_start(void)
+{
 #if AO_HSE
-#define STM_RCC_CFGR_SWS_TARGET_CLOCK          STM_RCC_CFGR_SWS_HSE
-#define STM_RCC_CFGR_SW_TARGET_CLOCK           STM_RCC_CFGR_SW_HSE
+       uint32_t        cfgr;
+#define STM_RCC_CFGR_SWS_TARGET_CLOCK          STM_RCC_CFGR_SWS_PLL
+#define STM_RCC_CFGR_SW_TARGET_CLOCK           STM_RCC_CFGR_SW_PLL
 #define STM_PLLSRC                             AO_HSE
-#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK       1
+#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK       STM_RCC_CFGR_PLLSRC_HSE
 
 #if AO_HSE_BYPASS
        stm_rcc.cr |= (1 << STM_RCC_CR_HSEBYP);
@@ -172,6 +174,33 @@ ao_clock_init(void)
        stm_rcc.cr |= (1 << STM_RCC_CR_HSEON);
        while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSERDY)))
                asm("nop");
+
+#ifdef STM_PLLSRC
+       /* Disable the PLL */
+       stm_rcc.cr &= ~(1 << STM_RCC_CR_PLLON);
+       while (stm_rcc.cr & (1 << STM_RCC_CR_PLLRDY))
+               asm("nop");
+
+       /* PLLVCO to 48MHz (for USB) -> PLLMUL = 3 */
+       cfgr = stm_rcc.cfgr;
+       cfgr &= ~(STM_RCC_CFGR_PLLMUL_MASK << STM_RCC_CFGR_PLLMUL);
+       cfgr |= (AO_RCC_CFGR_PLLMUL << STM_RCC_CFGR_PLLMUL);
+
+       /* PLL source */
+       cfgr &= ~(1 << STM_RCC_CFGR_PLLSRC);
+       cfgr |= (STM_RCC_CFGR_PLLSRC_TARGET_CLOCK  << STM_RCC_CFGR_PLLSRC);
+       stm_rcc.cfgr = cfgr;
+
+       /* Disable pre divider */
+       stm_rcc.cfgr2 = (STM_RCC_CFGR2_PREDIV_1 << STM_RCC_CFGR2_PREDIV);
+
+       /* Enable the PLL and wait for it */
+       stm_rcc.cr |= (1 << STM_RCC_CR_PLLON);
+       while (!(stm_rcc.cr & (1 << STM_RCC_CR_PLLRDY)))
+               asm("nop");
+
+#endif
+
 #endif
 
 
@@ -196,10 +225,50 @@ ao_clock_init(void)
 #define STM_PLLSRC                             STM_HSI
 #define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK       0
 #endif
+}
+
+static void
+ao_clock_normal_switch(void)
+{
+       uint32_t        cfgr;
 
+       cfgr = stm_rcc.cfgr;
+       cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW);
+       cfgr |= (STM_RCC_CFGR_SW_TARGET_CLOCK << STM_RCC_CFGR_SW);
+       stm_rcc.cfgr = cfgr;
+       for (;;) {
+               uint32_t        c, part, mask, val;
+
+               c = stm_rcc.cfgr;
+               mask = (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS);
+               val = (STM_RCC_CFGR_SWS_TARGET_CLOCK << STM_RCC_CFGR_SWS);
+               part = c & mask;
+               if (part == val)
+                       break;
+       }
+#if !AO_HSI && !AO_NEED_HSI
+       /* Turn off the HSI clock */
+       stm_rcc.cr &= ~(1 << STM_RCC_CR_HSION);
+#endif
 #ifdef STM_PLLSRC
-#error No code for PLL initialization yet
+       /* USB PLL source */
+       stm_rcc.cfgr3 |= (1 << STM_RCC_CFGR3_USBSW);
 #endif
+}
+
+void
+ao_clock_init(void)
+{
+       uint32_t        cfgr;
+
+       /* Switch to HSI while messing about */
+       ao_clock_hsi();
+
+       /* Disable all interrupts */
+       stm_rcc.cir = 0;
+
+       /* Start high speed clock */
+       ao_clock_normal_start();
 
        /* Set flash latency to tolerate 48MHz SYSCLK  -> 1 wait state */
 
@@ -228,29 +297,11 @@ ao_clock_init(void)
        stm_rcc.cfgr = cfgr;
 
        /* Switch to the desired system clock */
-
-       cfgr = stm_rcc.cfgr;
-       cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW);
-       cfgr |= (STM_RCC_CFGR_SW_TARGET_CLOCK << STM_RCC_CFGR_SW);
-       stm_rcc.cfgr = cfgr;
-       for (;;) {
-               uint32_t        c, part, mask, val;
-
-               c = stm_rcc.cfgr;
-               mask = (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS);
-               val = (STM_RCC_CFGR_SWS_TARGET_CLOCK << STM_RCC_CFGR_SWS);
-               part = c & mask;
-               if (part == val)
-                       break;
-       }
+       ao_clock_normal_switch();
 
        /* Clear reset flags */
        stm_rcc.csr |= (1 << STM_RCC_CSR_RMVF);
 
-#if !AO_HSI && !AO_NEED_HSI
-       /* Turn off the HSI clock */
-       stm_rcc.cr &= ~(1 << STM_RCC_CR_HSION);
-#endif
 #if DEBUG_THE_CLOCK
        /* Output SYSCLK on PA8 for measurments */
 
@@ -264,3 +315,18 @@ ao_clock_init(void)
        stm_rcc.cfgr |= (STM_RCC_CFGR_MCOSEL_HSE << STM_RCC_CFGR_MCOSEL);
 #endif
 }
+
+#if AO_POWER_MANAGEMENT
+void
+ao_clock_suspend(void)
+{
+       ao_clock_hsi();
+}
+
+void
+ao_clock_resume(void)
+{
+       ao_clock_normal_start();
+       ao_clock_normal_switch();
+}
+#endif
index b8146c216f1a2b0538e964dd8bc24862895d984c..253506d59800623a5884e3f90f8814a2a19f71e4 100644 (file)
 #include "ao.h"
 #include "ao_usb.h"
 #include "ao_product.h"
+#include "ao_power.h"
 
 #define USB_DEBUG      0
+#define USB_STATUS     0
 #define USB_DEBUG_DATA 0
 #define USB_ECHO       0
 
 #error "must define AO_PA11_PA12_RMP"
 #endif
 
+#ifndef AO_POWER_MANAGEMENT
+#define AO_POWER_MANAGEMENT    0
+#endif
+
 #ifndef USE_USB_STDIO
 #define USE_USB_STDIO  1
 #endif
@@ -83,23 +89,42 @@ static uint16_t     ao_usb_sram_addr;
 static uint16_t        *ao_usb_ep0_tx_buffer;
 static uint16_t        *ao_usb_ep0_rx_buffer;
 
+#if AO_USB_HAS_INT
 /* Pointer to interrupt buffer in USB memory */
 static uint16_t ao_usb_int_tx_offset;
+#endif
 
 /* Pointer to bulk data tx/rx buffers in USB memory */
+#if AO_USB_HAS_IN
 static uint16_t ao_usb_in_tx_offset;
 static uint16_t        *ao_usb_in_tx_buffer;
-static uint16_t ao_usb_out_rx_offset;
-static uint16_t        *ao_usb_out_rx_buffer;
 
 /* System ram shadow of USB buffer; writing individual bytes is
  * too much of a pain (sigh) */
 static uint8_t ao_usb_tx_buffer[AO_USB_IN_SIZE];
 static uint8_t ao_usb_tx_count;
 
+#endif
+#if AO_USB_HAS_OUT
+static uint16_t ao_usb_out_rx_offset;
+static uint16_t        *ao_usb_out_rx_buffer;
+
+/* System ram shadow of USB buffer; writing individual bytes is
+ * too much of a pain (sigh) */
 static uint8_t ao_usb_rx_buffer[AO_USB_OUT_SIZE];
 static uint8_t ao_usb_rx_count, ao_usb_rx_pos;
 
+#endif
+#if AO_USB_HAS_IN2
+static uint16_t ao_usb_in2_tx_offset;
+static uint16_t *ao_usb_in2_tx_buffer;
+
+/* System ram shadow of USB buffer; writing individual bytes is
+ * too much of a pain (sigh) */
+static uint8_t ao_usb_tx2_buffer[AO_USB_IN_SIZE];
+static uint8_t ao_usb_tx2_count;
+#endif
+
 /*
  * End point register indices
  */
@@ -108,6 +133,7 @@ static uint8_t      ao_usb_rx_count, ao_usb_rx_pos;
 #define AO_USB_INT_EPR         1
 #define AO_USB_OUT_EPR         2
 #define AO_USB_IN_EPR          3
+#define AO_USB_IN2_EPR         4
 
 /* Marks when we don't need to send an IN packet.
  * This happens only when the last IN packet is not full,
@@ -122,6 +148,16 @@ static uint8_t     ao_usb_in_flushed;
  */
 static uint8_t ao_usb_in_pending;
 
+#if AO_USB_HAS_IN2
+/* Marks when we have delivered an IN packet to the hardware
+ * and it has not been received yet. ao_sleep on this address
+ * to wait for it to be delivered.
+ */
+static uint8_t ao_usb_in2_pending;
+static uint16_t        in2_count;
+static uint8_t ao_usb_in2_flushed;
+#endif
+
 /* Marks when an OUT packet has been received by the hardware
  * but not pulled to the shadow buffer.
  */
@@ -129,10 +165,9 @@ static uint8_t     ao_usb_out_avail;
 uint8_t                ao_usb_running;
 static uint8_t ao_usb_configuration;
 
-#define AO_USB_EP0_GOT_RESET   1
-#define AO_USB_EP0_GOT_SETUP   2
-#define AO_USB_EP0_GOT_RX_DATA 4
-#define AO_USB_EP0_GOT_TX_ACK  8
+#define AO_USB_EP0_GOT_SETUP   1
+#define AO_USB_EP0_GOT_RX_DATA 2
+#define AO_USB_EP0_GOT_TX_ACK  4
 
 static uint8_t ao_usb_ep0_receive;
 static uint8_t ao_usb_address;
@@ -338,16 +373,29 @@ ao_usb_alloc_buffers(void)
        ao_usb_ep0_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr);
        ao_usb_sram_addr += AO_USB_CONTROL_SIZE;
 
+
+#if AO_USB_HAS_INT
        ao_usb_int_tx_offset = ao_usb_sram_addr;
        ao_usb_sram_addr += AO_USB_INT_SIZE;
+#endif
 
+#if AO_USB_HAS_OUT
        ao_usb_out_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr);
        ao_usb_out_rx_offset = ao_usb_sram_addr;
        ao_usb_sram_addr += AO_USB_OUT_SIZE;
+#endif
 
+#if AO_USB_HAS_IN
        ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr);
        ao_usb_in_tx_offset = ao_usb_sram_addr;
        ao_usb_sram_addr += AO_USB_IN_SIZE;
+#endif
+
+#if AO_USB_HAS_IN2
+       ao_usb_in2_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr);
+       ao_usb_in2_tx_offset = ao_usb_sram_addr;
+       ao_usb_sram_addr += AO_USB_IN_SIZE;
+#endif
 }
 
 static void
@@ -396,6 +444,7 @@ ao_usb_set_configuration(void)
 {
        debug ("ao_usb_set_configuration\n");
 
+#if AO_USB_HAS_INT
        /* Set up the INT end point */
        ao_usb_bdt[AO_USB_INT_EPR].single.addr_tx = ao_usb_int_tx_offset;
        ao_usb_bdt[AO_USB_INT_EPR].single.count_tx = 0;
@@ -405,7 +454,9 @@ ao_usb_set_configuration(void)
                       STM_USB_EPR_EP_TYPE_INTERRUPT,
                       STM_USB_EPR_STAT_RX_DISABLED,
                       STM_USB_EPR_STAT_TX_NAK);
+#endif
 
+#if AO_USB_HAS_OUT
        /* Set up the OUT end point */
        ao_usb_bdt[AO_USB_OUT_EPR].single.addr_rx = ao_usb_out_rx_offset;
        ao_usb_bdt[AO_USB_OUT_EPR].single.count_rx = ((1 << STM_USB_BDT_COUNT_RX_BL_SIZE) |
@@ -416,7 +467,9 @@ ao_usb_set_configuration(void)
                       STM_USB_EPR_EP_TYPE_BULK,
                       STM_USB_EPR_STAT_RX_VALID,
                       STM_USB_EPR_STAT_TX_DISABLED);
+#endif
 
+#if AO_USB_HAS_IN
        /* Set up the IN end point */
        ao_usb_bdt[AO_USB_IN_EPR].single.addr_tx = ao_usb_in_tx_offset;
        ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = 0;
@@ -426,6 +479,19 @@ ao_usb_set_configuration(void)
                       STM_USB_EPR_EP_TYPE_BULK,
                       STM_USB_EPR_STAT_RX_DISABLED,
                       STM_USB_EPR_STAT_TX_NAK);
+#endif
+
+#if AO_USB_HAS_IN2
+       /* Set up the IN2 end point */
+       ao_usb_bdt[AO_USB_IN2_EPR].single.addr_tx = ao_usb_in2_tx_offset;
+       ao_usb_bdt[AO_USB_IN2_EPR].single.count_tx = 0;
+
+       ao_usb_init_ep(AO_USB_IN2_EPR,
+                      AO_USB_IN2_EP,
+                      STM_USB_EPR_EP_TYPE_BULK,
+                      STM_USB_EPR_STAT_RX_DISABLED,
+                      STM_USB_EPR_STAT_TX_NAK);
+#endif
 
        ao_usb_running = 1;
 #if AO_USB_DIRECTIO
@@ -559,6 +625,36 @@ ao_usb_ep0_in_start(uint16_t max)
 
 static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8};
 
+#if AO_USB_DEVICE_ID_SERIAL
+static uint8_t ao_usb_serial[2 + 48];
+
+/* Convert a 32-bit value to 8 hexidecimal UCS2 characters */
+static void
+hex_to_ucs2(uint32_t in, uint8_t *out)
+{
+       int     i;
+
+       for (i = 28; i >= 0; i -= 4) {
+               uint8_t bits = (in >> i) & 0xf;
+               *out++ = ((bits < 10) ? '0' : ('a' - 10)) + bits;
+               *out++ = 0;
+       }
+}
+
+/* Encode the device ID (96 bits) in hexidecimal to use as a device
+ * serial number
+ */
+static void
+ao_usb_serial_init(void)
+{
+       ao_usb_serial[0] = 50;  /* length */
+       ao_usb_serial[1] = AO_USB_DESC_STRING;
+       hex_to_ucs2(stm_device_id.u_id0, ao_usb_serial + 2 + 0);
+       hex_to_ucs2(stm_device_id.u_id1, ao_usb_serial + 2 + 16);
+       hex_to_ucs2(stm_device_id.u_id2, ao_usb_serial + 2 + 32);
+}
+#endif
+
 /* Walk through the list of descriptors and find a match
  */
 static void
@@ -576,6 +672,13 @@ ao_usb_get_descriptor(uint16_t value)
                                len = descriptor[2];
                        else
                                len = descriptor[0];
+#if AO_USB_DEVICE_ID_SERIAL
+                       /* Slightly hacky - the serial number is string 3 */
+                       if (type == AO_USB_DESC_STRING && (value & 0xff) == 3) {
+                               descriptor = ao_usb_serial;
+                               len = sizeof (ao_usb_serial);
+                       }
+#endif
                        ao_usb_ep0_in_set(descriptor, len);
                        break;
                }
@@ -686,11 +789,6 @@ static void
 ao_usb_ep0_handle(uint8_t receive)
 {
        ao_usb_ep0_receive = 0;
-       if (receive & AO_USB_EP0_GOT_RESET) {
-               debug ("\treset\n");
-               ao_usb_set_ep0();
-               return;
-       }
        if (receive & AO_USB_EP0_GOT_SETUP) {
                debug ("\tsetup\n");
                ao_usb_ep0_setup();
@@ -721,6 +819,25 @@ ao_usb_ep0_handle(uint8_t receive)
        }
 }
 
+#if AO_POWER_MANAGEMENT
+void
+ao_usb_suspend(void)
+{
+       stm_usb.cntr |= (1 << STM_USB_CNTR_FSUSP);
+       ao_power_suspend();
+       stm_usb.cntr |= (1 << STM_USB_CNTR_LP_MODE);
+       ao_clock_suspend();
+}
+
+void
+ao_usb_wakeup(void)
+{
+       ao_clock_resume();
+       stm_usb.cntr &= ~(1 << STM_USB_CNTR_FSUSP);
+       ao_power_resume();
+}
+#endif
+
 void
 stm_usb_isr(void)
 {
@@ -773,6 +890,16 @@ stm_usb_isr(void)
                                ao_wakeup(&ao_usb_in_pending);
                        }
                        break;
+#if AO_USB_HAS_IN2
+               case AO_USB_IN2_EPR:
+                       ++in2_count;
+                       _tx_dbg1("TX2 ISR", epr);
+                       if (ao_usb_epr_ctr_tx(epr)) {
+                               ao_usb_in2_pending = 0;
+                               ao_wakeup(&ao_usb_in2_pending);
+                       }
+                       break;
+#endif
                case AO_USB_INT_EPR:
                        ++int_count;
                        if (ao_usb_epr_ctr_tx(epr))
@@ -784,12 +911,22 @@ stm_usb_isr(void)
 
        if (istr & (1 << STM_USB_ISTR_RESET)) {
                ++reset_count;
-               ao_usb_ep0_receive |= AO_USB_EP0_GOT_RESET;
-               ao_usb_ep0_handle(ao_usb_ep0_receive);
+               debug ("\treset\n");
+               ao_usb_set_ep0();
        }
-
+#if AO_POWER_MANAGEMENT
+       if (istr & (1 << STM_USB_ISTR_SUSP)) {
+               debug ("\tsuspend\n");
+               ao_usb_suspend();
+       }
+       if (istr & (1 << STM_USB_ISTR_WKUP)) {
+               debug ("\twakeup\n");
+               ao_usb_wakeup();
+       }
+#endif
 }
 
+#if AO_USB_HAS_IN
 /* Queue the current IN buffer for transmission */
 static void
 _ao_usb_in_send(void)
@@ -868,7 +1005,90 @@ ao_usb_putchar(char c)
        }
        ao_arch_release_interrupts();
 }
+#endif
+
+#if AO_USB_HAS_IN2
+/* Queue the current IN buffer for transmission */
+static void
+_ao_usb_in2_send(void)
+{
+       _tx_dbg0("in2_send start");
+       debug ("send2 %d\n", ao_usb_tx_count);
+       while (ao_usb_in2_pending)
+               ao_sleep(&ao_usb_in2_pending);
+       ao_usb_in2_pending = 1;
+       if (ao_usb_tx2_count != AO_USB_IN_SIZE)
+               ao_usb_in2_flushed = 1;
+       ao_usb_copy_tx(ao_usb_tx2_buffer, ao_usb_in2_tx_buffer, ao_usb_tx2_count);
+       ao_usb_bdt[AO_USB_IN2_EPR].single.addr_tx = ao_usb_in_tx_offset;
+       ao_usb_bdt[AO_USB_IN2_EPR].single.count_tx = ao_usb_tx_count;
+       ao_usb_tx2_count = 0;
+       _ao_usb_set_stat_tx(AO_USB_IN2_EPR, STM_USB_EPR_STAT_TX_VALID);
+       _tx_dbg0("in2_send end");
+}
+
+/* Wait for a free IN buffer. Interrupts are blocked */
+static void
+_ao_usb_in2_wait(void)
+{
+       for (;;) {
+               /* Check if the current buffer is writable */
+               if (ao_usb_tx2_count < AO_USB_IN_SIZE)
+                       break;
+
+               _tx_dbg0("in2_wait top");
+               /* Wait for an IN buffer to be ready */
+               while (ao_usb_in2_pending)
+                       ao_sleep(&ao_usb_in2_pending);
+               _tx_dbg0("in_wait bottom");
+       }
+}
+
+void
+ao_usb_flush2(void)
+{
+       if (!ao_usb_running)
+               return;
+
+       /* Anytime we've sent a character since
+        * the last time we flushed, we'll need
+        * to send a packet -- the only other time
+        * we would send a packet is when that
+        * packet was full, in which case we now
+        * want to send an empty packet
+        */
+       ao_arch_block_interrupts();
+       while (!ao_usb_in2_flushed) {
+               _tx_dbg0("flush2 top");
+               _ao_usb_in2_send();
+               _tx_dbg0("flush2 end");
+       }
+       ao_arch_release_interrupts();
+}
+
+void
+ao_usb_putchar2(char c)
+{
+       if (!ao_usb_running)
+               return;
+
+       ao_arch_block_interrupts();
+       _ao_usb_in2_wait();
 
+       ao_usb_in2_flushed = 0;
+       ao_usb_tx2_buffer[ao_usb_tx2_count++] = (uint8_t) c;
+
+       /* Send the packet when full */
+       if (ao_usb_tx2_count == AO_USB_IN_SIZE) {
+               _tx_dbg0("putchar2 full");
+               _ao_usb_in2_send();
+               _tx_dbg0("putchar2 flushed");
+       }
+       ao_arch_release_interrupts();
+}
+#endif
+
+#if AO_USB_HAS_OUT
 static void
 _ao_usb_out_recv(void)
 {
@@ -925,6 +1145,7 @@ ao_usb_getchar(void)
        ao_arch_release_interrupts();
        return c;
 }
+#endif
 
 #if AO_USB_DIRECTIO
 uint16_t *
@@ -979,6 +1200,43 @@ ao_usb_write(uint16_t *buffer, uint16_t len)
        _ao_usb_set_stat_tx(AO_USB_IN_EPR, STM_USB_EPR_STAT_TX_VALID);
        ao_arch_release_interrupts();
 }
+
+#if AO_USB_HAS_IN2
+void
+ao_usb_write2(uint16_t *buffer, uint16_t len)
+{
+       ao_arch_block_interrupts();
+
+       /* Wait for everything to be ready at the same time */
+       for (;;) {
+               /* Make sure USB is connected */
+               if (!ao_usb_running) {
+                       ao_sleep(&ao_usb_running);
+                       continue;
+               }
+
+               /* Flush any pending regular I/O */
+               if (ao_usb_tx2_count) {
+                       _ao_usb_in2_send();
+                       continue;
+               }
+
+               /* Wait for an idle IN buffer */
+               if (ao_usb_in2_pending) {
+                       ao_sleep(&ao_usb_in2_pending);
+                       continue;
+               }
+               break;
+       }
+
+       ao_usb_in2_pending = 1;
+       ao_usb_in2_flushed = (len != AO_USB_IN_SIZE);
+       ao_usb_bdt[AO_USB_IN2_EPR].single.addr_tx = ao_usb_packet_buffer_offset(buffer);
+       ao_usb_bdt[AO_USB_IN2_EPR].single.count_tx = len;
+       _ao_usb_set_stat_tx(AO_USB_IN2_EPR, STM_USB_EPR_STAT_TX_VALID);
+       ao_arch_release_interrupts();
+}
+#endif
 #endif
 
 void
@@ -1050,8 +1308,8 @@ ao_usb_enable(void)
        stm_usb.cntr = ((1 << STM_USB_CNTR_CTRM) |
                        (0 << STM_USB_CNTR_PMAOVRM) |
                        (0 << STM_USB_CNTR_ERRM) |
-                       (0 << STM_USB_CNTR_WKUPM) |
-                       (0 << STM_USB_CNTR_SUSPM) |
+                       (AO_POWER_MANAGEMENT << STM_USB_CNTR_WKUPM) |
+                       (AO_POWER_MANAGEMENT << STM_USB_CNTR_SUSPM) |
                        (1 << STM_USB_CNTR_RESETM) |
                        (0 << STM_USB_CNTR_SOFM) |
                        (0 << STM_USB_CNTR_ESOFM) |
@@ -1086,7 +1344,7 @@ ao_usb_echo(void)
 }
 #endif
 
-#if USB_DEBUG
+#if USB_STATUS
 static void
 ao_usb_irq(void)
 {
@@ -1109,7 +1367,13 @@ ao_usb_init(void)
        /* Set PA11/PA12 remapping bit */
        stm_syscfg.cfgr1 |= (AO_PA11_PA12_RMP << STM_SYSCFG_CFGR1_PA11_PA12_RMP);
 
+#ifndef AO_USB_START_DISABLED
        ao_usb_enable();
+#endif
+
+#if AO_USB_DEVICE_ID_SERIAL
+       ao_usb_serial_init();
+#endif
 
        debug ("ao_usb_init\n");
        ao_usb_ep0_state = AO_USB_EP0_IDLE;
@@ -1119,7 +1383,7 @@ ao_usb_init(void)
 #if USB_ECHO
        ao_add_task(&ao_usb_echo_task, ao_usb_echo, "usb echo");
 #endif
-#if USB_DEBUG
+#if USB_STATUS
        ao_cmd_register(&ao_usb_cmds[0]);
 #endif
 #if !USB_ECHO
index 598fc1afb2c2ec612527d15e14d1d47be7a0233b..1f9862b185c843a1f38c21ab672cb4ea9f495880 100644 (file)
@@ -54,4 +54,4 @@ stm_mpu    = 0xe000ed90;
 /* calibration data in system memory */
 stm_cal = 0x1ffff7b8;
 stm_flash_size_04x = 0x1ffff7cc;
-stm_device_id = 0x1ff80050;
+stm_device_id = 0x1ffff7ac;
index ce8ca456d66d2660d7e073f4e3e93db9256d8ccb..33eb9c88ced11d2a77225a2fd247a5ff5db4efe5 100644 (file)
@@ -475,6 +475,24 @@ extern struct stm_rcc stm_rcc;
 #define STM_RCC_CR2_HSI14RDY           1
 #define STM_RCC_CR2_HSI14ON            0
 
+#define STM_RCC_CFGR2_PREDIV           0
+#define  STM_RCC_CFGR2_PREDIV_1                        0x0
+#define  STM_RCC_CFGR2_PREDIV_2                        0x1
+#define  STM_RCC_CFGR2_PREDIV_3                        0x2
+#define  STM_RCC_CFGR2_PREDIV_4                        0x3
+#define  STM_RCC_CFGR2_PREDIV_5                        0x4
+#define  STM_RCC_CFGR2_PREDIV_6                        0x5
+#define  STM_RCC_CFGR2_PREDIV_7                        0x6
+#define  STM_RCC_CFGR2_PREDIV_8                        0x7
+#define  STM_RCC_CFGR2_PREDIV_9                        0x8
+#define  STM_RCC_CFGR2_PREDIV_10               0x9
+#define  STM_RCC_CFGR2_PREDIV_11               0xa
+#define  STM_RCC_CFGR2_PREDIV_12               0xb
+#define  STM_RCC_CFGR2_PREDIV_13               0xc
+#define  STM_RCC_CFGR2_PREDIV_14               0xd
+#define  STM_RCC_CFGR2_PREDIV_15               0xe
+#define  STM_RCC_CFGR2_PREDIV_16               0xf
+
 #define STM_RCC_CFGR3_USART3SW         18
 #define STM_RCC_CFGR3_USART2SW         16
 #define STM_RCC_CFGR3_ADCSW            8
@@ -795,7 +813,7 @@ isr(tim7)
 #define STM_ISR_TSC_POS                        8
 #define STM_ISR_DMA_CH1_POS            9
 #define STM_ISR_DMA_CH2_3_DMA2_CH1_2_POS       10
-#define STM_ISR_DMA_CH44_5_6_7_DMA2_CH3_4_5_POS        11
+#define STM_ISR_DMA_CH4_5_6_7_DMA2_CH3_4_5_POS 11
 #define STM_ISR_ADC_COMP_POS           12
 #define STM_ISR_TIM1_BRK_UP_TRG_COM_POS        13
 #define STM_ISR_TIM1_CC_POS            14
@@ -819,8 +837,11 @@ isr(tim7)
 
 struct stm_syscfg {
        vuint32_t       cfgr1;
+       uint32_t        reserved_04;
        vuint32_t       exticr[4];
        vuint32_t       cfgr2;
+       uint8_t         reserved_1c[0x80-0x1c];
+       vuint32_t       itline[31];
 };
 
 extern struct stm_syscfg stm_syscfg;
@@ -858,7 +879,13 @@ extern struct stm_syscfg stm_syscfg;
 #define  STM_SYSCFG_CFGR1_MEM_MODE_SRAM                3
 #define  STM_SYSCFG_CFGR1_MEM_MODE_MASK                3
 
-#if 0
+#define STM_SYSCFG_EXTICR_PA           0
+#define STM_SYSCFG_EXTICR_PB           1
+#define STM_SYSCFG_EXTICR_PC           2
+#define STM_SYSCFG_EXTICR_PD           3
+#define STM_SYSCFG_EXTICR_PE           4
+#define STM_SYSCFG_EXTICR_PF           5
+
 static inline void
 stm_exticr_set(struct stm_gpio *gpio, int pin) {
        uint8_t reg = pin >> 2;
@@ -879,8 +906,6 @@ stm_exticr_set(struct stm_gpio *gpio, int pin) {
 
        stm_syscfg.exticr[reg] = (stm_syscfg.exticr[reg] & ~(0xf << shift)) | val << shift;
 }
-#endif
-
 
 struct stm_dma_channel {
        vuint32_t       ccr;
@@ -890,7 +915,7 @@ struct stm_dma_channel {
        vuint32_t       reserved;
 };
 
-#define STM_NUM_DMA    6
+#define STM_NUM_DMA    5
 
 struct stm_dma {
        vuint32_t               isr;
@@ -900,7 +925,7 @@ struct stm_dma {
 
 extern struct stm_dma stm_dma;
 
-/* DMA channels go from 1 to 6, instead of 0 to 5 (sigh)
+/* DMA channels go from 1 to 5, instead of 0 to 4 (sigh)
  */
 
 #define STM_DMA_INDEX(channel)         ((channel) - 1)
@@ -1042,7 +1067,7 @@ extern struct stm_spi stm_spi1, stm_spi2, stm_spi3;
 #define STM_SPI_CR1_BIDIOE             14
 #define STM_SPI_CR1_CRCEN              13
 #define STM_SPI_CR1_CRCNEXT            12
-#define STM_SPI_CR1_DFF                        11
+#define STM_SPI_CR1_CRCL               11
 #define STM_SPI_CR1_RXONLY             10
 #define STM_SPI_CR1_SSM                        9
 #define STM_SPI_CR1_SSI                        8
@@ -1063,17 +1088,43 @@ extern struct stm_spi stm_spi1, stm_spi2, stm_spi3;
 #define STM_SPI_CR1_CPOL               1
 #define STM_SPI_CR1_CPHA               0
 
+#define STM_SPI_CR2_LDMA_TX    14
+#define STM_SPI_CR2_LDMA_RX    13
+#define STM_SPI_CR2_FRXTH      12
+#define STM_SPI_CR2_DS         8
+#define  STM_SPI_CR2_DS_4              0x3
+#define  STM_SPI_CR2_DS_5              0x4
+#define  STM_SPI_CR2_DS_6              0x5
+#define  STM_SPI_CR2_DS_7              0x6
+#define  STM_SPI_CR2_DS_8              0x7
+#define  STM_SPI_CR2_DS_9              0x8
+#define  STM_SPI_CR2_DS_10             0x9
+#define  STM_SPI_CR2_DS_11             0xa
+#define  STM_SPI_CR2_DS_12             0xb
+#define  STM_SPI_CR2_DS_13             0xc
+#define  STM_SPI_CR2_DS_14             0xd
+#define  STM_SPI_CR2_DS_15             0xe
+#define  STM_SPI_CR2_DS_16             0xf
 #define STM_SPI_CR2_TXEIE      7
 #define STM_SPI_CR2_RXNEIE     6
 #define STM_SPI_CR2_ERRIE      5
+#define STM_SPI_CR2_FRF                4
+# define STM_SPI_CR2_FRF_MOTOROLA      0
+# define STM_SPI_CR2_FRF_TI            1
+#define STM_SPI_CR2_NSSP       3
 #define STM_SPI_CR2_SSOE       2
 #define STM_SPI_CR2_TXDMAEN    1
 #define STM_SPI_CR2_RXDMAEN    0
 
+#define STM_SPI_SR_FTLVL       11
+#define STM_SPI_SR_FRLVL       9
+#define STM_SPI_SR_FRE         8
 #define STM_SPI_SR_BSY         7
 #define STM_SPI_SR_OVR         6
 #define STM_SPI_SR_MODF                5
 #define STM_SPI_SR_CRCERR      4
+#define STM_SPI_SR_UDR         3
+#define STM_SPI_SR_CHSIDE      2
 #define STM_SPI_SR_TXE         1
 #define STM_SPI_SR_RXNE                0
 
@@ -1293,7 +1344,7 @@ extern struct stm_i2c stm_i2c1, stm_i2c2;
 #define STM_I2C_CCR_CCR                0
 #define  STM_I2C_CCR_MASK      0x7ff
 
-struct stm_tim234 {
+struct stm_tim23 {
        vuint32_t       cr1;
        vuint32_t       cr2;
        vuint32_t       smcr;
@@ -1318,204 +1369,205 @@ struct stm_tim234 {
        uint32_t        reserved_44;
        vuint32_t       dcr;
        vuint32_t       dmar;
-
-       uint32_t        reserved_50;
 };
 
-extern struct stm_tim234 stm_tim2, stm_tim3, stm_tim4;
-
-#define STM_TIM234_CR1_CKD     8
-#define  STM_TIM234_CR1_CKD_1          0
-#define  STM_TIM234_CR1_CKD_2          1
-#define  STM_TIM234_CR1_CKD_4          2
-#define  STM_TIM234_CR1_CKD_MASK       3
-#define STM_TIM234_CR1_ARPE    7
-#define STM_TIM234_CR1_CMS     5
-#define  STM_TIM234_CR1_CMS_EDGE       0
-#define  STM_TIM234_CR1_CMS_CENTER_1   1
-#define  STM_TIM234_CR1_CMS_CENTER_2   2
-#define  STM_TIM234_CR1_CMS_CENTER_3   3
-#define  STM_TIM234_CR1_CMS_MASK       3
-#define STM_TIM234_CR1_DIR     4
-#define  STM_TIM234_CR1_DIR_UP         0
-#define  STM_TIM234_CR1_DIR_DOWN       1
-#define STM_TIM234_CR1_OPM     3
-#define STM_TIM234_CR1_URS     2
-#define STM_TIM234_CR1_UDIS    1
-#define STM_TIM234_CR1_CEN     0
-
-#define STM_TIM234_CR2_TI1S    7
-#define STM_TIM234_CR2_MMS     4
-#define  STM_TIM234_CR2_MMS_RESET              0
-#define  STM_TIM234_CR2_MMS_ENABLE             1
-#define  STM_TIM234_CR2_MMS_UPDATE             2
-#define  STM_TIM234_CR2_MMS_COMPARE_PULSE      3
-#define  STM_TIM234_CR2_MMS_COMPARE_OC1REF     4
-#define  STM_TIM234_CR2_MMS_COMPARE_OC2REF     5
-#define  STM_TIM234_CR2_MMS_COMPARE_OC3REF     6
-#define  STM_TIM234_CR2_MMS_COMPARE_OC4REF     7
-#define  STM_TIM234_CR2_MMS_MASK               7
-#define STM_TIM234_CR2_CCDS    3
-
-#define STM_TIM234_SMCR_ETP    15
-#define STM_TIM234_SMCR_ECE    14
-#define STM_TIM234_SMCR_ETPS   12
-#define  STM_TIM234_SMCR_ETPS_OFF              0
-#define  STM_TIM234_SMCR_ETPS_DIV_2            1
-#define  STM_TIM234_SMCR_ETPS_DIV_4            2
-#define  STM_TIM234_SMCR_ETPS_DIV_8            3
-#define  STM_TIM234_SMCR_ETPS_MASK             3
-#define STM_TIM234_SMCR_ETF    8
-#define  STM_TIM234_SMCR_ETF_NONE              0
-#define  STM_TIM234_SMCR_ETF_INT_N_2           1
-#define  STM_TIM234_SMCR_ETF_INT_N_4           2
-#define  STM_TIM234_SMCR_ETF_INT_N_8           3
-#define  STM_TIM234_SMCR_ETF_DTS_2_N_6         4
-#define  STM_TIM234_SMCR_ETF_DTS_2_N_8         5
-#define  STM_TIM234_SMCR_ETF_DTS_4_N_6         6
-#define  STM_TIM234_SMCR_ETF_DTS_4_N_8         7
-#define  STM_TIM234_SMCR_ETF_DTS_8_N_6         8
-#define  STM_TIM234_SMCR_ETF_DTS_8_N_8         9
-#define  STM_TIM234_SMCR_ETF_DTS_16_N_5                10
-#define  STM_TIM234_SMCR_ETF_DTS_16_N_6                11
-#define  STM_TIM234_SMCR_ETF_DTS_16_N_8                12
-#define  STM_TIM234_SMCR_ETF_DTS_32_N_5                13
-#define  STM_TIM234_SMCR_ETF_DTS_32_N_6                14
-#define  STM_TIM234_SMCR_ETF_DTS_32_N_8                15
-#define  STM_TIM234_SMCR_ETF_MASK              15
-#define STM_TIM234_SMCR_MSM    7
-#define STM_TIM234_SMCR_TS     4
-#define  STM_TIM234_SMCR_TS_ITR0               0
-#define  STM_TIM234_SMCR_TS_ITR1               1
-#define  STM_TIM234_SMCR_TS_ITR2               2
-#define  STM_TIM234_SMCR_TS_ITR3               3
-#define  STM_TIM234_SMCR_TS_TI1F_ED            4
-#define  STM_TIM234_SMCR_TS_TI1FP1             5
-#define  STM_TIM234_SMCR_TS_TI2FP2             6
-#define  STM_TIM234_SMCR_TS_ETRF               7
-#define  STM_TIM234_SMCR_TS_MASK               7
-#define STM_TIM234_SMCR_OCCS   3
-#define STM_TIM234_SMCR_SMS    0
-#define  STM_TIM234_SMCR_SMS_DISABLE           0
-#define  STM_TIM234_SMCR_SMS_ENCODER_MODE_1    1
-#define  STM_TIM234_SMCR_SMS_ENCODER_MODE_2    2
-#define  STM_TIM234_SMCR_SMS_ENCODER_MODE_3    3
-#define  STM_TIM234_SMCR_SMS_RESET_MODE                4
-#define  STM_TIM234_SMCR_SMS_GATED_MODE                5
-#define  STM_TIM234_SMCR_SMS_TRIGGER_MODE      6
-#define  STM_TIM234_SMCR_SMS_EXTERNAL_CLOCK    7
-#define  STM_TIM234_SMCR_SMS_MASK              7
-
-#define STM_TIM234_SR_CC4OF    12
-#define STM_TIM234_SR_CC3OF    11
-#define STM_TIM234_SR_CC2OF    10
-#define STM_TIM234_SR_CC1OF    9
-#define STM_TIM234_SR_TIF      6
-#define STM_TIM234_SR_CC4IF    4
-#define STM_TIM234_SR_CC3IF    3
-#define STM_TIM234_SR_CC2IF    2
-#define STM_TIM234_SR_CC1IF    1
-#define STM_TIM234_SR_UIF      0
-
-#define STM_TIM234_EGR_TG      6
-#define STM_TIM234_EGR_CC4G    4
-#define STM_TIM234_EGR_CC3G    3
-#define STM_TIM234_EGR_CC2G    2
-#define STM_TIM234_EGR_CC1G    1
-#define STM_TIM234_EGR_UG      0
-
-#define STM_TIM234_CCMR1_OC2CE 15
-#define STM_TIM234_CCMR1_OC2M  12
-#define  STM_TIM234_CCMR1_OC2M_FROZEN                  0
-#define  STM_TIM234_CCMR1_OC2M_SET_HIGH_ON_MATCH       1
-#define  STM_TIM234_CCMR1_OC2M_SET_LOW_ON_MATCH                2
-#define  STM_TIM234_CCMR1_OC2M_TOGGLE                  3
-#define  STM_TIM234_CCMR1_OC2M_FORCE_LOW               4
-#define  STM_TIM234_CCMR1_OC2M_FORCE_HIGH              5
-#define  STM_TIM234_CCMR1_OC2M_PWM_MODE_1              6
-#define  STM_TIM234_CCMR1_OC2M_PWM_MODE_2              7
-#define  STM_TIM234_CCMR1_OC2M_MASK                    7
-#define STM_TIM234_CCMR1_OC2PE 11
-#define STM_TIM234_CCMR1_OC2FE 10
-#define STM_TIM234_CCMR1_CC2S  8
-#define  STM_TIM234_CCMR1_CC2S_OUTPUT                  0
-#define  STM_TIM234_CCMR1_CC2S_INPUT_TI2               1
-#define  STM_TIM234_CCMR1_CC2S_INPUT_TI1               2
-#define  STM_TIM234_CCMR1_CC2S_INPUT_TRC               3
-#define  STM_TIM234_CCMR1_CC2S_MASK                    3
-
-#define STM_TIM234_CCMR1_OC1CE 7
-#define STM_TIM234_CCMR1_OC1M  4
-#define  STM_TIM234_CCMR1_OC1M_FROZEN                  0
-#define  STM_TIM234_CCMR1_OC1M_SET_HIGH_ON_MATCH       1
-#define  STM_TIM234_CCMR1_OC1M_SET_LOW_ON_MATCH                2
-#define  STM_TIM234_CCMR1_OC1M_TOGGLE                  3
-#define  STM_TIM234_CCMR1_OC1M_FORCE_LOW               4
-#define  STM_TIM234_CCMR1_OC1M_FORCE_HIGH              5
-#define  STM_TIM234_CCMR1_OC1M_PWM_MODE_1              6
-#define  STM_TIM234_CCMR1_OC1M_PWM_MODE_2              7
-#define  STM_TIM234_CCMR1_OC1M_MASK                    7
-#define STM_TIM234_CCMR1_OC1PE 11
-#define STM_TIM234_CCMR1_OC1FE 2
-#define STM_TIM234_CCMR1_CC1S  0
-#define  STM_TIM234_CCMR1_CC1S_OUTPUT                  0
-#define  STM_TIM234_CCMR1_CC1S_INPUT_TI1               1
-#define  STM_TIM234_CCMR1_CC1S_INPUT_TI2               2
-#define  STM_TIM234_CCMR1_CC1S_INPUT_TRC               3
-#define  STM_TIM234_CCMR1_CC1S_MASK                    3
-
-#define STM_TIM234_CCMR2_OC4CE 15
-#define STM_TIM234_CCMR2_OC4M  12
-#define  STM_TIM234_CCMR2_OC4M_FROZEN                  0
-#define  STM_TIM234_CCMR2_OC4M_SET_HIGH_ON_MATCH       1
-#define  STM_TIM234_CCMR2_OC4M_SET_LOW_ON_MATCH                2
-#define  STM_TIM234_CCMR2_OC4M_TOGGLE                  3
-#define  STM_TIM234_CCMR2_OC4M_FORCE_LOW               4
-#define  STM_TIM234_CCMR2_OC4M_FORCE_HIGH              5
-#define  STM_TIM234_CCMR2_OC4M_PWM_MODE_1              6
-#define  STM_TIM234_CCMR2_OC4M_PWM_MODE_2              7
-#define  STM_TIM234_CCMR2_OC4M_MASK                    7
-#define STM_TIM234_CCMR2_OC4PE 11
-#define STM_TIM234_CCMR2_OC4FE 10
-#define STM_TIM234_CCMR2_CC4S  8
-#define  STM_TIM234_CCMR2_CC4S_OUTPUT                  0
-#define  STM_TIM234_CCMR2_CC4S_INPUT_TI4               1
-#define  STM_TIM234_CCMR2_CC4S_INPUT_TI3               2
-#define  STM_TIM234_CCMR2_CC4S_INPUT_TRC               3
-#define  STM_TIM234_CCMR2_CC4S_MASK                    3
-
-#define STM_TIM234_CCMR2_OC3CE 7
-#define STM_TIM234_CCMR2_OC3M  4
-#define  STM_TIM234_CCMR2_OC3M_FROZEN                  0
-#define  STM_TIM234_CCMR2_OC3M_SET_HIGH_ON_MATCH       1
-#define  STM_TIM234_CCMR2_OC3M_SET_LOW_ON_MATCH                2
-#define  STM_TIM234_CCMR2_OC3M_TOGGLE                  3
-#define  STM_TIM234_CCMR2_OC3M_FORCE_LOW               4
-#define  STM_TIM234_CCMR2_OC3M_FORCE_HIGH              5
-#define  STM_TIM234_CCMR2_OC3M_PWM_MODE_1              6
-#define  STM_TIM234_CCMR2_OC3M_PWM_MODE_2              7
-#define  STM_TIM234_CCMR2_OC3M_MASK                    7
-#define STM_TIM234_CCMR2_OC3PE 11
-#define STM_TIM234_CCMR2_OC3FE 2
-#define STM_TIM234_CCMR2_CC3S  0
-#define  STM_TIM234_CCMR2_CC3S_OUTPUT                  0
-#define  STM_TIM234_CCMR2_CC3S_INPUT_TI3               1
-#define  STM_TIM234_CCMR2_CC3S_INPUT_TI4               2
-#define  STM_TIM234_CCMR2_CC3S_INPUT_TRC               3
-#define  STM_TIM234_CCMR2_CC3S_MASK                    3
-
-#define STM_TIM234_CCER_CC4NP  15
-#define STM_TIM234_CCER_CC4P   13
-#define STM_TIM234_CCER_CC4E   12
-#define STM_TIM234_CCER_CC3NP  11
-#define STM_TIM234_CCER_CC3P   9
-#define STM_TIM234_CCER_CC3E   8
-#define STM_TIM234_CCER_CC2NP  7
-#define STM_TIM234_CCER_CC2P   5
-#define STM_TIM234_CCER_CC2E   4
-#define STM_TIM234_CCER_CC1NP  3
-#define STM_TIM234_CCER_CC1P   1
-#define STM_TIM234_CCER_CC1E   0
+extern struct stm_tim23 stm_tim2, stm_tim3;
+
+#define stm_tim3       (*(struct stm_tim23 *) 0x40000400)
+#define stm_tim2       (*(struct stm_tim23 *) 0x40000000)
+
+#define STM_TIM23_CR1_CKD      8
+#define  STM_TIM23_CR1_CKD_1           0
+#define  STM_TIM23_CR1_CKD_2           1
+#define  STM_TIM23_CR1_CKD_4           2
+#define  STM_TIM23_CR1_CKD_MASK        3
+#define STM_TIM23_CR1_ARPE     7
+#define STM_TIM23_CR1_CMS      5
+#define  STM_TIM23_CR1_CMS_EDGE                0
+#define  STM_TIM23_CR1_CMS_CENTER_1    1
+#define  STM_TIM23_CR1_CMS_CENTER_2    2
+#define  STM_TIM23_CR1_CMS_CENTER_3    3
+#define  STM_TIM23_CR1_CMS_MASK                3
+#define STM_TIM23_CR1_DIR      4
+#define  STM_TIM23_CR1_DIR_UP          0
+#define  STM_TIM23_CR1_DIR_DOWN                1
+#define STM_TIM23_CR1_OPM      3
+#define STM_TIM23_CR1_URS      2
+#define STM_TIM23_CR1_UDIS     1
+#define STM_TIM23_CR1_CEN      0
+
+#define STM_TIM23_CR2_TI1S     7
+#define STM_TIM23_CR2_MMS      4
+#define  STM_TIM23_CR2_MMS_RESET               0
+#define  STM_TIM23_CR2_MMS_ENABLE              1
+#define  STM_TIM23_CR2_MMS_UPDATE              2
+#define  STM_TIM23_CR2_MMS_COMPARE_PULSE       3
+#define  STM_TIM23_CR2_MMS_COMPARE_OC1REF      4
+#define  STM_TIM23_CR2_MMS_COMPARE_OC2REF      5
+#define  STM_TIM23_CR2_MMS_COMPARE_OC3REF      6
+#define  STM_TIM23_CR2_MMS_COMPARE_OC4REF      7
+#define  STM_TIM23_CR2_MMS_MASK                        7
+#define STM_TIM23_CR2_CCDS     3
+
+#define STM_TIM23_SMCR_ETP     15
+#define STM_TIM23_SMCR_ECE     14
+#define STM_TIM23_SMCR_ETPS    12
+#define  STM_TIM23_SMCR_ETPS_OFF               0
+#define  STM_TIM23_SMCR_ETPS_DIV_2             1
+#define  STM_TIM23_SMCR_ETPS_DIV_4             2
+#define  STM_TIM23_SMCR_ETPS_DIV_8             3
+#define  STM_TIM23_SMCR_ETPS_MASK              3
+#define STM_TIM23_SMCR_ETF     8
+#define  STM_TIM23_SMCR_ETF_NONE               0
+#define  STM_TIM23_SMCR_ETF_INT_N_2            1
+#define  STM_TIM23_SMCR_ETF_INT_N_4            2
+#define  STM_TIM23_SMCR_ETF_INT_N_8            3
+#define  STM_TIM23_SMCR_ETF_DTS_2_N_6          4
+#define  STM_TIM23_SMCR_ETF_DTS_2_N_8          5
+#define  STM_TIM23_SMCR_ETF_DTS_4_N_6          6
+#define  STM_TIM23_SMCR_ETF_DTS_4_N_8          7
+#define  STM_TIM23_SMCR_ETF_DTS_8_N_6          8
+#define  STM_TIM23_SMCR_ETF_DTS_8_N_8          9
+#define  STM_TIM23_SMCR_ETF_DTS_16_N_5         10
+#define  STM_TIM23_SMCR_ETF_DTS_16_N_6         11
+#define  STM_TIM23_SMCR_ETF_DTS_16_N_8         12
+#define  STM_TIM23_SMCR_ETF_DTS_32_N_5         13
+#define  STM_TIM23_SMCR_ETF_DTS_32_N_6         14
+#define  STM_TIM23_SMCR_ETF_DTS_32_N_8         15
+#define  STM_TIM23_SMCR_ETF_MASK               15
+#define STM_TIM23_SMCR_MSM     7
+#define STM_TIM23_SMCR_TS      4
+#define  STM_TIM23_SMCR_TS_ITR0                        0
+#define  STM_TIM23_SMCR_TS_ITR1                        1
+#define  STM_TIM23_SMCR_TS_ITR2                        2
+#define  STM_TIM23_SMCR_TS_ITR3                        3
+#define  STM_TIM23_SMCR_TS_TI1F_ED             4
+#define  STM_TIM23_SMCR_TS_TI1FP1              5
+#define  STM_TIM23_SMCR_TS_TI2FP2              6
+#define  STM_TIM23_SMCR_TS_ETRF                        7
+#define  STM_TIM23_SMCR_TS_MASK                        7
+#define STM_TIM23_SMCR_OCCS    3
+#define STM_TIM23_SMCR_SMS     0
+#define  STM_TIM23_SMCR_SMS_DISABLE            0
+#define  STM_TIM23_SMCR_SMS_ENCODER_MODE_1     1
+#define  STM_TIM23_SMCR_SMS_ENCODER_MODE_2     2
+#define  STM_TIM23_SMCR_SMS_ENCODER_MODE_3     3
+#define  STM_TIM23_SMCR_SMS_RESET_MODE         4
+#define  STM_TIM23_SMCR_SMS_GATED_MODE         5
+#define  STM_TIM23_SMCR_SMS_TRIGGER_MODE       6
+#define  STM_TIM23_SMCR_SMS_EXTERNAL_CLOCK     7
+#define  STM_TIM23_SMCR_SMS_MASK               7
+
+#define STM_TIM23_SR_CC4OF     12
+#define STM_TIM23_SR_CC3OF     11
+#define STM_TIM23_SR_CC2OF     10
+#define STM_TIM23_SR_CC1OF     9
+#define STM_TIM23_SR_TIF       6
+#define STM_TIM23_SR_CC4IF     4
+#define STM_TIM23_SR_CC3IF     3
+#define STM_TIM23_SR_CC2IF     2
+#define STM_TIM23_SR_CC1IF     1
+#define STM_TIM23_SR_UIF       0
+
+#define STM_TIM23_EGR_TG       6
+#define STM_TIM23_EGR_CC4G     4
+#define STM_TIM23_EGR_CC3G     3
+#define STM_TIM23_EGR_CC2G     2
+#define STM_TIM23_EGR_CC1G     1
+#define STM_TIM23_EGR_UG       0
+
+#define STM_TIM23_CCMR1_OC2CE  15
+#define STM_TIM23_CCMR1_OC2M   12
+#define  STM_TIM23_CCMR1_OC2M_FROZEN                   0
+#define  STM_TIM23_CCMR1_OC2M_SET_HIGH_ON_MATCH                1
+#define  STM_TIM23_CCMR1_OC2M_SET_LOW_ON_MATCH         2
+#define  STM_TIM23_CCMR1_OC2M_TOGGLE                   3
+#define  STM_TIM23_CCMR1_OC2M_FORCE_LOW                        4
+#define  STM_TIM23_CCMR1_OC2M_FORCE_HIGH               5
+#define  STM_TIM23_CCMR1_OC2M_PWM_MODE_1               6
+#define  STM_TIM23_CCMR1_OC2M_PWM_MODE_2               7
+#define  STM_TIM23_CCMR1_OC2M_MASK                     7
+#define STM_TIM23_CCMR1_OC2PE  11
+#define STM_TIM23_CCMR1_OC2FE  10
+#define STM_TIM23_CCMR1_CC2S   8
+#define  STM_TIM23_CCMR1_CC2S_OUTPUT                   0
+#define  STM_TIM23_CCMR1_CC2S_INPUT_TI2                        1
+#define  STM_TIM23_CCMR1_CC2S_INPUT_TI1                        2
+#define  STM_TIM23_CCMR1_CC2S_INPUT_TRC                        3
+#define  STM_TIM23_CCMR1_CC2S_MASK                     3
+
+#define STM_TIM23_CCMR1_OC1CE  7
+#define STM_TIM23_CCMR1_OC1M   4
+#define  STM_TIM23_CCMR1_OC1M_FROZEN                   0
+#define  STM_TIM23_CCMR1_OC1M_SET_HIGH_ON_MATCH                1
+#define  STM_TIM23_CCMR1_OC1M_SET_LOW_ON_MATCH         2
+#define  STM_TIM23_CCMR1_OC1M_TOGGLE                   3
+#define  STM_TIM23_CCMR1_OC1M_FORCE_LOW                        4
+#define  STM_TIM23_CCMR1_OC1M_FORCE_HIGH               5
+#define  STM_TIM23_CCMR1_OC1M_PWM_MODE_1               6
+#define  STM_TIM23_CCMR1_OC1M_PWM_MODE_2               7
+#define  STM_TIM23_CCMR1_OC1M_MASK                     7
+#define STM_TIM23_CCMR1_OC1PE  11
+#define STM_TIM23_CCMR1_OC1FE  2
+#define STM_TIM23_CCMR1_CC1S   0
+#define  STM_TIM23_CCMR1_CC1S_OUTPUT                   0
+#define  STM_TIM23_CCMR1_CC1S_INPUT_TI1                        1
+#define  STM_TIM23_CCMR1_CC1S_INPUT_TI2                        2
+#define  STM_TIM23_CCMR1_CC1S_INPUT_TRC                        3
+#define  STM_TIM23_CCMR1_CC1S_MASK                     3
+
+#define STM_TIM23_CCMR2_OC4CE  15
+#define STM_TIM23_CCMR2_OC4M   12
+#define  STM_TIM23_CCMR2_OC4M_FROZEN                   0
+#define  STM_TIM23_CCMR2_OC4M_SET_HIGH_ON_MATCH        1
+#define  STM_TIM23_CCMR2_OC4M_SET_LOW_ON_MATCH         2
+#define  STM_TIM23_CCMR2_OC4M_TOGGLE                   3
+#define  STM_TIM23_CCMR2_OC4M_FORCE_LOW                        4
+#define  STM_TIM23_CCMR2_OC4M_FORCE_HIGH               5
+#define  STM_TIM23_CCMR2_OC4M_PWM_MODE_1               6
+#define  STM_TIM23_CCMR2_OC4M_PWM_MODE_2               7
+#define  STM_TIM23_CCMR2_OC4M_MASK                     7
+#define STM_TIM23_CCMR2_OC4PE  11
+#define STM_TIM23_CCMR2_OC4FE  10
+#define STM_TIM23_CCMR2_CC4S   8
+#define  STM_TIM23_CCMR2_CC4S_OUTPUT                   0
+#define  STM_TIM23_CCMR2_CC4S_INPUT_TI4                        1
+#define  STM_TIM23_CCMR2_CC4S_INPUT_TI3                        2
+#define  STM_TIM23_CCMR2_CC4S_INPUT_TRC                        3
+#define  STM_TIM23_CCMR2_CC4S_MASK                     3
+
+#define STM_TIM23_CCMR2_OC3CE  7
+#define STM_TIM23_CCMR2_OC3M   4
+#define  STM_TIM23_CCMR2_OC3M_FROZEN                   0
+#define  STM_TIM23_CCMR2_OC3M_SET_HIGH_ON_MATCH                1
+#define  STM_TIM23_CCMR2_OC3M_SET_LOW_ON_MATCH         2
+#define  STM_TIM23_CCMR2_OC3M_TOGGLE                   3
+#define  STM_TIM23_CCMR2_OC3M_FORCE_LOW                        4
+#define  STM_TIM23_CCMR2_OC3M_FORCE_HIGH               5
+#define  STM_TIM23_CCMR2_OC3M_PWM_MODE_1               6
+#define  STM_TIM23_CCMR2_OC3M_PWM_MODE_2               7
+#define  STM_TIM23_CCMR2_OC3M_MASK                     7
+#define STM_TIM23_CCMR2_OC3PE  11
+#define STM_TIM23_CCMR2_OC3FE  2
+#define STM_TIM23_CCMR2_CC3S   0
+#define  STM_TIM23_CCMR2_CC3S_OUTPUT                   0
+#define  STM_TIM23_CCMR2_CC3S_INPUT_TI3                        1
+#define  STM_TIM23_CCMR2_CC3S_INPUT_TI4                        2
+#define  STM_TIM23_CCMR2_CC3S_INPUT_TRC                        3
+#define  STM_TIM23_CCMR2_CC3S_MASK                     3
+
+#define STM_TIM23_CCER_CC4NP   15
+#define STM_TIM23_CCER_CC4P    13
+#define STM_TIM23_CCER_CC4E    12
+#define STM_TIM23_CCER_CC3NP   11
+#define STM_TIM23_CCER_CC3P    9
+#define STM_TIM23_CCER_CC3E    8
+#define STM_TIM23_CCER_CC2NP   7
+#define STM_TIM23_CCER_CC2P    5
+#define STM_TIM23_CCER_CC2E    4
+#define STM_TIM23_CCER_CC1NP   3
+#define STM_TIM23_CCER_CC1P    1
+#define STM_TIM23_CCER_CC1E    0
 
 struct stm_usb {
        struct {
index a6a016622fa06aa364262d53db15b402cf9d92ea..5058494008c46559f9adcd9f75decc3e2067e108 100644 (file)
 #define USE_SERIAL_2_STDIN     1
 #define DELAY_SERIAL_2_STDIN   1
 #define USE_SERIAL_2_FLOW      1
+#define USE_SERIAL_2_SW_FLOW   1
 #define SERIAL_2_PA2_PA3       1
 #define SERIAL_2_PD5_PD6       0
+#define SERIAL_2_PORT_RTS      (&stm_gpioa)
+#define SERIAL_2_PIN_RTS       0
+#define SERIAL_2_PORT_CTS      (&stm_gpioa)
+#define SERIAL_2_PIN_CTS       1
 
 #define HAS_SERIAL_3           0
 #define USE_SERIAL_3_STDIN     0
index 44ee4f3dabe745369527fa3040b228369c21e382..1fe06b1ac42137beca30107ff12f4ef943ba156c 100644 (file)
@@ -31,7 +31,6 @@ main(void)
        ao_clock_init();
 
        ao_task_init();
-       ao_serial_init();
        ao_led_init(LEDS_AVAILABLE);
        ao_led_on(AO_LED_RED);
        ao_timer_init();
index 47ae663f1811af6be510d52913c9fd01e30125fd..1087c7c90d828d1c97fce92b7a8794f9c596fa32 100644 (file)
@@ -39,6 +39,8 @@
 #define PACKET_HAS_MASTER      0
 #define PACKET_HAS_SLAVE       0
 
+#define PAD_BOX                        0
+
 #define AO_LED_CONTINUITY(c)   (1 << ((c) + 2))
 #define AO_LED_CONTINUITY_MASK (0xc)
 #define AO_LED_ARMED           0x10
diff --git a/src/telefiretwo-v0.1/.gitignore b/src/telefiretwo-v0.1/.gitignore
new file mode 100644 (file)
index 0000000..e89f9fd
--- /dev/null
@@ -0,0 +1,2 @@
+telefiretwo-*
+ao_product.h
diff --git a/src/telefiretwo-v0.1/Makefile b/src/telefiretwo-v0.1/Makefile
new file mode 100644 (file)
index 0000000..6454d6f
--- /dev/null
@@ -0,0 +1,89 @@
+#
+# TeleFire build file
+#
+
+include ../stm/Makefile.defs
+
+INC = \
+       ao.h \
+       ao_pins.h \
+       ao_arch.h \
+       ao_arch_funcs.h \
+       ao_pad.h \
+       ao_product.h \
+       ao_radio_spi.h \
+       ao_radio_cmac.h \
+       ao_cc1200_CC1200.h \
+       ao_cc1200.h \
+       stm32l.h
+#
+# Common AltOS sources
+#
+
+#PROFILE=ao_profile.c
+#PROFILE_DEF=-DAO_PROFILE=1
+
+ALTOS_SRC = \
+       ao_boot_chain.c \
+       ao_interrupt.c \
+       ao_product.c \
+       ao_romconfig.c \
+       ao_cmd.c \
+       ao_adc_stm.c \
+       ao_data.c \
+       ao_config.c \
+       ao_task.c \
+       ao_led.c \
+       ao_stdio.c \
+       ao_panic.c \
+       ao_timer.c \
+       ao_mutex.c \
+       ao_freq.c \
+       ao_dma_stm.c \
+       ao_spi_stm.c \
+       ao_eeprom_stm.c \
+       ao_usb_stm.c \
+       ao_exti_stm.c \
+       ao_cc1200.c \
+       ao_radio_cmac.c \
+       ao_aes.c \
+       ao_aes_tables.c \
+       ao_pad.c \
+       ao_radio_cmac_cmd.c
+
+PRODUCT_SRC = \
+       ao_telefiretwo.c
+
+PRODUCT=TeleFire-v0.1
+PRODUCT_DEF=-DTELEFIRETWO_V_0_1
+IDPRODUCT=0x000f
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g
+
+PROGNAME = telefiretwo-v0.1
+PROG = $(PROGNAME)-$(VERSION).elf
+HEX = $(PROGNAME)-$(VERSION).ihx
+
+SRC = $(ALTOS_SRC) $(PRODUCT_SRC)
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(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 $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+       rm -f ao_product.h
+
+install:
+
+uninstall:
+
diff --git a/src/telefiretwo-v0.1/ao_pins.h b/src/telefiretwo-v0.1/ao_pins.h
new file mode 100644 (file)
index 0000000..fd840f4
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define HAS_RADIO              1
+#define HAS_RADIO_RATE         1
+#define HAS_TELEMETRY          0
+
+#define HAS_FLIGHT             0
+#define HAS_USB                        1
+#define HAS_BEEP               0
+#define HAS_GPS                        0
+#define HAS_SERIAL_1           0
+#define HAS_ADC                        1
+#define HAS_DBG                        0
+#define HAS_EEPROM             1
+#define HAS_LOG                        0
+#define HAS_PAD                        1
+#define USE_INTERNAL_FLASH     1
+#define IGNITE_ON_P0           0
+#define PACKET_HAS_MASTER      0
+#define PACKET_HAS_SLAVE       0
+#define AO_DATA_RING           32
+#define HAS_FIXED_PAD_BOX      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)
+
+#define AO_CC1200_FOSC         40000000
+
+/* 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_EEPROM             1
+#define USE_INTERNAL_FLASH     1
+#define USE_EEPROM_CONFIG      1
+#define USE_STORAGE_CONFIG     0
+#define HAS_USB                        1
+#define HAS_BEEP               0
+#define HAS_RADIO              1
+#define HAS_RADIO_RATE         1
+#define HAS_TELEMETRY          0
+#define HAS_AES                        1
+
+#define HAS_SPI_1              0
+#define SPI_1_PA5_PA6_PA7      0
+#define SPI_1_PB3_PB4_PB5      0
+#define SPI_1_PE13_PE14_PE15   0
+
+#define HAS_SPI_2              1       /* CC1200 */
+#define SPI_2_PB13_PB14_PB15   1
+#define SPI_2_PD1_PD3_PD4      0
+#define SPI_2_GPIO             (&stm_gpiob)
+#define SPI_2_SCK              13
+#define SPI_2_MISO             14
+#define SPI_2_MOSI             15
+#define SPI_2_OSPEEDR          STM_OSPEEDR_10MHz
+
+#define HAS_I2C_1              0
+
+#define HAS_I2C_2              0
+
+#define PACKET_HAS_SLAVE       0
+#define PACKET_HAS_MASTER      0
+
+#define FAST_TIMER_FREQ                10000   /* .1ms for debouncing */
+
+/*
+ * Radio is a cc1200 connected via SPI
+ */
+
+#define AO_RADIO_CAL_DEFAULT   5695733
+
+#define AO_FEC_DEBUG           0
+#define AO_CC1200_SPI_CS_PORT  (&stm_gpioa)
+#define AO_CC1200_SPI_CS_PIN   7
+#define AO_CC1200_SPI_BUS      AO_SPI_2_PB13_PB14_PB15
+#define AO_CC1200_SPI          stm_spi2
+
+#define AO_CC1200_INT_PORT             (&stm_gpiob)
+#define AO_CC1200_INT_PIN              (11)
+
+#define AO_CC1200_INT_GPIO     2
+#define AO_CC1200_INT_GPIO_IOCFG       CC1200_IOCFG2
+
+#define LED_PORT_0             (&stm_gpioa)
+#define LED_PORT_1             (&stm_gpiob)
+
+#define LED_PORT_0_ENABLE      STM_RCC_AHBENR_GPIOAEN
+#define LED_PORT_1_ENABLE      STM_RCC_AHBENR_GPIOBEN
+
+/* Port A, pins 4-6 */
+#define LED_PORT_0_SHIFT       4
+#define LED_PORT_0_MASK                0x7
+#define LED_PIN_GREEN          0
+#define LED_PIN_AMBER          1
+#define LED_PIN_RED            2
+#define AO_LED_RED             (1 << LED_PIN_RED)
+#define AO_LED_AMBER           (1 << LED_PIN_AMBER)
+#define AO_LED_GREEN           (1 << LED_PIN_GREEN)
+
+/* Port B, pins 3-5 */
+#define LED_PORT_1_SHIFT       0
+#define LED_PORT_1_MASK                (0x7 << 3)
+#define LED_PIN_CONT_1         3
+#define LED_PIN_CONT_0         4
+#define LED_PIN_ARMED          5
+
+#define AO_LED_ARMED           (1 << LED_PIN_ARMED)
+#define AO_LED_CONTINUITY(c)   (1 << (4 - (c)))
+#define AO_LED_CONTINUITY_MASK (0x3 << 3)
+
+#define LEDS_AVAILABLE         (LED_PORT_0_MASK|LED_PORT_1_MASK)
+
+#define SPI_CS_PORT    P1
+#define SPI_CS_SEL     P1SEL
+#define SPI_CS_DIR     P1DIR
+
+#define SPI_CONST      0x00
+
+#define AO_PAD_NUM             2
+#define        AO_PAD_PORT             (&stm_gpiob)
+
+#define AO_PAD_PIN_0           9
+#define AO_PAD_ADC_0           0
+
+#define AO_PAD_PIN_1           8
+#define AO_PAD_ADC_1           1
+
+#define AO_PAD_ALL_PINS                ((1 << AO_PAD_PIN_0) | (1 << AO_PAD_PIN_1))
+#define AO_PAD_ALL_CHANNELS    ((1 << 0) | (1 << 1))
+
+/* test these values with real igniters */
+#define AO_PAD_RELAY_CLOSED    3524
+#define AO_PAD_NO_IGNITER      16904
+#define AO_PAD_GOOD_IGNITER    22514
+
+#define AO_PAD_ADC_PYRO                8
+#define AO_PAD_ADC_BATT                2
+
+#define AO_ADC_FIRST_PIN       0
+
+#define AO_NUM_ADC             4
+
+#define AO_ADC_SQ1             AO_PAD_ADC_0
+#define AO_ADC_SQ2             AO_PAD_ADC_1
+#define AO_ADC_SQ3             AO_PAD_ADC_PYRO
+#define AO_ADC_SQ4             AO_PAD_ADC_BATT
+
+#define AO_PYRO_R_PYRO_SENSE   200
+#define AO_PYRO_R_SENSE_GND    22
+
+#define AO_FIRE_R_POWER_FET    0
+#define AO_FIRE_R_FET_SENSE    200
+#define AO_FIRE_R_SENSE_GND    22
+
+#define HAS_ADC_TEMP           0
+
+struct ao_adc {
+       int16_t         sense[AO_PAD_NUM];
+       int16_t         pyro;
+       int16_t         batt;
+};
+
+#define AO_ADC_DUMP(p)                                                 \
+       printf ("tick: %5u 0: %5d 1: %5d pyro: %5d batt %5d\n", \
+               (p)->tick,                                              \
+               (p)->adc.sense[0],                                      \
+               (p)->adc.sense[1],                                      \
+               (p)->adc.pyro,                                          \
+               (p)->adc.batt)
+
+#define AO_ADC_PINS    ((1 << AO_PAD_ADC_0) | \
+                        (1 << AO_PAD_ADC_1) | \
+                        (1 << AO_PAD_ADC_PYRO) | \
+                        (1 << AO_PAD_ADC_BATT))
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/telefiretwo-v0.1/ao_telefiretwo.c b/src/telefiretwo-v0.1/ao_telefiretwo.c
new file mode 100644 (file)
index 0000000..38629d8
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+#include <ao.h>
+#include <ao_pad.h>
+#include <ao_exti.h>
+#include <ao_radio_cmac_cmd.h>
+
+void
+main(void)
+{
+       ao_clock_init();
+
+       ao_led_init(LEDS_AVAILABLE);
+
+       ao_task_init();
+
+       ao_timer_init();
+       ao_spi_init();
+       ao_dma_init();
+       ao_exti_init();
+
+       ao_cmd_init();
+
+       ao_adc_init();
+
+       ao_eeprom_init();
+
+       ao_radio_init();
+
+       ao_usb_init();
+
+       ao_config_init();
+
+       ao_pad_init();
+
+//     ao_radio_cmac_cmd_init();
+
+       ao_start_scheduler();
+}
diff --git a/src/telefiretwo-v0.1/flash-loader/.gitignore b/src/telefiretwo-v0.1/flash-loader/.gitignore
new file mode 100644 (file)
index 0000000..65fe7ea
--- /dev/null
@@ -0,0 +1,2 @@
+*.elf
+*.ihx
diff --git a/src/telefiretwo-v0.1/flash-loader/Makefile b/src/telefiretwo-v0.1/flash-loader/Makefile
new file mode 100644 (file)
index 0000000..108cd55
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=telefiretwo-v0.1
+include $(TOPDIR)/stm/Makefile-flash.defs
diff --git a/src/telefiretwo-v0.1/flash-loader/ao_pins.h b/src/telefiretwo-v0.1/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..daa9048
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * 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>
+
+#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/telefiretwo-v0.2/.gitignore b/src/telefiretwo-v0.2/.gitignore
new file mode 100644 (file)
index 0000000..e89f9fd
--- /dev/null
@@ -0,0 +1,2 @@
+telefiretwo-*
+ao_product.h
diff --git a/src/telefiretwo-v0.2/Makefile b/src/telefiretwo-v0.2/Makefile
new file mode 100644 (file)
index 0000000..30985f9
--- /dev/null
@@ -0,0 +1,90 @@
+#
+# TeleFire build file
+#
+
+include ../stm/Makefile.defs
+
+INC = \
+       ao.h \
+       ao_pins.h \
+       ao_arch.h \
+       ao_arch_funcs.h \
+       ao_pad.h \
+       ao_product.h \
+       ao_radio_spi.h \
+       ao_radio_cmac.h \
+       ao_cc1200_CC1200.h \
+       ao_cc1200.h \
+       stm32l.h
+#
+# Common AltOS sources
+#
+
+#PROFILE=ao_profile.c
+#PROFILE_DEF=-DAO_PROFILE=1
+
+ALTOS_SRC = \
+       ao_boot_chain.c \
+       ao_interrupt.c \
+       ao_product.c \
+       ao_romconfig.c \
+       ao_cmd.c \
+       ao_adc_stm.c \
+       ao_data.c \
+       ao_config.c \
+       ao_task.c \
+       ao_led.c \
+       ao_stdio.c \
+       ao_panic.c \
+       ao_timer.c \
+       ao_mutex.c \
+       ao_freq.c \
+       ao_dma_stm.c \
+       ao_spi_stm.c \
+       ao_beep_stm.c \
+       ao_eeprom_stm.c \
+       ao_usb_stm.c \
+       ao_exti_stm.c \
+       ao_cc1200.c \
+       ao_radio_cmac.c \
+       ao_aes.c \
+       ao_aes_tables.c \
+       ao_pad.c \
+       ao_radio_cmac_cmd.c
+
+PRODUCT_SRC = \
+       ao_telefiretwo.c
+
+PRODUCT=TeleFire-v0.2
+PRODUCT_DEF=-DTELEFIRETWO_V_0_2
+IDPRODUCT=0x000f
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g
+
+PROGNAME = telefiretwo-v0.2
+PROG = $(PROGNAME)-$(VERSION).elf
+HEX = $(PROGNAME)-$(VERSION).ihx
+
+SRC = $(ALTOS_SRC) $(PRODUCT_SRC)
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(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 $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+       rm -f ao_product.h
+
+install:
+
+uninstall:
+
diff --git a/src/telefiretwo-v0.2/ao_pins.h b/src/telefiretwo-v0.2/ao_pins.h
new file mode 100644 (file)
index 0000000..0fddc6d
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define HAS_RADIO              1
+#define HAS_RADIO_RATE         1
+#define HAS_TELEMETRY          0
+
+#define HAS_FLIGHT             0
+#define HAS_USB                        1
+#define HAS_BEEP               1
+#define BEEPER_CHANNEL         4
+#define HAS_GPS                        0
+#define HAS_SERIAL_1           0
+#define HAS_ADC                        1
+#define HAS_DBG                        0
+#define HAS_EEPROM             1
+#define HAS_LOG                        0
+#define HAS_PAD                        1
+#define USE_INTERNAL_FLASH     1
+#define IGNITE_ON_P0           0
+#define PACKET_HAS_MASTER      0
+#define PACKET_HAS_SLAVE       0
+#define AO_DATA_RING           32
+#define HAS_FIXED_PAD_BOX      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)
+
+#define AO_CC1200_FOSC         40000000
+
+/* 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_EEPROM             1
+#define USE_INTERNAL_FLASH     1
+#define USE_EEPROM_CONFIG      1
+#define USE_STORAGE_CONFIG     0
+#define HAS_USB                        1
+#define HAS_RADIO              1
+#define HAS_RADIO_RATE         1
+#define HAS_TELEMETRY          0
+#define HAS_AES                        1
+
+#define HAS_SPI_1              0
+#define SPI_1_PA5_PA6_PA7      0
+#define SPI_1_PB3_PB4_PB5      0
+#define SPI_1_PE13_PE14_PE15   0
+
+#define HAS_SPI_2              1       /* CC1200 */
+#define SPI_2_PB13_PB14_PB15   1
+#define SPI_2_PD1_PD3_PD4      0
+#define SPI_2_GPIO             (&stm_gpiob)
+#define SPI_2_SCK              13
+#define SPI_2_MISO             14
+#define SPI_2_MOSI             15
+#define SPI_2_OSPEEDR          STM_OSPEEDR_10MHz
+
+#define HAS_I2C_1              0
+
+#define HAS_I2C_2              0
+
+#define PACKET_HAS_SLAVE       0
+#define PACKET_HAS_MASTER      0
+
+#define FAST_TIMER_FREQ                10000   /* .1ms for debouncing */
+
+/*
+ * Radio is a cc1200 connected via SPI
+ */
+
+#define AO_RADIO_CAL_DEFAULT   5695733
+
+#define AO_FEC_DEBUG           0
+#define AO_CC1200_SPI_CS_PORT  (&stm_gpioa)
+#define AO_CC1200_SPI_CS_PIN   7
+#define AO_CC1200_SPI_BUS      AO_SPI_2_PB13_PB14_PB15
+#define AO_CC1200_SPI          stm_spi2
+
+#define AO_CC1200_INT_PORT             (&stm_gpiob)
+#define AO_CC1200_INT_PIN              (11)
+
+#define AO_CC1200_INT_GPIO     2
+#define AO_CC1200_INT_GPIO_IOCFG       CC1200_IOCFG2
+
+#define LED_PORT_0             (&stm_gpioa)
+#define LED_PORT_1             (&stm_gpiob)
+
+#define LED_PORT_0_ENABLE      STM_RCC_AHBENR_GPIOAEN
+#define LED_PORT_1_ENABLE      STM_RCC_AHBENR_GPIOBEN
+
+/* Port A, pins 4-6 */
+#define LED_PORT_0_SHIFT       4
+#define LED_PORT_0_MASK                0x7
+#define LED_PIN_GREEN          0
+#define LED_PIN_AMBER          1
+#define LED_PIN_RED            2
+#define AO_LED_RED             (1 << LED_PIN_RED)
+#define AO_LED_AMBER           (1 << LED_PIN_AMBER)
+#define AO_LED_GREEN           (1 << LED_PIN_GREEN)
+
+/* Port B, pins 4-5 */
+#define LED_PORT_1_SHIFT       0
+#define LED_PORT_1_MASK                (0x3 << 4)
+#define LED_PIN_CONT_0         4
+#define LED_PIN_ARMED          5
+
+#define AO_LED_ARMED           (1 << LED_PIN_ARMED)
+#define AO_LED_CONTINUITY(c)   (1 << (4 - (c)))
+#define AO_LED_CONTINUITY_MASK (0x1 << 4)
+
+#define LEDS_AVAILABLE         (LED_PORT_0_MASK|LED_PORT_1_MASK)
+
+/* Alarm A */
+#define AO_SIREN
+#define AO_SIREN_PORT          (&stm_gpiob)
+#define AO_SIREN_PIN           8
+
+/* Alarm B */
+#define AO_STROBE
+#define AO_STROBE_PORT         (&stm_gpiob)
+#define AO_STROBE_PIN          9
+
+#define SPI_CONST      0x00
+
+#define AO_PAD_NUM             1
+#define        AO_PAD_PORT             (&stm_gpioa)
+
+#define AO_PAD_PIN_0           1
+#define AO_PAD_ADC_0           0
+
+#define AO_PAD_ALL_PINS                ((1 << AO_PAD_PIN_0))
+#define AO_PAD_ALL_CHANNELS    ((1 << 0))
+
+/* test these values with real igniters */
+#define AO_PAD_RELAY_CLOSED    3524
+#define AO_PAD_NO_IGNITER      16904
+#define AO_PAD_GOOD_IGNITER    22514
+
+#define AO_PAD_ADC_PYRO                2
+#define AO_PAD_ADC_BATT                8
+
+#define AO_ADC_FIRST_PIN       0
+
+#define AO_NUM_ADC             3
+
+#define AO_ADC_SQ1             AO_PAD_ADC_0
+#define AO_ADC_SQ2             AO_PAD_ADC_PYRO
+#define AO_ADC_SQ3             AO_PAD_ADC_BATT
+
+#define AO_PYRO_R_PYRO_SENSE   200
+#define AO_PYRO_R_SENSE_GND    22
+
+#define AO_FIRE_R_POWER_FET    0
+#define AO_FIRE_R_FET_SENSE    200
+#define AO_FIRE_R_SENSE_GND    22
+
+#define HAS_ADC_TEMP           0
+
+struct ao_adc {
+       int16_t         sense[AO_PAD_NUM];
+       int16_t         pyro;
+       int16_t         batt;
+};
+
+#define AO_ADC_DUMP(p)                                                 \
+       printf ("tick: %5u 0: %5d pyro: %5d batt %5d\n", \
+               (p)->tick,                                              \
+               (p)->adc.sense[0],                                      \
+               (p)->adc.pyro,                                          \
+               (p)->adc.batt)
+
+#define AO_ADC_PINS    ((1 << AO_PAD_ADC_0) | \
+                        (1 << AO_PAD_ADC_PYRO) | \
+                        (1 << AO_PAD_ADC_BATT))
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/telefiretwo-v0.2/ao_telefiretwo.c b/src/telefiretwo-v0.2/ao_telefiretwo.c
new file mode 100644 (file)
index 0000000..38629d8
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+#include <ao.h>
+#include <ao_pad.h>
+#include <ao_exti.h>
+#include <ao_radio_cmac_cmd.h>
+
+void
+main(void)
+{
+       ao_clock_init();
+
+       ao_led_init(LEDS_AVAILABLE);
+
+       ao_task_init();
+
+       ao_timer_init();
+       ao_spi_init();
+       ao_dma_init();
+       ao_exti_init();
+
+       ao_cmd_init();
+
+       ao_adc_init();
+
+       ao_eeprom_init();
+
+       ao_radio_init();
+
+       ao_usb_init();
+
+       ao_config_init();
+
+       ao_pad_init();
+
+//     ao_radio_cmac_cmd_init();
+
+       ao_start_scheduler();
+}
diff --git a/src/telefiretwo-v0.2/flash-loader/.gitignore b/src/telefiretwo-v0.2/flash-loader/.gitignore
new file mode 100644 (file)
index 0000000..65fe7ea
--- /dev/null
@@ -0,0 +1,2 @@
+*.elf
+*.ihx
diff --git a/src/telefiretwo-v0.2/flash-loader/Makefile b/src/telefiretwo-v0.2/flash-loader/Makefile
new file mode 100644 (file)
index 0000000..2b029ee
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=telefiretwo-v0.2
+include $(TOPDIR)/stm/Makefile-flash.defs
diff --git a/src/telefiretwo-v0.2/flash-loader/ao_pins.h b/src/telefiretwo-v0.2/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..daa9048
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * 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>
+
+#define AO_BOOT_PIN                    1
+#define AO_BOOT_APPLICATION_GPIO       stm_gpiob
+#define AO_BOOT_APPLICATION_PIN                6
+#define AO_BOOT_APPLICATION_VALUE      1
+#define AO_BOOT_APPLICATION_MODE       AO_EXTI_MODE_PULL_UP
+
+#endif /* _AO_PINS_H_ */
index 7a21f099c742ebd3440081f90b9427ed1629a491..8c1ced6c035d44a75db7e9b293f03d194adf4b59 100644 (file)
@@ -22,7 +22,6 @@ INC = \
        ao_radio_spi.h \
        ao_radio_cmac.h \
        ao_cc1120_CC1120.h \
-       ao_debounce.h \
        stm32l.h
 
 #
@@ -61,7 +60,6 @@ ALTOS_SRC = \
        ao_fec_tx.c \
        ao_fec_rx.c \
        ao_seven_segment.c \
-       ao_debounce.c \
        ao_quadrature.c \
        ao_button.c \
        ao_event.c \
index 83d3fc43aa803fa92f17554fef1e0e348d566856..0bb0f9dc94816bb2878586bd970085eb3b5415dc 100644 (file)
@@ -23,7 +23,6 @@ INC = \
        ao_radio_cmac.h \
        ao_cc1200_CC1200.h \
        ao_cc1200.h \
-       ao_debounce.h \
        stm32l.h
 
 #
@@ -62,7 +61,6 @@ ALTOS_SRC = \
        ao_fec_tx.c \
        ao_fec_rx.c \
        ao_seven_segment.c \
-       ao_debounce.c \
        ao_quadrature.c \
        ao_button.c \
        ao_event.c \
diff --git a/src/telelcotwo-v0.1/.gitignore b/src/telelcotwo-v0.1/.gitignore
new file mode 100644 (file)
index 0000000..a32ec26
--- /dev/null
@@ -0,0 +1,2 @@
+ao_product.h
+telelco*.elf
diff --git a/src/telelcotwo-v0.1/Makefile b/src/telelcotwo-v0.1/Makefile
new file mode 100644 (file)
index 0000000..42188bb
--- /dev/null
@@ -0,0 +1,96 @@
+#
+# AltOS build for TeleLCO
+#
+#
+
+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 \
+       ao_product.h \
+       ao_radio_spi.h \
+       ao_radio_cmac.h \
+       ao_cc1200_CC1200.h \
+       ao_cc1200.h \
+       stm32l.h
+
+#
+# Common AltOS sources
+#
+
+#PROFILE=ao_profile.c
+#PROFILE_DEF=-DAO_PROFILE=1
+
+ALTOS_SRC = \
+       ao_boot_chain.c \
+       ao_interrupt.c \
+       ao_product.c \
+       ao_romconfig.c \
+       ao_cmd.c \
+       ao_config.c \
+       ao_task.c \
+       ao_led.c \
+       ao_stdio.c \
+       ao_panic.c \
+       ao_timer.c \
+       ao_mutex.c \
+       ao_freq.c \
+       ao_dma_stm.c \
+       ao_spi_stm.c \
+       ao_beep_stm.c \
+       ao_eeprom_stm.c \
+       ao_fast_timer.c \
+       ao_usb_stm.c \
+       ao_exti_stm.c \
+       ao_cc1200.c \
+       ao_radio_cmac.c \
+       ao_aes.c \
+       ao_aes_tables.c \
+       ao_fec_tx.c \
+       ao_fec_rx.c \
+       ao_button.c \
+       ao_event.c \
+       ao_lco_two.c \
+       ao_lco_func.c \
+       ao_lco_cmd.c \
+       ao_radio_cmac_cmd.c
+
+PRODUCT=TeleLCOTwo-v0.1
+PRODUCT_DEF=-DTELELCOTWO
+IDPRODUCT=0x0023
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g
+
+PROGNAME=telelcotwo-v0.1
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_telelcotwo.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(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 $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+       rm -f ao_product.h
+
+install:
+
+uninstall:
diff --git a/src/telelcotwo-v0.1/ao_pins.h b/src/telelcotwo-v0.1/ao_pins.h
new file mode 100644 (file)
index 0000000..ce797a3
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * 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_
+
+/* 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)
+
+#define AO_CC1200_FOSC         40000000
+
+/* 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_EEPROM             1
+#define USE_INTERNAL_FLASH     1
+#define USE_EEPROM_CONFIG      1
+#define USE_STORAGE_CONFIG     0
+#define HAS_USB                        1
+#define HAS_BEEP               1
+#define BEEPER_CHANNEL         4
+#define HAS_RADIO              1
+#define HAS_RADIO_RATE         1
+#define HAS_TELEMETRY          0
+#define HAS_AES                        1
+#define HAS_FIXED_PAD_BOX      1
+
+#define HAS_SPI_1              0
+#define SPI_1_PA5_PA6_PA7      0
+#define SPI_1_PB3_PB4_PB5      0
+#define SPI_1_PE13_PE14_PE15   0
+
+#define HAS_SPI_2              1       /* CC1200 */
+#define SPI_2_PB13_PB14_PB15   1
+#define SPI_2_PD1_PD3_PD4      0
+#define SPI_2_GPIO             (&stm_gpiod)
+#define SPI_2_SCK              13
+#define SPI_2_MISO             14
+#define SPI_2_MOSI             15
+#define SPI_2_OSPEEDR          STM_OSPEEDR_10MHz
+
+#define HAS_I2C_1              0
+
+#define HAS_I2C_2              0
+
+#define PACKET_HAS_SLAVE       0
+#define PACKET_HAS_MASTER      0
+
+#define FAST_TIMER_FREQ                10000   /* .1ms for debouncing */
+
+/*
+ * Radio is a cc1200 connected via SPI
+ */
+
+#define AO_RADIO_CAL_DEFAULT   5695733
+
+#define AO_FEC_DEBUG           0
+#define AO_CC1200_SPI_CS_PORT  (&stm_gpioa)
+#define AO_CC1200_SPI_CS_PIN   7
+#define AO_CC1200_SPI_BUS      AO_SPI_2_PB13_PB14_PB15
+#define AO_CC1200_SPI          stm_spi2
+
+#define AO_CC1200_INT_PORT             (&stm_gpiob)
+#define AO_CC1200_INT_PIN              (11)
+
+#define AO_CC1200_INT_GPIO     2
+#define AO_CC1200_INT_GPIO_IOCFG       CC1200_IOCFG2
+
+#define LOW_LEVEL_DEBUG                0
+
+#define LED_PORT_0             (&stm_gpioa)
+#define LED_PORT_1             (&stm_gpiob)
+
+#define LED_PORT_0_ENABLE      STM_RCC_AHBENR_GPIOAEN
+#define LED_PORT_1_ENABLE      STM_RCC_AHBENR_GPIOBEN
+
+/* Port A, pins 4-6 */
+#define LED_PORT_0_SHIFT       4
+#define LED_PORT_0_MASK                0x7
+
+#define LED_PIN_GREEN          0
+#define LED_PIN_AMBER          1
+#define LED_PIN_RED            2
+
+#define AO_LED_RED             (1 << LED_PIN_RED)
+#define AO_LED_AMBER           (1 << LED_PIN_AMBER)
+#define AO_LED_GREEN           (1 << LED_PIN_GREEN)
+
+/* Port B, pins 3-5 */
+#define LED_PORT_1_SHIFT       0
+#define LED_PORT_1_MASK                (0x7 << 3)
+
+#define LED_PIN_CONTINUITY_1   3
+#define LED_PIN_CONTINUITY_0   4
+#define LED_PIN_REMOTE_ARM     5
+
+#define AO_LED_CONTINUITY_1    (1 << LED_PIN_CONTINUITY_1)
+#define AO_LED_CONTINUITY_0    (1 << LED_PIN_CONTINUITY_0)
+
+#define AO_LED_CONTINUITY_NUM  2
+
+#define AO_LED_REMOTE_ARM      (1 << LED_PIN_REMOTE_ARM)
+
+#define LEDS_AVAILABLE         (AO_LED_RED |           \
+                                AO_LED_AMBER |         \
+                                AO_LED_GREEN |         \
+                                AO_LED_CONTINUITY_1 |  \
+                                AO_LED_CONTINUITY_0 |  \
+                                AO_LED_REMOTE_ARM)
+
+/*
+ * Use event queue for input devices
+ */
+
+#define AO_EVENT               1
+
+/*
+ * Buttons
+ */
+
+#define AO_BUTTON_COUNT                3
+#define AO_BUTTON_MODE         AO_EXTI_MODE_PULL_UP
+
+#define AO_BUTTON_0_PORT       &stm_gpioa
+#define AO_BUTTON_0            0
+
+#define AO_BUTTON_ARM_0                0
+
+#define AO_BUTTON_1_PORT       &stm_gpioa
+#define AO_BUTTON_1            1
+
+#define AO_BUTTON_ARM_1                1
+
+#define AO_BUTTON_ARM_NUM      2
+
+#define AO_BUTTON_2_PORT       &stm_gpioa
+#define AO_BUTTON_2            2
+
+#define AO_BUTTON_FIRE         2
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/telelcotwo-v0.1/ao_telelcotwo.c b/src/telelcotwo-v0.1/ao_telelcotwo.c
new file mode 100644 (file)
index 0000000..318875e
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * 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_exti.h>
+#include <ao_packet.h>
+#include <ao_companion.h>
+#include <ao_profile.h>
+#include <ao_pyro.h>
+#include <ao_aes.h>
+#include <ao_button.h>
+#include <ao_lco.h>
+#include <ao_lco_cmd.h>
+#include <ao_radio_cmac_cmd.h>
+#include <ao_eeprom.h>
+
+int
+main(void)
+{
+       ao_clock_init();
+
+       ao_led_init(LEDS_AVAILABLE);
+       ao_led_on(AO_LED_GREEN);
+       ao_beep_init();
+       ao_task_init();
+
+       ao_timer_init();
+
+       ao_spi_init();
+       ao_dma_init();
+       ao_exti_init();
+
+       ao_cmd_init();
+
+       ao_button_init();
+
+       ao_eeprom_init();
+
+       ao_radio_init();
+
+       ao_usb_init();
+
+       ao_config_init();
+
+       ao_lco_init();
+       ao_lco_cmd_init();
+//     ao_radio_cmac_cmd_init();
+
+       ao_start_scheduler();
+       return 0;
+}
diff --git a/src/telelcotwo-v0.1/flash-loader/Makefile b/src/telelcotwo-v0.1/flash-loader/Makefile
new file mode 100644 (file)
index 0000000..6983331
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=telelcotwo-v0.1
+include $(TOPDIR)/stm/Makefile-flash.defs
diff --git a/src/telelcotwo-v0.1/flash-loader/ao_pins.h b/src/telelcotwo-v0.1/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..266bff6
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+/* External crystal at 8MHz */
+#define AO_HSE         8000000
+
+#include <ao_flash_stm_pins.h>
+
+/* Fire switch. Press at power on to get boot loader */
+
+#define AO_BOOT_PIN                    1
+#define AO_BOOT_APPLICATION_GPIO       stm_gpioa
+#define AO_BOOT_APPLICATION_PIN                2
+#define AO_BOOT_APPLICATION_VALUE      1
+#define AO_BOOT_APPLICATION_MODE       AO_EXTI_MODE_PULL_UP
+
+#endif /* _AO_PINS_H_ */
index 7ccc6085ba1b49139dcf1c6ba164304a2393b19f..1815ef547304c695b4538e6b9657a2f476a9fe73 100644 (file)
@@ -346,6 +346,7 @@ struct ao_adc {
  */
 
 #define HAS_MMA655X            1
+#define AO_MMA655X_INVERT      0
 #define AO_MMA655X_SPI_INDEX   AO_SPI_1_PE13_PE14_PE15
 #define AO_MMA655X_CS_PORT     (&stm_gpiod)
 #define AO_MMA655X_CS_PIN      4
index 664546c2fc02d4ba3aa5b0462b6b0bae747f24dd..b81e59a9a340bb309c88a66a41f09a56d36a554f 100644 (file)
@@ -348,6 +348,7 @@ struct ao_adc {
  */
 
 #define HAS_MMA655X            1
+#define AO_MMA655X_INVERT      0
 #define AO_MMA655X_SPI_INDEX   AO_SPI_1_PE13_PE14_PE15
 #define AO_MMA655X_CS_PORT     (&stm_gpiod)
 #define AO_MMA655X_CS_PIN      4
index 9095a350f1757713637870d80eee78220f5cf82b..242f0ab229216d60b3de0c9573b7fb55a1ff5fc3 100644 (file)
@@ -348,6 +348,7 @@ struct ao_adc {
  */
 
 #define HAS_MMA655X            1
+#define AO_MMA655X_INVERT      0
 #define AO_MMA655X_SPI_INDEX   AO_SPI_1_PE13_PE14_PE15
 #define AO_MMA655X_CS_PORT     (&stm_gpiod)
 #define AO_MMA655X_CS_PIN      4
diff --git a/src/test/plotem b/src/test/plotem
new file mode 100755 (executable)
index 0000000..8bc392c
--- /dev/null
@@ -0,0 +1,10 @@
+gnuplot -persist << EOF
+set ylabel "altitude (m)"
+set y2label "error"
+set xlabel "time (s)"
+set xtics border out nomirror
+set ytics border out nomirror
+set y2tics border out nomirror
+plot "$1" using 1:3 with lines axes x1y1 title "raw height",\
+"$1" using 1:21 with lines axes x1y2 title "error"
+EOF
index 0250a38ee3ef1b4d6ba031e874292574c0f05eac..122b1182c1801d122fce66ff9bd39b06805094d2 100644 (file)
@@ -24,8 +24,8 @@ import java.io.*;
 import java.util.concurrent.*;
 import java.util.*;
 import java.text.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class TeleGPS
        extends AltosUIFrame
index 165981f99e3ca6612fe6f79a07ab84dd61388945..daef1cac5f031f284ae29cfc042884167376b71e 100644 (file)
@@ -22,8 +22,8 @@ import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
 import java.text.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class TeleGPSConfig implements ActionListener {
 
index 5a3a05eb395fc5368085b8c0f0ca28ca46797f7e..0f8a3d25756351c1301098a24fecc7d18e410c4d 100644 (file)
@@ -22,8 +22,8 @@ import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
 import javax.swing.event.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class TeleGPSConfigUI
        extends AltosUIDialog
@@ -54,7 +54,7 @@ public class TeleGPSConfigUI
        JLabel                  version_value;
        JLabel                  serial_value;
        AltosUIFreqList         radio_frequency_value;
-       JTextField              radio_calibration_value;
+       JLabel                  radio_calibration_value;
        JRadioButton            radio_enable_value;
        AltosUIRateList         rate_value;
        JComboBox<String>       aprs_interval_value;
@@ -138,13 +138,6 @@ public class TeleGPSConfigUI
                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");
@@ -316,10 +309,8 @@ public class TeleGPSConfigUI
                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);
+               radio_calibration_value = new JLabel(String.format("%d", 1186611));
                pane.add(radio_calibration_value, c);
-               set_radio_calibration_tool_tip();
                row++;
 
                /* Radio Enable */
@@ -760,10 +751,6 @@ public class TeleGPSConfigUI
                }
        }
 
-       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);
index 4d8fdcc97900ce924a2e7b8d95ace8aa69af91d0..e44b4fedd5d81d477d96b3b58bd0c7f7452ffafa 100644 (file)
@@ -21,8 +21,8 @@ import java.awt.*;
 import javax.swing.*;
 import java.io.*;
 import java.text.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class TeleGPSDisplayThread extends Thread {
 
index e3902d2f63773214f70c2fbdda287bbbe19fef01..233c8c1ae475b8cbbe3473eb92399d76f2d4033e 100644 (file)
@@ -26,8 +26,8 @@ import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
 import java.util.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 import org.jfree.chart.ChartPanel;
 import org.jfree.chart.JFreeChart;
index ae197abe7919ba0918f0a6274ffc77e49f09836d..590f1d1acafdeb95cc14142b3089442ece7cec67 100644 (file)
@@ -21,8 +21,8 @@ import java.util.*;
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class TeleGPSInfo extends AltosUIFlightTab {
 
index eab9350aadabef4cda8126249fa95f58dd9f4c2e..c03b42d32eabb73f58421ec8ef45bda626b7f29b 100644 (file)
@@ -22,7 +22,7 @@ import java.awt.event.*;
 import java.beans.*;
 import javax.swing.*;
 import javax.swing.event.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class TeleGPSPreferences
        extends AltosUIConfigure
index 516eb797002408c5341e96ed952a29c9df781692..46e48fc43d697e5d05b33105a304ebc6350bea16 100644 (file)
@@ -21,8 +21,8 @@ import java.util.*;
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class TeleGPSState extends AltosUIFlightTab {
 
index 3a6b25151abf503c811fdd73b9c605bd855ed103..81a1b305d062cfb757e09f1040bd5bf1e2a82409 100644 (file)
@@ -19,8 +19,8 @@ package org.altusmetrum.telegps;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
 
 public class TeleGPSStatus extends JComponent implements AltosFlightDisplay {
        GridBagLayout   layout;
index 655f42f50df0804cd8bcd176219d5715a9c05c40..6740ff70b912ec8d483bfc7da9da1386abab2b00 100644 (file)
@@ -18,7 +18,7 @@
 package org.altusmetrum.telegps;
 
 import java.awt.event.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
 
 public class TeleGPSStatusUpdate implements ActionListener {