Merge branch 'branch-1.9' into debian
authorBdale Garbee <bdale@gag.com>
Fri, 6 Dec 2019 05:45:10 +0000 (22:45 -0700)
committerBdale Garbee <bdale@gag.com>
Fri, 6 Dec 2019 05:45:10 +0000 (22:45 -0700)
553 files changed:
ChangeLog
Releasing
altosdroid/.classpath [deleted file]
altosdroid/.externalToolBuilders/Generate BuildInfo.java.launch [deleted file]
altosdroid/.gitignore
altosdroid/.settings/org.eclipse.jdt.core.prefs [deleted file]
altosdroid/AndroidManifest.xml.in [deleted file]
altosdroid/Makefile.am
altosdroid/app/build.gradle [new file with mode: 0644]
altosdroid/app/proguard-rules.pro [new file with mode: 0644]
altosdroid/app/src/main/AndroidManifest.xml.in [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosBluetooth.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDebug.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroid.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroidLink.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroidMapInterface.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroidMapSourceListener.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroidPreferences.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroidTab.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosMapOffline.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosMapOnline.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosUsb.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosViewPager.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosVoice.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/BuildInfo.java.in [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/DeviceAddress.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/DeviceListActivity.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/Dumper.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/GoNoGoLights.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/IdleModeActivity.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/IgniterActivity.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/ManageFrequenciesActivity.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/MapTypeActivity.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/PreloadMapActivity.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/SetupActivity.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TabFlight.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TabMap.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TabPad.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TabRecover.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TabsAdapter.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TelemetryLogger.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TelemetryReader.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TelemetryService.java [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TelemetryState.java [new file with mode: 0644]
altosdroid/app/src/main/res/drawable-hdpi/am_status_c.png [new file with mode: 0644]
altosdroid/app/src/main/res/drawable-hdpi/am_status_g.png [new file with mode: 0644]
altosdroid/app/src/main/res/drawable-hdpi/app_icon.png [new file with mode: 0644]
altosdroid/app/src/main/res/drawable-hdpi/ic_maps_indicator_current_position.png [new file with mode: 0644]
altosdroid/app/src/main/res/drawable-mdpi/am_status_c.png [new file with mode: 0644]
altosdroid/app/src/main/res/drawable-mdpi/am_status_g.png [new file with mode: 0644]
altosdroid/app/src/main/res/drawable-mdpi/ic_maps_indicator_current_position.png [new file with mode: 0644]
altosdroid/app/src/main/res/drawable/app_icon.png [new file with mode: 0644]
altosdroid/app/src/main/res/drawable/pad.png [new file with mode: 0644]
altosdroid/app/src/main/res/drawable/rocket.png [new file with mode: 0644]
altosdroid/app/src/main/res/layout/altosdroid.xml [new file with mode: 0644]
altosdroid/app/src/main/res/layout/custom_title.xml [new file with mode: 0644]
altosdroid/app/src/main/res/layout/device_list.xml [new file with mode: 0644]
altosdroid/app/src/main/res/layout/device_name.xml [new file with mode: 0644]
altosdroid/app/src/main/res/layout/frequency.xml [new file with mode: 0644]
altosdroid/app/src/main/res/layout/idle_mode.xml [new file with mode: 0644]
altosdroid/app/src/main/res/layout/igniter_status.xml [new file with mode: 0644]
altosdroid/app/src/main/res/layout/igniters.xml [new file with mode: 0644]
altosdroid/app/src/main/res/layout/manage_frequencies.xml [new file with mode: 0644]
altosdroid/app/src/main/res/layout/map_preload.xml [new file with mode: 0644]
altosdroid/app/src/main/res/layout/map_type.xml [new file with mode: 0644]
altosdroid/app/src/main/res/layout/setup.xml [new file with mode: 0644]
altosdroid/app/src/main/res/layout/tab_flight.xml [new file with mode: 0644]
altosdroid/app/src/main/res/layout/tab_layout.xml [new file with mode: 0644]
altosdroid/app/src/main/res/layout/tab_map.xml [new file with mode: 0644]
altosdroid/app/src/main/res/layout/tab_pad.xml [new file with mode: 0644]
altosdroid/app/src/main/res/layout/tab_recover.xml [new file with mode: 0644]
altosdroid/app/src/main/res/menu/option_menu.xml [new file with mode: 0644]
altosdroid/app/src/main/res/values/Colors.xml [new file with mode: 0644]
altosdroid/app/src/main/res/values/CustomTheme.xml [new file with mode: 0644]
altosdroid/app/src/main/res/values/strings.xml [new file with mode: 0644]
altosdroid/app/src/main/res/xml/device_filter.xml [new file with mode: 0644]
altosdroid/build.gradle [new file with mode: 0644]
altosdroid/build.xml [deleted file]
altosdroid/buildinfo.sh
altosdroid/default.properties [deleted file]
altosdroid/gradle.properties [new file with mode: 0644]
altosdroid/gradle/wrapper/gradle-wrapper.jar [new file with mode: 0644]
altosdroid/gradle/wrapper/gradle-wrapper.properties [new file with mode: 0644]
altosdroid/gradlew [new file with mode: 0755]
altosdroid/gradlew.bat [new file with mode: 0644]
altosdroid/keystore [deleted file]
altosdroid/project.properties [deleted file]
altosdroid/release.keystore [deleted file]
altosdroid/res/drawable-hdpi/am_status_c.png [deleted file]
altosdroid/res/drawable-hdpi/am_status_g.png [deleted file]
altosdroid/res/drawable-hdpi/app_icon.png [deleted file]
altosdroid/res/drawable-hdpi/ic_maps_indicator_current_position.png [deleted file]
altosdroid/res/drawable-mdpi/am_status_c.png [deleted file]
altosdroid/res/drawable-mdpi/am_status_g.png [deleted file]
altosdroid/res/drawable-mdpi/ic_maps_indicator_current_position.png [deleted file]
altosdroid/res/drawable/app_icon.png [deleted file]
altosdroid/res/drawable/pad.png [deleted file]
altosdroid/res/drawable/rocket.png [deleted file]
altosdroid/res/layout/altosdroid.xml [deleted file]
altosdroid/res/layout/custom_title.xml [deleted file]
altosdroid/res/layout/device_list.xml [deleted file]
altosdroid/res/layout/device_name.xml [deleted file]
altosdroid/res/layout/frequency.xml [deleted file]
altosdroid/res/layout/idle_mode.xml [deleted file]
altosdroid/res/layout/igniter_status.xml [deleted file]
altosdroid/res/layout/igniters.xml [deleted file]
altosdroid/res/layout/manage_frequencies.xml [deleted file]
altosdroid/res/layout/map_preload.xml [deleted file]
altosdroid/res/layout/map_type.xml [deleted file]
altosdroid/res/layout/setup.xml [deleted file]
altosdroid/res/layout/tab_flight.xml [deleted file]
altosdroid/res/layout/tab_layout.xml [deleted file]
altosdroid/res/layout/tab_map.xml [deleted file]
altosdroid/res/layout/tab_pad.xml [deleted file]
altosdroid/res/layout/tab_recover.xml [deleted file]
altosdroid/res/menu/option_menu.xml [deleted file]
altosdroid/res/values/Colors.xml [deleted file]
altosdroid/res/values/CustomTheme.xml [deleted file]
altosdroid/res/values/strings.xml [deleted file]
altosdroid/res/xml/device_filter.xml [deleted file]
altosdroid/settings.gradle [new file with mode: 0644]
altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/AltosDebug.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidLink.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapInterface.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapSourceListener.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOffline.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOnline.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/AltosUsb.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/AltosViewPager.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/BuildInfo.java.in [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/DeviceAddress.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/DeviceListActivity.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/Dumper.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/GoNoGoLights.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/IdleModeActivity.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/IgniterActivity.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/ManageFrequenciesActivity.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/MapTypeActivity.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/SetupActivity.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/TabFlight.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/TabRecover.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/TabsAdapter.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java [deleted file]
altosdroid/src/org/altusmetrum/AltosDroid/TelemetryState.java [deleted file]
altoslib/AltosConfigData.java
altoslib/AltosDataListener.java
altoslib/AltosEepromDownload.java
altoslib/AltosEepromFile.java
altoslib/AltosEepromRecordMega.java
altoslib/AltosEepromRecordMicroPeak2.java [new file with mode: 0644]
altoslib/AltosEepromRecordSet.java
altoslib/AltosFrequency.java
altoslib/AltosGPS.java
altoslib/AltosHexfile.java
altoslib/AltosIMU.java
altoslib/AltosIdleFetch.java
altoslib/AltosJson.java
altoslib/AltosLatLon.java
altoslib/AltosLib.java
altoslib/AltosMap.java
altoslib/AltosMapPath.java
altoslib/AltosMapPathPoint.java
altoslib/AltosMapTransform.java
altoslib/AltosPointDouble.java
altoslib/AltosRecordSet.java
altoslib/AltosTelemetryFile.java
altoslib/AltosTelemetrySensor.java
altoslib/AltosUnits.java
altoslib/Makefile.am
altosui/AltosConfigFCUI.java
altosui/AltosGraphUI.java
altosui/AltosUI.java
altosui/Makefile.am
altosuilib/AltosFlashUI.java
altosuilib/AltosRomconfigUI.java
altosuilib/AltosUIGraph.java
altosuilib/AltosUIMap.java
altosuilib/Makefile.am
ao-bringup/test-chaoskey
ao-bringup/test-telemetrum
ao-bringup/test-telemetrum-v2.0 [new file with mode: 0755]
ao-bringup/turnon_telefireeight [new file with mode: 0755]
ao-bringup/turnon_telemetrum
ao-bringup/turnon_telemetrum_v2.0 [new file with mode: 0755]
ao-tools/Makefile.am
ao-tools/ao-bitbang/Makefile.am
ao-tools/ao-bm70/Makefile.am [new file with mode: 0644]
ao-tools/ao-boot-stm32/Makefile.am [new file with mode: 0644]
ao-tools/ao-cal-accel/Makefile.am
ao-tools/ao-cal-accel/ao-cal-accel.c
ao-tools/ao-cal-freq/Makefile.am
ao-tools/ao-cal-freq/ao-cal-freq.c
ao-tools/ao-chaosread/.gitignore [deleted file]
ao-tools/ao-chaosread/Makefile.am [deleted file]
ao-tools/ao-chaosread/ao-chaosread.1 [deleted file]
ao-tools/ao-chaosread/ao-chaosread.c [deleted file]
ao-tools/ao-dbg/Makefile.am
ao-tools/ao-dbg/ao-dbg-command.c
ao-tools/ao-dbg/ao-dbg-main.c
ao-tools/ao-dbg/ao-dbg-parse.c
ao-tools/ao-dbg/ao-dbg.h
ao-tools/ao-dump-up/Makefile.am
ao-tools/ao-dump-up/ao-dump-up.1
ao-tools/ao-dump-up/ao-dump-up.c
ao-tools/ao-dumpflash/Makefile.am
ao-tools/ao-dumpflash/ao-dumpflash.c
ao-tools/ao-dumplog/Makefile.am
ao-tools/ao-edit-telem/Makefile.am
ao-tools/ao-edit-telem/ao-edit-telem.c
ao-tools/ao-eeprom/Makefile.am
ao-tools/ao-eeprom/ao-eeprom.1
ao-tools/ao-eeprom/ao-eeprom.c
ao-tools/ao-elftohex/Makefile.am
ao-tools/ao-list/Makefile.am
ao-tools/ao-load/Makefile.am
ao-tools/ao-load/ao-load.c
ao-tools/ao-makebin/Makefile.am
ao-tools/ao-mega/Makefile.am
ao-tools/ao-postflight/Makefile.am
ao-tools/ao-rawload/Makefile.am
ao-tools/ao-rawload/ao-rawload.c
ao-tools/ao-send-telem/Makefile.am
ao-tools/ao-send-telem/ao-send-telem.c
ao-tools/ao-sky-flash/Makefile.am
ao-tools/ao-sky-flash/sky_bin.c
ao-tools/ao-sky-flash/sky_flash.c
ao-tools/ao-sky-flash/sky_flash.h
ao-tools/ao-sky-flash/sky_serial.c
ao-tools/ao-stmload/Makefile.am
ao-tools/ao-telem/Makefile.am
ao-tools/ao-telem/ao-telem.1
ao-tools/ao-telem/ao-telem.c
ao-tools/ao-test-baro/Makefile.am
ao-tools/ao-test-baro/ao-test-baro.c
ao-tools/ao-test-flash/Makefile.am
ao-tools/ao-test-flash/ao-test-flash.c
ao-tools/ao-test-gps/Makefile.am
ao-tools/ao-test-gps/ao-test-gps.c
ao-tools/ao-test-igniter/Makefile.am
ao-tools/ao-test-igniter/ao-test-igniter.c
ao-tools/ao-usbload/Makefile.am
ao-tools/ao-usbload/ao-usbload.c
ao-tools/ao-usbtrng/Makefile.am
ao-tools/ao-usbtrng/ao-usbtrng.c
ao-tools/ao-view/Makefile.am
ao-tools/lib/Makefile.am
ao-tools/lib/ao-atmosphere.c [new file with mode: 0644]
ao-tools/lib/ao-atmosphere.h [new file with mode: 0644]
ao-tools/lib/ao-editaltos.c
ao-tools/lib/ao-eeprom-read.c [new file with mode: 0644]
ao-tools/lib/ao-eeprom-read.h [new file with mode: 0644]
ao-tools/lib/ao-hex.c
ao-tools/lib/ao-ms5607-convert.c [new file with mode: 0644]
ao-tools/lib/ao-ms5607.h [new file with mode: 0644]
ao-tools/lib/cc-convert.c
ao-tools/lib/cc-logfile.c
ao-tools/lib/cc-process.c
ao-tools/lib/cc-telemetry.h
ao-tools/lib/cc-usbdev.c
configure.ac
doc/Makefile.am
doc/RELNOTES
doc/altosui.inc
doc/altusmetrum-theme.yml
doc/altusmetrum.txt
doc/config-device.inc
doc/easymini-release-notes.inc
doc/easymini.txt
doc/flight-data-recording.inc
doc/getting-started.inc
doc/graph-map.png
doc/intro.inc
doc/micropeak-flight-foam.png [new file with mode: 0644]
doc/micropeak-flight-nofoam.png [new file with mode: 0644]
doc/micropeak-foam.jpg [new file with mode: 0644]
doc/micropeak.txt
doc/release-notes-1.9.1.inc [new file with mode: 0644]
doc/release-notes.inc
doc/specs.inc
doc/system-operation.inc
doc/telegps-release-notes.inc
doc/telegps-using.inc
doc/telegps.txt
doc/telelaunch-acknowledgements.inc [new file with mode: 0644]
doc/telelaunch-cables.inc [new file with mode: 0644]
doc/telelaunch-configuration.inc [new file with mode: 0644]
doc/telelaunch-intro.inc [new file with mode: 0644]
doc/telelaunch-operation.inc [new file with mode: 0644]
doc/telelaunch-specs.inc [new file with mode: 0644]
doc/telelaunch-troubleshooting.inc [new file with mode: 0644]
doc/telelaunch-updating-firmware.inc [new file with mode: 0644]
doc/telelaunch.txt [new file with mode: 0644]
doc/telemetrum.inc
doc/telemetry.txt
doc/updating-firmware.inc
icon/.gitignore
icon/Makefile.am
icon/altosdroid.png [new file with mode: 0644]
icon/altosdroid.svg [new file with mode: 0644]
libaltos/.gitignore
libaltos/Makefile.am
map-server/altos-mapd/Makefile.am
map-server/altos-mapj/Makefile.am
micropeak/Makefile.am
src/Makedefs.in
src/Makefile
src/Makefile.defs [new file with mode: 0644]
src/Version.in [deleted file]
src/attiny/Makefile-attiny.defs [new file with mode: 0644]
src/attiny/Makefile.defs [new file with mode: 0644]
src/attiny/ao_arch.h
src/attiny/ao_clock.c
src/attiny/ao_exti.c
src/avr-demo/Makefile
src/avr/Makefile-avr.defs [new file with mode: 0644]
src/avr/Makefile.defs
src/avr/ao_arch.h
src/chaoskey-v0.1/Makefile
src/chaoskey-v1.0/Makefile
src/chaoskey-v1.0/ao_chaoskey.c
src/cortexelf-v1/Makefile
src/detherm/Makefile
src/drivers/ao_25lc1024.c
src/drivers/ao_ads124s0x.c [new file with mode: 0644]
src/drivers/ao_ads124s0x.h [new file with mode: 0644]
src/drivers/ao_ads131a0x.h [new file with mode: 0644]
src/drivers/ao_adxl375.c
src/drivers/ao_aprs.c
src/drivers/ao_at45db161d.c
src/drivers/ao_bmx160.c [new file with mode: 0644]
src/drivers/ao_bmx160.h [new file with mode: 0644]
src/drivers/ao_btm.c
src/drivers/ao_button.c
src/drivers/ao_cc115l.c
src/drivers/ao_companion.c
src/drivers/ao_gps_skytraq.c
src/drivers/ao_hmc5883.c
src/drivers/ao_lco.c
src/drivers/ao_lco_two.c
src/drivers/ao_led.c
src/drivers/ao_max6691.c [new file with mode: 0644]
src/drivers/ao_max6691.h [new file with mode: 0644]
src/drivers/ao_mma655x.c
src/drivers/ao_mpu6000.c
src/drivers/ao_mpu9250.c
src/drivers/ao_ms5607.c
src/drivers/ao_packet.c
src/drivers/ao_packet_master.c
src/drivers/ao_packet_slave.c
src/drivers/ao_pad.c
src/drivers/ao_radio_master.c
src/drivers/ao_radio_slave.c
src/drivers/ao_rn4678.c
src/easymega-v1.0/Makefile
src/easymega-v2.0/.gitignore [new file with mode: 0644]
src/easymega-v2.0/Makefile
src/easymega-v3.0/.gitignore [new file with mode: 0644]
src/easymega-v3.0/Makefile [new file with mode: 0644]
src/easymega-v3.0/ao_easymega.c [new file with mode: 0644]
src/easymega-v3.0/ao_pins.h [new file with mode: 0644]
src/easymega-v3.0/flash-loader/Makefile [new file with mode: 0644]
src/easymega-v3.0/flash-loader/ao_pins.h [new file with mode: 0644]
src/easymini-v1.0/Makefile
src/easymini-v1.0/ao_easymini.c
src/easymini-v2.0/Makefile
src/easymini-v2.0/ao_easymini.c
src/fox1ihu/Makefile
src/kernel/ao.h
src/kernel/ao_config.c
src/kernel/ao_data.h
src/kernel/ao_ee_fake.c
src/kernel/ao_flight.h
src/kernel/ao_freq.c
src/kernel/ao_gps_report.c
src/kernel/ao_gps_report_mega.c
src/kernel/ao_gps_report_metrum.c
src/kernel/ao_host.h
src/kernel/ao_ignite.c
src/kernel/ao_led.h
src/kernel/ao_log.c
src/kernel/ao_log.h
src/kernel/ao_log_fireone.c
src/kernel/ao_log_gps.h
src/kernel/ao_log_telem.c
src/kernel/ao_log_telestatic.c [new file with mode: 0644]
src/kernel/ao_monitor.c
src/kernel/ao_radio_cmac.c
src/kernel/ao_report.c
src/kernel/ao_send_packet.c
src/kernel/ao_serial.h
src/kernel/ao_stdio.c
src/kernel/ao_storage.c
src/kernel/ao_task.c
src/kernel/ao_task.h
src/kernel/ao_telemetry.c
src/lambdakey-v1.0/Makefile
src/lambdakey-v1.0/ao_lambdakey.c
src/lpc/Makefile-flash.defs
src/lpc/Makefile-lpc.defs
src/lpc/Makefile.defs
src/lpc/ao_arch.h
src/lpc/ao_arch_funcs.h
src/lpc/ao_exti.h
src/lpc/ao_exti_lpc.c
src/lpc/ao_led_lpc.c
src/lpc/ao_timer_lpc.c
src/lpc/ao_usb_lpc.c
src/lpc/clock_figure.5c [new file with mode: 0644]
src/lpc/lpc.h
src/lpcxpresso/Makefile
src/microkite/Makefile
src/microkite/ao_pins.h
src/micropeak-v2.0/.gitignore
src/micropeak-v2.0/Makefile
src/micropeak-v2.0/ao_micropeak.c
src/micropeak-v2.0/ao_pins.h
src/micropeak/Makefile
src/micropeak/ao_pins.h
src/microsplash/Makefile
src/microsplash/ao_pins.h
src/mpusb-v3.0/Makefile
src/nucleao-32/Makefile
src/pnpservo-v1/Makefile
src/product/ao_terraui.c
src/stm-bringup/Makefile
src/stm-demo/Makefile
src/stm-demo/ao_demo.c
src/stm-flash/Makefile
src/stm-scheme-newlib/Makefile
src/stm-vga/Makefile
src/stm/Makefile-flash.defs
src/stm/Makefile-stm.defs [new file with mode: 0644]
src/stm/Makefile.defs
src/stm/ao-parse-font.5c
src/stm/ao_adc_single_stm.c
src/stm/ao_adc_stm.c
src/stm/ao_arch.h
src/stm/ao_arch_funcs.h
src/stm/ao_beep_stm.c
src/stm/ao_exti.h
src/stm/ao_exti_stm.c
src/stm/ao_i2c_stm.c
src/stm/ao_lcd_font.c
src/stm/ao_lcd_font.h
src/stm/ao_lcd_font_bits.h [new file with mode: 0644]
src/stm/ao_led_stm.c
src/stm/ao_profile.h
src/stm/ao_serial_stm.c
src/stm/ao_timer.c
src/stm/ao_usb_stm.c
src/stm/stm32l.h
src/stm32f4-disco/Makefile
src/stm32f4-disco/ao_disco.c
src/stm32f4/Makefile-flash.defs
src/stm32f4/Makefile-stm32f4.defs
src/stm32f4/Makefile.defs
src/stm32f4/ao_arch.h
src/stm32f4/ao_arch_funcs.h
src/stm32f4/ao_exti.h
src/stm32f4/ao_exti_stm32f4.c
src/stm32f4/ao_timer.c
src/stm32f4/ao_usb_gen.c
src/stm32f4/ao_usb_gen.h
src/stm32f4/ao_usb_stm32f4.c
src/stm32f4/stm32f4.h
src/stmf0/Makefile-flash.defs
src/stmf0/Makefile-stmf0.defs
src/stmf0/Makefile.defs
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
src/stmf0/ao_interrupt.c
src/stmf0/ao_serial_stm.c
src/stmf0/ao_spi_stm.c
src/stmf0/ao_storage_stm.c
src/stmf0/ao_timer.c
src/stmf0/ao_usb_stm.c
src/stmf0/stm32f0.h
src/teleballoon-v2.0/Makefile
src/telebt-v3.0/Makefile
src/telebt-v4.0/Makefile
src/teledongle-v3.0/Makefile
src/telefireeight-v1.0/Makefile
src/telefireeight-v1.0/ao_telefireeight.c
src/telefireeight-v2.0/.gitignore [new file with mode: 0644]
src/telefireeight-v2.0/Makefile [new file with mode: 0644]
src/telefireeight-v2.0/ao_pins.h [new file with mode: 0644]
src/telefireeight-v2.0/ao_telefireeight.c [new file with mode: 0644]
src/telefireeight-v2.0/flash-loader/.gitignore [new file with mode: 0644]
src/telefireeight-v2.0/flash-loader/Makefile [new file with mode: 0644]
src/telefireeight-v2.0/flash-loader/ao_pins.h [new file with mode: 0644]
src/telefireone-v1.0/.gitignore [new file with mode: 0644]
src/telefireone-v1.0/Makefile
src/telefireone-v1.0/ao_pins.h
src/telefireone-v1.0/ao_telefireone.c
src/telefireone-v2.0/Makefile [new file with mode: 0644]
src/telefireone-v2.0/ao_pins.h [new file with mode: 0644]
src/telefireone-v2.0/ao_telefireone.c [new file with mode: 0644]
src/telefireone-v2.0/flash-loader/.gitignore [new file with mode: 0644]
src/telefireone-v2.0/flash-loader/Makefile [new file with mode: 0644]
src/telefireone-v2.0/flash-loader/ao_pins.h [new file with mode: 0644]
src/telefiretwo-v0.1/Makefile
src/telefiretwo-v0.1/ao_telefiretwo.c
src/telefiretwo-v0.2/Makefile
src/telegps-v0.1/Makefile
src/telegps-v0.3/Makefile
src/telegps-v1.0/Makefile
src/telegps-v2.0/Makefile
src/telelco-v0.2-cc1200/.gitignore [new file with mode: 0644]
src/telelco-v0.2-cc1200/Makefile
src/telelco-v0.2/Makefile
src/telelco-v0.3/Makefile
src/telelco-v2.0/Makefile
src/telelco-v2.0/ao_lco_v2.c
src/telelcotwo-v0.1/Makefile
src/telemega-v0.1/Makefile
src/telemega-v1.0/Makefile
src/telemega-v2.0/Makefile
src/telemega-v3.0/Makefile
src/telemetrum-v2.0/Makefile
src/telemetrum-v3.0/Makefile
src/telemetrum-v3.0/ao_pins.h
src/telemetrum-v3.0/ao_telemetrum.c
src/telemini-v3.0/Makefile
src/telemini-v3.0/ao_telemini.c
src/telestatic-v3.0/.gitignore [new file with mode: 0644]
src/telestatic-v3.0/Makefile [new file with mode: 0644]
src/telestatic-v3.0/ao_pins.h [new file with mode: 0644]
src/telestatic-v3.0/ao_telestatic.c [new file with mode: 0644]
src/telestatic-v3.0/flash-loader/.gitignore [new file with mode: 0644]
src/telestatic-v3.0/flash-loader/Makefile [new file with mode: 0644]
src/telestatic-v3.0/flash-loader/ao_pins.h [new file with mode: 0644]
src/test/ao_aprs_test.c
src/test/ao_flight_test.c
src/tmgps-v2.0/Makefile
src/vidtime/Makefile
telegps/Makefile.am
telegps/TeleGPS.java
telegps/TeleGPSGraphUI.java

index 130dd1998ae1fb2f7dca6a7bc84bf0a8654a8a72..b6749b6defb8f5d47933f318a2e93c0486510f0c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
+commit fdf1dbd3d945f6f34f404ffbcb57781f4df23015
+Merge: 5b4da841 bfc4999c
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Thu Dec 5 22:21:29 2019 -0700
+
+    Merge branch 'master' into branch-1.9
+
+commit bfc4999c99dc7ba29226a956f3991c2a45a1dd88
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Thu Dec 5 22:18:12 2019 -0700
+
+    update release date in all documents
+
+commit 55af5c3a0df734cedbac98bbe350846add45d5e3
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Thu Dec 5 22:15:21 2019 -0700
+
+    start the process of releasing 1.9.1
+
+commit 2ff2b4962f3241ede9a7718e373a68296c4e308a
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Dec 5 21:05:28 2019 -0800
+
+    Release note about self-flashing on windows waiting for devices
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 695dba4e37ccca9a2dc06e1656699a13406002c1
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Dec 5 16:59:40 2019 -0800
+
+    altosuilib: Wait for Windows to get ready with new device
+    
+    Windows appears to report the new device path long before
+    the path is actually usable. Stick some long delays trying to
+    open the device before giving up.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2b3c6806a3039ac8c4c1a1e2d6715b0cdc5b9632
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Dec 3 19:34:06 2019 -0800
+
+    altosuilib: Show the recovered product name in the Configure Rom dialog
+    
+    This lets the user know that things are actually working as expected
+    as the correct device name should appear in the dialog.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5bdf8eeb1cdc1a50c9abd0f8962533f6970bd7f0
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Dec 3 19:31:34 2019 -0800
+
+    altoslib: Linker script changed -> the USB desc is two bytes off
+    
+    The USB descriptor used to be at 0x0800110c in previous releases and
+    is now at 0x0800110a, presumably because the linker script changed the
+    padding requirements of those sections.
+    
+    Search forward and backwards two bytes to see if we can't find the
+    descriptors by checking for the descriptor value and size at each
+    location.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 946faa1541f69c6cf2759c13760fa9bc16e2298e
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Nov 26 15:47:07 2019 -0800
+
+    doc: Update docs to reference TeleMetrum v3 where appropriate
+    
+    Mostly just add 'or newer' to various TeleMetrum v2 bits. Also add
+    specs for the v3 board.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 68aa05881239264b95e37c648faa821fd0230402
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Nov 26 15:33:25 2019 -0800
+
+    doc: Mention TeleMetrum v3.0 in release notes for 1.9.1
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 56767df42a2582c9663554f27b354c2b9c180119
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Nov 25 18:38:14 2019 -0800
+
+    ao-telem: Show all 24 bits of GPS altitude data
+    
+    Need to mix in the upper 8 bits from devices which include them.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4a47071b7f23874ca3d889ba18cd218d6445df29
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Nov 25 18:36:16 2019 -0800
+
+    altos: Send "metrum" telemetry packets for TeleMetrum v3.0 boards
+    
+    This includes the ADC values, which report igniter continuity
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 66b6b2d5fb1313d5e16a3f802c2af8cc6585362b
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Nov 25 18:15:16 2019 -0800
+
+    altoslib: Set up adxl375 for TM v3.0 in idle mode
+    
+    Need to select axis and polarity for each adxl375 product.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9bb091f6d6aec6e5e887eebc93174106b25a7a98
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Mon Nov 25 18:02:06 2019 -0700
+
+    ao-bringup: add production test support for TeleMetrum v3.0
+
+commit f95b359aa1a3ba3982a162bdf398d0b261806d47
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Mon Nov 25 17:57:27 2019 -0700
+
+    altosuilib: TeleMetrum v3, like v2, doesn't use flash for config
+
+commit 8554da3b6c05c1094045f4fb21b43c183029408f
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Mon Nov 25 17:55:10 2019 -0700
+
+    altosui: add TeleMetrum v3 to delivered firmware list
+
+commit 0072e9741719367a1f6748d242cd6195a1a7c6a5
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Mon Nov 25 17:50:41 2019 -0700
+
+    altosui: add monitor idle support for TeleMetrum v3
+
+commit 6d55d03587e9f71a7e8320a6b36fde25edc63b28
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Nov 22 17:18:58 2019 -0800
+
+    altos: TeleMetrum v3.0 has ADXL375 and Max-8Q
+    
+    Replacce the mma655x driver with the adxl375 driver
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b215bed45798ea30f8f13128204493e7afdc9af1
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Oct 27 10:24:52 2019 -0700
+
+    altoslib: Fix original telemetry sensor packet parsing
+    
+    ground_pres is at byte 24, ground_accel at byte 26. These were flipped
+    around.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit cdbc29d6d86c69e70b0f105d273ee8ddd7ae290e
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Oct 27 10:24:10 2019 -0700
+
+    altoslib: Fix setting of CLASSPATH
+    
+    Need to include bin for local files.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3aeb1a310069811a2e043a5df28dc2df17436fc4
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Wed Oct 23 10:43:54 2019 -0600
+
+    doc: add some text about cross-bank drag race safe/arm to TeleLaunch manual
+
+commit 1cb529e0532d0a7430487c856bb9b037ff6cea0f
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Wed Oct 23 10:41:30 2019 -0600
+
+    doc: add some text to TeleLaunch troubleshooting about SAFE/ARM on TeleFire
+
+commit 88e279b15b3d2357f142e58d20d73c24bf2561eb
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Oct 23 09:24:18 2019 -0700
+
+    altos: Improve labeling of telefire receive packet information
+    
+    Avoid the use of 'cmac_recv', which is not exactly descriptive.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c31db066e5ba7a6708ebe4bf350963697c611816
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Oct 23 09:20:53 2019 -0700
+
+    altos: Relabel packet receive status line for TeleFire boxes
+    
+    The status line included return value and RSSI, but neither was
+    labeled, which left the user unsure as to what it meant.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b6602d8c4053932a72c2bf4a63e24793634b2ad0
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Tue Oct 22 09:30:25 2019 -0600
+
+    doc: add more text to TeleLaunch manual, be less sloppy with dBm assertions
+
+commit c349eb9d1b90abd7c0492b5d0ba2116ae5ad6ec2
+Author: Mike Beattie <mike@ethernal.org>
+Date:   Sun Oct 13 20:22:37 2019 +1300
+
+    Update app to use Material Design Light theme
+    
+    The Holo theme does weird things these days
+    
+    Signed-off-by: Mike Beattie <mike@ethernal.org>
+
+commit b8560bd91d603e4697f0cddc095952f923366d30
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Oct 18 01:06:55 2019 -0700
+
+    altoslib: Don't bother adding FREETTS to CLASSPATH
+    
+    altoslib doesn't use freetts at all
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4696687ef84181e363ac79f43016d347d7e14a23
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Oct 18 01:05:15 2019 -0700
+
+    altosdroid: Make altosdroid code more resilient to weird androidisms
+    
+    Sometimes altosdroid was crashing when messing with configuration bits
+    like selecting different themes. These fixes seem to make that happen
+    less.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8be4e3b8faac362665641e98a1df1e1e8a681b7a
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Oct 18 01:02:51 2019 -0700
+
+    altos/test: Get test code working again after restructuring
+    
+    Something changed, the test code wasn't building. Now it does.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8d5792e32dc35441ec98339149fb4df3cc16f44b
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Oct 17 23:09:47 2019 -0700
+
+    altos/telefire: Don't arm the box if the local arm switch is off
+    
+    This skips arming the box when the local arming switch is off. This
+    keeps the siren and light from going off, and also avoids attempting
+    to fire the channels in case something else screwy is going on.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 75cd8196ee9ba4ed983abdc83f1fe60fb94f2866
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Mon Sep 30 21:15:56 2019 -0600
+
+    TeleFireEight has simple green LEDs for continuity
+
+commit ff68c8855bc6983638db5102ffbc6822b83edb5d
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Sep 25 13:10:36 2019 -0700
+
+    telegps: Get --graph mode working after recent changes
+    
+    Was just exiting due to a null pointer exception caused by mis-ordered
+    setup of the map data. Also using stale API.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 35351c7db337c4384ef642fbc8b8676f0944686a
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Sep 25 13:09:22 2019 -0700
+
+    altoslib: Don't crash when map flight data is missing
+    
+    Just a couple of null pointer checks to allow the map display to come
+    up even when no data are available.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4df77f2ac7f34986b8e7c0584c57d77dc74d9df9
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Sep 24 20:49:56 2019 -0700
+
+    doc: Update for 1.9.1
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 51cca3b3405da7408fd8af18f8d1ff7db97fe1bc
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Sep 24 20:50:08 2019 -0700
+
+    doc: Describe new 'show nearest values' in map view
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6032ca7f418924e5794a886c06ca752dee0ada83
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Sep 23 12:40:19 2019 -0700
+
+    altos: Rename 'log' in ao_log_fireone to 'ao_fireone_data'
+    
+    Avoids conflict with global 'log' function
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 77e6bad5e66023e487430ef31244edaeaef7c606
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Sep 23 12:39:42 2019 -0700
+
+    altos: Switch all main() to return 'int'
+    
+    Makes gcc happy
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3979c88417fd5512447f5d02cc660522dff5d9d6
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Sep 18 17:38:44 2019 -0700
+
+    altosdroid: Update Makefile.am to run gradle-based build
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d607cbee5c9b406ef0f4e522c12e56993632cf00
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Sep 18 17:10:14 2019 -0700
+
+    altos: Add missing build files for avr/attiny devices
+    
+    These were sitting in my src directory but not in git
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 260dd06107c8f8f5c7e606a283d388cb3ba46465
+Merge: 28618a72 faa5abe0
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Sep 18 16:26:44 2019 -0700
+
+    Merge remote-tracking branch 'mjb/android-build-update'
+
+commit faa5abe0bc9aa071ffa55534a24638bc0972e3c2
+Author: Mike Beattie <mike@ethernal.org>
+Date:   Thu Sep 19 10:26:40 2019 +1200
+
+    Update Google Maps API usage.
+    
+    Signed-off-by: Mike Beattie <mike@ethernal.org>
+
+commit 3af69b00a94b473dbc98fcf6d26fa90b66065e8b
+Author: Mike Beattie <mike@ethernal.org>
+Date:   Thu Sep 19 10:25:47 2019 +1200
+
+    Update persistent notification in TelemetryService
+    
+    Signed-off-by: Mike Beattie <mike@ethernal.org>
+
+commit be9ed3ffc9b00c97e8513bbfab23b8e16329bc4b
+Author: Mike Beattie <mike@ethernal.org>
+Date:   Thu Sep 19 10:25:09 2019 +1200
+
+    Convert to AndroidX from support_v4
+    
+    Signed-off-by: Mike Beattie <mike@ethernal.org>
+
+commit d7ef39ba104a1ac6024af875c730a645f282719f
+Author: Mike Beattie <mike@ethernal.org>
+Date:   Thu Sep 19 10:24:13 2019 +1200
+
+    Import cleanup
+    
+    Signed-off-by: Mike Beattie <mike@ethernal.org>
+
+commit 5c1acdabd211346936423ec8bc147a47f62bb8ae
+Author: Mike Beattie <mike@ethernal.org>
+Date:   Thu Sep 19 10:19:11 2019 +1200
+
+    Commented out duplicate strings
+    
+    Signed-off-by: Mike Beattie <mike@ethernal.org>
+
+commit ffdac6b48b43dc5610ddb926191a7cff738c97de
+Author: Mike Beattie <mike@ethernal.org>
+Date:   Thu Sep 19 10:18:48 2019 +1200
+
+    Indentation cleanup
+    
+    Signed-off-by: Mike Beattie <mike@ethernal.org>
+
+commit b6cb79994a58f37f6c743c1f2fafe30337e89d79
+Author: Mike Beattie <mike@ethernal.org>
+Date:   Thu Sep 19 10:17:52 2019 +1200
+
+    Add FOREGROUND_SERVICE permission which is now required
+    
+    Signed-off-by: Mike Beattie <mike@ethernal.org>
+
+commit f2c652d5115eb64568d9ae8ed6426a16e6154999
+Author: Mike Beattie <mike@ethernal.org>
+Date:   Thu Sep 19 10:17:09 2019 +1200
+
+    Remove versioning data from AndroidManifest.xml.in
+    
+    (now in build.gradle)
+    
+    Signed-off-by: Mike Beattie <mike@ethernal.org>
+
+commit 198c868a25b3cbcde9634bbbcce57d71f3659eee
+Author: Mike Beattie <mike@ethernal.org>
+Date:   Thu Sep 19 10:16:18 2019 +1200
+
+    Clean up duplication in AndroidManifest.xml.in
+    
+    Signed-off-by: Mike Beattie <mike@ethernal.org>
+
+commit 1ba8ffe41defe411390197c56b03762fa51c20bf
+Author: Mike Beattie <mike@ethernal.org>
+Date:   Thu Sep 19 10:12:59 2019 +1200
+
+    buildinfo data comes from Makedefs now, not Version
+    
+    Signed-off-by: Mike Beattie <mike@ethernal.org>
+
+commit 3c4d4d5cc1a8361a713aba075b29c3f6509f3f90
+Author: Mike Beattie <mike@ethernal.org>
+Date:   Thu Sep 19 10:12:30 2019 +1200
+
+    Add gradle build files
+    
+    Signed-off-by: Mike Beattie <mike@ethernal.org>
+
+commit 70fb078cac4203e76e04211a0b8f1a6eceb6298b
+Author: Mike Beattie <mike@ethernal.org>
+Date:   Thu Sep 19 10:09:26 2019 +1200
+
+    Update files that reference new paths
+    
+    Signed-off-by: Mike Beattie <mike@ethernal.org>
+
+commit 8b53f860eb3171cd43e4bd0e440f2889bd810662
+Author: Mike Beattie <mike@ethernal.org>
+Date:   Thu Sep 19 10:04:58 2019 +1200
+
+    Move java source, and resources to new paths for gradle
+    
+    Signed-off-by: Mike Beattie <mike@ethernal.org>
+
+commit 4a257455b2dc57069c41e1845daf66239c5cbe1d
+Author: Mike Beattie <mike@ethernal.org>
+Date:   Thu Sep 19 09:58:06 2019 +1200
+
+    Remove ant build files
+    
+    Signed-off-by: Mike Beattie <mike@ethernal.org>
+
+commit 28618a728e85b70ecac73983531894a25e90d7f6
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Sep 16 13:12:08 2019 -0700
+
+    altos: Add EasyMega v3.0 bits (not setup correctly yet)
+    
+    This adds a new directory for EasyMega v3.0, replacing the mpu9250
+    with a bmx160.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 28add4f616dbaf06a1ca3234b81c68c4a299d056
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Sep 16 13:10:09 2019 -0700
+
+    altos: Integrate BMX160 into data code
+    
+    Get conversion functions written and fix up a few warnings
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a87698663f8a5ced468755068a0468755d8f2746
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Sep 16 12:39:09 2019 -0700
+
+    altos: Add bmx160 driver
+    
+    This just adds the driver, it doesn't hook it up yet
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 99525a748e00406424b98a0952f0156437b30b6c
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Sep 15 17:09:26 2019 -0700
+
+    altos: Replace ao_xmem functions with direct mem calls
+    
+    We no longer need to wrap these functions
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 46d3cbadce6808b4cd29ad1e034efac7b5e4fa42
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Sep 15 17:05:59 2019 -0700
+
+    drivers: Use 'main_value' instead of 'main'
+    
+    GCC can emit a warning when programs redefine 'main'.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2524730217e6972f3d0f04a9954350ba1964a83a
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Sep 2 15:20:14 2019 -0500
+
+    altosui: Add speed and gps height to map display data
+    
+    And generalize the API so that any other GPS data could be added in
+    the future.
+    
+    This feature was proposed by Mike Beattie
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b13893245e8c66b48e23bb2005ef6ce46e69744f
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Aug 31 23:20:31 2019 -0500
+
+    altosui: Display data for point nearest cursor in map view
+    
+    Include time, lat and lon
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 936a5ff21d01db6f0084ee7e4712042c914942a5
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Aug 28 22:40:21 2019 -0500
+
+    libaltos: gitignore btletest
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 252009db6451f01c9707970d05e69f39e3a047dd
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Aug 28 22:39:25 2019 -0500
+
+    Add .gitignore files for new projects
+    
+    EasyMega v2.0
+    TeleFireEight v2.0
+    TeleFireOne v1.0
+    TeleLco v0.2 with cc1200 radio
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 415302a81f7bf0cdfd79999e1fcd5ea41dc39d13
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Aug 28 22:34:53 2019 -0500
+
+    icon: Ignore generated LED images
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 025c53a14804385ad96afcc9bf29a8d5c202a93a
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Aug 28 22:33:35 2019 -0500
+
+    Add new altosdroid icon
+    
+    Remove drop shadow
+    Change size to make Google happier
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit fcb5d55e94058810fc8b31ad5e8caa99fa61200c
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Aug 12 17:30:48 2019 -0700
+
+    altos: Use fast timer for buttons instead of edge-triggered ISR
+    
+    If the button bounces between the triggering interrupt and the button
+    state check, we could lose the final state change of the button and
+    send an incorrect event to the application. In the worst case, the button
+    would end up in exactly the wrong state, toggling in the wrong direction.
+    
+    Use the fast timer to poll all buttons instead so that there is only
+    one check of each button at each poll interval (instead of the
+    interrupt and the state check). This makes buttons reliably debounced.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5e738fd2e3602c6a92f205df99361dbe06c1719e
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Aug 4 21:12:29 2019 -0700
+
+    altosui: Make it possible to disable APRS
+    
+    The menu says "Disabled", but the device wants "0". Translate back and
+    forth to avoid an error.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1105cfe0c065483e8a97a800bc870fbdecaab9b6
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Aug 4 20:33:21 2019 -0700
+
+    altosui: Fix path to easymini-v2.0 ihx file
+    
+    This gets the bits included in macosx and linux builds
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 489b429dbeb8b0fb69881161ff32fdc2fdfcf9f8
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jul 16 11:15:20 2019 -0700
+
+    altosdroid: Hack up build to 'work' for now
+    
+    Android apps are now build with gradle instead of ant; the ant bits
+    are stale and only work with old java. Use old java to run ant while
+    using the current java compiler to build things.
+    
+    This requires a custom version of the google play API library.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 93401542ab1bf53c5b7b2a2cad5da97e44d7244e
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Fri Aug 2 14:20:39 2019 -0600
+
+    ao-bringup: add a turnon_telefireeight script
+
+commit 318b81d59e6f34a92a7a78c0896aa331bc14d0a1
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jul 17 11:40:06 2019 -0700
+
+    Use discovered java path for compiler and jni include files
+    
+    Instead of using the discovered java bits just for jni.h, also use
+    javac from that directory. Add JAVA_VERSION param to set language
+    version for newer compilers.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 784ccd37d051e8b88ef1b150ccb4e89103675b3e
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jul 17 11:38:43 2019 -0700
+
+    altoslib: Stop using deprecated Java functionality
+    
+    new Double(x) -> Double.valueOf(x)
+    c.newInstance() -> c.getDeclaredConstructor().newInstance()
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 25be2785cf34773bdcac5ec7b2a41769e352812a
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jul 16 12:08:33 2019 -0700
+
+    ao-tools/ao-eeprom: Add support for TeleFireTwo
+    
+    Display converted pressure and thrust data along with raw thermistor
+    data.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8b2e457db8c4536440ecd7dc35d06f827fc008dc
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jul 16 11:12:49 2019 -0700
+
+    altos: Record all failed sensors and report status at power up
+    
+    Use DATA bits to mark which sensors have failed, then report that in
+    beeps at startup time to help diagnose hardware failures while still
+    allowing the board to be used over USB.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c37cd66b7c11f904b528c5ff7e80e18c5e0d26e5
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jul 16 11:10:36 2019 -0700
+
+    altos/micropeak-v2.0: Reduce power usage
+    
+    This gets power consumption down under 1mA on the pad. Not really low
+    enough to sell, but I think this is about as low as the chip will go.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 40624256be70088d7608742b71e1241d95a7fcdf
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jul 16 11:07:27 2019 -0700
+
+    altos/stmf0: Allow SPI to be powered down when idle if desired
+    
+    Set SPI_1_POWER_MANAGE and/or SPI_2_POWER_MANAGE to have the spi
+    blocks powered down when not in use.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit bdcb3653bd9fb97f98773ac3bc1f87a6f52b1121
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jul 16 11:04:16 2019 -0700
+
+    altos/stmf0: Add 'ao_serial_shutdown'
+    
+    This powers down the UART logic on request.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 009d56b4f03c1ba3c9a36bdb54c772ad21844057
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jul 16 11:02:56 2019 -0700
+
+    altos/stmf0: Leave power interface disabled until needed
+    
+    We only need the power interface when placing the chip in the lowest
+    power state, so don't power up the power interface clock at startup,
+    instead wait until later.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e879d739c394602043e8ed512ad1a433fbf96c1c
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jul 16 10:23:54 2019 -0700
+
+    icon: Add altosdroid-specific icon
+    
+    Google style guides have no drop shadows anymore, so create an icon
+    for the play store without one.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9abacdaacf5ad1211da4fc72f5320ba9c43ff509
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jul 16 10:22:02 2019 -0700
+
+    altosuilib: Don't crash when flashing an unknown device
+    
+    An unknown device will not have a config; check for that before
+    showing radio calibration dialogs.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a0a109d8c82e7f362253a0f1e52d14843ddec996
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jul 16 09:57:24 2019 -0700
+
+    ao-tools/ao-eeprom: Add altitude data for baro values
+    
+    Displays altitude along with pressure and temp for baro sensor data.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0a60b7addddc302c66556c0f25ba1e71d14cf53d
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jul 16 09:56:39 2019 -0700
+
+    ao-tools/lib: Add atmosphere model
+    
+    Converts between pressure and altitude
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit fa214ca689449af3a241750e6c759dd3f2d52327
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jul 15 13:28:11 2019 -0700
+
+    ao-tools/ao-telem: Fix man page and usage to match code
+    
+    ao-telem just parses .telem files.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 245a49a85dd7b6a7cb9ec36ad02f6bb66e42f4e2
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jul 15 13:26:30 2019 -0700
+
+    altos: Allow ms5607 driver to either set ao_sensor_errors or panic
+    
+    Products that want to remain usable (over USB) after a sensor failure
+    don't want to panic when the ms5607 fails, but products with limited
+    ROM space don't want to have extra code to check for the sensor
+    failure and panic. Change the MS5607 driver to allow either option,
+    and then make the micropeak based devices use it.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 98f7c1c116aab672a29db1f81213cabe2d72ae16
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jul 15 13:22:15 2019 -0700
+
+    ao-tools: Change ao-eeprom into eeprom analysis tool
+    
+    ao-eeprom used to be a TeleMetrum v0.2 specific tool for fetching
+    eeprom contents from that device. ao-dumpflash handles that case now.
+    
+    ao-eeprom now parses .eeprom files and displays their contents.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e3eb285ff6be17afe592dca4a2fb5526c0626283
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 18 23:18:19 2019 -0700
+
+    altos/micropeak-v2: Update .gitignore
+    
+    Ignore built stuff
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 06be34ea0750743b85823b873041188dac7b06d9
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 18 23:17:10 2019 -0700
+
+    altos/micropeak-v2: Correct AO_LOG_ID value
+    
+    Typo wasn't caught by the compiler (thanks!)
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c4b8aff07d5366cef2c7209729f6cd22fa67de0c
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 18 23:16:12 2019 -0700
+
+    altos/micropeak-v2: Erase log space at end of BOOST_DELAY
+    
+    We have to erase the log before the flight starts, so this seems like
+    the latest possible moment.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 835faccc2c1141f7cd8ff93629d583fcaf785e48
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 18 23:14:54 2019 -0700
+
+    altos: Don't dump MS5607 eeprom in 'B' command
+    
+    MicroPeak v2 now has config stuff where these values get shown
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit bcf609837eefd431415c979942a31abda1227eb9
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 18 23:14:05 2019 -0700
+
+    altoslib: Add support for MicroPeak v2 eeprom format
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ee7a54b3215ffa1eb38f16a151c0740b14b60857
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 18 14:50:53 2019 -0700
+
+    altos/micropeak-v2.0: expose log and config commands over USB
+    
+    This lets AltosUI handle the eeprom data
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6529fd623f0e4b921aea1110c723d7dc03954def
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 18 14:50:18 2019 -0700
+
+    altosui/telegps: Display error message when attempting to graph unknown files
+    
+    Instead of presenting an empty graph window.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit bd351b9e3b1ba21851b2c87f5202ac3bf5c479c0
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 18 14:25:09 2019 -0700
+
+    altoslib: Always create an ordered record set for eeprom files
+    
+    If we can't parse the format, just leave it empty. This makes code
+    handling arbitrary records much easier as it doesn't have to check for
+    the ordered set existing.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4d4f018f22a0a9814e675a232b1c4239572bdd9a
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 18 13:02:51 2019 -0700
+
+    altos/micropeak-v2.0: Go into standby mode after landing
+    
+    This is the lowest power state we can reach, and consumes about 15µA
+    or less.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2ef794e60b4f6a6e9cb5e9a14ef732f7d6d36b3d
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 18 13:02:12 2019 -0700
+
+    altos/micropeak-v2.0: Fix LED blinking sequence at power-on
+    
+    'pips' happens between altitude report and data dump.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8ec178bbc3babb072b8d53975632cf6294626e98
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 18 00:11:49 2019 -0700
+
+    altos/micropeak-v2.0: Wait for the power supply to stabilize before measuring
+    
+    If we don't wait before measuring the battery, it will often read
+    under 3.2V right at boot time, which puts MicroPeak in flight mode
+    instead of USB mode.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 77df3f636ef8bf461800f5e08c28c09bfb69c48b
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jun 17 23:44:50 2019 -0700
+
+    altos/micropeak-v2.0: Don't run flight code when plugged in
+    
+    No sense running the flight code when there's a USB cable attached.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ff7fa802f632700f73418246f1be5017ac0a09b4
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jun 17 23:43:02 2019 -0700
+
+    altos: Support ao_ms5607_dump when no ms5607 task
+    
+    MicroPeak v2.0 has tasking support, but doesn't have a separate ms5607
+    task. That means the device isn't getting initialized when not running
+    the flight code, so in cmd mode we need to make sure it's initialized,
+    and we also need to actually fetch a value to display.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7c5ba25e61f98fd4537062dce52ab22d1445fa24
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jun 17 23:41:51 2019 -0700
+
+    doc: Say 'thousands of feet' instead of '3000-4000 feet'
+    
+    No reason to try and be precise here.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4be194a350987cff5b459ebaa751347b216fde05
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jun 17 14:49:36 2019 -0700
+
+    altosui: Ship EasyMini v2.0 firwmare
+    
+    Left this out in the last release...
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0a466e9869633c6ce7e43ff24ba2afff938461dd
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jun 17 14:47:56 2019 -0700
+
+    doc: Describe what sunlight does to MicroPeak and how to protect it
+    
+    Show flight data from micropeak in sunlight, a picture of foam
+    installed on micropeak and the resulting data.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit fa8e0fb8b75a808e029b090747fb60b35debb44a
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Wed Jun 5 10:46:57 2019 -0600
+
+    add an explicit reference to Poron open-cell foam in Appendix A
+
+commit a6e8b739c47c50fa472e3f2a41cf13abb8d82c07
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri May 3 21:51:28 2019 -0700
+
+    altos: Directly compute radio tuning values from frequency
+    
+    The 8051 compiler doesn't support 64-bit ints, so the old
+    code used an iterative method in 32-bit values. That could take
+    a long time when the frequency was mis-entered in Hz or MHz instead of
+    kHz.
+    
+    This direct-computation uses 64-bit ints, but takes a fixed amount of
+    time for any inputs.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1d3a8443d8de832b8e76a005e56ac5ff09b71849
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Apr 23 06:45:54 2019 -0700
+
+    Add TeleStatic-v3.0 makefiles
+
+commit 0800970a4c9c6ed38bb76bfed6374093ca16b459
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Apr 21 18:30:43 2019 -0700
+
+    altos: Add preliminary TeleStatic v3.0 code
+    
+    This adds the pin definitions and all of the code except for the
+    ads131a04 driver.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6a29b84cffcd31b2a74dd14a18aa4790eb4f14f9
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Apr 21 18:19:59 2019 -0700
+
+    altos/telefireone-v2.0: Include MAX6691 data in ring
+    
+    Define HAS_MAX6691 which tells the data code to pull the MAX6691 data
+    into the data ring for logging etc.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 83823e4ee901edb893db68e36deb2b92ffec3958
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Apr 21 18:18:55 2019 -0700
+
+    altos: Change MAX6691 driver to run its own thread
+    
+    This just captures temp data continuously; it takes 100ms to get the
+    temp data from the sensor, so the maximum rate is around 10 samples/sec.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 188f9efadd480de872f86a8eb741e8738db84c6b
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Apr 21 18:14:05 2019 -0700
+
+    altos: Add MAX6691 and ADS131A0X data to ring if present
+    
+    Add these two devices as potential data sources to be added into the
+    ring if available.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2c19d410f9d6ff1075ea2de0c0ad7b6a84e1e378
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Apr 21 16:53:51 2019 -0700
+
+    altos/telefireone-v2.0: Definitions needed for MAX6691 driver
+    
+    Fix the DMA channel definition (STM starts values at 1 for unknown reasons).
+    Add definition of the power enable bit for the timer.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5d3436ed8551537287dc6cf418f93b0989e1aee8
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Apr 21 16:49:19 2019 -0700
+
+    altos: get ao_max6691 driver working
+    
+    The driver uses a timer connected to a DMA engine to measure pulse
+    widths from the chip. We get 11 pulses for 4 channels; the first pulse
+    is caused by the timer starting up, the next two are the marker pulse
+    and then 8 more indicating the end of the high and low periods for
+    each channel.
+    
+    The driver API returns the 8 pulse widths; the caller is expected to
+    know what to do with those values as using them requires knowing the
+    value of the configuration resistor and the characteristics of the
+    thermistors.
+    
+    The test code assumes a 1k configuration resistor, using that it computes
+    the resistance of the four thermistors.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 49ce3e9a2eb4e1918773b80c355d720a3dadc7e0
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Apr 11 23:54:37 2019 -0700
+
+    altos: Work on MAX6691 driver
+
+commit 0e8970c7f4eb7e8dd4ef325e4db4fe7412d0ed78
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Apr 21 12:55:20 2019 -0700
+
+    altos/lambdakey-v1.0: Fix obvious build errors
+    
+    The code is too large to run on this device at this point, but at least
+    it doesn't fail to compile?
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8d77d5032781c5ef0dbb19de07ea97389b809f08
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Apr 18 19:48:00 2019 -0700
+
+    altoslib: Correct monitor idle IMU data for EasyMega v2
+    
+    The IMU on EasyMega v2 is rotated from the other devices using this sensor.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6dea82844075348049ce5ff9bb8670ba8efc6668
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Apr 18 19:46:24 2019 -0700
+
+    altoslib: Fetch correct mag along data for EasyMega v2
+    
+    Was using the wrong axis (y) instead of the correct one (x)
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit df08028ff5dd892dafa667fde1fbf9de43f82fea
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Apr 18 14:42:15 2019 -0700
+
+    altos: Use ao_data_accel_invert when changing orientation value
+    
+    Instead of using AO_ACCEL_INVERT, use the macro which flips the values
+    around. This fixes a bug with ADXL375 flight computers (EasyMega v2.0) where the
+    accel cal values would be scrambled when changing orientation.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 774001a9426493fd5c0d5a237da6cb903b1259a8
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Apr 18 14:32:48 2019 -0700
+
+    doc: Make sure all 'code' examples are in DejaVu Sans Mono
+    
+    We were inheriting the default value for this setting, which was Courier
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b4ee716c0026cf997cde36ef00720d63a4c62c0c
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Mar 28 22:29:21 2019 -0700
+
+    doc: Document LEDs on TeleGPS devices
+    
+    V1 has just the battery charger. V2 adds the GPS lock indicator.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 226f422b1fe5ccdf0bb3c07fa4983ec1615ce066
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Mar 18 17:21:57 2019 -0700
+
+    altos/stm32f4-disco: Remove scheme
+    
+    This demo doesn't need a lisp interpreter
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 96c446b4dba6814d61317efb4d2dc99a3ca29e0c
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Mar 18 17:20:52 2019 -0700
+
+    altos/stm32f4: Working on USB
+    
+    Reset now works, still no packets
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e38e1a2f735a1bb4aebf0817cdd99a05567c6340
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Mar 18 17:20:14 2019 -0700
+
+    altos/stm32f4: Wrong value for CK48MSEL_PLL_Q
+    
+    This meant that the USB clock wasn't actually getting started...
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 65be5d1e07ff4ae619233f3b541b9599c44490ab
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Mar 18 17:17:21 2019 -0700
+
+    altos/stm32f4: Need to read-back register after clock enable
+    
+    This was reported as necessary; I have no idea, but it's not
+    expensive, so why not...
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit efc2c093819b3ec2e5743126efb76d3a9c0ad231
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Mar 18 17:16:16 2019 -0700
+
+    altos/stm32f4: Add -mfloat-abi=hard compile option
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a2df970fca0e719e4b32e1642803590ff7bbd1ee
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Mar 18 17:15:16 2019 -0700
+
+    altos: ARM ABI requires 8-byte aligned stack
+    
+    This makes doubles on the stack (as for var-args functions) work
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b7de266431ee7bf05ba68ccae3e43a0468045860
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Mar 12 12:58:20 2019 +0100
+
+    altos/drivers/ao_led.c: Declare LED port as void * to allow any SoC to use this code
+    
+    The generic LED code needs a generic type for the GPIO port.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3a01a7e36dd475adf96468f42c95aa352b5fdf11
+Merge: 338372b9 6b0754ce
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Tue Mar 5 18:31:37 2019 -0700
+
+    Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos
+
+commit 6b0754cee625c6e2c19dc70fb5be6cd2f0125d47
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Mar 5 17:25:44 2019 -0800
+
+    doc: A few minor edits to telelaunch docs
+    
+    3 → three
+    less → fewer
+    transreflexive -> reflective
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 338372b97d441c30d2a23df540163a66a7f8d8c0
+Merge: 8d0df64b cd920a0e
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Mon Feb 25 18:30:08 2019 -0700
+
+    Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos
+
+commit cd920a0e5321166ef8b1d6afc3d63fc5de998a93
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Feb 25 16:42:25 2019 -0700
+
+    altos: add ao_time_ns API
+    
+    This provides nano-second resolution times by reading the systick
+    value (which runs at 250ns ticks on stm).
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0448b9b638f8599633227a639ef9d8572780bbd9
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Feb 25 16:41:45 2019 -0700
+
+    altos: Change default time type to 32-bits
+    
+    Offers additional range for internal use without increasing cost on
+    32-bit platforms.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6fec7b5affd223c18bad78377d7655af958dffc2
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Feb 25 16:40:16 2019 -0700
+
+    altos: Fix several mis-specified time types
+    
+    Make sure AO_TICK_TYPE is used "everywhere", instead of uint16_t or other.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8d0df64bbc5ed31188b4b4bea0be52a52dbece3b
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Sun Feb 24 15:10:25 2019 -0700
+
+    altos: ads124s0x successfully reading data
+
+commit 14fe18559d2eb7e568f07fcbaec89b6ef55fae24
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Sun Feb 24 11:51:58 2019 -0700
+
+    altos: snapshot - working on ads124x0x driver
+
+commit 2f87e182d9f0b3c2856f62149371ad70b16148cf
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Sun Feb 24 10:49:47 2019 -0700
+
+    altos: ADS124S0X driver compiles now
+
+commit 69bdb309f46a28803e93b08921720805b28b18a2
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Sun Feb 24 10:28:15 2019 -0700
+
+    altos: fix ads124s0x data structure
+
+commit 8cc418ed3b0df0e465f0af27c2255cb97294e6ce
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Sun Feb 24 10:25:31 2019 -0700
+
+    altos: first cut at ADS124S0X driver interrupt handling
+
+commit 654a23168f59d04d7e9cad657bebf8ecfdd8e41e
+Merge: d0f66918 655c5d2c
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Thu Feb 21 21:57:26 2019 -0700
+
+    Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos
+
+commit d0f6691804ee8de633601483354c93f1c2d75219
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Thu Feb 21 21:57:08 2019 -0700
+
+    doc: actually add the telelaunch files
+
+commit 655c5d2c1124182ba336db368474cf4de0b9ce9d
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Feb 21 19:28:14 2019 -0800
+
+    altos: Allow applications to override newlib printf selection
+    
+    Re-defining NEWLIB_PRINTF_CFLAGS will allow applications to select
+    printf with floating point support if desired.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3310b22e28d953a6569cd50e83f91c25577424a5
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Feb 21 19:26:41 2019 -0800
+
+    altos: Fix ISR declarations to make them non-weak
+    
+    In my zeal to eliminate warnings, I added declarations of all ISR
+    functions to a shared header file. However, I managed to include the
+    'weak' declaration, which meant that the intended ISR functions were
+    as weak as the 'default' ISR functions. This left all interrupts
+    non-functional, which doesn't make for a happy program.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit eaf2ee0f498b519d64e1664a2b8c66c52ac1497c
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Feb 18 16:43:50 2019 -0800
+
+    altos/telefireone-v2.0: Remove build of ao_product.h from Makefile
+    
+    This is built in common code now.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c411c7ec71be0263a958c0803772cd6068e6bdad
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Thu Feb 21 17:14:24 2019 -0700
+
+    doc: new TeleLaunch system manual
+
+commit 5c772d58ba83e147f0a404261a34c39183f2aac3
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Mon Feb 18 17:39:34 2019 -0700
+
+    altos: first cut of code for telefireone-v2.0
+
+commit d31fda73fef37cf6a9e449c99f3197b713b93acb
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Feb 18 16:26:39 2019 -0800
+
+    altos: Build telefireone-v1.0 by default
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6aeb000899ad7f22e92b487b5891664554bc4d33
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Feb 18 16:26:08 2019 -0800
+
+    altos/telefireone-v1.0: Track ao_led_init API change
+    
+    No longer takes a parameter.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2e468bfbf9f430b6a3970283d818ea4405ccfc5b
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Feb 18 16:25:38 2019 -0800
+
+    altos/telefireone-v1.0: Set various ADC values
+    
+    Reference voltage and divider resistor values.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4b41b14ea46ff6954895824a60637c0eb4353b17
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Feb 18 16:25:06 2019 -0800
+
+    altos/telefireone-v1.0: Set AO_LOG_FORMAT
+    
+    Use AO_LOG_FORMAT_TELFIRETWO for now; perhaps we'll have a new format
+    at some point.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 58f77ec66f5e40095917905578e36566b7e3401e
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Feb 18 16:24:21 2019 -0800
+
+    altos/telefireone-v1.0: Turn off USE_INTERNAL_FLASH
+    
+    This is for TeleMini v1.0 which stored log data to the program flash.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9ea50f00039c812ea6a4a4235d78c140a0252662
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Feb 18 16:23:13 2019 -0800
+
+    altos/telefireone-v1.0: Clean up Makefile
+    
+    Follow other projects and remove common bits which are now in
+    Makefile.defs
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d19f1888d736943e8b51aeb56ec7097e11a505fc
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Feb 18 16:22:07 2019 -0800
+
+    altos/telefireone-v1.0: Doesn't have a beeper
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f9f1776f61cf365e3c8862f9f93cd2773391da16
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Feb 18 16:20:14 2019 -0800
+
+    altos: Remove AO_LOG_STATE from ao_log_telefiretwo
+    
+    Telefiretwo never changes flight state, so these packets weren't going
+    to be written.
+    
+    Also stop passing &log to ao_log_firetwo -- it always got the global
+    anyways, just use it directly.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7a89aa1ea7e1b02b5cd310986adf4239ec0ce91d
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Feb 18 12:59:05 2019 -0800
+
+    altos: Move common build definitions to src/Makefile.defs
+    
+    This cleans up the build process for all architectures, providing a
+    common place to specify vpath, cflags and build rules for various
+    common files.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 889518aeee080b0f8bb954db86d08105898d8161
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Feb 18 11:25:21 2019 -0800
+
+    altos/attiny: Mark 'mode' param to ao_exti_setup_port as used
+    
+    Retain API.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a12dc56db6d5245ee8ac594337576dd85791a984
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Feb 18 10:42:23 2019 -0800
+
+    altos: Add -Wshadow to CFLAGS
+    
+    And fix up the related messages.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit fda36e57205138f6c180a18b54956ea1682a5293
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Feb 18 10:41:31 2019 -0800
+
+    altos/stm-demo: Make this build again after various API and CFLAGS changes
+    
+    Deal with LED API change. Remove unused functions.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 85104dbe9684af579c9255553b609fd28f8ee276
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Feb 18 10:40:06 2019 -0800
+
+    ao-tools/ao-dump-up: Document --wait flag
+    
+    --wait means to poll for a µPusb device instead of bailing when none
+    exists at startup. Quite useful for testing a batch of new device.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b6021e8dd866d6db54d28c79f0572aadd1861a5f
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Feb 18 10:39:11 2019 -0800
+
+    ao-bringup: chaosread is no longer part of altos
+    
+    this has been moved to a separate project.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a43bc96ad4a524480a2d47500fb0cfaeeba8ad3d
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Feb 18 10:38:21 2019 -0800
+
+    stm: Expose LCD font API in ao_lcd_font.h
+    
+    That required renaming the existing LCD font defintions from
+    ao_lcd_font.h to ao_lcd_font_bits.h.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ebb8ab6a2f5f1245098ad68d0cd007d3f115a24d
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Feb 4 22:39:34 2019 -0800
+
+    altos: Add a pile more compiler warnings
+    
+    Adds:
+            -Wpointer-arith
+            -Wstrict-prototypes
+            -Wmissing-prototypes
+            -Wmissing-declarations
+            -Wnested-externs
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d6c3c3618a708d2a1a7948454710e6ae21c2a426
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Feb 4 22:38:23 2019 -0800
+
+    altos: Declare task stack as union of uint8_t and uint32_t
+    
+    Support -Wcast-align and -Wpointer-arith while still allowing
+    architectures to pick whether they want an 8-bit or 32-bit stack.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 63a44b9c169d042fb1a3997620477e7f00bb0918
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Feb 4 22:34:21 2019 -0800
+
+    altos: Remove unused ao_adc_get from ao_adc_stm.c
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f26197f0eec650330b476514c47978b4ba087719
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Feb 4 22:33:32 2019 -0800
+
+    altos: Stop doing pointer arith on void *
+    
+    Switch to uint8_t * instead.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 54dd2a6e3a05b940d9daebb3d73f6876c182b3e7
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Feb 4 22:32:24 2019 -0800
+
+    altos: Add 'void' to function declarations with no params.
+    
+    Support -Wstrict-prototypes
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 873f511173c637016b5e173813bd03c1725797bb
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Feb 4 22:28:02 2019 -0800
+
+    altos: Declare all public functions in header files
+    
+    Including interrupt vectors to catch mis-spellings.
+    Working toward supporting -Wmissing-prototypes
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c11427819ca24bb77523496309b5b6f699d126c5
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Feb 4 22:24:37 2019 -0800
+
+    altos: Mark local functions 'static'
+    
+    Working towards supporting -Wmissing-prototypes
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 119a829e58aff5dd7801fe7ef8cae886bf31fec1
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Feb 4 22:35:02 2019 -0800
+
+    altos/stm: Note that ao_i2c_recv_dma_isr isn't actually used
+    
+    This function resets the i2c transceiver after DMA completes, but it
+    hasn't ever been hooked up. Some testing would be a good idea. For
+    now, just add a comment and mark the function as referenced to avoid a
+    compiler warning.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit acf032eb39504657e9289ca54844967b9c3bed76
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Feb 4 22:42:05 2019 -0800
+
+    altos: Fix spelling of stm_dma_ch4_5_6_isr
+    
+    This spellingn error would have caused all DMA to these channels to fail.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d7f8c9262f7979ddcc93cb64b913e392c18ef674
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Sun Feb 17 17:35:25 2019 -0700
+
+    altos: ADS124S0X driver compiles with initialization code maybe completed
+
+commit c29f65a5696df66efb7e84e3ae8a3ea4b1f1494c
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Sun Feb 17 14:38:53 2019 -0700
+
+    altos: add initial support for TeleFireOne v2.0
+
+commit 630f457666b48321be0a5b6fbf391efef1fa3eb4
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Feb 3 12:48:45 2019 -0800
+
+    Use strip-nondeterminism to fix JAR timestamps
+    
+    .jar files are just zip files, and contain dates. These will cause the
+    build to be non-reproducible. Use strip-nondeterminism to smash all of
+    these back to a fixed value.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 145e5a1ac557c4990e74fb64b005fc68d6941bdc
+Merge: e2c9ef80 db730875
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Mon Jan 28 13:46:59 2019 -0700
+
+    Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos
+
+commit e2c9ef801abacd2533d9b4321c24a490d4556134
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Mon Jan 28 13:45:31 2019 -0700
+
+    Makefiles, too
+
+commit db7308750b3478ec3d2332e81db9957a9d4f2cfc
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jan 28 11:35:32 2019 -0800
+
+    altos/telefireeight-v2.0: Add flash loader Makefile
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e40407467f28ab44b9f7c7d51a65a51f802410d5
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jan 28 11:33:19 2019 -0800
+
+    altos: Delete unused config bits for telefireeight-v2.0. Add Makefile
+    
+    Clean up the config and set the copyright year.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 38dc7545a98a851af447ad3d69fa5bc85583fed9
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Sun Jan 27 19:20:02 2019 -0700
+
+    altos: add telefireeight-v2.0 to src/Makefile and to Releasing
+
+commit f29b55691c9f160898b49bf15f46a88ae00b115f
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Sun Jan 27 19:16:41 2019 -0700
+
+    altos: add support for telefireeight-v2.0
+
+commit 37f4a66e47370e0e5ef42b0d70cda060fa2baa64
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Wed Jan 9 15:42:42 2019 -0700
+
+    doc: add force-bootloader instructions for TeleGPS v1 and v2
+
+commit 3703aef1b8b043697e8b99df24b987ba696909bc
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jan 7 17:15:41 2019 -0800
+
+    doc: Fix typo in TeleBT v3 flash-force instructions
+    
+    taht → that
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 38630c65460b5e873a0df0fef937d498a37ea329
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jan 7 17:12:56 2019 -0800
+
+    Remove ao-chaosread
+    
+    This program is now provided by the independent chaosread program.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 31f9ed231e63b214b405a141cabce3eb758e82e6
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Sat Jan 5 18:02:34 2019 -0700
+
+    doc: add flash-force instructions for TeleBT v3.0
+
+commit 72bcff4c1af10571314e5cbbe29f073de818088e
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Jan 3 11:59:02 2019 -0800
+
+    ao-tools/ao-telem: Print out 'log_max' value. Clean up compiler warnings.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 14900d539c9d379a39ec157bb7e1914aad8fde3c
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Jan 3 11:57:42 2019 -0800
+
+    ao-tools/ao-cal-accel: Initialize byte count var 'l'
+    
+    When left uninitialized, the program would randomly segfault at startup.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 96be286b3a9daa9bdb7872118be0118872d483f8
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Jan 3 11:55:38 2019 -0800
+
+    ao-tools/ao-load: Return status from 'rewrite'
+    
+    Was just falling off the end of this function, returning a random value.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6f729ff46b2f4531db68f0af85e7e9fe0f6d1969
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Jan 3 11:41:49 2019 -0800
+
+    ao-tools: Fix warnings in ao-tools
+    
+    None of these appear likely to have caused actual problems.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f14c799ae7ff3be56c28f5694f04c03daff7708e
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Jan 3 11:40:32 2019 -0800
+
+    ao-tools: Add lots of compiler warning flags to ao-tools build
+    
+    This catches some uninitialized variable errors which cause
+    ao-cal-accel to crash (fixes coming next)
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit adf4bec88df1822031e1a8b00422de8b8b0c0cd4
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jan 2 23:51:58 2019 -0800
+
+    doc: Update all docs to 1.9. Note this in doc/RELNOTES
+    
+    Missed a bunch of 1.8.7 numbers due to a missing step in the release process
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a3177edd807b12a58d684ece60b0f3329e742af6
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Thu Jan 3 00:49:22 2019 -0700
+
+    updates to Releasing based on 1.9 release process learnings
+
+commit 5b4da841459a650e641924aab132f566c6259c4d
+Merge: 95ffec07 ecf40a3a
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Wed Jan 2 23:03:41 2019 -0700
+
+    Merge branch 'master' into branch-1.9
+
+commit ecf40a3a190fb2f7d7d2654c1e87daddf0362b0c
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jan 2 22:02:42 2019 -0800
+
+    doc: Skip .pdf generation when asciidoctor-pdf is missing
+    
+    Not available in debian unstable yet
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 95ffec073b0758801df04a77eca0bd2bc6e57e35
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Wed Jan 2 22:19:36 2019 -0700
+
+    changelog for 1.9 release
+
 commit 4e9e0bf99d6b71086110038fa1e3231d00bb2496
 Author: Keith Packard <keithp@keithp.com>
 Date:   Mon Dec 31 15:20:57 2018 -0800
index 9fe3a7a6d546026b8275d16098b12ed85cbae0b3..613635ce4f1dc76c83e5baae9eda0c19e50ac9dd 100644 (file)
--- a/Releasing
+++ b/Releasing
@@ -29,9 +29,12 @@ These are Keith's notes on how to do a release
 
 These are Bdale's notes on how to do a release.
 
-       - make sure build environment is up to date
+       - make sure Debian build environment is up to date
                sudo cowbuilder --update
 
+       - make sure fat build environment is up to date
+               sudo apt update && sudo apt upgrade
+
        - ensure i386 build support is available, and we have tools to build
          installers for Windows and Mac OS X
 
@@ -54,12 +57,9 @@ These are Bdale's notes on how to do a release.
                - cherry-pick or merge appropriate content from master
        
        - make sure there is a doc/release-notes-<version>.inc
-       - make sure that doc/altusmetrum-docinfo.xml has the right copyright 
-         year, and add release to the revision history at the front (release 
-         notes will be pulled in automatically)
+       - make sure that doc/*.txt have the right copyright year and the
+         new release is included
        - make absolutely sure checked-out tree is "clean" 
-       - make absolutely sure the pdclib/ submodule is on the master branch,
-         up to date, and "clean"
 
         git log > ChangeLog
        git commit -a
@@ -77,14 +77,14 @@ These are Bdale's notes on how to do a release.
         git commit -n debian/changelog -m "update changelog for Debian build"
 
        - if this is a -1 release, then
-               gbp buildpackage --git-no-pristine-tar --git-submodules \
+               gbp buildpackage --git-no-pristine-tar \
                        --git-upstream-branch=branch-<version> \ # eg 1.3
                        --git-upstream-tag=<version>             # eg 1.3.1
                pristine-tar commit \
                        ../build-area/altos_<version>.orig.tar.gz \
                        branch-<version>
          else if this is not a -1 release
-               gbp buildpackage --git-submodules
+               gbp buildpackage
 
        git tag debian/<version>
 
@@ -116,6 +116,7 @@ These are Bdale's notes on how to do a release.
           src/telemini-v3.0/{*.elf,*.ihx} \
           src/telelco-v2.0/{*.elf,*.ihx} \
           src/telefireeight-v1.0/{*.elf,*.ihx} \
+          src/telefireeight-v2.0/{*.elf,*.ihx} \
           ~/altusmetrumllc/Binaries/
        cp src/chaoskey-v1.0/flash-loader/{*.elf,*.bin} \
           src/easymega-v1.0/flash-loader/*.elf \
@@ -134,6 +135,7 @@ These are Bdale's notes on how to do a release.
           src/telemini-v3.0/flash-loader/{*.elf,*.bin} \
           src/telelco-v2.0/flash-loader/*.elf \
           src/telefireeight-v1.0/flash-loader/*.elf \
+          src/telefireeight-v2.0/flash-loader/*.elf \
           ~/altusmetrumllc/Binaries/loaders/
        (cd ~/altusmetrumllc ; git add Binaries ; git commit -a) 
        - remove previous versions (only keep latest release)
diff --git a/altosdroid/.classpath b/altosdroid/.classpath
deleted file mode 100644 (file)
index fce248e..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-       <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
-       <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
-       <classpathentry kind="src" path="src"/>
-       <classpathentry kind="src" path="gen"/>
-       <classpathentry kind="lib" path="libs/android-support-v4.jar"/>
-       <classpathentry kind="lib" path="libs/altoslib_1.jar"/>
-       <classpathentry kind="output" path="bin/classes"/>
-</classpath>
diff --git a/altosdroid/.externalToolBuilders/Generate BuildInfo.java.launch b/altosdroid/.externalToolBuilders/Generate BuildInfo.java.launch
deleted file mode 100644 (file)
index 3b8eff4..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">
-<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${working_set:&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;resources&gt;&#10;&lt;item path=&quot;/AltosDroid/src/org/altusmetrum/AltosDroid/BuildInfo.java&quot; type=&quot;1&quot;/&gt;&#10;&lt;/resources&gt;}"/>
-<booleanAttribute key="org.eclipse.debug.core.capture_output" value="false"/>
-<booleanAttribute key="org.eclipse.debug.ui.ATTR_CONSOLE_OUTPUT_ON" value="false"/>
-<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
-<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/AltosDroid/buildinfo.sh}"/>
-<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,auto,"/>
-<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
-<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/AltosDroid}"/>
-</launchConfiguration>
index cf7ad5a8bea9e5c8321dee3b62fb4740450b9353..c9f36f70d26586bb9a4675f2ef40035e763f52b3 100644 (file)
@@ -1,8 +1,11 @@
+.gradle
+.idea
+build/
+app/build/
+app/libs/
+app/app.iml
+altosdroid.iml
 local.properties
-bin
-gen
-libs
-google-play-services_lib
-src/org/altusmetrum/AltosDroid/BuildInfo.java
-res/drawable/*led.png
-AndroidManifest.xml
+app/src/main/AndroidManifest.xml
+app/src/main/java/org/altusmetrum/AltosDroid/BuildInfo.java
+app/src/main/res/drawable/*led.png
diff --git a/altosdroid/.settings/org.eclipse.jdt.core.prefs b/altosdroid/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644 (file)
index e5d1cd3..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#Wed Sep 28 19:51:24 NZDT 2011
-eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
-org.eclipse.jdt.core.compiler.compliance=1.5
-org.eclipse.jdt.core.compiler.source=1.5
diff --git a/altosdroid/AndroidManifest.xml.in b/altosdroid/AndroidManifest.xml.in
deleted file mode 100644 (file)
index 3f17188..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-
- Copyright © 2012 Mike Beattie <mike@ethernal.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; 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.
-
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="org.altusmetrum.AltosDroid"
-          android:versionCode="@ANDROID_VERSION@"
-          android:versionName="@VERSION@">
-    <uses-sdk android:targetSdkVersion="12" android:minSdkVersion="12"/>
-    <!-- Google Maps -->
-    <uses-feature android:glEsVersion="0x00020000" android:required="true"/>
-
-    <!-- Permissions needed to access bluetooth -->
-    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
-    <uses-permission android:name="android.permission.BLUETOOTH" />
-    <!-- Permissions needed to save Telemetry logs to SD card -->
-    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-    <!-- Permissions needed for GoogleMaps -->
-    <uses-permission android:name="android.permission.INTERNET"/>
-    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
-    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
-    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
-
-    <permission android:name="org.altusmetrum.AltosDroid.permission.MAPS_RECEIVE"
-                android:protectionLevel="signature"/>
-    <uses-permission android:name="org.altusmetrum.AltosDroid.permission.MAPS_RECEIVE"/>
-
-    <!-- Permissions needed to access USB OTG -->
-    <uses-feature android:name="android.hardware.usb.host" android:required="false" />
-
-    <application android:label="@string/app_name"
-                 android:icon="@drawable/app_icon"
-                 android:allowBackup="true"
-                android:theme="@style/CustomTheme">
-        <activity android:name="org.altusmetrum.AltosDroid.AltosDroid"
-                  android:label="@string/app_name"
-                  android:configChanges="orientation|keyboardHidden"
-                 android:launchMode="singleTop">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity>
-
-       <activity android:name="org.altusmetrum.AltosDroid.AltosDroid"
-                  android:configChanges="orientation|keyboardHidden"
-                 android:launchMode="singleTop">
-         <intent-filter>
-           <action
-               android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"/>
-         </intent-filter>
-         <meta-data
-             android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
-             android:resource="@xml/device_filter" />
-       </activity>
-
-        <activity android:name=".DeviceListActivity"
-                  android:label="@string/select_device"
-                  android:theme="@android:style/Theme.Dialog"
-                  android:configChanges="orientation|keyboardHidden" />
-
-        <activity android:name=".PreloadMapActivity"
-                  android:label="@string/preload_maps"
-                  android:theme="@android:style/Theme.Dialog"
-                  android:configChanges="orientation|keyboardHidden" />
-
-        <activity android:name=".MapTypeActivity"
-                  android:label="@string/map_type"
-                  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="@GOOGLEKEY@"/>
-        <meta-data android:name="com.google.android.gms.version"
-                   android:value="@integer/google_play_services_version" />
-    </application>
-</manifest>
index 686aeabfc5c6f39dae60a7ca5b33af2d13ccc365..3a4edde17044256d1833be3e85df8ccbc5a03d2e 100644 (file)
@@ -1,7 +1,10 @@
+DBG_APK=app/build/outputs/apk/debug/app-debug.apk
+REL_APK=app/build/outputs/apk/release/app-release.apk
+
 if ANDROID
-all_target=bin/AltosDroid-debug.apk
+all_target=$(DBG_APK)
 if ANDROID_RELEASE
-all_target+=bin/AltosDroid-release.apk
+all_target+=$(REL_APK)
 endif
 else
 all_target=
@@ -17,26 +20,19 @@ APKBUILDER=$(SDK)/tools/apkbuilder
 ZIPALIGN_A=$(SDK)/tools/zipalign
 ZIPALIGN_B=$(shell ls $(SDK)/build-tools/*/zipalign | tail -1)
 
-JAVA_SRC_DIR=src/org/altusmetrum/AltosDroid
-EXT_LIBDIR=libs
-DRAWABLE_DIR=res/drawable
-LAYOUT_DIR=res/layout
-MENU_DIR=res/menu
-VALUES_DIR=res/values
-XML_DIR=res/xml
+JAVA_SRC_DIR=app/src/main/java/org/altusmetrum/AltosDroid
+EXT_LIBDIR=app/libs
+RES_DIR=app/src/main/res
+DRAWABLE_DIR=$(RES_DIR)/drawable
+LAYOUT_DIR=$(RES_DIR)/layout
+MENU_DIR=$(RES_DIR)/menu
+VALUES_DIR=$(RES_DIR)/values
+XML_DIR=$(RES_DIR)/xml
 ALTOSLIB_SRCDIR=../altoslib
 ALTOSLIB_JAR=altoslib_$(ALTOSLIB_VERSION).jar
 
 ALTOSLIB=$(EXT_LIBDIR)/$(ALTOSLIB_JAR)
 
-SUPPORT_V4_SRCDIR=$(SDK)/extras/android/support/v4
-SUPPORT_V4_JAR=android-support-v4.jar
-
-SUPPORT_V4=$(EXT_LIBDIR)/$(SUPPORT_V4_JAR)
-
-GOOGLE_PLAY_SERVICES_LIB_SRCDIR=$(SDK)/extras/google/google_play_services/libproject
-GOOGLE_PLAY_SERVICES_LIB=google-play-services_lib
-
 JAVA_SRC=$(JAVA_SRC_DIR)/*.java $(JAVA_SRC_DIR)/BuildInfo.java
 
 DRAWABLES=\
@@ -44,10 +40,12 @@ DRAWABLES=\
     $(DRAWABLE_DIR)/greenled.png \
     $(DRAWABLE_DIR)/grayled.png
 
+GRADLEW=bash ./gradlew --no-daemon
+
 LAYOUTS=$(LAYOUT_DIR)/*.xml
 MENUS=$(MENU_DIR)/*.xml
 VALUES=$(VALUES_DIR)/*.xml
-XMLS=$(XML_DIR)/*.xml AndroidManifest.xml
+XMLS=$(XML_DIR)/*.xml app/src/main/AndroidManifest.xml
 
 RES=$(LAYOUTS) $(MENUS) $(VALUES) $(XMLS)
 
@@ -61,14 +59,6 @@ $(ALTOSLIB): $(ALTOSLIB_SRCDIR)/$(ALTOSLIB_JAR)
        mkdir -p $(EXT_LIBDIR)
        cd $(EXT_LIBDIR) && ln -sf $(shell echo $(EXT_LIBDIR) | sed 's|[^/]\+|..|g')/$(ALTOSLIB_SRCDIR)/$(ALTOSLIB_JAR) .
 
-$(SUPPORT_V4): $(SUPPORT_V4_SRCDIR)/$(SUPPORT_V4_JAR)
-       mkdir -p $(EXT_LIBDIR)
-       cd $(EXT_LIBDIR) && ln -sf $(SUPPORT_V4_SRCDIR)/$(SUPPORT_V4_JAR) .
-
-$(GOOGLE_PLAY_SERVICES_LIB): $(GOOGLE_PLAY_SERVICES_LIB_SRCDIR)/$(GOOGLE_PLAY_SERVICES_LIB)
-       cp -a $(GOOGLE_PLAY_SERVICES_LIB_SRCDIR)/$(GOOGLE_PLAY_SERVICES_LIB) .
-       cd $(GOOGLE_PLAY_SERVICES_LIB) && $(SDK)/tools/android update project --target $(SDK_TARGET) --path .
-
 $(JAVA_SRC_DIR)/BuildInfo.java: $(filter-out $(JAVA_SRC_DIR)/BuildInfo.java,$(shell echo $(JAVA_SRC)))
        ./buildinfo.sh
 
@@ -76,38 +66,22 @@ $(DRAWABLE_DIR)/%.png: ../icon/%.png
        cd $(DRAWABLE_DIR) && ln -sf $(shell echo $(DRAWABLE_DIR) | sed 's|[^/]\+|..|g')/$< .
 
 if ANDROID
-install-release: bin/AltosDroid-release.apk
-       $(ADB) install -r bin/AltosDroid-release.apk
-
-install-debug: bin/AltosDroid-debug.apk
-       $(ADB) install -r bin/AltosDroid-debug.apk
-
-bin/AltosDroid-debug.apk: $(SRC) $(ALTOSLIB) $(SUPPORT_V4) $(GOOGLE_PLAY_SERVICES_LIB)
-       ant debug
-
-bin/AltosDroid-release-unsigned.apk: $(SRC) $(ALTOSLIB) $(SUPPORT_V4) $(GOOGLE_PLAY_SERVICES_LIB)
-       ant release
-
-bin/AltosDroid-release.apk: bin/AltosDroid-release-unsigned.apk
-       jarsigner -sigalg SHA1withDSA -digestalg SHA1 \
-          -keystore ~/altusmetrumllc/google-play-release.keystore \
-          -storepass:file ~/altusmetrumllc/google-play-passphrase \
-          -signedjar bin/AltosDroid-release-signed.apk \
-          bin/AltosDroid-release-unsigned.apk AltosDroid
-       if [ -f $(ZIPALIGN_A) ]; then \
-               $(ZIPALIGN_A) -f 4 \
-                  bin/AltosDroid-release-signed.apk \
-                  bin/AltosDroid-release.apk; \
-       else \
-               $(ZIPALIGN_B) -f 4 \
-                  bin/AltosDroid-release-signed.apk \
-                  bin/AltosDroid-release.apk; \
-       fi
-
-release: bin/AltosDroid-release.apk
+install-release: $(REL_APK)
+       $(ADB) install -r $(REL_APK)
+
+install-debug: $(DBG_APK)
+       $(ADB) install -r $(DBG_APK)
+
+$(DBG_APK): $(SRC) $(ALTOSLIB)
+       $(GRADLEW) assembleDebug
+
+$(REL_APK): $(SRC) $(ALTOSLIB)
+       $(GRADLEW) build
+
+release: $(REL_APK)
 
 clean-local: $(GOOGLE_PLAY_SERVICES_LIB)
-       ant clean
+       $(GRADLEW) clean
        rm -f $(JAVA_SRC_DIR)/BuildInfo.java
        rm -f $(DRAWABLES)
        rm -rf $(EXT_LIBDIR)
diff --git a/altosdroid/app/build.gradle b/altosdroid/app/build.gradle
new file mode 100644 (file)
index 0000000..1d97693
--- /dev/null
@@ -0,0 +1,47 @@
+apply plugin: 'com.android.application'
+
+def keystorePropertiesFile = file(System.properties['user.home'] + "/altusmetrumllc/android_keystore.properties")
+def keystoreProperties = new Properties()
+keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
+
+android {
+    signingConfigs {
+        release {
+            storeFile file(System.properties['user.home'] + "/altusmetrumllc/android_keystore.jks")
+            storePassword keystoreProperties['storePassword']
+            keyAlias keystoreProperties['keyAlias']
+            keyPassword keystoreProperties['keyPassword']
+        }
+    }
+
+    compileSdkVersion 28
+    defaultConfig {
+        applicationId "org.altusmetrum.AltosDroid"
+        minSdkVersion 26
+        targetSdkVersion 28
+        versionCode 19
+        versionName "1.9.1rc1"
+    }
+    buildTypes {
+        release {
+            signingConfig signingConfigs.release
+            minifyEnabled false
+            debuggable false
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+        debug {
+            debuggable true
+        }
+    }
+    lintOptions {
+        abortOnError false
+    }
+}
+
+dependencies {
+    implementation 'androidx.appcompat:appcompat:1.0.0'
+    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
+    implementation 'com.google.android.gms:play-services-maps:17.0.0'
+    implementation fileTree(dir: 'libs', include: ['*.jar'])
+}
+
diff --git a/altosdroid/app/proguard-rules.pro b/altosdroid/app/proguard-rules.pro
new file mode 100644 (file)
index 0000000..f1b4245
--- /dev/null
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/altosdroid/app/src/main/AndroidManifest.xml.in b/altosdroid/app/src/main/AndroidManifest.xml.in
new file mode 100644 (file)
index 0000000..69b5463
--- /dev/null
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright © 2012 Mike Beattie <mike@ethernal.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; 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.
+
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="org.altusmetrum.AltosDroid">
+    <!-- Google Maps -->
+    <uses-feature android:glEsVersion="0x00020000" android:required="true"/>
+
+    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
+
+    <!-- Permissions needed to access bluetooth -->
+    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
+    <uses-permission android:name="android.permission.BLUETOOTH" />
+    <!-- Permissions needed to save Telemetry logs to SD card -->
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <!-- Permissions needed for GoogleMaps -->
+    <uses-permission android:name="android.permission.INTERNET"/>
+    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+
+    <permission android:name="org.altusmetrum.AltosDroid.permission.MAPS_RECEIVE"
+                android:protectionLevel="signature"/>
+    <uses-permission android:name="org.altusmetrum.AltosDroid.permission.MAPS_RECEIVE"/>
+
+    <!-- Permissions needed to access USB OTG -->
+    <uses-feature android:name="android.hardware.usb.host" android:required="false" />
+
+    <application android:label="@string/app_name"
+                 android:icon="@drawable/app_icon"
+                 android:allowBackup="true"
+                 android:theme="@style/CustomTheme">
+
+        <activity android:name="org.altusmetrum.AltosDroid.AltosDroid"
+                  android:label="@string/app_name"
+                  android:configChanges="orientation|keyboardHidden"
+                  android:launchMode="singleTop">
+            <intent-filter>
+                <category android:name="android.intent.category.LAUNCHER" />
+                <action android:name="android.intent.action.MAIN" />
+                <action android:name="android.intent.action.VIEW" />
+                <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"/>
+            </intent-filter>
+            <meta-data
+                    android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
+                    android:resource="@xml/device_filter" />
+        </activity>
+
+        <activity android:name=".DeviceListActivity"
+                  android:label="@string/select_device"
+                  android:theme="@android:style/Theme.Dialog"
+                  android:configChanges="orientation|keyboardHidden" />
+
+        <activity android:name=".PreloadMapActivity"
+                  android:label="@string/preload_maps"
+                  android:theme="@android:style/Theme.Dialog"
+                  android:configChanges="orientation|keyboardHidden" />
+
+        <activity android:name=".MapTypeActivity"
+                  android:label="@string/map_type"
+                  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="@GOOGLEKEY@"/>
+        <meta-data android:name="com.google.android.gms.version"
+                   android:value="@integer/google_play_services_version" />
+    </application>
+</manifest>
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosBluetooth.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosBluetooth.java
new file mode 100644 (file)
index 0000000..9c4b4b2
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ * Copyright © 2012 Mike Beattie <mike@ethernal.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.UUID;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothSocket;
+import android.os.Handler;
+
+public class AltosBluetooth extends AltosDroidLink {
+
+       private ConnectThread    connect_thread = null;
+
+       private BluetoothDevice  device;
+       private BluetoothSocket  socket;
+       private InputStream      input;
+       private OutputStream     output;
+       private boolean          pause;
+
+       // Constructor
+       public AltosBluetooth(BluetoothDevice device, Handler handler, boolean pause) {
+               super(handler);
+               this.device = device;
+               this.handler = handler;
+               this.pause = pause;
+
+               connect_thread = new ConnectThread();
+               connect_thread.start();
+       }
+
+       void connected() {
+               if (closed()) {
+                       AltosDebug.debug("connected after closed");
+                       return;
+               }
+
+               AltosDebug.check_ui("connected\n");
+               try {
+                       synchronized(this) {
+                               if (socket != null) {
+                                       input = socket.getInputStream();
+                                       output = socket.getOutputStream();
+                                       super.connected();
+                               }
+                       }
+               } catch (InterruptedException ie) {
+                       connect_failed();
+               } catch (IOException io) {
+                       connect_failed();
+               }
+       }
+
+       private void connect_failed() {
+               if (closed()) {
+                       AltosDebug.debug("connect_failed after closed");
+                       return;
+               }
+
+               close_device();
+               input = null;
+               output = null;
+               handler.obtainMessage(TelemetryService.MSG_CONNECT_FAILED, this).sendToTarget();
+               AltosDebug.error("ConnectThread: Failed to establish connection");
+       }
+
+       void close_device() {
+               BluetoothSocket tmp_socket;
+
+               synchronized(this) {
+                       tmp_socket = socket;
+                       socket = null;
+               }
+
+               if (tmp_socket != null) {
+                       try {
+                               tmp_socket.close();
+                       } catch (IOException e) {
+                               AltosDebug.error("close_socket failed");
+                       }
+               }
+       }
+
+       public void close() {
+               super.close();
+               input = null;
+               output = null;
+       }
+
+       private final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
+
+       private void create_socket(BluetoothDevice  device) {
+
+               BluetoothSocket tmp_socket = null;
+
+               AltosDebug.check_ui("create_socket\n");
+               try {
+                       tmp_socket = device.createInsecureRfcommSocketToServiceRecord(SPP_UUID);
+               } catch (IOException e) {
+                       e.printStackTrace();
+               }
+               if (socket != null) {
+                       AltosDebug.debug("Socket already allocated %s", socket.toString());
+                       close_device();
+               }
+               synchronized (this) {
+                       socket = tmp_socket;
+               }
+       }
+
+       private class ConnectThread extends Thread {
+
+               public void run() {
+                       AltosDebug.debug("ConnectThread: BEGIN (pause %b)", pause);
+                       setName("ConnectThread");
+
+                       if (pause) {
+                               try {
+                                       Thread.sleep(4000);
+                               } catch (InterruptedException e) {
+                               }
+                       }
+
+                       create_socket(device);
+                       // Always cancel discovery because it will slow down a connection
+                       try {
+                               BluetoothAdapter.getDefaultAdapter().cancelDiscovery();
+                       } catch (Exception e) {
+                               AltosDebug.debug("cancelDiscovery exception %s", e.toString());
+                       }
+
+                       BluetoothSocket local_socket = null;
+
+                       synchronized (AltosBluetooth.this) {
+                               if (!closed())
+                                       local_socket = socket;
+                       }
+
+                       if (local_socket != null) {
+                               try {
+                                       // Make a connection to the BluetoothSocket
+                                       // This is a blocking call and will only return on a
+                                       // successful connection or an exception
+                                       local_socket.connect();
+                               } catch (Exception e) {
+                                       AltosDebug.debug("Connect exception %s", e.toString());
+                                       try {
+                                               local_socket.close();
+                                       } catch (Exception ce) {
+                                               AltosDebug.debug("Close exception %s", ce.toString());
+                                       }
+                                       local_socket = null;
+                               }
+                       }
+
+                       if (local_socket != null) {
+                               connected();
+                       } else {
+                               connect_failed();
+                       }
+
+                       AltosDebug.debug("ConnectThread: completed");
+               }
+       }
+
+       private synchronized void wait_connected() throws InterruptedException, IOException {
+               AltosDebug.check_ui("wait_connected\n");
+               if (input == null && socket != null) {
+                       AltosDebug.debug("wait_connected...");
+                       wait();
+                       AltosDebug.debug("wait_connected done");
+               }
+               if (socket == null)
+                       throw new IOException();
+       }
+
+       int write(byte[] buffer, int len) {
+               if (output == null)
+                       return -1;
+               try {
+                       output.write(buffer, 0, len);
+               } catch (IOException ie) {
+                       return -1;
+               }
+               return len;
+       }
+
+       int read(byte[] buffer, int len) {
+               if (input == null)
+                       return -1;
+               try {
+                       return input.read(buffer, 0, len);
+               } catch (IOException ie) {
+                       return -1;
+               }
+       }
+
+       // Stubs of required methods when extending AltosLink
+       public boolean can_cancel_reply()   { return false; }
+       public boolean show_reply_timeout() { return true; }
+       public void hide_reply_timeout()    { }
+
+}
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDebug.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDebug.java
new file mode 100644 (file)
index 0000000..469ec50
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright © 2015 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+package org.altusmetrum.AltosDroid;
+
+import java.lang.*;
+
+import android.content.*;
+import android.util.Log;
+import android.os.*;
+import android.content.pm.*;
+
+public class AltosDebug {
+       // Debugging
+       static final String TAG = "AltosDroid";
+
+       static boolean  D = true;
+
+       static void init(Context context) {
+               ApplicationInfo app_info = context.getApplicationInfo();
+
+               if ((app_info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
+                       Log.d(TAG, "Enable debugging\n");
+                       D = true;
+               } else {
+                       Log.d(TAG, "Disable debugging\n");
+                       D = false;
+               }
+       }
+
+
+       static void info(String format, Object ... arguments) {
+               Log.i(TAG, String.format(format, arguments));
+       }
+
+       static void debug(String format, Object ... arguments) {
+               if (D)
+                       Log.d(TAG, String.format(format, arguments));
+       }
+
+       static void error(String format, Object ... arguments) {
+               Log.e(TAG, String.format(format, arguments));
+       }
+
+       static void check_ui(String format, Object ... arguments) {
+               if (Looper.myLooper() == Looper.getMainLooper()) {
+                       Log.e(TAG, String.format("ON UI THREAD " + format, arguments));
+                       for (StackTraceElement el : Thread.currentThread().getStackTrace())
+                               Log.e(TAG, "\t" + el.toString() + "\n");
+               }
+       }
+}
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroid.java
new file mode 100644 (file)
index 0000000..2854836
--- /dev/null
@@ -0,0 +1,1217 @@
+/*
+ * Copyright © 2012-2013 Mike Beattie <mike@ethernal.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.lang.ref.WeakReference;
+import java.util.*;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.bluetooth.BluetoothAdapter;
+import android.content.Intent;
+import android.content.Context;
+import android.content.ComponentName;
+import android.content.ServiceConnection;
+import android.content.DialogInterface;
+import android.os.IBinder;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+import androidx.fragment.app.FragmentActivity;
+import androidx.fragment.app.FragmentManager;
+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 org.altusmetrum.altoslib_13.*;
+
+class SavedState {
+       long    received_time;
+       int     state;
+       boolean locked;
+       String  callsign;
+       int     serial;
+       int     flight;
+       int     rssi;
+
+       SavedState(AltosState state) {
+               received_time = state.received_time;
+               this.state = state.state();
+               if (state.gps != null)
+                       locked = state.gps.locked;
+               else
+                       locked = false;
+               callsign = state.cal_data().callsign;
+               serial = state.cal_data().serial;
+               flight = state.cal_data().flight;
+               rssi = state.rssi;
+       }
+}
+
+class Tracker implements CharSequence, Comparable {
+       int     serial;
+       String  call;
+       double  frequency;
+
+       String  display;
+
+       public Tracker(int serial, String call, double frequency) {
+               if (call == null)
+                       call = "none";
+
+               this.serial = serial;
+               this.call = call;
+               this.frequency = frequency;
+               if (frequency == 0.0)
+                       display = "Auto";
+               else if (frequency == AltosLib.MISSING) {
+                       display = String.format("%-8.8s  %6d", call, serial);
+               } else {
+                       display = String.format("%-8.8s %7.3f %6d", call, frequency, serial);
+               }
+       }
+
+       public Tracker(AltosState s) {
+               this(s == null ? 0 : s.cal_data().serial,
+                    s == null ? null : s.cal_data().callsign,
+                    s == null ? 0.0 : s.frequency);
+       }
+
+       /* CharSequence */
+       public char charAt(int index) {
+               return display.charAt(index);
+       }
+
+       public int length() {
+               return display.length();
+       }
+
+       public CharSequence subSequence(int start, int end) throws IndexOutOfBoundsException {
+               return display.subSequence(start, end);
+       }
+
+       public String toString() {
+               return display.toString();
+       }
+
+       /* Comparable */
+       public int compareTo (Object other) {
+               Tracker o = (Tracker) other;
+               if (frequency == 0.0) {
+                       if (o.frequency == 0.0)
+                               return 0;
+                       return -1;
+               }
+               if (o.frequency == 0.0)
+                       return 1;
+
+               int     a = serial - o.serial;
+               int     b = call.compareTo(o.call);
+               int     c = (int) Math.signum(frequency - o.frequency);
+
+               if (b != 0)
+                       return b;
+               if (c != 0)
+                       return c;
+               return a;
+       }
+}
+
+public class AltosDroid extends FragmentActivity implements AltosUnitsListener, LocationListener {
+
+       // Actions sent to the telemetry server at startup time
+
+       public static final String ACTION_BLUETOOTH = "org.altusmetrum.AltosDroid.BLUETOOTH";
+       public static final String ACTION_USB = "org.altusmetrum.AltosDroid.USB";
+
+       // Message types received by our Handler
+
+       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_IDLE_MODE      = 5;
+       public static final int REQUEST_IGNITERS       = 6;
+       public static final int REQUEST_SETUP          = 7;
+
+       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;
+
+       private BluetoothAdapter mBluetoothAdapter = null;
+
+       // Flight state values
+       private TextView mCallsignView;
+       private TextView mRSSIView;
+       private TextView mSerialView;
+       private TextView mFlightView;
+       private RelativeLayout mStateLayout;
+       private TextView mStateView;
+       private TextView mAgeView;
+       private boolean  mAgeViewOld;
+       private int mAgeNewColor;
+       private int mAgeOldColor;
+
+       public static final String      tab_pad_name = "pad";
+       public static final String      tab_flight_name = "flight";
+       public static final String      tab_recover_name = "recover";
+       public static final String      tab_map_name = "map";
+
+       // field to display the version at the bottom of the screen
+       private TextView mVersion;
+
+       private boolean idle_mode = false;
+
+       public Location location = null;
+
+       private AltosState      state;
+       private SavedState      saved_state;
+
+       // Tabs
+       TabHost         mTabHost;
+       AltosViewPager  mViewPager;
+       TabsAdapter     mTabsAdapter;
+       ArrayList<AltosDroidTab> mTabs = new ArrayList<AltosDroidTab>();
+       int             tabHeight;
+
+       // Timer and Saved flight state for Age calculation
+       private Timer timer;
+
+       TelemetryState  telemetry_state;
+       Tracker[]       trackers;
+
+
+       UsbDevice       pending_usb_device;
+       boolean         start_with_usb;
+
+       // Service
+       private boolean mIsBound   = false;
+       private Messenger mService = null;
+       final Messenger mMessenger = new Messenger(new IncomingHandler(this));
+
+       // Text to Speech
+       private AltosVoice mAltosVoice = null;
+
+       // The Handler that gets information back from the Telemetry Service
+       static class IncomingHandler extends Handler {
+               private final WeakReference<AltosDroid> mAltosDroid;
+               IncomingHandler(AltosDroid ad) { mAltosDroid = new WeakReference<AltosDroid>(ad); }
+
+               @Override
+               public void handleMessage(Message msg) {
+                       AltosDroid ad = mAltosDroid.get();
+
+                       switch (msg.what) {
+                       case MSG_STATE:
+                               if (msg.obj == null) {
+                                       AltosDebug.debug("telemetry_state null!");
+                                       return;
+                               }
+                               ad.update_state((TelemetryState) msg.obj);
+                               break;
+                       case MSG_UPDATE_AGE:
+                               ad.update_age();
+                               break;
+                       case MSG_IDLE_MODE:
+                               ad.idle_mode = (Boolean) msg.obj;
+                               ad.update_state(null);
+                               break;
+                       }
+               }
+       };
+
+
+       private ServiceConnection mConnection = new ServiceConnection() {
+               public void onServiceConnected(ComponentName className, IBinder service) {
+                       mService = new Messenger(service);
+                       try {
+                               Message msg = Message.obtain(null, TelemetryService.MSG_REGISTER_CLIENT);
+                               msg.replyTo = mMessenger;
+                               mService.send(msg);
+                       } catch (RemoteException e) {
+                               // In this case the service has crashed before we could even do anything with it
+                       }
+                       if (pending_usb_device != null) {
+                               try {
+                                       mService.send(Message.obtain(null, TelemetryService.MSG_OPEN_USB, pending_usb_device));
+                                       pending_usb_device = null;
+                               } catch (RemoteException e) {
+                               }
+                       }
+               }
+
+               public void onServiceDisconnected(ComponentName className) {
+                       // This is called when the connection with the service has been unexpectedly disconnected - process crashed.
+                       mService = null;
+               }
+       };
+
+       void doBindService() {
+               bindService(new Intent(this, TelemetryService.class), mConnection, Context.BIND_AUTO_CREATE);
+               mIsBound = true;
+       }
+
+       void doUnbindService() {
+               if (mIsBound) {
+                       // If we have received the service, and hence registered with it, then now is the time to unregister.
+                       if (mService != null) {
+                               try {
+                                       Message msg = Message.obtain(null, TelemetryService.MSG_UNREGISTER_CLIENT);
+                                       msg.replyTo = mMessenger;
+                                       mService.send(msg);
+                               } catch (RemoteException e) {
+                                       // There is nothing special we need to do if the service has crashed.
+                               }
+                       }
+                       // Detach our existing connection.
+                       unbindService(mConnection);
+                       mIsBound = false;
+               }
+       }
+
+       public void registerTab(AltosDroidTab mTab) {
+               mTabs.add(mTab);
+       }
+
+       public void unregisterTab(AltosDroidTab mTab) {
+               mTabs.remove(mTab);
+       }
+
+       public void units_changed(boolean imperial_units) {
+               for (AltosDroidTab mTab : mTabs)
+                       mTab.units_changed(imperial_units);
+       }
+
+       void update_title(TelemetryState telemetry_state) {
+               switch (telemetry_state.connect) {
+               case TelemetryState.CONNECT_CONNECTED:
+                       if (telemetry_state.config != null) {
+                               String str = String.format("S/N %d %6.3f MHz%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]));
+                               setTitle(str);
+                       } else {
+                               setTitle(R.string.title_connected_to);
+                       }
+                       break;
+               case TelemetryState.CONNECT_CONNECTING:
+                       if (telemetry_state.address != null)
+                               setTitle(String.format("Connecting to %s...", telemetry_state.address.name));
+                       else
+                               setTitle("Connecting to something...");
+                       break;
+               case TelemetryState.CONNECT_DISCONNECTED:
+               case TelemetryState.CONNECT_NONE:
+                       setTitle(R.string.title_not_connected);
+                       break;
+               }
+       }
+
+       void start_timer() {
+               if (timer == null) {
+                       timer = new Timer();
+                       timer.scheduleAtFixedRate(new TimerTask(){ public void run() {onTimerTick();}}, 1000L, 1000L);
+               }
+       }
+
+       void stop_timer() {
+               if (timer != null) {
+                       timer.cancel();
+                       timer.purge();
+                       timer = null;
+               }
+       }
+
+       int     selected_serial = 0;
+       int     current_serial;
+       long    switch_time;
+
+       void set_switch_time() {
+               switch_time = System.currentTimeMillis();
+               selected_serial = 0;
+       }
+
+       boolean registered_units_listener;
+
+       void update_state(TelemetryState new_telemetry_state) {
+
+               if (new_telemetry_state != null)
+                       telemetry_state = new_telemetry_state;
+
+               if (selected_serial != 0)
+                       current_serial = selected_serial;
+
+               if (current_serial == 0)
+                       current_serial = telemetry_state.latest_serial;
+
+               if (!registered_units_listener) {
+                       registered_units_listener = true;
+                       AltosPreferences.register_units_listener(this);
+               }
+
+               int     num_trackers = 0;
+               for (AltosState s : telemetry_state.states.values()) {
+                       num_trackers++;
+               }
+
+               trackers = new Tracker[num_trackers + 1];
+
+               int n = 0;
+               trackers[n++] = new Tracker(0, "auto", 0.0);
+
+               for (AltosState s : telemetry_state.states.values())
+                       trackers[n++] = new Tracker(s);
+
+               Arrays.sort(trackers);
+
+               update_title(telemetry_state);
+
+               AltosState      state = null;
+               boolean         aged = true;
+
+               if (telemetry_state.states.containsKey(current_serial)) {
+                       state = telemetry_state.states.get(current_serial);
+                       int age = state_age(state.received_time);
+                       if (age < 20)
+                               aged = false;
+                       if (current_serial == selected_serial)
+                               aged = false;
+                       else if (switch_time != 0 && (switch_time - state.received_time) > 0)
+                               aged = true;
+               }
+
+               if (aged) {
+                       AltosState      newest_state = null;
+                       int             newest_age = 0;
+
+                       for (int serial : telemetry_state.states.keySet()) {
+                               AltosState      existing = telemetry_state.states.get(serial);
+                               int             existing_age = state_age(existing.received_time);
+
+                               if (newest_state == null || existing_age < newest_age) {
+                                       newest_state = existing;
+                                       newest_age = existing_age;
+                               }
+                       }
+
+                       if (newest_state != null)
+                               state = newest_state;
+               }
+
+               update_ui(telemetry_state, state, telemetry_state.quiet);
+
+               start_timer();
+       }
+
+       boolean same_string(String a, String b) {
+               if (a == null) {
+                       if (b == null)
+                               return true;
+                       return false;
+               } else {
+                       if (b == null)
+                               return false;
+                       return a.equals(b);
+               }
+       }
+
+
+       private int blend_component(int a, int b, double r, int shift, int mask) {
+               return ((int) (((a >> shift) & mask) * r + ((b >> shift) & mask) * (1 - r)) & mask) << shift;
+       }
+       private int blend_color(int a, int b, double r) {
+               return (blend_component(a, b, r, 0, 0xff) |
+                       blend_component(a, b, r, 8, 0xff) |
+                       blend_component(a, b, r, 16, 0xff) |
+                       blend_component(a, b, r, 24, 0xff));
+       }
+
+       int state_age(long received_time) {
+               return (int) ((System.currentTimeMillis() - received_time + 500) / 1000);
+       }
+
+       void set_screen_on(int age) {
+               if (age < 60)
+                       getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+               else
+                       getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+       }
+
+       void update_age() {
+               if (saved_state != null) {
+                       int age = state_age(saved_state.received_time);
+
+                       double age_scale = age / 100.0;
+
+                       if (age_scale > 1.0)
+                               age_scale = 1.0;
+
+                       mAgeView.setTextColor(blend_color(mAgeOldColor, mAgeNewColor, age_scale));
+
+                       set_screen_on(age);
+
+                       String  text;
+                       if (age < 60)
+                               text = String.format("%ds", age);
+                       else if (age < 60 * 60)
+                               text = String.format("%dm", age / 60);
+                       else if (age < 60 * 60 * 24)
+                               text = String.format("%dh", age / (60 * 60));
+                       else
+                               text = String.format("%dd", age / (24 * 60 * 60));
+                       mAgeView.setText(text);
+               }
+       }
+
+       void update_ui(TelemetryState telem_state, AltosState state, boolean quiet) {
+
+               this.state = state;
+
+               int prev_state = AltosLib.ao_flight_invalid;
+
+               AltosGreatCircle from_receiver = null;
+
+               if (saved_state != null)
+                       prev_state = saved_state.state;
+
+               if (state != null) {
+                       set_screen_on(state_age(state.received_time));
+
+                       if (state.state() == AltosLib.ao_flight_stateless) {
+                               boolean prev_locked = false;
+                               boolean locked = false;
+
+                               if(state.gps != null)
+                                       locked = state.gps.locked;
+                               if (saved_state != null)
+                                       prev_locked = saved_state.locked;
+                               if (prev_locked != locked) {
+                                       String currentTab = mTabHost.getCurrentTabTag();
+                                       if (locked) {
+                                               if (currentTab.equals(tab_pad_name)) mTabHost.setCurrentTabByTag(tab_flight_name);
+                                       } else {
+                                               if (currentTab.equals(tab_flight_name)) mTabHost.setCurrentTabByTag(tab_pad_name);
+                                       }
+                               }
+                       } else {
+                               if (prev_state != state.state()) {
+                                       String currentTab = mTabHost.getCurrentTabTag();
+                                       switch (state.state()) {
+                                       case AltosLib.ao_flight_boost:
+                                               if (currentTab.equals(tab_pad_name)) mTabHost.setCurrentTabByTag(tab_flight_name);
+                                               break;
+                                       case AltosLib.ao_flight_landed:
+                                               if (currentTab.equals(tab_flight_name)) mTabHost.setCurrentTabByTag(tab_recover_name);
+                                               break;
+                                       case AltosLib.ao_flight_stateless:
+                                               if (currentTab.equals(tab_pad_name)) mTabHost.setCurrentTabByTag(tab_flight_name);
+                                               break;
+                                       }
+                               }
+                       }
+
+                       if (location != null && state.gps != null && state.gps.locked) {
+                               double altitude = 0;
+                               if (location.hasAltitude())
+                                       altitude = location.getAltitude();
+                               from_receiver = new AltosGreatCircle(location.getLatitude(),
+                                                                    location.getLongitude(),
+                                                                    altitude,
+                                                                    state.gps.lat,
+                                                                    state.gps.lon,
+                                                                    state.gps.alt);
+                       }
+
+                       if (saved_state == null || !same_string(saved_state.callsign, state.cal_data().callsign)) {
+                               mCallsignView.setText(state.cal_data().callsign);
+                       }
+                       if (saved_state == null || state.cal_data().serial != saved_state.serial) {
+                               if (state.cal_data().serial == AltosLib.MISSING)
+                                       mSerialView.setText("");
+                               else
+                                       mSerialView.setText(String.format("%d", state.cal_data().serial));
+                       }
+                       if (saved_state == null || state.cal_data().flight != saved_state.flight) {
+                               if (state.cal_data().flight == AltosLib.MISSING)
+                                       mFlightView.setText("");
+                               else
+                                       mFlightView.setText(String.format("%d", state.cal_data().flight));
+                       }
+                       if (saved_state == null || state.state() != saved_state.state) {
+                               if (state.state() == AltosLib.ao_flight_stateless) {
+                                       mStateLayout.setVisibility(View.GONE);
+                               } else {
+                                       mStateView.setText(state.state_name());
+                                       mStateLayout.setVisibility(View.VISIBLE);
+                               }
+                       }
+                       if (saved_state == null || state.rssi != saved_state.rssi) {
+                               if (state.rssi == AltosLib.MISSING)
+                                       mRSSIView.setText("");
+                               else
+                                       mRSSIView.setText(String.format("%d", state.rssi));
+                       }
+                       saved_state = new SavedState(state);
+               }
+
+               for (AltosDroidTab mTab : mTabs)
+                       mTab.update_ui(telem_state, state, from_receiver, location, mTab == mTabsAdapter.currentItem());
+
+               AltosDebug.debug("quiet %b\n", quiet);
+               if (mAltosVoice != null && mTabsAdapter.currentItem() != null)
+                       mAltosVoice.tell(telem_state, state, from_receiver, location, (AltosDroidTab) mTabsAdapter.currentItem(), quiet);
+
+       }
+
+       private void onTimerTick() {
+               try {
+                       mMessenger.send(Message.obtain(null, MSG_UPDATE_AGE));
+               } catch (RemoteException e) {
+               }
+       }
+
+       static String pos(double p, String pos, String neg) {
+               String  h = pos;
+               if (p == AltosLib.MISSING)
+                       return "";
+               if (p < 0) {
+                       h = neg;
+                       p = -p;
+               }
+               int deg = (int) Math.floor(p);
+               double min = (p - Math.floor(p)) * 60.0;
+               return String.format("%d°%9.4f\" %s", deg, min, h);
+       }
+
+       static String number(String format, double value) {
+               if (value == AltosLib.MISSING)
+                       return "";
+               return String.format(format, value);
+       }
+
+       static String integer(String format, int value) {
+               if (value == AltosLib.MISSING)
+                       return "";
+               return String.format(format, value);
+       }
+
+       private View create_tab_view(String label) {
+               LayoutInflater inflater = (LayoutInflater) this.getLayoutInflater();
+               View tab_view = inflater.inflate(R.layout.tab_layout, null);
+               TextView text_view = (TextView) tab_view.findViewById (R.id.tabLabel);
+               text_view.setText(label);
+               return tab_view;
+       }
+
+       @Override
+       public void onCreate(Bundle savedInstanceState) {
+               super.onCreate(savedInstanceState);
+               AltosDebug.init(this);
+               AltosDebug.debug("+++ ON CREATE +++");
+
+               // Initialise preferences
+               AltosDroidPreferences.init(this);
+
+               fm = getSupportFragmentManager();
+
+               // Set up the window layout
+               setContentView(R.layout.altosdroid);
+
+               // Create the Tabs and ViewPager
+               mTabHost = (TabHost)findViewById(android.R.id.tabhost);
+               mTabHost.setup();
+
+               mViewPager = (AltosViewPager)findViewById(R.id.pager);
+               mViewPager.setOffscreenPageLimit(4);
+
+               mTabsAdapter = new TabsAdapter(this, mTabHost, mViewPager);
+
+               mTabsAdapter.addTab(mTabHost.newTabSpec(tab_pad_name).setIndicator(create_tab_view("Pad")), TabPad.class, null);
+               mTabsAdapter.addTab(mTabHost.newTabSpec(tab_flight_name).setIndicator(create_tab_view("Flight")), TabFlight.class, null);
+               mTabsAdapter.addTab(mTabHost.newTabSpec(tab_recover_name).setIndicator(create_tab_view("Recover")), TabRecover.class, null);
+               mTabsAdapter.addTab(mTabHost.newTabSpec(tab_map_name).setIndicator(create_tab_view("Map")), TabMap.class, null);
+
+               // Display the Version
+               mVersion = (TextView) findViewById(R.id.version);
+               mVersion.setText("Version: " + BuildInfo.version +
+                                " Built: " + BuildInfo.builddate + " " + BuildInfo.buildtime + " " + BuildInfo.buildtz +
+                                " (" + BuildInfo.branch + "-" + BuildInfo.commitnum + "-" + BuildInfo.commithash + ")");
+
+               mCallsignView  = (TextView) findViewById(R.id.callsign_value);
+               mRSSIView      = (TextView) findViewById(R.id.rssi_value);
+               mSerialView    = (TextView) findViewById(R.id.serial_value);
+               mFlightView    = (TextView) findViewById(R.id.flight_value);
+               mStateLayout   = (RelativeLayout) findViewById(R.id.state_container);
+               mStateView     = (TextView) findViewById(R.id.state_value);
+               mAgeView       = (TextView) findViewById(R.id.age_value);
+               mAgeNewColor   = mAgeView.getTextColors().getDefaultColor();
+               mAgeOldColor   = getResources().getColor(R.color.old_color);
+       }
+
+       private void ensureBluetooth() {
+               // Get local Bluetooth adapter
+               mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+
+               /* 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);
+               }
+       }
+
+       private boolean check_usb() {
+               UsbDevice       device = AltosUsb.find_device(this, AltosLib.product_basestation);
+
+               if (device != null) {
+                       Intent          i = new Intent(this, AltosDroid.class);
+                       PendingIntent   pi = PendingIntent.getActivity(this, 0, new Intent("hello world", null, this, AltosDroid.class), 0);
+
+                       if (AltosUsb.request_permission(this, device, pi)) {
+                               connectUsb(device);
+                       }
+                       start_with_usb = true;
+                       return true;
+               }
+
+               start_with_usb = false;
+
+               return false;
+       }
+
+       private void noticeIntent(Intent intent) {
+
+               /* Ok, this is pretty convenient.
+                *
+                * When a USB device is plugged in, and our 'hotplug'
+                * intent registration fires, we get an Intent with
+                * EXTRA_DEVICE set.
+                *
+                * When we start up and see a usb device and request
+                * permission to access it, that queues a
+                * PendingIntent, which has the EXTRA_DEVICE added in,
+                * along with the EXTRA_PERMISSION_GRANTED field as
+                * well.
+                *
+                * So, in both cases, we get the device name using the
+                * same call. We check to see if access was granted,
+                * in which case we ignore the device field and do our
+                * usual startup thing.
+                */
+
+               UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
+               boolean granted = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true);
+
+               AltosDebug.debug("intent %s device %s granted %s", intent, device, granted);
+
+               if (!granted)
+                       device = null;
+
+               if (device != null) {
+                       AltosDebug.debug("intent has usb device " + device.toString());
+                       connectUsb(device);
+               } else {
+
+                       /* 'granted' is only false if this intent came
+                        * from the request_permission call and
+                        * permission was denied. In which case, we
+                        * don't want to loop forever...
+                        */
+                       if (granted) {
+                               AltosDebug.debug("check for a USB device at startup");
+                               if (check_usb())
+                                       return;
+                       }
+                       AltosDebug.debug("Starting by looking for bluetooth devices");
+                       ensureBluetooth();
+               }
+       }
+
+       @Override
+       public void onStart() {
+               super.onStart();
+               AltosDebug.debug("++ ON START ++");
+
+               set_switch_time();
+
+               noticeIntent(getIntent());
+
+               // Start Telemetry Service
+               String  action = start_with_usb ? ACTION_USB : ACTION_BLUETOOTH;
+
+               startService(new Intent(action, null, AltosDroid.this, TelemetryService.class));
+
+               doBindService();
+
+               if (mAltosVoice == null)
+                       mAltosVoice = new AltosVoice(this);
+
+       }
+
+       @Override
+       public void onNewIntent(Intent intent) {
+               super.onNewIntent(intent);
+               AltosDebug.debug("onNewIntent");
+               noticeIntent(intent);
+       }
+
+       @Override
+       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, state, true);
+       }
+
+       @Override
+       public void onPause() {
+               super.onPause();
+               AltosDebug.debug("- ON PAUSE -");
+               // Stop listening for location updates
+               ((LocationManager) getSystemService(Context.LOCATION_SERVICE)).removeUpdates(this);
+       }
+
+       @Override
+       public void onStop() {
+               super.onStop();
+               AltosDebug.debug("-- ON STOP --");
+       }
+
+       @Override
+       public void onDestroy() {
+               super.onDestroy();
+               AltosDebug.debug("--- ON DESTROY ---");
+
+               doUnbindService();
+               if (mAltosVoice != null) {
+                       mAltosVoice.stop();
+                       mAltosVoice = null;
+               }
+               stop_timer();
+       }
+
+       protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+               AltosDebug.debug("onActivityResult " + resultCode);
+               switch (requestCode) {
+               case REQUEST_CONNECT_DEVICE:
+                       // When DeviceListActivity returns with a device to connect to
+                       if (resultCode == Activity.RESULT_OK) {
+                               connectDevice(data);
+                       }
+                       break;
+               case REQUEST_ENABLE_BT:
+                       // When the request to enable Bluetooth returns
+                       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.debug("BT not enabled");
+                       }
+                       break;
+               case REQUEST_IDLE_MODE:
+                       if (resultCode == Activity.RESULT_OK)
+                               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) {
+               if (mService == null)
+                       pending_usb_device = device;
+               else {
+                       // Attempt to connect to the device
+                       try {
+                               mService.send(Message.obtain(null, TelemetryService.MSG_OPEN_USB, device));
+                               AltosDebug.debug("Sent OPEN_USB message");
+                       } catch (RemoteException e) {
+                               AltosDebug.debug("connect device message failed");
+                       }
+               }
+       }
+
+       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 {
+                       String address = data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
+                       String name = data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_NAME);
+
+                       AltosDebug.debug("Connecting to " + address + " " + name);
+                       DeviceAddress   a = new DeviceAddress(address, name);
+                       mService.send(Message.obtain(null, TelemetryService.MSG_CONNECT, a));
+                       AltosDebug.debug("Sent connecting message");
+               } catch (RemoteException e) {
+                       AltosDebug.debug("connect device message failed");
+               }
+       }
+
+       private void disconnectDevice(boolean remember) {
+               try {
+                       mService.send(Message.obtain(null, TelemetryService.MSG_DISCONNECT, (Boolean) remember));
+               } catch (RemoteException e) {
+               }
+       }
+
+       private void idle_mode(Intent data) {
+               int type = data.getIntExtra(IdleModeActivity.EXTRA_IDLE_RESULT, -1);
+               Message msg;
+
+               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;
+               }
+       }
+
+       @Override
+       public boolean onCreateOptionsMenu(Menu menu) {
+               MenuInflater inflater = getMenuInflater();
+               inflater.inflate(R.menu.option_menu, menu);
+               return true;
+       }
+
+       void setFrequency(double freq) {
+               try {
+                       mService.send(Message.obtain(null, TelemetryService.MSG_SETFREQUENCY, freq));
+                       set_switch_time();
+               } catch (RemoteException e) {
+               }
+       }
+
+       void setFrequency(AltosFrequency frequency) {
+               setFrequency (frequency.frequency);
+       }
+
+       void setBaud(int baud) {
+               try {
+                       mService.send(Message.obtain(null, TelemetryService.MSG_SETBAUD, baud));
+                       set_switch_time();
+               } catch (RemoteException e) {
+               }
+       }
+
+       void setBaud(String baud) {
+               try {
+                       int     value = Integer.parseInt(baud);
+                       int     rate = AltosLib.ao_telemetry_rate_38400;
+                       switch (value) {
+                       case 2400:
+                               rate = AltosLib.ao_telemetry_rate_2400;
+                               break;
+                       case 9600:
+                               rate = AltosLib.ao_telemetry_rate_9600;
+                               break;
+                       case 38400:
+                               rate = AltosLib.ao_telemetry_rate_38400;
+                               break;
+                       }
+                       setBaud(rate);
+               } catch (NumberFormatException e) {
+               }
+       }
+
+       void select_tracker(int serial) {
+               int i;
+
+               AltosDebug.debug("select tracker %d\n", serial);
+
+               if (serial == selected_serial) {
+                       AltosDebug.debug("%d already selected\n", serial);
+                       return;
+               }
+
+               if (serial != 0) {
+                       for (i = 0; i < trackers.length; i++)
+                               if (trackers[i].serial == serial)
+                                       break;
+
+                       if (i == trackers.length) {
+                               AltosDebug.debug("attempt to select unknown tracker %d\n", serial);
+                               return;
+                       }
+               }
+
+               current_serial = selected_serial = serial;
+               update_state(null);
+       }
+
+       void touch_trackers(Integer[] serials) {
+               AlertDialog.Builder builder_tracker = new AlertDialog.Builder(this);
+               builder_tracker.setTitle("Select Tracker");
+
+               final Tracker[] my_trackers = new Tracker[serials.length + 1];
+
+               my_trackers[0] = new Tracker(null);
+
+               for (int i = 0; i < serials.length; i++) {
+                       AltosState      s = telemetry_state.states.get(serials[i]);
+                       my_trackers[i+1] = new Tracker(s);
+               }
+               builder_tracker.setItems(my_trackers,
+                                        new DialogInterface.OnClickListener() {
+                                                public void onClick(DialogInterface dialog, int item) {
+                                                        if (item == 0)
+                                                                select_tracker(0);
+                                                        else
+                                                                select_tracker(my_trackers[item].serial);
+                                                }
+                                        });
+               AlertDialog alert_tracker = builder_tracker.create();
+               alert_tracker.show();
+       }
+
+       void delete_track(int serial) {
+               try {
+                       mService.send(Message.obtain(null, TelemetryService.MSG_DELETE_SERIAL, (Integer) serial));
+               } catch (Exception ex) {
+               }
+       }
+
+       @Override
+       public boolean onOptionsItemSelected(MenuItem item) {
+               Intent serverIntent = null;
+               switch (item.getItemId()) {
+               case R.id.connect_scan:
+                       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
+                        */
+                       disconnectDevice(false);
+                       return true;
+               case R.id.quit:
+                       AltosDebug.debug("R.id.quit");
+                       disconnectDevice(true);
+                       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 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(frequency_strings,
+                                        new DialogInterface.OnClickListener() {
+                                                public void onClick(DialogInterface dialog, int item) {
+                                                        setFrequency(frequencies[item]);
+                                                }
+                                        });
+                       AlertDialog alert_freq = builder_freq.create();
+                       alert_freq.show();
+                       return true;
+               case R.id.select_tracker:
+                       if (trackers != null) {
+                               AlertDialog.Builder builder_serial = new AlertDialog.Builder(this);
+                               builder_serial.setTitle("Select a tracker");
+                               builder_serial.setItems(trackers,
+                                                       new DialogInterface.OnClickListener() {
+                                                               public void onClick(DialogInterface dialog, int item) {
+                                                                       System.out.printf("select item %d %s\n", item, trackers[item].display);
+                                                                       if (item == 0)
+                                                                               select_tracker(0);
+                                                                       else
+                                                                               select_tracker(trackers[item].serial);
+                                                               }
+                                                       });
+                               AlertDialog alert_serial = builder_serial.create();
+                               alert_serial.show();
+
+                       }
+                       return true;
+               case R.id.delete_track:
+                       if (trackers != null) {
+                               AlertDialog.Builder builder_serial = new AlertDialog.Builder(this);
+                               builder_serial.setTitle("Delete a track");
+                               final Tracker[] my_trackers = new Tracker[trackers.length - 1];
+                               for (int i = 0; i < trackers.length - 1; i++)
+                                       my_trackers[i] = trackers[i+1];
+                               builder_serial.setItems(my_trackers,
+                                                       new DialogInterface.OnClickListener() {
+                                                               public void onClick(DialogInterface dialog, int item) {
+                                                                       delete_track(my_trackers[item].serial);
+                                                               }
+                                                       });
+                               AlertDialog alert_serial = builder_serial.create();
+                               alert_serial.show();
+
+                       }
+                       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) {
+               if (from_receiver == null)
+                       return null;
+
+               if (receiver == null)
+                       return null;
+
+               if (!receiver.hasBearing())
+                       return null;
+
+               float   bearing = receiver.getBearing();
+               float   heading = (float) from_receiver.bearing - bearing;
+
+               while (heading <= -180.0f)
+                       heading += 360.0f;
+               while (heading > 180.0f)
+                       heading -= 360.0f;
+
+               int iheading = (int) (heading + 0.5f);
+
+               if (-1 < iheading && iheading < 1)
+                       return "ahead";
+               else if (iheading < -179 || 179 < iheading)
+                       return "backwards";
+               else if (iheading < 0)
+                       return String.format("left %d°", -iheading);
+               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, state, false);
+       }
+
+       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);
+       }
+}
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroidLink.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroidLink.java
new file mode 100644 (file)
index 0000000..1e22e8f
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * Copyright © 2015 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import android.os.Handler;
+
+import org.altusmetrum.altoslib_13.*;
+
+public abstract class AltosDroidLink extends AltosLink {
+
+       Handler         handler;
+
+       Thread          input_thread   = null;
+
+       public double frequency() {
+               return frequency;
+       }
+
+       public int telemetry_rate() {
+               return telemetry_rate;
+       }
+
+       public void save_frequency() {
+               AltosPreferences.set_frequency(0, frequency);
+       }
+
+       public void save_telemetry_rate() {
+               AltosPreferences.set_telemetry_rate(0, telemetry_rate);
+       }
+
+       Object closed_lock = new Object();
+       boolean closing = false;
+       boolean closed = false;
+
+       public boolean closed() {
+               synchronized(closed_lock) {
+                       return closing;
+               }
+       }
+
+       void connected() throws InterruptedException {
+               input_thread = new Thread(this);
+               input_thread.start();
+
+               // Configure the newly connected device for telemetry
+               print("~\nE 0\n");
+               set_monitor(false);
+               AltosDebug.debug("ConnectThread: connected");
+
+               /* Let TelemetryService know we're connected
+                */
+               handler.obtainMessage(TelemetryService.MSG_CONNECTED, this).sendToTarget();
+
+               /* Notify other waiting threads that we're connected now
+                */
+               notifyAll();
+       }
+
+       public void closing() {
+               synchronized(closed_lock) {
+                       AltosDebug.debug("Marked closing true");
+                       closing = true;
+               }
+       }
+
+       private boolean actually_closed() {
+               synchronized(closed_lock) {
+                       return closed;
+               }
+       }
+
+       abstract void close_device();
+
+       public void close() {
+               AltosDebug.debug("close(): begin");
+
+               closing();
+
+               flush_output();
+
+               synchronized (closed_lock) {
+                       AltosDebug.debug("Marked closed true");
+                       closed = true;
+               }
+
+               close_device();
+
+               synchronized(this) {
+
+                       if (input_thread != null) {
+                               AltosDebug.debug("close(): stopping input_thread");
+                               try {
+                                       AltosDebug.debug("close(): input_thread.interrupt().....");
+                                       input_thread.interrupt();
+                                       AltosDebug.debug("close(): input_thread.join().....");
+                                       input_thread.join();
+                               } catch (Exception e) {}
+                               input_thread = null;
+                       }
+                       notifyAll();
+               }
+       }
+
+       abstract int write(byte[] buffer, int len);
+
+       abstract int read(byte[] buffer, int len);
+
+       private static final int buffer_size = 64;
+
+       private byte[] in_buffer = new byte[buffer_size];
+       private byte[] out_buffer = new byte[buffer_size];
+       private int buffer_len = 0;
+       private int buffer_off = 0;
+       private int out_buffer_off = 0;
+
+       private byte[] debug_chars = new byte[buffer_size];
+       private int debug_off;
+
+       private void debug_input(byte b) {
+               if (b == '\n') {
+                       AltosDebug.debug("            " + new String(debug_chars, 0, debug_off));
+                       debug_off = 0;
+               } else {
+                       if (debug_off < buffer_size)
+                               debug_chars[debug_off++] = b;
+               }
+       }
+
+       private void disconnected() {
+               if (closed()) {
+                       AltosDebug.debug("disconnected after closed");
+                       return;
+               }
+
+               AltosDebug.debug("Sending disconnected message");
+               handler.obtainMessage(TelemetryService.MSG_DISCONNECTED, this).sendToTarget();
+       }
+
+       public int getchar() {
+
+               if (actually_closed())
+                       return ERROR;
+
+               while (buffer_off == buffer_len) {
+                       buffer_len = read(in_buffer, buffer_size);
+                       if (buffer_len < 0) {
+                               AltosDebug.debug("ERROR returned from getchar()");
+                               disconnected();
+                               return ERROR;
+                       }
+                       buffer_off = 0;
+               }
+//             if (AltosDebug.D)
+//                     debug_input(in_buffer[buffer_off]);
+               return in_buffer[buffer_off++];
+       }
+
+       public void flush_output() {
+               super.flush_output();
+
+               if (actually_closed()) {
+                       out_buffer_off = 0;
+                       return;
+               }
+
+               while (out_buffer_off != 0) {
+                       int     sent = write(out_buffer, out_buffer_off);
+
+                       if (sent <= 0) {
+                               AltosDebug.debug("flush_output() failed");
+                               out_buffer_off = 0;
+                               break;
+                       }
+
+                       if (sent < out_buffer_off)
+                               System.arraycopy(out_buffer, 0, out_buffer, sent, out_buffer_off - sent);
+
+                       out_buffer_off -= sent;
+               }
+       }
+
+       public void putchar(byte c) {
+               out_buffer[out_buffer_off++] = c;
+               if (out_buffer_off == buffer_size)
+                       flush_output();
+       }
+
+       public void print(String data) {
+               byte[] bytes = data.getBytes();
+//             AltosDebug.debug(data.replace('\n', '\\'));
+               for (byte b : bytes)
+                       putchar(b);
+       }
+
+       public AltosDroidLink(Handler handler) {
+               this.handler = handler;
+       }
+}
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroidMapInterface.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroidMapInterface.java
new file mode 100644 (file)
index 0000000..b22849a
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2015 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import android.location.Location;
+import org.altusmetrum.altoslib_13.*;
+
+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);
+
+       public void show(TelemetryState telem_state, AltosState state, AltosGreatCircle from_receiver, Location receiver);
+}
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroidMapSourceListener.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroidMapSourceListener.java
new file mode 100644 (file)
index 0000000..294094c
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+public interface AltosDroidMapSourceListener {
+       public void map_source_changed(int map_source);
+}
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroidPreferences.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroidPreferences.java
new file mode 100644 (file)
index 0000000..6ec9e4d
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+package org.altusmetrum.AltosDroid;
+
+import java.util.*;
+
+import android.content.Context;
+import org.altusmetrum.altoslib_13.*;
+
+public class AltosDroidPreferences extends AltosPreferences {
+
+       /* Active device preference name */
+       final static String activeDeviceAddressPreference = "ACTIVE-DEVICE-ADDRESS";
+       final static String activeDeviceNamePreference = "ACTIVE-DEVICE-NAME";
+
+       static DeviceAddress    active_device_address;
+
+       /* Map source preference name */
+       final static String mapSourcePreference = "MAP-SOURCE";
+
+       static final int        MAP_SOURCE_OFFLINE = 0;
+       static final int        MAP_SOURCE_ONLINE = 1;
+
+       static int      map_source;
+
+       public static void init(Context context) {
+               if (backend != null)
+                       return;
+
+               AltosPreferences.init(new AltosDroidPreferencesBackend(context));
+
+               String address = backend.getString(activeDeviceAddressPreference, null);
+               String name = backend.getString(activeDeviceNamePreference, null);
+
+               if (address != null && name != null)
+                       active_device_address = new DeviceAddress (address, name);
+
+               map_source = backend.getInt(mapSourcePreference, MAP_SOURCE_ONLINE);
+       }
+
+       public static void set_active_device(DeviceAddress address) {
+               synchronized(backend) {
+                       active_device_address = address;
+                       if (active_device_address != null) {
+                               backend.putString(activeDeviceAddressPreference, active_device_address.address);
+                               backend.putString(activeDeviceNamePreference, active_device_address.name);
+                       } else {
+                               backend.remove(activeDeviceAddressPreference);
+                               backend.remove(activeDeviceNamePreference);
+                       }
+                       flush_preferences();
+               }
+       }
+
+       public static DeviceAddress active_device() {
+               synchronized(backend) {
+                       return active_device_address;
+               }
+       }
+
+       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() {
+               synchronized(backend) {
+                       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);
+               }
+       }
+}
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java
new file mode 100644 (file)
index 0000000..854fe86
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright © 2012 Mike Beattie <mike@ethernal.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.io.File;
+import java.util.Map;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Environment;
+import android.util.*;
+
+import org.altusmetrum.altoslib_13.*;
+
+public class AltosDroidPreferencesBackend extends AltosPreferencesBackend {
+       public final static String        NAME    = "org.altusmetrum.AltosDroid";
+       private Context                   context = null;
+       private SharedPreferences         prefs   = null;
+       private SharedPreferences.Editor  editor  = null;
+
+       public AltosDroidPreferencesBackend(Context in_context) {
+               this(in_context, NAME);
+       }
+
+       public AltosDroidPreferencesBackend(Context in_context, String in_prefs) {
+               context = in_context;
+               prefs   = context.getSharedPreferences(in_prefs, 0);
+               editor  = prefs.edit();
+       }
+
+       public String[] keys() {
+               Map<String, ?> all = prefs.getAll();
+               Object[] ao = all.keySet().toArray();
+
+               String[] as = new String[ao.length];
+               for (int i = 0; i < ao.length; i++)
+                       as[i] = (String) ao[i];
+               return as;
+       }
+
+       public AltosPreferencesBackend node(String key) {
+               if (!nodeExists(key))
+                       putBoolean(key, true);
+               return new AltosDroidPreferencesBackend(context, key);
+       }
+
+       public boolean nodeExists(String key) {
+               return prefs.contains(key);
+       }
+
+       public boolean getBoolean(String key, boolean def) {
+               return prefs.getBoolean(key, def);
+       }
+
+       public double getDouble(String key, double def) {
+               Float f = Float.valueOf(prefs.getFloat(key, (float)def));
+               return f.doubleValue();
+       }
+
+       public int getInt(String key, int def) {
+               return prefs.getInt(key, def);
+       }
+
+       public String getString(String key, String def) {
+               String  ret;
+               ret = prefs.getString(key, def);
+//             AltosDebug.debug("AltosDroidPreferencesBackend get string %s:\n", key);
+//             if (ret == null)
+//                     AltosDebug.debug("      (null)\n");
+//             else {
+//                     String[] lines = ret.split("\n");
+//                     for (String l : lines)
+//                             AltosDebug.debug("        %s\n", l);
+//             }
+               return ret;
+       }
+
+       public byte[] getBytes(String key, byte[] def) {
+               String save = prefs.getString(key, null);
+
+               if (save == null)
+                       return def;
+
+               byte[] bytes = Base64.decode(save, Base64.DEFAULT);
+               return bytes;
+       }
+
+       public void putBoolean(String key, boolean value) {
+               editor.putBoolean(key, value);
+       }
+
+       public void putDouble(String key, double value) {
+               editor.putFloat(key, (float)value);
+       }
+
+       public void putInt(String key, int value) {
+               editor.putInt(key, value);
+       }
+
+       public void putString(String key, String value) {
+//             AltosDebug.debug("AltosDroidPreferencesBackend put string %s:\n", key);
+//             String[] lines = value.split("\n");
+//             for (String l : lines)
+//                     AltosDebug.debug("        %s\n", l);
+               editor.putString(key, value);
+       }
+
+       public void putBytes(String key, byte[] bytes) {
+               String save = Base64.encodeToString(bytes, Base64.DEFAULT);
+               editor.putString(key, save);
+       }
+
+       public void remove(String key) {
+               AltosDebug.debug("remove preference %s\n", key);
+               editor.remove(key);
+       }
+
+       public void flush() {
+               editor.apply();
+       }
+
+       public File homeDirectory() {
+               return Environment.getExternalStorageDirectory();
+       }
+
+       public void debug(String format, Object ... arguments) {
+               AltosDebug.debug(format, arguments);
+       }
+}
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroidTab.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroidTab.java
new file mode 100644 (file)
index 0000000..4f0fb1f
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright © 2013 Mike Beattie <mike@ethernal.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import org.altusmetrum.altoslib_13.*;
+import android.location.Location;
+import android.app.Activity;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentTransaction;
+import android.widget.TextView;
+
+public abstract class AltosDroidTab extends Fragment implements AltosUnitsListener {
+       TelemetryState          last_telem_state;
+       AltosState              last_state;
+       AltosGreatCircle        last_from_receiver;
+       Location                last_receiver;
+       AltosDroid              altos_droid;
+
+       public abstract void show(TelemetryState telem_state, AltosState state, AltosGreatCircle from_receiver, Location receiver);
+
+       public abstract String tab_name();
+
+       public void units_changed(boolean imperial_units) {
+               if (!isHidden())
+                       show(last_telem_state, last_state, last_from_receiver, last_receiver);
+       }
+
+       public void set_value(TextView text_view,
+                             AltosUnits units,
+                             int width,
+                             double value) {
+               if (value == AltosLib.MISSING)
+                       text_view.setText("");
+               else
+                       text_view.setText(units.show(width, value));
+       }
+
+       public void set_visible(boolean visible) {
+               FragmentTransaction     ft = AltosDroid.fm.beginTransaction();
+               AltosDebug.debug("set visible %b %s\n", visible, tab_name());
+               if (visible) {
+                       ft.show(this);
+                       show(last_telem_state, last_state, last_from_receiver, last_receiver);
+               } else
+                       ft.hide(this);
+               try {
+                       ft.commitAllowingStateLoss();
+               } catch (IllegalStateException ie) {
+               }
+       }
+
+       @Override
+       public void onAttach(Activity activity) {
+               super.onAttach(activity);
+               altos_droid = (AltosDroid) activity;
+               altos_droid.registerTab(this);
+       }
+
+       @Override
+       public void onDetach() {
+               super.onDetach();
+               altos_droid.unregisterTab(this);
+               altos_droid = null;
+       }
+
+       @Override
+       public void onResume() {
+               super.onResume();
+               AltosDebug.debug("onResume tab %s\n", tab_name());
+               set_visible(true);
+       }
+
+       public void update_ui(TelemetryState telem_state, AltosState state,
+                             AltosGreatCircle from_receiver, Location receiver, boolean is_current)
+       {
+               last_telem_state = telem_state;
+               last_state = state;
+               last_from_receiver = from_receiver;
+               last_receiver = receiver;
+               if (is_current)
+                       show(telem_state, state, from_receiver, receiver);
+               else
+                       return;
+       }
+}
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosMapOffline.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosMapOffline.java
new file mode 100644 (file)
index 0000000..c320433
--- /dev/null
@@ -0,0 +1,527 @@
+/*
+ * Copyright © 2015 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.util.*;
+import java.io.*;
+
+import org.altusmetrum.altoslib_13.*;
+
+import android.graphics.*;
+import android.view.*;
+import android.location.Location;
+import android.content.*;
+import android.util.*;
+
+class Rocket implements Comparable {
+       AltosLatLon     position;
+       String          name;
+       int             serial;
+       long            last_packet;
+       boolean         active;
+       AltosMapOffline map_offline;
+
+       void paint() {
+               map_offline.draw_bitmap(position, map_offline.rocket_bitmap, map_offline.rocket_off_x, map_offline.rocket_off_y);
+               map_offline.draw_text(position, name, 0, 3*map_offline.rocket_bitmap.getHeight()/4);
+       }
+
+       void set_position(AltosLatLon position, long last_packet) {
+               this.position = position;
+               this.last_packet = last_packet;
+       }
+
+       void set_active(boolean active) {
+               this.active = active;
+       }
+
+       public int compareTo(Object o) {
+               Rocket other = (Rocket) o;
+
+               if (active && !other.active)
+                       return 1;
+               if (other.active && !active)
+                       return -1;
+
+               long    diff = last_packet - other.last_packet;
+
+               if (diff > 0)
+                       return 1;
+               if (diff < 0)
+                       return -1;
+               return 0;
+       }
+
+       Rocket(int serial, AltosMapOffline map_offline) {
+               this.serial = serial;
+               this.name = String.format("%d", serial);
+               this.map_offline = map_offline;
+       }
+}
+
+public class AltosMapOffline extends View implements ScaleGestureDetector.OnScaleGestureListener, AltosMapInterface, AltosDroidMapInterface, AltosMapTypeListener {
+       ScaleGestureDetector    scale_detector;
+       boolean                 scaling;
+       AltosMap                map;
+       AltosDroid              altos_droid;
+
+       static int scale = 1;
+
+       AltosLatLon     here;
+       AltosLatLon     there;
+       AltosLatLon     pad;
+
+       Canvas  canvas;
+       Paint   paint;
+
+       Bitmap  pad_bitmap;
+       int     pad_off_x, pad_off_y;
+       Bitmap  rocket_bitmap;
+       int     rocket_off_x, rocket_off_y;
+       Bitmap  here_bitmap;
+       int     here_off_x, here_off_y;
+
+       static  final int       WHITE = 0xffffffff;
+       static  final int       RED   = 0xffff0000;
+       static  final int       PINK  = 0xffff8080;
+       static  final int       YELLOW= 0xffffff00;
+       static  final int       CYAN  = 0xff00ffff;
+       static  final int       BLUE  = 0xff0000ff;
+       static  final int       BLACK = 0xff000000;
+
+       public static final int stateColors[] = {
+               WHITE,  // startup
+               WHITE,  // idle
+               WHITE,  // pad
+               RED,    // boost
+               PINK,   // fast
+               YELLOW, // coast
+               CYAN,   // drogue
+               BLUE,   // main
+               BLACK,  // landed
+               BLACK,  // invalid
+               CYAN,   // stateless
+       };
+
+       /* AltosMapInterface */
+       public void debug(String format, Object ... arguments) {
+               AltosDebug.debug(format, arguments);
+       }
+
+       class MapTile extends AltosMapTile {
+               public void paint(AltosMapTransform t) {
+                       AltosPointInt           pt = new AltosPointInt(t.screen(upper_left));
+
+                       if (canvas.quickReject(pt.x, pt.y, pt.x + px_size, pt.y + px_size, Canvas.EdgeType.AA))
+                               return;
+
+                       AltosImage              altos_image = this.get_image();
+
+                       MapImage                map_image = (MapImage) altos_image;
+
+                       Bitmap                  bitmap = null;
+
+                       if (map_image != null)
+                               bitmap = map_image.bitmap;
+
+                       if (bitmap != null) {
+                               canvas.drawBitmap(bitmap, pt.x, pt.y, paint);
+                       } else {
+                               paint.setColor(0xff808080);
+                               canvas.drawRect(pt.x, pt.y, pt.x + px_size, pt.y + px_size, paint);
+                               if (t.has_location()) {
+                                       String  message = null;
+                                       switch (status) {
+                                       case AltosMapTile.fetching:
+                                               message = "Fetching...";
+                                               break;
+                                       case AltosMapTile.bad_request:
+                                               message = "Internal error";
+                                               break;
+                                       case AltosMapTile.failed:
+                                               message = "Network error";
+                                               break;
+                                       case AltosMapTile.forbidden:
+                                               message = "Outside of known launch areas";
+                                               break;
+                                       }
+                                       if (message != null) {
+                                               Rect    bounds = new Rect();
+                                               paint.getTextBounds(message, 0, message.length(), bounds);
+
+                                               int     width = bounds.right - bounds.left;
+                                               int     height = bounds.bottom - bounds.top;
+
+                                               float x = pt.x + px_size / 2.0f;
+                                               float y = pt.y + px_size / 2.0f;
+                                               x = x - width / 2.0f;
+                                               y = y + height / 2.0f;
+                                               paint.setColor(0xff000000);
+                                               canvas.drawText(message, 0, message.length(), x, y, paint);
+                                       }
+                               }
+                       }
+               }
+
+               public MapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size, int scale) {
+                       super(cache, upper_left, center, zoom, maptype, px_size, scale);
+               }
+
+       }
+
+       public AltosMapTile new_tile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size, int scale) {
+               return new MapTile(cache, upper_left, center, zoom, maptype, px_size, scale);
+       }
+
+       public AltosMapPath new_path() {
+               return null;
+       }
+
+       public AltosMapLine new_line() {
+               return null;
+       }
+
+       class MapImage implements AltosImage {
+               public Bitmap   bitmap;
+
+               public void flush() {
+                       if (bitmap != null) {
+                               bitmap.recycle();
+                               bitmap = null;
+                       }
+               }
+
+               public MapImage(File file) {
+                       bitmap = BitmapFactory.decodeFile(file.getPath());
+               }
+       }
+
+       public AltosImage load_image(File file) throws Exception {
+               return new MapImage(file);
+       }
+
+       class MapMark extends AltosMapMark {
+               public void paint(AltosMapTransform t) {
+               }
+
+               MapMark(double lat, double lon, int state) {
+                       super(lat, lon, state);
+               }
+       }
+
+       public AltosMapMark new_mark(double lat, double lon, int state) {
+               return new MapMark(lat, lon, state);
+       }
+
+       public int width() {
+               return getWidth();
+       }
+
+       public int height() {
+               return getHeight();
+       }
+
+       public void repaint() {
+               postInvalidate();
+       }
+
+       public void repaint(AltosRectangle damage) {
+               postInvalidate(damage.x, damage.y, damage.x + damage.width, damage.y + damage.height);
+       }
+
+       public void set_zoom_label(String label) {
+       }
+
+       public void select_object(AltosLatLon latlon) {
+               if (map.transform == null)
+                       return;
+               ArrayList<Integer>      near = new ArrayList<Integer>();
+
+               for (Rocket rocket : sorted_rockets()) {
+                       if (rocket.position == null) {
+                               debug("rocket %d has no position\n", rocket.serial);
+                               continue;
+                       }
+                       double distance = map.transform.hypot(latlon, rocket.position);
+                       debug("check select %d distance %g width %d\n", rocket.serial, distance, rocket_bitmap.getWidth());
+                       if (distance < rocket_bitmap.getWidth() * 2.0) {
+                               debug("selecting %d\n", rocket.serial);
+                               near.add(rocket.serial);
+                       }
+               }
+               if (near.size() != 0)
+                       altos_droid.touch_trackers(near.toArray(new Integer[0]));
+       }
+
+       class Line {
+               AltosLatLon     a, b;
+
+               void paint() {
+                       if (a != null && b != null) {
+                               AltosPointDouble        a_screen = map.transform.screen(a);
+                               AltosPointDouble        b_screen = map.transform.screen(b);
+                               paint.setColor(0xff8080ff);
+                               canvas.drawLine((float) a_screen.x, (float) a_screen.y,
+                                                   (float) b_screen.x, (float) b_screen.y,
+                                                   paint);
+                       }
+               }
+
+               void set_a(AltosLatLon a) {
+                       this.a = a;
+               }
+
+               void set_b(AltosLatLon b) {
+                       this.b = b;
+               }
+
+               Line() {
+               }
+       }
+
+       Line line = new Line();
+
+       int     stroke_width = 20;
+
+       void draw_text(AltosLatLon lat_lon, String text, int off_x, int off_y) {
+               if (lat_lon != null && map != null && map.transform != null) {
+                       AltosPointInt pt = new AltosPointInt(map.transform.screen(lat_lon));
+
+                       Rect    bounds = new Rect();
+                       paint.getTextBounds(text, 0, text.length(), bounds);
+
+                       int     width = bounds.right - bounds.left;
+                       int     height = bounds.bottom - bounds.top;
+
+                       float x = pt.x;
+                       float y = pt.y;
+                       x = x - width / 2.0f - off_x;
+                       y = y + height / 2.0f - off_y;
+                       paint.setColor(0xff000000);
+                       canvas.drawText(text, 0, text.length(), x, y, paint);
+               }
+       }
+
+       HashMap<Integer,Rocket> rockets = new HashMap<Integer,Rocket>();
+
+       void draw_bitmap(AltosLatLon lat_lon, Bitmap bitmap, int off_x, int off_y) {
+               if (lat_lon != null && map != null && map.transform != null) {
+                       AltosPointInt pt = new AltosPointInt(map.transform.screen(lat_lon));
+
+                       canvas.drawBitmap(bitmap, pt.x - off_x, pt.y - off_y, paint);
+               }
+       }
+
+       private Rocket[] sorted_rockets() {
+               Rocket[]        rocket_array = rockets.values().toArray(new Rocket[0]);
+
+               Arrays.sort(rocket_array);
+               return rocket_array;
+       }
+
+       private void draw_positions() {
+               line.set_a(there);
+               line.set_b(here);
+               line.paint();
+               draw_bitmap(pad, pad_bitmap, pad_off_x, pad_off_y);
+
+               for (Rocket rocket : sorted_rockets())
+                       rocket.paint();
+               draw_bitmap(here, here_bitmap, here_off_x, here_off_y);
+       }
+
+       @Override public void invalidate() {
+               Rect r = new Rect();
+               getDrawingRect(r);
+               super.invalidate();
+       }
+
+       @Override public void invalidate(int l, int t, int r, int b) {
+               Rect rect = new Rect();
+               getDrawingRect(rect);
+               super.invalidate();
+       }
+
+       @Override
+       protected void onDraw(Canvas view_canvas) {
+               if (map == null) {
+                       debug("MapView draw without map\n");
+                       return;
+               }
+               canvas = view_canvas;
+               paint = new Paint(Paint.ANTI_ALIAS_FLAG);
+               paint.setStrokeWidth(stroke_width);
+               paint.setStrokeCap(Paint.Cap.ROUND);
+               paint.setStrokeJoin(Paint.Join.ROUND);
+               paint.setTextSize(40);
+               map.paint();
+               draw_positions();
+               canvas = null;
+       }
+
+       public boolean onScale(ScaleGestureDetector detector) {
+               float   f = detector.getScaleFactor();
+
+               if (f <= 0.8) {
+                       map.set_zoom_centre(map.get_zoom() - 1, new AltosPointInt((int) detector.getFocusX(), (int) detector.getFocusY()));
+                       return true;
+               }
+               if (f >= 1.2) {
+                       map.set_zoom_centre(map.get_zoom() + 1, new AltosPointInt((int) detector.getFocusX(), (int) detector.getFocusY()));
+                       return true;
+               }
+               return false;
+       }
+
+       public boolean onScaleBegin(ScaleGestureDetector detector) {
+               return true;
+       }
+
+       public void onScaleEnd(ScaleGestureDetector detector) {
+       }
+
+       @Override
+       public boolean dispatchTouchEvent(MotionEvent event) {
+               scale_detector.onTouchEvent(event);
+
+               if (scale_detector.isInProgress()) {
+                       scaling = true;
+               }
+
+               if (scaling) {
+                       if (event.getAction() == MotionEvent.ACTION_UP) {
+                               scaling = false;
+                       }
+                       return true;
+               }
+
+               if (event.getAction() == MotionEvent.ACTION_DOWN) {
+                       map.touch_start((int) event.getX(), (int) event.getY(), true);
+               } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
+                       map.touch_continue((int) event.getX(), (int) event.getY(), true);
+               } else if (event.getAction() == MotionEvent.ACTION_UP) {
+                       map.touch_stop((int) event.getX(), (int) event.getY(), true);
+               }
+               return true;
+       }
+
+       double  mapAccuracy;
+
+       public void center(double lat, double lon, double accuracy) {
+               if (mapAccuracy <= 0 || accuracy < mapAccuracy/10 || (map != null && !map.has_centre())) {
+                       if (map != null)
+                               map.maybe_centre(lat, lon);
+                       mapAccuracy = accuracy;
+               }
+       }
+
+       public void set_visible(boolean visible) {
+               if (visible)
+                       setVisibility(VISIBLE);
+               else
+                       setVisibility(GONE);
+       }
+
+       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)
+                               pad = new AltosLatLon(state.pad_lat, state.pad_lon);
+               }
+
+               if (telem_state != null) {
+                       Integer[] old_serial = rockets.keySet().toArray(new Integer[0]);
+                       Integer[] new_serial = telem_state.states.keySet().toArray(new Integer[0]);
+
+                       /* remove deleted keys */
+                       for (int serial : old_serial) {
+                               if (!telem_state.states.containsKey(serial))
+                                       rockets.remove(serial);
+                       }
+
+                       /* set remaining keys */
+
+                       for (int serial : new_serial) {
+                               Rocket          rocket;
+                               AltosState      t_state = telem_state.states.get(serial);
+                               if (rockets.containsKey(serial))
+                                       rocket = rockets.get(serial);
+                               else {
+                                       rocket = new Rocket(serial, this);
+                                       rockets.put(serial, rocket);
+                               }
+                               if (t_state.gps != null) {
+                                       AltosLatLon     latlon = new AltosLatLon(t_state.gps.lat, t_state.gps.lon);
+                                       rocket.set_position(latlon, t_state.received_time);
+                                       if (state.cal_data().serial == serial)
+                                               there = latlon;
+                               }
+                               if (state != null)
+                                       rocket.set_active(state.cal_data().serial == serial);
+                       }
+               }
+               if (receiver != null) {
+                       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, scale);
+               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 */
+               pad_off_x = pad_bitmap.getWidth() / 2;
+               pad_off_y = pad_bitmap.getHeight();
+
+               rocket_bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.rocket);
+               /* arrow at the bottom of the rocket image */
+               rocket_off_x = rocket_bitmap.getWidth() / 2;
+               rocket_off_y = rocket_bitmap.getHeight();
+
+               here_bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_maps_indicator_current_position);
+               /* Center of the dot */
+               here_off_x = here_bitmap.getWidth() / 2;
+               here_off_y = here_bitmap.getHeight() / 2;
+       }
+
+       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);
+       }
+
+       public AltosMapOffline(Context context, AttributeSet attrs) {
+               super(context, attrs);
+               this.altos_droid = altos_droid;
+               scale_detector = new ScaleGestureDetector(context, this);
+       }
+}
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosMapOnline.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosMapOnline.java
new file mode 100644 (file)
index 0000000..272744a
--- /dev/null
@@ -0,0 +1,341 @@
+/*
+ * Copyright © 2013 Mike Beattie <mike@ethernal.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.util.*;
+
+import org.altusmetrum.altoslib_13.*;
+
+import com.google.android.gms.maps.*;
+import com.google.android.gms.maps.model.*;
+
+import android.graphics.Color;
+import android.graphics.*;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.location.Location;
+import android.content.*;
+
+class RocketOnline implements Comparable {
+       Marker          marker;
+       int             serial;
+       long            last_packet;
+       int             size;
+
+       void set_position(AltosLatLon position, long last_packet) {
+               marker.setPosition(new LatLng(position.lat, position.lon));
+               this.last_packet = last_packet;
+       }
+
+       private Bitmap rocket_bitmap(Context context, String text) {
+
+               /* From: http://mapicons.nicolasmollet.com/markers/industry/military/missile-2/
+                */
+               Bitmap orig_bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.rocket);
+               Bitmap bitmap = orig_bitmap.copy(Bitmap.Config.ARGB_8888, true);
+
+               Canvas canvas = new Canvas(bitmap);
+               Paint paint = new Paint();
+               paint.setTextSize(40);
+               paint.setColor(0xff000000);
+
+               Rect    bounds = new Rect();
+               paint.getTextBounds(text, 0, text.length(), bounds);
+
+               int     width = bounds.right - bounds.left;
+               int     height = bounds.bottom - bounds.top;
+
+               float x = bitmap.getWidth() / 2.0f - width / 2.0f;
+               float y = bitmap.getHeight() / 2.0f - height / 2.0f;
+
+               size = bitmap.getWidth();
+
+               canvas.drawText(text, 0, text.length(), x, y, paint);
+               return bitmap;
+       }
+
+       public void remove() {
+               marker.remove();
+       }
+
+       public int compareTo(Object o) {
+               RocketOnline other = (RocketOnline) o;
+
+               long    diff = last_packet - other.last_packet;
+
+               if (diff > 0)
+                       return 1;
+               if (diff < 0)
+                       return -1;
+               return 0;
+       }
+
+       RocketOnline(Context context, int serial, GoogleMap map, double lat, double lon, long last_packet) {
+               this.serial = serial;
+               String name = String.format("%d", serial);
+               this.marker = map.addMarker(new MarkerOptions()
+                                           .icon(BitmapDescriptorFactory.fromBitmap(rocket_bitmap(context, name)))
+                                           .position(new LatLng(lat, lon))
+                                           .visible(true));
+               this.last_packet = last_packet;
+       }
+}
+
+public class AltosMapOnline implements AltosDroidMapInterface, GoogleMap.OnMarkerClickListener, GoogleMap.OnMapClickListener, OnMapReadyCallback, AltosMapTypeListener {
+       public AltosOnlineMapFragment mMapFragment;
+       private GoogleMap mMap;
+       private boolean mapLoaded = false;
+       Context context;
+
+       private HashMap<Integer,RocketOnline> rockets = new HashMap<Integer,RocketOnline>();
+       private Marker mPadMarker;
+       private boolean pad_set;
+       private Polyline mPolyline;
+
+       private double mapAccuracy = -1;
+
+       private AltosLatLon my_position = null;
+       private AltosLatLon target_position = null;
+
+       private AltosDroid altos_droid;
+
+       public static class AltosOnlineMapFragment extends SupportMapFragment {
+               AltosMapOnline c;
+               View map_view;
+
+               public AltosOnlineMapFragment(AltosMapOnline c) {
+                       this.c = c;
+               }
+
+               public AltosOnlineMapFragment() {
+               }
+
+               @Override
+               public void onActivityCreated(Bundle savedInstanceState) {
+                       super.onActivityCreated(savedInstanceState);
+                       if (c != null)
+                               getMapAsync(c);
+               }
+               @Override
+               public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+                       map_view = super.onCreateView(inflater, container, savedInstanceState);
+                       return map_view;
+               }
+               @Override
+               public void onDestroyView() {
+                       super.onDestroyView();
+                       map_view = null;
+               }
+               public void set_visible(boolean visible) {
+                       if (map_view == null)
+                               return;
+                       if (visible)
+                               map_view.setVisibility(View.VISIBLE);
+                       else
+                               map_view.setVisibility(View.GONE);
+               }
+       }
+
+       public void onCreateView(AltosDroid altos_droid) {
+               this.altos_droid = altos_droid;
+               AltosPreferences.register_map_type_listener(this);
+               mMapFragment = new AltosOnlineMapFragment(this);
+       }
+
+       public void onDestroyView() {
+               AltosPreferences.unregister_map_type_listener(this);
+       }
+
+       private double pixel_distance(LatLng a, LatLng b) {
+               Projection projection = mMap.getProjection();
+
+               Point   a_pt = projection.toScreenLocation(a);
+               Point   b_pt = projection.toScreenLocation(b);
+
+               return Math.hypot((double) (a_pt.x - b_pt.x), (double) (a_pt.y - b_pt.y));
+       }
+
+       private RocketOnline[] sorted_rockets() {
+               RocketOnline[]  rocket_array = rockets.values().toArray(new RocketOnline[0]);
+
+               Arrays.sort(rocket_array);
+               return rocket_array;
+       }
+
+       public void onMapClick(LatLng lat_lng) {
+               ArrayList<Integer>      near = new ArrayList<Integer>();
+
+               for (RocketOnline rocket : sorted_rockets()) {
+                       LatLng  pos = rocket.marker.getPosition();
+
+                       if (pos == null)
+                               continue;
+
+                       double distance = pixel_distance(lat_lng, pos);
+                       if (distance < rocket.size * 2)
+                               near.add(rocket.serial);
+               }
+
+               if (near.size() != 0)
+                       altos_droid.touch_trackers(near.toArray(new Integer[0]));
+       }
+
+       public boolean onMarkerClick(Marker marker) {
+               onMapClick(marker.getPosition());
+               return true;
+       }
+
+       @Override
+       public void onMapReady(GoogleMap googleMap) {
+               final int map_type = AltosPreferences.map_type();
+               mMap = googleMap;
+               if (mMap != null) {
+                       map_type_changed(map_type);
+                       mMap.setMyLocationEnabled(true);
+                       mMap.getUiSettings().setTiltGesturesEnabled(false);
+                       mMap.getUiSettings().setZoomControlsEnabled(false);
+                       mMap.setOnMarkerClickListener(this);
+                       mMap.setOnMapClickListener(this);
+
+                       mPadMarker = mMap.addMarker(
+                                       new MarkerOptions().icon(BitmapDescriptorFactory.fromResource(R.drawable.pad))
+                                                          .position(new LatLng(0,0))
+                                                          .visible(false)
+                                       );
+
+                       mPolyline = mMap.addPolyline(
+                                       new PolylineOptions().add(new LatLng(0,0), new LatLng(0,0))
+                                                            .width(20)
+                                                            .color(Color.BLUE)
+                                                            .visible(false)
+                                       );
+
+                       mapLoaded = true;
+               }
+       }
+
+       public void center(double lat, double lon, double accuracy) {
+               if (mMap == null)
+                       return;
+
+               if (mapAccuracy < 0 || accuracy < mapAccuracy/10) {
+                       mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(lat, lon),14));
+                       mapAccuracy = accuracy;
+               }
+       }
+
+       private void set_rocket(int serial, AltosState state) {
+               RocketOnline    rocket;
+
+               if (state.gps == null || state.gps.lat == AltosLib.MISSING)
+                       return;
+
+               if (mMap == null)
+                       return;
+
+               if (rockets.containsKey(serial)) {
+                       rocket = rockets.get(serial);
+                       rocket.set_position(new AltosLatLon(state.gps.lat, state.gps.lon), state.received_time);
+               } else {
+                       rocket = new RocketOnline(context,
+                                                 serial,
+                                                 mMap, state.gps.lat, state.gps.lon,
+                                                 state.received_time);
+                       rockets.put(serial, rocket);
+               }
+       }
+
+       private void remove_rocket(int serial) {
+               RocketOnline rocket = rockets.get(serial);
+               rocket.remove();
+               rockets.remove(serial);
+       }
+
+       public void set_visible(boolean visible) {
+               if (mMapFragment != null)
+                       mMapFragment.set_visible(visible);
+       }
+
+       public void show(TelemetryState telem_state, AltosState state, AltosGreatCircle from_receiver, Location receiver) {
+
+               if (telem_state != null) {
+                       for (int serial : rockets.keySet()) {
+                               if (!telem_state.states.containsKey(serial))
+                                       remove_rocket(serial);
+                       }
+
+                       for (int serial : telem_state.states.keySet()) {
+                               set_rocket(serial, telem_state.states.get(serial));
+                       }
+               }
+
+               if (state != null) {
+                       if (mapLoaded) {
+                               if (!pad_set && state.pad_lat != AltosLib.MISSING) {
+                                       pad_set = true;
+                                       mPadMarker.setPosition(new LatLng(state.pad_lat, state.pad_lon));
+                                       mPadMarker.setVisible(true);
+                               }
+                       }
+                       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)
+                                       center (state.gps.lat, state.gps.lon, 10);
+                       }
+               }
+
+               if (receiver != null) {
+                       double accuracy;
+
+                       if (receiver.hasAccuracy())
+                               accuracy = receiver.getAccuracy();
+                       else
+                               accuracy = 1000;
+
+                       my_position = new AltosLatLon(receiver.getLatitude(), receiver.getLongitude());
+                       center (my_position.lat, my_position.lon, accuracy);
+               }
+
+               if (my_position != null && target_position != null && mPolyline != null) {
+                       mPolyline.setPoints(Arrays.asList(new LatLng(my_position.lat, my_position.lon), new LatLng(target_position.lat, target_position.lon)));
+                       mPolyline.setVisible(true);
+               }
+
+       }
+
+       public void map_type_changed(int map_type) {
+               if (mMap != null) {
+                       if (map_type == AltosMap.maptype_hybrid)
+                               mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
+                       else if (map_type == AltosMap.maptype_satellite)
+                               mMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
+                       else if (map_type == AltosMap.maptype_terrain)
+                               mMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
+                       else
+                               mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
+               }
+       }
+
+       public AltosMapOnline(Context context) {
+               this.context = context;
+       }
+}
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosUsb.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosUsb.java
new file mode 100644 (file)
index 0000000..ae82032
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * Copyright © 2015 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.HashMap;
+
+import android.content.Context;
+import android.hardware.usb.*;
+import android.app.*;
+import android.os.Handler;
+
+import org.altusmetrum.altoslib_13.*;
+
+public class AltosUsb extends AltosDroidLink {
+
+       private Thread           input_thread   = null;
+
+       private Handler          handler;
+
+       private UsbManager              manager;
+       private UsbDevice               device;
+       private UsbDeviceConnection     connection;
+       private UsbInterface            iface;
+       private UsbEndpoint             in, out;
+
+       private InputStream      input;
+       private OutputStream     output;
+
+       // Constructor
+       public AltosUsb(Context context, UsbDevice device, Handler handler) {
+               super(handler);
+//             set_debug(D);
+               this.handler = handler;
+
+               iface = null;
+               in = null;
+               out = null;
+
+               int     niface = device.getInterfaceCount();
+
+               for (int i = 0; i < niface; i++) {
+
+                       iface = device.getInterface(i);
+
+                       in = null;
+                       out = null;
+
+                       int nendpoints = iface.getEndpointCount();
+
+                       for (int e = 0; e < nendpoints; e++) {
+                               UsbEndpoint     endpoint = iface.getEndpoint(e);
+
+                               if (endpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
+                                       switch (endpoint.getDirection()) {
+                                       case UsbConstants.USB_DIR_OUT:
+                                               out = endpoint;
+                                               break;
+                                       case UsbConstants.USB_DIR_IN:
+                                               in = endpoint;
+                                               break;
+                                       }
+                               }
+                       }
+
+                       if (in != null && out != null)
+                               break;
+               }
+
+               if (in != null && out != null) {
+                       AltosDebug.debug("\tin %s out %s\n", in.toString(), out.toString());
+
+                       manager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
+
+                       if (manager == null) {
+                               AltosDebug.debug("USB_SERVICE failed");
+                               return;
+                       }
+
+                       connection = manager.openDevice(device);
+
+                       if (connection == null) {
+                               AltosDebug.debug("openDevice failed");
+                               return;
+                       }
+
+                       connection.claimInterface(iface, true);
+
+                       input_thread = new Thread(this);
+                       input_thread.start();
+
+                       // Configure the newly connected device for telemetry
+                       print("~\nE 0\n");
+                       set_monitor(false);
+               }
+       }
+
+       static private boolean isAltusMetrum(UsbDevice device) {
+               if (device.getVendorId() != AltosLib.vendor_altusmetrum)
+                       return false;
+               if (device.getProductId() < AltosLib.product_altusmetrum_min)
+                       return false;
+               if (device.getProductId() > AltosLib.product_altusmetrum_max)
+                       return false;
+               return true;
+       }
+
+       static boolean matchProduct(int want_product, UsbDevice device) {
+
+               if (!isAltusMetrum(device))
+                       return false;
+
+               if (want_product == AltosLib.product_any)
+                       return true;
+
+               int have_product = device.getProductId();
+
+               if (want_product == AltosLib.product_basestation)
+                       return have_product == AltosLib.product_teledongle ||
+                               have_product == AltosLib.product_teleterra ||
+                               have_product == AltosLib.product_telebt ||
+                               have_product == AltosLib.product_megadongle;
+
+               if (want_product == AltosLib.product_altimeter)
+                       return have_product == AltosLib.product_telemetrum ||
+                               have_product == AltosLib.product_telemega ||
+                               have_product == AltosLib.product_easymega ||
+                               have_product == AltosLib.product_telegps ||
+                               have_product == AltosLib.product_easymini ||
+                               have_product == AltosLib.product_telemini;
+
+               if (have_product == AltosLib.product_altusmetrum)       /* old devices match any request */
+                       return true;
+
+               if (want_product == have_product)
+                       return true;
+
+               return false;
+       }
+
+       static public boolean request_permission(Context context, UsbDevice device, PendingIntent pi) {
+               UsbManager      manager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
+
+//             if (manager.hasPermission(device))
+//                     return true;
+
+               AltosDebug.debug("request permission for USB device " + device.toString());
+
+               manager.requestPermission(device, pi);
+               return false;
+       }
+
+       static public UsbDevice find_device(Context context, int match_product) {
+               UsbManager      manager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
+
+               HashMap<String,UsbDevice>       devices = manager.getDeviceList();
+
+               for (UsbDevice  device : devices.values()) {
+                       int     vendor = device.getVendorId();
+                       int     product = device.getProductId();
+
+                       if (matchProduct(match_product, device)) {
+                               AltosDebug.debug("found USB device " + device.toString());
+                               return device;
+                       }
+               }
+
+               return null;
+       }
+
+       private void disconnected() {
+               if (closed()) {
+                       AltosDebug.debug("disconnected after closed");
+                       return;
+               }
+
+               AltosDebug.debug("Sending disconnected message");
+               handler.obtainMessage(TelemetryService.MSG_DISCONNECTED, this).sendToTarget();
+       }
+
+       void close_device() {
+               UsbDeviceConnection     tmp_connection;
+
+               synchronized(this) {
+                       tmp_connection = connection;
+                       connection = null;
+               }
+
+               if (tmp_connection != null) {
+                       AltosDebug.debug("Closing USB device");
+                       tmp_connection.close();
+               }
+       }
+
+       int read(byte[] buffer, int len) {
+               int ret = connection.bulkTransfer(in, buffer, len, -1);
+               AltosDebug.debug("read(%d) = %d\n", len, ret);
+               return ret;
+       }
+
+       int write(byte[] buffer, int len) {
+               int ret = connection.bulkTransfer(out, buffer, len, -1);
+               AltosDebug.debug("write(%d) = %d\n", len, ret);
+               return ret;
+       }
+
+       // Stubs of required methods when extending AltosLink
+       public boolean can_cancel_reply()   { return false; }
+       public boolean show_reply_timeout() { return true; }
+       public void hide_reply_timeout()    { }
+
+}
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosViewPager.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosViewPager.java
new file mode 100644 (file)
index 0000000..abe3a45
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright © 2013 Mike Beattie <mike@ethernal.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import android.content.Context;
+import androidx.viewpager.widget.ViewPager;
+import android.util.AttributeSet;
+import android.view.View;
+
+public class AltosViewPager extends ViewPager {
+
+    public AltosViewPager(Context context) {
+        super(context);
+    }
+
+    public AltosViewPager(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
+
+           if (v.getClass() != null &&
+               v.getClass().getName() != null &&
+               v.getClass().getName().endsWith("MapOffline"))
+                   return true;
+
+           if(v.getClass() != null &&
+              v.getClass().getPackage() != null &&
+              v.getClass().getPackage().getName() != null &&
+              v.getClass().getPackage().getName().startsWith("maps."))
+                   return true;
+
+           return super.canScroll(v, checkV, dx, x, y);
+    }
+
+}
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosVoice.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosVoice.java
new file mode 100644 (file)
index 0000000..ae3299f
--- /dev/null
@@ -0,0 +1,331 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ * Copyright © 2012 Mike Beattie <mike@ethernal.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import android.speech.tts.TextToSpeech;
+import android.speech.tts.TextToSpeech.OnInitListener;
+import android.location.Location;
+
+import org.altusmetrum.altoslib_13.*;
+
+public class AltosVoice {
+
+       private TextToSpeech tts         = null;
+       private boolean      tts_enabled = false;
+
+       static final int TELL_MODE_NONE = 0;
+       static final int TELL_MODE_PAD = 1;
+       static final int TELL_MODE_FLIGHT = 2;
+       static final int TELL_MODE_RECOVER = 3;
+
+       static final int TELL_FLIGHT_NONE = 0;
+       static final int TELL_FLIGHT_STATE = 1;
+       static final int TELL_FLIGHT_SPEED = 2;
+       static final int TELL_FLIGHT_HEIGHT = 3;
+       static final int TELL_FLIGHT_TRACK = 4;
+
+       private int             last_tell_mode;
+       private int             last_tell_serial = AltosLib.MISSING;
+       private int             last_state;
+       private AltosGPS        last_gps;
+       private double          last_height = AltosLib.MISSING;
+       private Location        last_receiver;
+       private long            last_speak_time;
+       private int             last_flight_tell = TELL_FLIGHT_NONE;
+       private boolean         quiet = false;
+
+       private long now() {
+               return System.currentTimeMillis();
+       }
+
+       private void reset_last() {
+               last_tell_mode = TELL_MODE_NONE;
+               last_speak_time = now() - 100 * 1000;
+               last_gps = null;
+               last_height = AltosLib.MISSING;
+               last_receiver = null;
+               last_state = AltosLib.ao_flight_invalid;
+               last_flight_tell = TELL_FLIGHT_NONE;
+       }
+
+       public AltosVoice(AltosDroid a) {
+               tts = new TextToSpeech(a, new OnInitListener() {
+                       public void onInit(int status) {
+                               if (status == TextToSpeech.SUCCESS) tts_enabled = true;
+                       }
+               });
+               reset_last();
+       }
+
+       public synchronized void set_enable(boolean enable) {
+               tts_enabled = enable;
+       }
+
+       public synchronized void speak(String s) {
+               if (!tts_enabled) return;
+               last_speak_time = now();
+               if (!quiet)
+                       tts.speak(s, TextToSpeech.QUEUE_ADD, null);
+       }
+
+       public synchronized long time_since_speak() {
+               return now() - last_speak_time;
+       }
+
+       public synchronized void speak(String format, Object ... arguments) {
+               speak(String.format(format, arguments));
+       }
+
+       public synchronized boolean is_speaking() {
+               return tts.isSpeaking();
+       }
+
+       public void stop() {
+               if (tts != null) {
+                       tts.stop();
+                       tts.shutdown();
+               }
+       }
+
+       private boolean         last_apogee_good;
+       private boolean         last_main_good;
+       private boolean         last_gps_good;
+
+       private boolean tell_gonogo(String name,
+                                 boolean current,
+                                 boolean previous,
+                                 boolean new_mode) {
+               if (current != previous || new_mode)
+                       speak("%s %s.", name, current ? "ready" : "not ready");
+               return current;
+       }
+
+       private boolean tell_pad(TelemetryState telem_state, AltosState state,
+                             AltosGreatCircle from_receiver, Location receiver) {
+
+               if (state == null)
+                       return false;
+
+               AltosDebug.debug("tell_pad lag %b ltm %d\n", last_apogee_good, last_tell_mode);
+
+               if (state.apogee_voltage != AltosLib.MISSING)
+                       last_apogee_good = tell_gonogo("apogee",
+                                                      state.apogee_voltage >= AltosLib.ao_igniter_good,
+                                                      last_apogee_good,
+                                                      last_tell_mode != TELL_MODE_PAD);
+
+               if (state.main_voltage != AltosLib.MISSING)
+                       last_main_good = tell_gonogo("main",
+                                                    state.main_voltage >= AltosLib.ao_igniter_good,
+                                                    last_main_good,
+                                                    last_tell_mode != TELL_MODE_PAD);
+
+               if (state.gps != null)
+                       last_gps_good = tell_gonogo("G P S",
+                                                   state.gps_ready,
+                                                   last_gps_good,
+                                                   last_tell_mode != TELL_MODE_PAD);
+               return true;
+       }
+
+
+       private boolean descending(int state) {
+               return AltosLib.ao_flight_drogue <= state && state <= AltosLib.ao_flight_landed;
+       }
+
+       private boolean target_moved(AltosState state) {
+               if (last_gps != null && state != null && state.gps != null) {
+                       AltosGreatCircle        moved = new AltosGreatCircle(last_gps.lat, last_gps.lon, last_gps.alt,
+                                                                            state.gps.lat, state.gps.lon, state.gps.alt);
+                       double                  height_change = 0;
+                       double                  height = state.height();
+
+                       if (height != AltosLib.MISSING && last_height != AltosLib.MISSING)
+                               height_change = Math.abs(last_height - height);
+
+                       if (moved.range < 10 && height_change < 10)
+                               return false;
+               }
+               return true;
+       }
+
+       private boolean receiver_moved(Location receiver) {
+               if (last_receiver != null && receiver != null) {
+                       AltosGreatCircle        moved = new AltosGreatCircle(last_receiver.getLatitude(),
+                                                                            last_receiver.getLongitude(),
+                                                                            last_receiver.getAltitude(),
+                                                                            receiver.getLatitude(),
+                                                                            receiver.getLongitude(),
+                                                                            receiver.getAltitude());
+                       if (moved.range < 10)
+                               return false;
+               }
+               return true;
+       }
+
+       private boolean tell_flight(TelemetryState telem_state, AltosState state,
+                                   AltosGreatCircle from_receiver, Location receiver) {
+
+               boolean spoken = false;
+
+               if (state == null)
+                       return false;
+
+               if (last_tell_mode != TELL_MODE_FLIGHT)
+                       last_flight_tell = TELL_FLIGHT_NONE;
+
+               if (state.state() != last_state && AltosLib.ao_flight_boost <= state.state() && state.state() <= AltosLib.ao_flight_landed) {
+                       speak(state.state_name());
+                       if (descending(state.state()) && !descending(last_state)) {
+                               if (state.max_height() != AltosLib.MISSING) {
+                                       speak("max height: %s.",
+                                             AltosConvert.height.say_units(state.max_height()));
+                               }
+                       }
+                       last_flight_tell = TELL_FLIGHT_STATE;
+                       return true;
+               }
+
+               if (last_tell_mode == TELL_MODE_FLIGHT && last_flight_tell == TELL_FLIGHT_TRACK) {
+                       if (time_since_speak() < 10 * 1000)
+                               return false;
+                       if (!target_moved(state) && !receiver_moved(receiver))
+                               return false;
+               }
+
+               double  speed;
+               double  height;
+
+               if (last_flight_tell == TELL_FLIGHT_NONE || last_flight_tell == TELL_FLIGHT_STATE || last_flight_tell == TELL_FLIGHT_TRACK) {
+                       last_flight_tell = TELL_FLIGHT_SPEED;
+
+                       if (state.state() <= AltosLib.ao_flight_coast) {
+                               speed = state.speed();
+                       } else {
+                               speed = state.gps_speed();
+                               if (speed == AltosLib.MISSING)
+                                       speed = state.speed();
+                       }
+
+                       if (speed != AltosLib.MISSING) {
+                               speak("speed: %s.", AltosConvert.speed.say_units(speed));
+                               return true;
+                       }
+               }
+
+               if (last_flight_tell == TELL_FLIGHT_SPEED) {
+                       last_flight_tell = TELL_FLIGHT_HEIGHT;
+                       height = state.height();
+
+                       if (height != AltosLib.MISSING) {
+                               speak("height: %s.", AltosConvert.height.say_units(height));
+                               return true;
+                       }
+               }
+
+               if (last_flight_tell == TELL_FLIGHT_HEIGHT) {
+                       last_flight_tell = TELL_FLIGHT_TRACK;
+                       if (from_receiver != null) {
+                               speak("bearing %s %d, elevation %d, distance %s.",
+                                     from_receiver.bearing_words(
+                                             AltosGreatCircle.BEARING_VOICE),
+                                     (int) (from_receiver.bearing + 0.5),
+                                     (int) (from_receiver.elevation + 0.5),
+                                     AltosConvert.distance.say(from_receiver.distance));
+                               return true;
+                       }
+               }
+
+               return spoken;
+       }
+
+       private boolean tell_recover(TelemetryState telem_state, AltosState state,
+                                    AltosGreatCircle from_receiver, Location receiver) {
+
+               if (from_receiver == null)
+                       return false;
+
+               if (last_tell_mode == TELL_MODE_RECOVER) {
+                       if (!target_moved(state) && !receiver_moved(receiver))
+                               return false;
+                       if (time_since_speak() <= 10 * 1000)
+                               return false;
+               }
+
+               String direction = AltosDroid.direction(from_receiver, receiver);
+               if (direction == null)
+                       direction = String.format("Bearing %d", (int) (from_receiver.bearing + 0.5));
+
+               speak("%s, distance %s.", direction,
+                     AltosConvert.distance.say_units(from_receiver.distance));
+
+               return true;
+       }
+
+       public void tell(TelemetryState telem_state, AltosState state,
+                        AltosGreatCircle from_receiver, Location receiver,
+                        AltosDroidTab tab, boolean quiet) {
+
+               this.quiet = quiet;
+
+               boolean spoken = false;
+
+               if (!tts_enabled) return;
+
+               if (is_speaking()) return;
+
+               int     tell_serial = last_tell_serial;
+
+               if (state != null)
+                       tell_serial = state.cal_data().serial;
+
+               if (tell_serial != last_tell_serial)
+                       reset_last();
+
+               int     tell_mode = TELL_MODE_NONE;
+
+               if (tab.tab_name().equals(AltosDroid.tab_pad_name))
+                       tell_mode = TELL_MODE_PAD;
+               else if (tab.tab_name().equals(AltosDroid.tab_flight_name))
+                       tell_mode = TELL_MODE_FLIGHT;
+               else
+                       tell_mode = TELL_MODE_RECOVER;
+
+               if (tell_mode == TELL_MODE_PAD)
+                       spoken = tell_pad(telem_state, state, from_receiver, receiver);
+               else if (tell_mode == TELL_MODE_FLIGHT)
+                       spoken = tell_flight(telem_state, state, from_receiver, receiver);
+               else
+                       spoken = tell_recover(telem_state, state, from_receiver, receiver);
+
+               if (spoken) {
+                       last_tell_mode = tell_mode;
+                       last_tell_serial = tell_serial;
+                       if (state != null) {
+                               last_state = state.state();
+                               last_height = state.height();
+                               if (state.gps != null)
+                                       last_gps = state.gps;
+                       }
+                       if (receiver != null)
+                               last_receiver = receiver;
+               }
+       }
+}
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/BuildInfo.java.in b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/BuildInfo.java.in
new file mode 100644 (file)
index 0000000..aa6c9a7
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright © 2012 Mike Beattie <mike@ethernal.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+public class BuildInfo {
+       public static final String version      = "@VERSION@";
+       public static final String git_describe = "@DESCRIBE@";
+       public static final String branch       = "@BRANCH@";
+       public static final String commitnum    = "@COMMITNUM@";
+       public static final String commithash   = "@COMMITHASH@";
+       public static final String builddate    = "@BUILDDATE@";
+       public static final String buildtime    = "@BUILDTIME@";
+       public static final String buildtz      = "@BUILDTZ@";
+}
+
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/DeviceAddress.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/DeviceAddress.java
new file mode 100644 (file)
index 0000000..6f84556
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright © 2015 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+public class DeviceAddress {
+       public String   address;
+       public String   name;
+
+       public DeviceAddress(String address, String name) {
+               this.address = address;
+               this.name = name;
+       }
+}
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/DeviceListActivity.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/DeviceListActivity.java
new file mode 100644 (file)
index 0000000..839fb53
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * 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
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.util.Set;
+
+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.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.AdapterView.OnItemClickListener;
+
+/**
+ * This Activity appears as a dialog. It lists any paired devices and
+ * devices detected in the area after discovery. When a device is chosen
+ * by the user, the MAC address of the device is sent back to the parent
+ * Activity in the result Intent.
+ */
+public class DeviceListActivity extends Activity {
+
+       // Return Intent extra
+       public static final String EXTRA_DEVICE_ADDRESS = "device_address";
+       public static final String EXTRA_DEVICE_NAME = "device_name";
+
+       // Member fields
+       private BluetoothAdapter mBtAdapter;
+       private ArrayAdapter<String> mPairedDevicesArrayAdapter;
+       private ArrayAdapter<String> mNewDevicesArrayAdapter;
+
+       @Override
+       protected void onCreate(Bundle savedInstanceState) {
+               super.onCreate(savedInstanceState);
+
+               // Setup the window
+               requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+               setContentView(R.layout.device_list);
+
+               // Set result CANCELED incase the user backs out
+               setResult(Activity.RESULT_CANCELED);
+
+               // Initialize the button to perform device discovery
+               Button scanButton = (Button) findViewById(R.id.button_scan);
+               scanButton.setOnClickListener(new OnClickListener() {
+                       public void onClick(View v) {
+                               doDiscovery();
+                               v.setVisibility(View.GONE);
+                       }
+               });
+
+               // Initialize array adapters. One for already paired devices and
+               // one for newly discovered devices
+               mPairedDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name);
+               mNewDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name);
+
+               // Find and set up the ListView for paired devices
+               ListView pairedListView = (ListView) findViewById(R.id.paired_devices);
+               pairedListView.setAdapter(mPairedDevicesArrayAdapter);
+               pairedListView.setOnItemClickListener(mDeviceClickListener);
+
+               // Find and set up the ListView for newly discovered devices
+               ListView newDevicesListView = (ListView) findViewById(R.id.new_devices);
+               newDevicesListView.setAdapter(mNewDevicesArrayAdapter);
+               newDevicesListView.setOnItemClickListener(mDeviceClickListener);
+
+               // Register for broadcasts when a device is discovered
+               IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
+               this.registerReceiver(mReceiver, filter);
+
+               // Register for broadcasts when discovery has finished
+               filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
+               this.registerReceiver(mReceiver, filter);
+
+               // Get the local Bluetooth adapter
+               mBtAdapter = BluetoothAdapter.getDefaultAdapter();
+
+               // Get a set of currently paired devices
+               Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices();
+
+               // If there are paired devices, add each one to the ArrayAdapter
+               if (pairedDevices.size() > 0) {
+                       findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE);
+                       for (BluetoothDevice device : pairedDevices)
+                               if (device.getName().startsWith("TeleBT"))
+                                       mPairedDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
+
+               } else {
+                       String noDevices = getResources().getText(R.string.none_paired).toString();
+                       mPairedDevicesArrayAdapter.add(noDevices);
+               }
+       }
+
+       @Override
+       protected void onDestroy() {
+               super.onDestroy();
+
+               // Make sure we're not doing discovery anymore
+               if (mBtAdapter != null) {
+                       mBtAdapter.cancelDiscovery();
+               }
+
+               // Unregister broadcast listeners
+               this.unregisterReceiver(mReceiver);
+       }
+
+       /**
+       * Start device discover with the BluetoothAdapter
+       */
+       private void doDiscovery() {
+               AltosDebug.debug("doDiscovery()");
+
+               // Indicate scanning in the title
+               setProgressBarIndeterminateVisibility(true);
+               setTitle(R.string.scanning);
+
+               // Turn on sub-title for new devices
+               findViewById(R.id.title_new_devices).setVisibility(View.VISIBLE);
+
+               // If we're already discovering, stop it
+               if (mBtAdapter.isDiscovering()) {
+                       mBtAdapter.cancelDiscovery();
+               }
+
+               // Request discover from BluetoothAdapter
+               mBtAdapter.startDiscovery();
+       }
+
+       // The on-click listener for all devices in the ListViews
+       private OnItemClickListener mDeviceClickListener = new OnItemClickListener() {
+               public void onItemClick(AdapterView<?> av, View v, int arg2, long arg3) {
+                       // Cancel discovery because it's costly and we're about to connect
+                       mBtAdapter.cancelDiscovery();
+
+                       // Get the device MAC address, which is the last 17 chars in the View
+                       String info = ((TextView) v).getText().toString();
+                       String address = info.substring(info.length() - 17);
+
+                       int newline = info.indexOf('\n');
+
+                       String name = null;
+                       if (newline > 0)
+                               name = info.substring(0, newline);
+                       else
+                               name = info;
+
+                       AltosDebug.debug("******* selected item '%s'", info);
+
+                       // Create the result Intent and include the MAC address
+                       Intent intent = new Intent();
+                       intent.putExtra(EXTRA_DEVICE_ADDRESS, address);
+                       intent.putExtra(EXTRA_DEVICE_NAME, name);
+
+                       // Set result and finish this Activity
+                       setResult(Activity.RESULT_OK, intent);
+                       finish();
+               }
+       };
+
+       // The BroadcastReceiver that listens for discovered devices and
+       // changes the title when discovery is finished
+       private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+               @Override
+               public void onReceive(Context context, Intent intent) {
+                       String action = intent.getAction();
+
+                       // When discovery finds a device
+                       if (BluetoothDevice.ACTION_FOUND.equals(action)) {
+
+                               /* Get the BluetoothDevice object from the Intent
+                                */
+                               BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+
+                               /* If it's already paired, skip it, because it's been listed already
+                                */
+                               if (device != null && device.getBondState() != BluetoothDevice.BOND_BONDED)
+                               {
+                                       String  name = device.getName();
+                                       if (name != null && name.startsWith("TeleBT"))
+                                               mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
+                               }
+
+                       /* When discovery is finished, change the Activity title
+                        */
+                       } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
+                               setProgressBarIndeterminateVisibility(false);
+                               setTitle(R.string.select_device);
+                               if (mNewDevicesArrayAdapter.getCount() == 0) {
+                                       String noDevices = getResources().getText(R.string.none_found).toString();
+                                       mNewDevicesArrayAdapter.add(noDevices);
+                               }
+                       }
+               }
+       };
+
+}
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/Dumper.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/Dumper.java
new file mode 100644 (file)
index 0000000..2797fc5
--- /dev/null
@@ -0,0 +1,183 @@
+package org.altusmetrum.AltosDroid;
+
+       import java.lang.reflect.Array;
+       import java.lang.reflect.Field;
+       import java.util.HashMap;
+
+       public class Dumper {
+               private static Dumper instance = new Dumper();
+
+               protected static Dumper getInstance() {
+                       return instance;
+               }
+
+               class DumpContext {
+                       int maxDepth = 0;
+                       int maxArrayElements = 0;
+                       int callCount = 0;
+                       HashMap<String, String> ignoreList = new HashMap<String, String>();
+                       HashMap<Object, Integer> visited = new HashMap<Object, Integer>();
+               }
+
+               public static String dump(Object o) {
+                       return dump(o, 0, 0, null);
+               }
+
+               public static String dump(Object o, int maxDepth, int maxArrayElements, String[] ignoreList) {
+                       DumpContext ctx = Dumper.getInstance().new DumpContext();
+                       ctx.maxDepth = maxDepth;
+                       ctx.maxArrayElements = maxArrayElements;
+
+                       if (ignoreList != null) {
+                               for (int i = 0; i < Array.getLength(ignoreList); i++) {
+                                       int colonIdx = ignoreList[i].indexOf(':');
+                                       if (colonIdx == -1)
+                                               ignoreList[i] = ignoreList[i] + ":";
+                                       ctx.ignoreList.put(ignoreList[i], ignoreList[i]);
+                               }
+                       }
+
+                       return dump(o, ctx);
+               }
+
+               protected static String dump(Object o, DumpContext ctx) {
+                       if (o == null) {
+                               return "<null>";
+                       }
+
+                       ctx.callCount++;
+                       StringBuffer tabs = new StringBuffer();
+                       for (int k = 0; k < ctx.callCount; k++) {
+                               tabs.append("\t");
+                       }
+                       StringBuffer buffer = new StringBuffer();
+                       @SuppressWarnings("rawtypes")
+                       Class oClass = o.getClass();
+
+                       String oSimpleName = getSimpleNameWithoutArrayQualifier(oClass);
+
+                       if (ctx.ignoreList.get(oSimpleName + ":") != null)
+                               return "<Ignored>";
+
+                       if (oClass.isArray()) {
+                               buffer.append("\n");
+                               buffer.append(tabs.toString().substring(1));
+                               buffer.append("[\n");
+                               int rowCount = ctx.maxArrayElements == 0 ? Array.getLength(o) : Math.min(ctx.maxArrayElements, Array.getLength(o));
+                               for (int i = 0; i < rowCount; i++) {
+                                       buffer.append(tabs.toString());
+                                       try {
+                                               Object value = Array.get(o, i);
+                                               buffer.append(dumpValue(value, ctx));
+                                       } catch (Exception e) {
+                                               buffer.append(e.getMessage());
+                                       }
+                                       if (i < Array.getLength(o) - 1)
+                                               buffer.append(",");
+                                       buffer.append("\n");
+                               }
+                               if (rowCount < Array.getLength(o)) {
+                                       buffer.append(tabs.toString());
+                                       buffer.append(Array.getLength(o) - rowCount + " more array elements...");
+                                       buffer.append("\n");
+                               }
+                               buffer.append(tabs.toString().substring(1));
+                               buffer.append("]");
+                       } else {
+                               buffer.append("\n");
+                               buffer.append(tabs.toString().substring(1));
+                               buffer.append("{\n");
+                               buffer.append(tabs.toString());
+                               buffer.append("hashCode: " + o.hashCode());
+                               buffer.append("\n");
+                               while (oClass != null && oClass != Object.class) {
+                                       Field[] fields = oClass.getDeclaredFields();
+
+                                       if (ctx.ignoreList.get(oClass.getSimpleName()) == null) {
+                                               if (oClass != o.getClass()) {
+                                                       buffer.append(tabs.toString().substring(1));
+                                                       buffer.append("  Inherited from superclass " + oSimpleName + ":\n");
+                                               }
+
+                                               for (int i = 0; i < fields.length; i++) {
+
+                                                       String fSimpleName = getSimpleNameWithoutArrayQualifier(fields[i].getType());
+                                                       String fName = fields[i].getName();
+
+                                                       fields[i].setAccessible(true);
+                                                       buffer.append(tabs.toString());
+                                                       buffer.append(fName + "(" + fSimpleName + ")");
+                                                       buffer.append("=");
+
+                                                       if (ctx.ignoreList.get(":" + fName) == null &&
+                                                               ctx.ignoreList.get(fSimpleName + ":" + fName) == null &&
+                                                               ctx.ignoreList.get(fSimpleName + ":") == null) {
+
+                                                               try {
+                                                                       Object value = fields[i].get(o);
+                                                                       buffer.append(dumpValue(value, ctx));
+                                                               } catch (Exception e) {
+                                                                       buffer.append(e.getMessage());
+                                                               }
+                                                               buffer.append("\n");
+                                                       } else {
+                                                               buffer.append("<Ignored>");
+                                                               buffer.append("\n");
+                                                       }
+                                               }
+                                               oClass = oClass.getSuperclass();
+                                               oSimpleName = oClass.getSimpleName();
+                                       } else {
+                                               oClass = null;
+                                               oSimpleName = "";
+                                       }
+                               }
+                               buffer.append(tabs.toString().substring(1));
+                               buffer.append("}");
+                       }
+                       ctx.callCount--;
+                       return buffer.toString();
+               }
+
+               protected static String dumpValue(Object value, DumpContext ctx) {
+                       if (value == null) {
+                               return "<null>";
+                       }
+                       if (value.getClass().isPrimitive() ||
+                               value.getClass() == java.lang.Short.class ||
+                               value.getClass() == java.lang.Long.class ||
+                               value.getClass() == java.lang.String.class ||
+                               value.getClass() == java.lang.Integer.class ||
+                               value.getClass() == java.lang.Float.class ||
+                               value.getClass() == java.lang.Byte.class ||
+                               value.getClass() == java.lang.Character.class ||
+                               value.getClass() == java.lang.Double.class ||
+                               value.getClass() == java.lang.Boolean.class) {
+
+                               return value.toString();
+
+                       } else {
+
+                               Integer visitedIndex = ctx.visited.get(value);
+                               if (visitedIndex == null) {
+                                       ctx.visited.put(value, ctx.callCount);
+                                       if (ctx.maxDepth == 0 || ctx.callCount < ctx.maxDepth) {
+                                               return dump(value, ctx);
+                                       } else {
+                                               return "<Reached max recursion depth>";
+                                       }
+                               } else {
+                                       return "<Previously visited - see hashCode " + value.hashCode() + ">";
+                               }
+                       }
+               }
+
+
+               private static String getSimpleNameWithoutArrayQualifier(@SuppressWarnings("rawtypes") Class clazz) {
+                       String simpleName = clazz.getSimpleName();
+                       int indexOfBracket = simpleName.indexOf('['); 
+                       if (indexOfBracket != -1)
+                               return simpleName.substring(0, indexOfBracket);
+                       return simpleName;
+               }
+}
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/GoNoGoLights.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/GoNoGoLights.java
new file mode 100644 (file)
index 0000000..a57758b
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright © 2013 Mike Beattie <mike@ethernal.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.widget.ImageView;
+
+public class GoNoGoLights {
+       private Boolean state;
+       private Boolean missing;
+       private Boolean set;
+
+       private ImageView red;
+       private ImageView green;
+
+       private Drawable dRed;
+       private Drawable dGreen;
+       private Drawable dGray;
+
+       public GoNoGoLights(ImageView in_red, ImageView in_green, Resources r) {
+               red = in_red;
+               green = in_green;
+               state = false;
+               missing = true;
+               set = false;
+
+               dRed   = r.getDrawable(R.drawable.redled);
+               dGreen = r.getDrawable(R.drawable.greenled);
+               dGray  = r.getDrawable(R.drawable.grayled);
+       }
+
+       public void set(Boolean s, Boolean m) {
+               if (set && s == state && m == missing) return;
+               state = s;
+               missing = m;
+               set = true;
+               if (missing) {
+                       red.setImageDrawable(dGray);
+                       green.setImageDrawable(dGray);
+               } else if (state) {
+                       red.setImageDrawable(dGray);
+                       green.setImageDrawable(dGreen);
+               } else {
+                       red.setImageDrawable(dRed);
+                       green.setImageDrawable(dGray);
+               }
+       }
+}
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/IdleModeActivity.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/IdleModeActivity.java
new file mode 100644 (file)
index 0000000..f10c718
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.view.Window;
+import android.view.View.OnClickListener;
+import android.widget.*;
+
+import org.altusmetrum.altoslib_13.*;
+
+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/app/src/main/java/org/altusmetrum/AltosDroid/IgniterActivity.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/IgniterActivity.java
new file mode 100644 (file)
index 0000000..9e5a14e
--- /dev/null
@@ -0,0 +1,410 @@
+/*
+ * 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.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.lang.ref.WeakReference;
+import java.util.*;
+
+import android.app.Activity;
+import android.content.*;
+import android.graphics.*;
+import android.os.*;
+import android.view.*;
+import android.view.View.*;
+import android.widget.*;
+
+import org.altusmetrum.altoslib_13.*;
+
+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/app/src/main/java/org/altusmetrum/AltosDroid/ManageFrequenciesActivity.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/ManageFrequenciesActivity.java
new file mode 100644 (file)
index 0000000..6e8e38d
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+ * 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.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.util.*;
+import java.text.*;
+
+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 org.altusmetrum.altoslib_13.*;
+
+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() {
+
+               set();
+
+               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 find(AltosFrequency frequency) {
+               for (int pos = 0; pos < frequencies_adapter.getCount(); pos++) {
+                       FrequencyItem   item = frequencies_adapter.getItem(pos);
+                       if (item.frequency.frequency == frequency.frequency &&
+                           item.frequency.description.equals(frequency.description))
+                               return pos;
+               }
+               return -1;
+       }
+
+       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);
+                       AltosFrequency frequency = new AltosFrequency(f, description_text);
+                       int pos;
+
+                       pos = find(frequency);
+                       if (pos < 0) {
+                               pos = insert_item(frequency);
+                               changed = true;
+                       }
+                       frequencies_adapter.selected_item = -1;
+                       select_item(pos);
+               } 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();
+       }
+}
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/MapTypeActivity.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/MapTypeActivity.java
new file mode 100644 (file)
index 0000000..167fb29
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright © 2015 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.view.Window;
+import android.widget.*;
+
+import org.altusmetrum.altoslib_13.*;
+
+public class MapTypeActivity extends Activity {
+       private Button hybrid;
+       private Button satellite;
+       private Button roadmap;
+       private Button terrain;
+       private int selected_type;
+
+       public static final String EXTRA_MAP_TYPE = "map_type";
+
+       private void done(int type) {
+
+               Intent intent = new Intent();
+               intent.putExtra(EXTRA_MAP_TYPE, type);
+               setResult(Activity.RESULT_OK, intent);
+               finish();
+       }
+
+       public void selectType(View view) {
+               AltosDebug.debug("selectType %s", view.toString());
+               if (view == hybrid)
+                       done(AltosMap.maptype_hybrid);
+               if (view == satellite)
+                       done(AltosMap.maptype_satellite);
+               if (view == roadmap)
+                       done(AltosMap.maptype_roadmap);
+               if (view == terrain)
+                       done(AltosMap.maptype_terrain);
+       }
+
+       @Override
+       protected void onCreate(Bundle savedInstanceState) {
+               super.onCreate(savedInstanceState);
+
+               // Setup the window
+               requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+               setContentView(R.layout.map_type);
+
+               hybrid = (Button) findViewById(R.id.map_type_hybrid);
+               satellite = (Button) findViewById(R.id.map_type_satellite);
+               roadmap = (Button) findViewById(R.id.map_type_roadmap);
+               terrain = (Button) findViewById(R.id.map_type_terrain);
+
+               // Set result CANCELED incase the user backs out
+               setResult(Activity.RESULT_CANCELED);
+       }
+}
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/PreloadMapActivity.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/PreloadMapActivity.java
new file mode 100644 (file)
index 0000000..a9f30f1
--- /dev/null
@@ -0,0 +1,375 @@
+/*
+ * Copyright © 2015 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.util.*;
+import java.text.*;
+
+import android.app.Activity;
+import android.content.Context;
+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 android.location.Location;
+import android.location.LocationManager;
+import android.location.LocationListener;
+
+import org.altusmetrum.altoslib_13.*;
+
+/**
+ * This Activity appears as a dialog. It lists any paired devices and
+ * devices detected in the area after discovery. When a device is chosen
+ * by the user, the MAC address of the device is sent back to the parent
+ * Activity in the result Intent.
+ */
+public class PreloadMapActivity extends Activity implements AltosLaunchSiteListener, AltosMapLoaderListener, LocationListener {
+
+       private ArrayAdapter<AltosLaunchSite> known_sites_adapter;
+
+/*
+       private CheckBox        hybrid;
+       private CheckBox        satellite;
+       private CheckBox        roadmap;
+       private CheckBox        terrain;
+*/
+
+       private Spinner         known_sites_spinner;
+       private Spinner         min_zoom;
+       private Spinner         max_zoom;
+       private TextView        radius_label;
+       private Spinner         radius;
+
+       private EditText        latitude;
+       private EditText        longitude;
+
+       private ProgressBar     progress;
+
+       private AltosMapLoader  loader;
+
+       long    loader_notify_time;
+
+       /* AltosMapLoaderListener interfaces */
+       public void loader_start(final int max) {
+               loader_notify_time = System.currentTimeMillis();
+
+               this.runOnUiThread(new Runnable() {
+                               public void run() {
+                                       progress.setMax(max);
+                                       progress.setProgress(0);
+                               }
+                       });
+       }
+
+       public void loader_notify(final int cur, final int max, final String name) {
+               long    now = System.currentTimeMillis();
+
+               if (now - loader_notify_time < 100)
+                       return;
+
+               loader_notify_time = now;
+
+               this.runOnUiThread(new Runnable() {
+                               public void run() {
+                                       progress.setProgress(cur);
+                               }
+                       });
+       }
+
+       public void loader_done(int max) {
+               loader = null;
+               this.runOnUiThread(new Runnable() {
+                               public void run() {
+                                       progress.setProgress(0);
+                                       finish();
+                               }
+                       });
+       }
+
+       public void debug(String format, Object ... arguments) {
+               AltosDebug.debug(format, arguments);
+       }
+
+       /* AltosLaunchSiteListener interface */
+
+       public void notify_launch_sites(final List<AltosLaunchSite> sites) {
+               this.runOnUiThread(new Runnable() {
+                               public void run() {
+                                       for (AltosLaunchSite site : sites)
+                                               known_sites_adapter.add(site);
+                               }
+                       });
+       }
+
+       /* LocationProvider interface */
+
+       AltosLaunchSite current_location_site;
+
+       public void onLocationChanged(Location location) {
+               AltosDebug.debug("location changed");
+               if (current_location_site == null) {
+                       AltosLaunchSite selected_item = (AltosLaunchSite) known_sites_spinner.getSelectedItem();
+
+                       current_location_site = new AltosLaunchSite("Current Location", location.getLatitude(), location.getLongitude());
+                       known_sites_adapter.insert(current_location_site, 0);
+
+                       if (selected_item != null)
+                               known_sites_spinner.setSelection(known_sites_adapter.getPosition(selected_item));
+                       else {
+                               latitude.setText(new StringBuffer(String.format("%12.6f", current_location_site.latitude)));
+                               longitude.setText(new StringBuffer(String.format("%12.6f", current_location_site.longitude)));
+                       }
+               } else {
+                       current_location_site.latitude = location.getLatitude();
+                       current_location_site.longitude = location.getLongitude();
+               }
+       }
+
+       public void onStatusChanged(String provider, int status, Bundle extras) {
+       }
+
+       public void onProviderEnabled(String provider) {
+       }
+
+       public void onProviderDisabled(String provider) {
+       }
+
+       private double text(EditText view) throws ParseException {
+               return AltosParse.parse_double_locale(view.getEditableText().toString());
+       }
+
+       private double latitude() throws ParseException {
+               return text(latitude);
+       }
+
+       private double longitude() throws ParseException {
+               return text(longitude);
+       }
+
+       private int value(Spinner spinner) {
+               return (Integer) spinner.getSelectedItem();
+       }
+
+       private int min_z() {
+               return value(min_zoom);
+       }
+
+       private int max_z() {
+               return value(max_zoom);
+       }
+
+       private double value_distance(Spinner spinner) {
+               return (Double) spinner.getSelectedItem();
+       }
+
+       private double radius() {
+               double r = value_distance(radius);
+               if (AltosPreferences.imperial_units())
+                       r = AltosConvert.miles_to_meters(r);
+               else
+                       r = r * 1000;
+               return r;
+       }
+
+/*
+       private int bit(CheckBox box, int value) {
+               if (box.isChecked())
+                       return 1 << value;
+               return 0;
+       }
+*/
+
+       private int types() {
+/*
+               return (bit(hybrid, AltosMap.maptype_hybrid) |
+                       bit(satellite, AltosMap.maptype_satellite) |
+                       bit(roadmap, AltosMap.maptype_roadmap) |
+                       bit(terrain, AltosMap.maptype_terrain));
+*/
+               return 1 << AltosMap.maptype_hybrid;
+       }
+
+       private void load() {
+               if (loader != null)
+                       return;
+
+               try {
+                       double  lat = latitude();
+                       double  lon = longitude();
+                       int     min = min_z();
+                       int     max = max_z();
+                       double  r = radius();
+                       int     t = types();
+
+                       AltosDebug.debug("PreloadMap load %f %f %d %d %f %d\n",
+                                        lat, lon, min, max, r, t);
+                       loader = new AltosMapLoader(this, lat, lon, min, max, r, t, AltosMapOffline.scale);
+               } catch (ParseException e) {
+                       AltosDebug.debug("PreloadMap load raised exception %s", e.toString());
+               }
+       }
+
+       private void add_numbers(Spinner spinner, int min, int max, int def) {
+
+               ArrayAdapter<Integer> adapter = new ArrayAdapter<Integer>(this, android.R.layout.simple_spinner_item);
+
+               int     spinner_def = 0;
+               int     pos = 0;
+
+               for (int i = min; i <= max; i++) {
+                       adapter.add(new Integer(i));
+                       if (i == def)
+                               spinner_def = pos;
+                       pos++;
+               }
+
+               spinner.setAdapter(adapter);
+               spinner.setSelection(spinner_def);
+       }
+
+
+       private void add_distance(Spinner spinner, double[] distances_km, double def_km, double[] distances_mi, double def_mi) {
+
+               ArrayAdapter<Double> adapter = new ArrayAdapter<Double>(this, android.R.layout.simple_spinner_item);
+
+               int     spinner_def = 0;
+               int     pos = 0;
+
+               double[] distances;
+               double  def;
+               if (AltosPreferences.imperial_units()) {
+                       distances = distances_mi;
+                       def = def_mi;
+               } else {
+                       distances = distances_km;
+                       def = def_km;
+               }
+
+               for (int i = 0; i < distances.length; i++) {
+                       adapter.add(distances[i]);
+                       if (distances[i] == def)
+                               spinner_def = pos;
+                       pos++;
+               }
+
+               spinner.setAdapter(adapter);
+               spinner.setSelection(spinner_def);
+       }
+
+
+
+       class SiteListListener implements OnItemSelectedListener {
+               public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+                       AltosLaunchSite site = (AltosLaunchSite) parent.getItemAtPosition(pos);
+                       latitude.setText(new StringBuffer(String.format("%12.6f", site.latitude)));
+                       longitude.setText(new StringBuffer(String.format("%12.6f", site.longitude)));
+               }
+               public void onNothingSelected(AdapterView<?> parent) {
+               }
+
+               public SiteListListener() {
+               }
+       }
+
+       double[]        radius_mi = { 1, 2, 5, 10, 20 };
+       double          radius_def_mi = 2;
+       double[]        radius_km = { 1, 2, 5, 10, 20, 30 };
+       double          radius_def_km = 2;
+
+       @Override
+       protected void onCreate(Bundle savedInstanceState) {
+               super.onCreate(savedInstanceState);
+
+               // Setup the window
+               requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+               setContentView(R.layout.map_preload);
+
+               // Set result CANCELED incase the user backs out
+               setResult(Activity.RESULT_CANCELED);
+
+               // Initialize the button to perform device discovery
+               Button loadButton = (Button) findViewById(R.id.preload_load);
+               loadButton.setOnClickListener(new OnClickListener() {
+                       public void onClick(View v) {
+                               load();
+                       }
+               });
+
+               latitude = (EditText) findViewById(R.id.preload_latitude);
+               longitude = (EditText) findViewById(R.id.preload_longitude);
+
+/*
+               hybrid = (CheckBox) findViewById(R.id.preload_hybrid);
+               satellite = (CheckBox) findViewById(R.id.preload_satellite);
+               roadmap = (CheckBox) findViewById(R.id.preload_roadmap);
+               terrain = (CheckBox) findViewById(R.id.preload_terrain);
+
+               hybrid.setChecked(true);
+*/
+
+               min_zoom = (Spinner) findViewById(R.id.preload_min_zoom);
+               add_numbers(min_zoom,
+                           AltosMap.min_zoom - AltosMap.default_zoom,
+                           AltosMap.max_zoom - AltosMap.default_zoom, -2);
+               max_zoom = (Spinner) findViewById(R.id.preload_max_zoom);
+               add_numbers(max_zoom,
+                           AltosMap.min_zoom - AltosMap.default_zoom,
+                           AltosMap.max_zoom - AltosMap.default_zoom, 2);
+               radius_label = (TextView) findViewById(R.id.preload_radius_label);
+               radius = (Spinner) findViewById(R.id.preload_radius);
+               if (AltosPreferences.imperial_units())
+                       radius_label.setText("Radius (miles)");
+               else
+                       radius_label.setText("Radius (km)");
+               add_distance(radius, radius_km, radius_def_km, radius_mi, radius_def_mi);
+
+               progress = (ProgressBar) findViewById(R.id.preload_progress);
+
+               // Initialize array adapters. One for already paired devices and
+               // one for newly discovered devices
+               known_sites_spinner = (Spinner) findViewById(R.id.preload_site_list);
+
+               known_sites_adapter = new ArrayAdapter<AltosLaunchSite>(this, android.R.layout.simple_spinner_item);
+
+               known_sites_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+
+               known_sites_spinner.setAdapter(known_sites_adapter);
+               known_sites_spinner.setOnItemSelectedListener(new SiteListListener());
+
+               // Listen for GPS and Network position updates
+               LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
+
+               locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, this);
+
+               new AltosLaunchSites(this);
+       }
+
+       @Override
+       protected void onDestroy() {
+               super.onDestroy();
+
+               if (loader != null)
+                       loader.abort();
+
+               // Stop listening for location updates
+               ((LocationManager) getSystemService(Context.LOCATION_SERVICE)).removeUpdates(this);
+       }
+}
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/SetupActivity.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/SetupActivity.java
new file mode 100644 (file)
index 0000000..55b3485
--- /dev/null
@@ -0,0 +1,341 @@
+/*
+ * 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.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import android.app.Activity;
+import android.content.*;
+import android.os.*;
+import android.view.*;
+import android.view.View.*;
+import android.widget.*;
+import android.widget.AdapterView.*;
+
+import org.altusmetrum.altoslib_13.*;
+
+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);
+
+               AltosDebug.init(this);
+               AltosDebug.debug("+++ ON CREATE +++");
+
+               // Initialise preferences
+               AltosDroidPreferences.init(this);
+
+               // 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();
+       }
+}
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TabFlight.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TabFlight.java
new file mode 100644 (file)
index 0000000..b2e7e19
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright © 2013 Mike Beattie <mike@ethernal.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import org.altusmetrum.altoslib_13.*;
+
+import android.os.Bundle;
+import android.view.*;
+import android.widget.*;
+import android.location.Location;
+
+public class TabFlight extends AltosDroidTab {
+       private TextView speed_view;
+       private TextView height_view;
+       private TextView max_speed_view;
+       private TextView max_height_view;
+       private TextView elevation_view;
+       private TextView range_view;
+       private TextView bearing_view;
+       private TextView compass_view;
+       private TextView distance_view;
+       private TextView latitude_view;
+       private TextView longitude_view;
+       private View apogee_view;
+       private TextView apogee_voltage_view;
+       private TextView apogee_voltage_label;
+       private GoNoGoLights apogee_lights;
+       private View main_view;
+       private TextView main_voltage_view;
+       private TextView main_voltage_label;
+       private GoNoGoLights main_lights;
+
+       @Override
+       public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+               View v = inflater.inflate(R.layout.tab_flight, container, false);
+
+               speed_view     = (TextView) v.findViewById(R.id.speed_value);
+               height_view    = (TextView) v.findViewById(R.id.height_value);
+               max_speed_view = (TextView) v.findViewById(R.id.max_speed_value);
+               max_height_view= (TextView) v.findViewById(R.id.max_height_value);
+               elevation_view = (TextView) v.findViewById(R.id.elevation_value);
+               range_view     = (TextView) v.findViewById(R.id.range_value);
+               bearing_view   = (TextView) v.findViewById(R.id.bearing_value);
+               compass_view   = (TextView) v.findViewById(R.id.compass_value);
+               distance_view  = (TextView) v.findViewById(R.id.distance_value);
+               latitude_view  = (TextView) v.findViewById(R.id.lat_value);
+               longitude_view = (TextView) v.findViewById(R.id.lon_value);
+
+               apogee_view = v.findViewById(R.id.apogee_view);
+               apogee_voltage_view = (TextView) v.findViewById(R.id.apogee_voltage_value);
+               apogee_lights = new GoNoGoLights((ImageView) v.findViewById(R.id.apogee_redled),
+                                                (ImageView) v.findViewById(R.id.apogee_greenled),
+                                                getResources());
+               apogee_voltage_label = (TextView) v.findViewById(R.id.apogee_voltage_label);
+
+               main_view = v.findViewById(R.id.main_view);
+               main_voltage_view = (TextView) v.findViewById(R.id.main_voltage_value);
+               main_lights = new GoNoGoLights((ImageView) v.findViewById(R.id.main_redled),
+                                              (ImageView) v.findViewById(R.id.main_greenled),
+                                              getResources());
+               main_voltage_label = (TextView) v.findViewById(R.id.main_voltage_label);
+
+               return v;
+       }
+
+       public String tab_name() { return AltosDroid.tab_flight_name; }
+
+       public void show(TelemetryState telem_state, AltosState state, AltosGreatCircle from_receiver, Location receiver) {
+               if (state != null) {
+                       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.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);
+                               bearing_view.setText(AltosDroid.number("%3.0f°", from_receiver.bearing));
+                               compass_view.setText(from_receiver.bearing_words(AltosGreatCircle.BEARING_LONG));
+                               set_value(distance_view, AltosConvert.distance, 6, from_receiver.distance);
+                       } else { 
+                               elevation_view.setText("<unknown>");
+                               range_view.setText("<unknown>");
+                               bearing_view.setText("<unknown>");
+                               compass_view.setText("<unknown>");
+                               distance_view.setText("<unknown>");
+                       }
+                       if (state.gps != null) {
+                               latitude_view.setText(AltosDroid.pos(state.gps.lat, "N", "S"));
+                               longitude_view.setText(AltosDroid.pos(state.gps.lon, "E", "W"));
+                       }
+
+                       if (state.apogee_voltage == AltosLib.MISSING) {
+                               apogee_view.setVisibility(View.GONE);
+                       } else {
+                               apogee_voltage_view.setText(AltosDroid.number("%4.2f V", state.apogee_voltage));
+                               apogee_lights.set(state.apogee_voltage > 3.2, state.apogee_voltage == AltosLib.MISSING);
+                               apogee_view.setVisibility(View.VISIBLE);
+                       }
+
+                       if (state.main_voltage == AltosLib.MISSING) {
+                               main_view.setVisibility(View.GONE);
+                       } else {
+                               main_voltage_view.setText(AltosDroid.number("%4.2f V", state.main_voltage));
+                               main_lights.set(state.main_voltage > 3.2, state.main_voltage == AltosLib.MISSING);
+                               main_view.setVisibility(View.VISIBLE);
+                       }
+               }
+       }
+
+}
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TabMap.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TabMap.java
new file mode 100644 (file)
index 0000000..53bfd27
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Copyright © 2013 Mike Beattie <mike@ethernal.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import org.altusmetrum.altoslib_13.*;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.*;
+import android.widget.*;
+import android.location.Location;
+
+public class TabMap extends AltosDroidTab implements AltosDroidMapSourceListener {
+
+       AltosLatLon     here;
+
+       private TextView mDistanceView;
+       private TextView mBearingLabel;
+       private TextView mBearingView;
+       private TextView mTargetLatitudeView;
+       private TextView mTargetLongitudeView;
+       private TextView mReceiverLatitudeView;
+       private TextView mReceiverLongitudeView;
+       private AltosMapOffline map_offline;
+       private AltosMapOnline map_online;
+       private View view;
+       private int map_source;
+
+       @Override
+       public void onAttach(Activity activity) {
+               super.onAttach(activity);
+       }
+
+       @Override
+       public void onCreate(Bundle savedInstanceState) {
+               super.onCreate(savedInstanceState);
+       }
+
+       @Override
+       public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+               view = inflater.inflate(R.layout.tab_map, container, false);
+               int map_source = AltosDroidPreferences.map_source();
+
+               mDistanceView  = (TextView)view.findViewById(R.id.distance_value);
+               mBearingLabel  = (TextView)view.findViewById(R.id.bearing_label);
+               mBearingView   = (TextView)view.findViewById(R.id.bearing_value);
+               mTargetLatitudeView  = (TextView)view.findViewById(R.id.target_lat_value);
+               mTargetLongitudeView = (TextView)view.findViewById(R.id.target_lon_value);
+               mReceiverLatitudeView  = (TextView)view.findViewById(R.id.receiver_lat_value);
+               mReceiverLongitudeView = (TextView)view.findViewById(R.id.receiver_lon_value);
+               map_offline = (AltosMapOffline)view.findViewById(R.id.map_offline);
+               map_offline.onCreateView(altos_droid);
+               map_online = new AltosMapOnline(view.getContext());
+               map_online.onCreateView(altos_droid);
+               map_source_changed(AltosDroidPreferences.map_source());
+               AltosDroidPreferences.register_map_source_listener(this);
+               return view;
+       }
+
+       @Override
+       public void onActivityCreated(Bundle savedInstanceState) {
+               super.onActivityCreated(savedInstanceState);
+               if (map_online != null)
+                       getChildFragmentManager().beginTransaction().add(R.id.map_online, map_online.mMapFragment).commit();
+       }
+
+       @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; }
+
+       private void center(double lat, double lon, double accuracy) {
+               if (map_offline != null)
+                       map_offline.center(lat, lon, accuracy);
+               if (map_online != null)
+                       map_online.center(lat, lon, accuracy);
+       }
+
+       public void show(TelemetryState telem_state, AltosState state, AltosGreatCircle from_receiver, Location receiver) {
+               if (from_receiver != null) {
+                       String  direction = AltosDroid.direction(from_receiver, receiver);
+                       if (direction != null) {
+                               mBearingLabel.setText("Direction");
+                               mBearingView.setText(direction);
+                       } else {
+                               mBearingLabel.setText("Bearing");
+                               mBearingView.setText(String.format("%3.0f°", from_receiver.bearing));
+                       }
+                       set_value(mDistanceView, AltosConvert.distance, 6, from_receiver.distance);
+               } else {
+                       mBearingLabel.setText("Bearing");
+                       mBearingView.setText("");
+                       set_value(mDistanceView, AltosConvert.distance, 6, AltosLib.MISSING);
+               }
+
+               if (state != null) {
+                       if (state.gps != null) {
+                               mTargetLatitudeView.setText(AltosDroid.pos(state.gps.lat, "N", "S"));
+                               mTargetLongitudeView.setText(AltosDroid.pos(state.gps.lon, "E", "W"));
+                       }
+               }
+
+               if (receiver != null) {
+                       double accuracy;
+
+                       here = new AltosLatLon(receiver.getLatitude(), receiver.getLongitude());
+                       if (receiver.hasAccuracy())
+                               accuracy = receiver.getAccuracy();
+                       else
+                               accuracy = 1000;
+                       mReceiverLatitudeView.setText(AltosDroid.pos(here.lat, "N", "S"));
+                       mReceiverLongitudeView.setText(AltosDroid.pos(here.lon, "E", "W"));
+                       center (here.lat, here.lon, accuracy);
+               }
+               if (map_source == AltosDroidPreferences.MAP_SOURCE_OFFLINE) {
+                       if (map_offline != null)
+                               map_offline.show(telem_state, state, from_receiver, receiver);
+               } else {
+                       if (map_online != null)
+                               map_online.show(telem_state, state, from_receiver, receiver);
+               }
+       }
+
+       public void map_source_changed(int map_source) {
+               this.map_source = map_source;
+               if (map_source == AltosDroidPreferences.MAP_SOURCE_OFFLINE) {
+                       if (map_online != null)
+                               map_online.set_visible(false);
+                       if (map_offline != null) {
+                               map_offline.set_visible(true);
+                               map_offline.show(last_telem_state, last_state, last_from_receiver, last_receiver);
+                       }
+               } else {
+                       if (map_offline != null)
+                               map_offline.set_visible(false);
+                       if (map_online != null) {
+                               map_online.set_visible(true);
+                               map_online.show(last_telem_state, last_state, last_from_receiver, last_receiver);
+                       }
+               }
+       }
+
+       public TabMap() {
+       }
+}
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TabPad.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TabPad.java
new file mode 100644 (file)
index 0000000..6e343f9
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ * Copyright © 2013 Mike Beattie <mike@ethernal.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import org.altusmetrum.altoslib_13.*;
+
+import android.os.Bundle;
+import android.view.*;
+import android.widget.*;
+import android.location.Location;
+
+public class TabPad extends AltosDroidTab {
+       private TextView battery_voltage_view;
+       private GoNoGoLights battery_lights;
+
+       private TableRow receiver_row;
+       private TextView receiver_voltage_view;
+       private TextView receiver_voltage_label;
+       private GoNoGoLights receiver_voltage_lights;
+
+       private TableRow apogee_row;
+       private TextView apogee_voltage_view;
+       private TextView apogee_voltage_label;
+       private GoNoGoLights apogee_lights;
+
+       private TableRow main_row;
+       private TextView main_voltage_view;
+       private TextView main_voltage_label;
+       private GoNoGoLights main_lights;
+
+       private TextView data_logging_view;
+       private GoNoGoLights data_logging_lights;
+
+       private TextView gps_locked_view;
+       private GoNoGoLights gps_locked_lights;
+
+       private TextView gps_ready_view;
+       private GoNoGoLights gps_ready_lights;
+
+       private TextView receiver_latitude_view;
+       private TextView receiver_longitude_view;
+       private TextView receiver_altitude_view;
+
+       private TableRow[] ignite_row = new TableRow[4];
+       private TextView[] ignite_voltage_view = new TextView[4];
+       private TextView[] ignite_voltage_label = new TextView[4];
+       private GoNoGoLights[] ignite_lights = new GoNoGoLights[4];
+
+
+       @Override
+       public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+               View v = inflater.inflate(R.layout.tab_pad, container, false);
+               battery_voltage_view = (TextView) v.findViewById(R.id.battery_voltage_value);
+               battery_lights = new GoNoGoLights((ImageView) v.findViewById(R.id.battery_redled),
+                                                 (ImageView) v.findViewById(R.id.battery_greenled),
+                                                 getResources());
+
+               receiver_row = (TableRow) v.findViewById(R.id.receiver_row);
+               receiver_voltage_view = (TextView) v.findViewById(R.id.receiver_voltage_value);
+               receiver_voltage_label = (TextView) v.findViewById(R.id.receiver_voltage_label);
+               receiver_voltage_lights = new GoNoGoLights((ImageView) v.findViewById(R.id.receiver_redled),
+                                                          (ImageView) v.findViewById(R.id.receiver_greenled),
+                                                          getResources());
+
+               apogee_row = (TableRow) v.findViewById(R.id.apogee_row);
+               apogee_voltage_view = (TextView) v.findViewById(R.id.apogee_voltage_value);
+               apogee_voltage_label = (TextView) v.findViewById(R.id.apogee_voltage_label);
+               apogee_lights = new GoNoGoLights((ImageView) v.findViewById(R.id.apogee_redled),
+                                                (ImageView) v.findViewById(R.id.apogee_greenled),
+                                                getResources());
+
+               main_row = (TableRow) v.findViewById(R.id.main_row);
+               main_voltage_view = (TextView) v.findViewById(R.id.main_voltage_value);
+               main_voltage_label = (TextView) v.findViewById(R.id.main_voltage_label);
+               main_lights = new GoNoGoLights((ImageView) v.findViewById(R.id.main_redled),
+                                              (ImageView) v.findViewById(R.id.main_greenled),
+                                              getResources());
+
+               data_logging_view = (TextView) v.findViewById(R.id.logging_value);
+               data_logging_lights = new GoNoGoLights((ImageView) v.findViewById(R.id.logging_redled),
+                                                     (ImageView) v.findViewById(R.id.logging_greenled),
+                                                     getResources());
+
+               gps_locked_view = (TextView) v.findViewById(R.id.gps_locked_value);
+               gps_locked_lights = new GoNoGoLights((ImageView) v.findViewById(R.id.gps_locked_redled),
+                                                   (ImageView) v.findViewById(R.id.gps_locked_greenled),
+                                                   getResources());
+
+               gps_ready_view = (TextView) v.findViewById(R.id.gps_ready_value);
+               gps_ready_lights = new GoNoGoLights((ImageView) v.findViewById(R.id.gps_ready_redled),
+                                                  (ImageView) v.findViewById(R.id.gps_ready_greenled),
+                                                  getResources());
+
+               for (int i = 0; i < 4; i++) {
+                       int row_id, view_id, label_id, lights_id;
+                       int red_id, green_id;
+                       switch (i) {
+                       case 0:
+                       default:
+                               row_id = R.id.ignite_a_row;
+                               view_id = R.id.ignite_a_voltage_value;
+                               label_id = R.id.ignite_a_voltage_label;
+                               red_id = R.id.ignite_a_redled;
+                               green_id = R.id.ignite_a_greenled;
+                               break;
+                       case 1:
+                               row_id = R.id.ignite_b_row;
+                               view_id = R.id.ignite_b_voltage_value;
+                               label_id = R.id.ignite_b_voltage_label;
+                               red_id = R.id.ignite_b_redled;
+                               green_id = R.id.ignite_b_greenled;
+                               break;
+                       case 2:
+                               row_id = R.id.ignite_c_row;
+                               view_id = R.id.ignite_c_voltage_value;
+                               label_id = R.id.ignite_c_voltage_label;
+                               red_id = R.id.ignite_c_redled;
+                               green_id = R.id.ignite_c_greenled;
+                               break;
+                       case 3:
+                               row_id = R.id.ignite_d_row;
+                               view_id = R.id.ignite_d_voltage_value;
+                               label_id = R.id.ignite_d_voltage_label;
+                               red_id = R.id.ignite_d_redled;
+                               green_id = R.id.ignite_d_greenled;
+                               break;
+                       }
+                       ignite_row[i] = (TableRow) v.findViewById(row_id);
+                       ignite_voltage_view[i] = (TextView) v.findViewById(view_id);
+                       ignite_voltage_label[i] = (TextView) v.findViewById(label_id);
+                       ignite_lights[i] = new GoNoGoLights((ImageView) v.findViewById(red_id),
+                                                            (ImageView) v.findViewById(green_id),
+                                                            getResources());
+               }
+
+               receiver_latitude_view = (TextView) v.findViewById(R.id.receiver_lat_value);
+               receiver_longitude_view = (TextView) v.findViewById(R.id.receiver_lon_value);
+               receiver_altitude_view = (TextView) v.findViewById(R.id.receiver_alt_value);
+        return v;
+       }
+
+       public String tab_name() { return AltosDroid.tab_pad_name; }
+
+       public void show(TelemetryState telem_state, AltosState state, AltosGreatCircle from_receiver, Location receiver) {
+               if (state != null) {
+                       battery_voltage_view.setText(AltosDroid.number(" %4.2f V", state.battery_voltage));
+                       battery_lights.set(state.battery_voltage >= AltosLib.ao_battery_good, state.battery_voltage == AltosLib.MISSING);
+                       if (state.apogee_voltage == AltosLib.MISSING) {
+                               apogee_row.setVisibility(View.GONE);
+                       } else {
+                               apogee_voltage_view.setText(AltosDroid.number(" %4.2f V", state.apogee_voltage));
+                               apogee_row.setVisibility(View.VISIBLE);
+                       }
+                       apogee_lights.set(state.apogee_voltage >= AltosLib.ao_igniter_good, state.apogee_voltage == AltosLib.MISSING);
+                       if (state.main_voltage == AltosLib.MISSING) {
+                               main_row.setVisibility(View.GONE);
+                       } else {
+                               main_voltage_view.setText(AltosDroid.number(" %4.2f V", state.main_voltage));
+                               main_row.setVisibility(View.VISIBLE);
+                       }
+                       main_lights.set(state.main_voltage >= AltosLib.ao_igniter_good, state.main_voltage == AltosLib.MISSING);
+
+                       int num_igniter = state.igniter_voltage == null ? 0 : state.igniter_voltage.length;
+
+                       for (int i = 0; i < 4; i++) {
+                               double voltage = i >= num_igniter ? AltosLib.MISSING : state.igniter_voltage[i];
+                               if (voltage == AltosLib.MISSING) {
+                                       ignite_row[i].setVisibility(View.GONE);
+                               } else {
+                                       ignite_voltage_view[i].setText(AltosDroid.number(" %4.2f V", voltage));
+                                       ignite_row[i].setVisibility(View.VISIBLE);
+                               }
+                               ignite_lights[i].set(voltage >= AltosLib.ao_igniter_good, voltage == AltosLib.MISSING);
+                       }
+
+                       if (state.cal_data().flight != 0) {
+                               if (state.state() <= AltosLib.ao_flight_pad)
+                                       data_logging_view.setText("Ready to record");
+                               else if (state.state() < AltosLib.ao_flight_landed)
+                                       data_logging_view.setText("Recording data");
+                               else
+                                       data_logging_view.setText("Recorded data");
+                       } else {
+                               data_logging_view.setText("Storage full");
+                       }
+                       data_logging_lights.set(state.cal_data().flight != 0, state.cal_data().flight == AltosLib.MISSING);
+
+                       if (state.gps != null) {
+                               int soln = state.gps.nsat;
+                               int nsat = state.gps.cc_gps_sat != null ? state.gps.cc_gps_sat.length : 0;
+                               gps_locked_view.setText(String.format("%d in soln, %d in view", soln, nsat));
+                               gps_locked_lights.set(state.gps.locked && state.gps.nsat >= 4, false);
+                               if (state.gps_ready)
+                                       gps_ready_view.setText("Ready");
+                               else
+                                       gps_ready_view.setText(AltosDroid.integer("Waiting %d", state.gps_waiting));
+                       } else
+                               gps_locked_lights.set(false, true);
+                       gps_ready_lights.set(state.gps_ready, state.gps == null);
+               }
+
+               if (telem_state != null) {
+                       if (telem_state.receiver_battery == AltosLib.MISSING) {
+                               receiver_row.setVisibility(View.GONE);
+                       } else {
+                               receiver_voltage_view.setText(AltosDroid.number(" %4.2f V", telem_state.receiver_battery));
+                               receiver_row.setVisibility(View.VISIBLE);
+                       }
+                       receiver_voltage_lights.set(telem_state.receiver_battery >= AltosLib.ao_battery_good, telem_state.receiver_battery == AltosLib.MISSING);
+               }
+
+               if (receiver != null) {
+                       double altitude = AltosLib.MISSING;
+                       if (receiver.hasAltitude())
+                               altitude = receiver.getAltitude();
+                       receiver_latitude_view.setText(AltosDroid.pos(receiver.getLatitude(), "N", "S"));
+                       receiver_longitude_view.setText(AltosDroid.pos(receiver.getLongitude(), "E", "W"));
+                       set_value(receiver_altitude_view, AltosConvert.height, 1, altitude);
+               }
+       }
+}
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TabRecover.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TabRecover.java
new file mode 100644 (file)
index 0000000..11c82f0
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright © 2013 Mike Beattie <mike@ethernal.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import org.altusmetrum.altoslib_13.*;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+import android.location.Location;
+
+public class TabRecover extends AltosDroidTab {
+       private TextView mBearingView;
+       private TextView mDirectionView;
+       private TextView mDistanceView;
+       private TextView mTargetLatitudeView;
+       private TextView mTargetLongitudeView;
+       private TextView mReceiverLatitudeView;
+       private TextView mReceiverLongitudeView;
+       private TextView mMaxHeightView;
+       private TextView mMaxSpeedView;
+       private TextView mMaxAccelView;
+
+       @Override
+       public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+               View v = inflater.inflate(R.layout.tab_recover, container, false);
+
+               mBearingView   = (TextView) v.findViewById(R.id.bearing_value);
+               mDirectionView = (TextView) v.findViewById(R.id.direction_value);
+               mDistanceView  = (TextView) v.findViewById(R.id.distance_value);
+               mTargetLatitudeView  = (TextView) v.findViewById(R.id.target_lat_value);
+               mTargetLongitudeView = (TextView) v.findViewById(R.id.target_lon_value);
+               mReceiverLatitudeView  = (TextView) v.findViewById(R.id.receiver_lat_value);
+               mReceiverLongitudeView = (TextView) v.findViewById(R.id.receiver_lon_value);
+               mMaxHeightView = (TextView) v.findViewById(R.id.max_height_value);
+               mMaxSpeedView  = (TextView) v.findViewById(R.id.max_speed_value);
+               mMaxAccelView  = (TextView) v.findViewById(R.id.max_accel_value);
+
+               return v;
+       }
+
+       public String tab_name() { return AltosDroid.tab_recover_name; }
+
+       public void show(TelemetryState telem_state, AltosState state, AltosGreatCircle from_receiver, Location receiver) {
+               if (from_receiver != null) {
+                       mBearingView.setText(String.format("%3.0f°", from_receiver.bearing));
+                       set_value(mDistanceView, AltosConvert.distance, 6, from_receiver.distance);
+                       String direction = AltosDroid.direction(from_receiver, receiver);
+                       if (direction == null)
+                               mDirectionView.setText("");
+                       else
+                               mDirectionView.setText(direction);
+               }
+               if (state != null && state.gps != null) {
+                       mTargetLatitudeView.setText(AltosDroid.pos(state.gps.lat, "N", "S"));
+                       mTargetLongitudeView.setText(AltosDroid.pos(state.gps.lon, "E", "W"));
+               }
+
+               if (receiver != null) {
+                       mReceiverLatitudeView.setText(AltosDroid.pos(receiver.getLatitude(), "N", "S"));
+                       mReceiverLongitudeView.setText(AltosDroid.pos(receiver.getLongitude(), "E", "W"));
+               }
+
+               if (state != null) {
+                       set_value(mMaxHeightView, AltosConvert.height, 6, state.max_height());
+                       set_value(mMaxAccelView, AltosConvert.accel, 6, state.max_acceleration());
+                       set_value(mMaxSpeedView, AltosConvert.speed, 6, state.max_speed());
+               }
+       }
+}
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TabsAdapter.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TabsAdapter.java
new file mode 100644 (file)
index 0000000..3158080
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * 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
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.util.ArrayList;
+
+import android.content.Context;
+import android.os.Bundle;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentActivity;
+import androidx.fragment.app.FragmentPagerAdapter;
+import androidx.viewpager.widget.ViewPager;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TabHost;
+import android.widget.TabWidget;
+
+/**
+ * This is a helper class that implements the management of tabs and all
+ * details of connecting a ViewPager with associated TabHost.  It relies on a
+ * trick.  Normally a tab host has a simple API for supplying a View or
+ * Intent that each tab will show.  This is not sufficient for switching
+ * between pages.  So instead we make the content part of the tab host
+ * 0dp high (it is not shown) and the TabsAdapter supplies its own dummy
+ * view to show as the tab content.  It listens to changes in tabs, and takes
+ * care of switch to the correct paged in the ViewPager whenever the selected
+ * tab changes.
+ */
+public class TabsAdapter extends FragmentPagerAdapter
+               implements TabHost.OnTabChangeListener, ViewPager.OnPageChangeListener {
+       private final Context mContext;
+       private final TabHost mTabHost;
+       private final ViewPager mViewPager;
+       private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
+       private int position;
+
+       static class TabInfo {
+               private final String tag;
+               private final Class<?> clss;
+               private final Bundle args;
+               private Fragment fragment;
+
+               TabInfo(String _tag, Class<?> _class, Bundle _args) {
+                       tag = _tag;
+                       clss = _class;
+                       args = _args;
+               }
+       }
+
+       static class DummyTabFactory implements TabHost.TabContentFactory {
+               private final Context mContext;
+
+               public DummyTabFactory(Context context) {
+                       mContext = context;
+               }
+
+               public View createTabContent(String tag) {
+                       View v = new View(mContext);
+                       v.setMinimumWidth(0);
+                       v.setMinimumHeight(0);
+                       return v;
+               }
+       }
+
+       public TabsAdapter(FragmentActivity activity, TabHost tabHost, ViewPager pager) {
+               super(activity.getSupportFragmentManager());
+               mContext = activity;
+               mTabHost = tabHost;
+               mViewPager = pager;
+               mTabHost.setOnTabChangedListener(this);
+               mViewPager.setAdapter(this);
+               mViewPager.setOnPageChangeListener(this);
+       }
+
+       public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) {
+               tabSpec.setContent(new DummyTabFactory(mContext));
+               String tag = tabSpec.getTag();
+
+               TabInfo info = new TabInfo(tag, clss, args);
+               mTabs.add(info);
+               mTabHost.addTab(tabSpec);
+               notifyDataSetChanged();
+       }
+
+       @Override
+       public int getCount() {
+               return mTabs.size();
+       }
+
+       @Override
+       public Fragment getItem(int position) {
+               TabInfo info = mTabs.get(position);
+               AltosDebug.debug("TabsAdapter.getItem(%d)", position);
+               info.fragment = Fragment.instantiate(mContext, info.clss.getName(), info.args);
+               return info.fragment;
+       }
+
+       public Fragment currentItem() {
+               TabInfo info = mTabs.get(position);
+               return info.fragment;
+       }
+
+       public void onTabChanged(String tabId) {
+               AltosDroidTab   prev_frag = (AltosDroidTab) mTabs.get(position).fragment;
+
+               position = mTabHost.getCurrentTab();
+
+               AltosDroidTab   cur_frag = (AltosDroidTab) mTabs.get(position).fragment;
+
+               if (prev_frag != cur_frag) {
+                       if (prev_frag != null) {
+                               prev_frag.set_visible(false);
+                       }
+               }
+               if (cur_frag != null) {
+                       cur_frag.set_visible(true);
+               }
+               AltosDebug.debug("TabsAdapter.onTabChanged(%s) = %d", tabId, position);
+               mViewPager.setCurrentItem(position);
+       }
+
+       public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+       }
+
+       public void onPageSelected(int position) {
+               // Unfortunately when TabHost changes the current tab, it kindly
+               // also takes care of putting focus on it when not in touch mode.
+               // The jerk.
+               // This hack tries to prevent this from pulling focus out of our
+               // ViewPager.
+               TabWidget widget = mTabHost.getTabWidget();
+               int oldFocusability = widget.getDescendantFocusability();
+               widget.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
+               mTabHost.setCurrentTab(position);
+               widget.setDescendantFocusability(oldFocusability);
+       }
+
+       public void onPageScrollStateChanged(int state) {
+       }
+}
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TelemetryLogger.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TelemetryLogger.java
new file mode 100644 (file)
index 0000000..49ba547
--- /dev/null
@@ -0,0 +1,69 @@
+package org.altusmetrum.AltosDroid;
+
+import org.altusmetrum.altoslib_13.*;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Environment;
+
+public class TelemetryLogger {
+       private Context   context = null;
+       private AltosLink link    = null;
+       private AltosLog  logger  = null;
+
+       private BroadcastReceiver mExternalStorageReceiver;
+
+       public TelemetryLogger(Context in_context, AltosLink in_link) {
+               context = in_context;
+               link    = in_link;
+
+               startWatchingExternalStorage();
+       }
+
+       public void stop() {
+               stopWatchingExternalStorage();
+               close();
+       }
+
+       private void close() {
+               if (logger != null) {
+                       AltosDebug.debug("Shutting down Telemetry Logging");
+                       logger.close();
+                       logger = null;
+               }
+       }
+
+       void handleExternalStorageState() {
+               String state = Environment.getExternalStorageState();
+               if (Environment.MEDIA_MOUNTED.equals(state)) {
+                       if (logger == null) {
+                               AltosDebug.debug("Starting up Telemetry Logging");
+                               logger = new AltosLog(link);
+                       }
+               } else {
+                       AltosDebug.debug("External Storage not present - stopping");
+                       close();
+               }
+       }
+
+       void startWatchingExternalStorage() {
+               mExternalStorageReceiver = new BroadcastReceiver() {
+                       @Override
+                       public void onReceive(Context context, Intent intent) {
+                               handleExternalStorageState();
+                       }
+               };
+               IntentFilter filter = new IntentFilter();
+               filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
+               filter.addAction(Intent.ACTION_MEDIA_REMOVED);
+               context.registerReceiver(mExternalStorageReceiver, filter);
+               handleExternalStorageState();
+       }
+
+       void stopWatchingExternalStorage() {
+               context.unregisterReceiver(mExternalStorageReceiver);
+       }
+
+}
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TelemetryReader.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TelemetryReader.java
new file mode 100644 (file)
index 0000000..de967e1
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ * Copyright © 2012 Mike Beattie <mike@ethernal.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+
+package org.altusmetrum.AltosDroid;
+
+import java.text.*;
+import java.io.*;
+import java.util.concurrent.*;
+import android.os.Handler;
+
+import org.altusmetrum.altoslib_13.*;
+
+
+public class TelemetryReader extends Thread {
+
+       int         crc_errors;
+
+       Handler     handler;
+
+       AltosLink   link;
+
+       LinkedBlockingQueue<AltosLine> telemQueue;
+
+       public AltosTelemetry read() throws ParseException, AltosCRCException, InterruptedException, IOException {
+               AltosLine l = telemQueue.take();
+               if (l.line == null)
+                       throw new IOException("IO error");
+               AltosTelemetry telem = AltosTelemetryLegacy.parse(l.line);
+               return telem;
+       }
+
+       public void close() {
+               link.remove_monitor(telemQueue);
+               link = null;
+               telemQueue.clear();
+               telemQueue = null;
+       }
+
+       public void run() {
+               try {
+                       AltosDebug.debug("starting loop");
+                       while (telemQueue != null) {
+                               try {
+                                       AltosTelemetry  telem = read();
+                                       telem.set_frequency(link.frequency);
+                                       handler.obtainMessage(TelemetryService.MSG_TELEMETRY, telem).sendToTarget();
+                               } catch (ParseException pp) {
+                                       AltosDebug.error("Parse error: %d \"%s\"", pp.getErrorOffset(), pp.getMessage());
+                               } catch (AltosCRCException ce) {
+                                       ++crc_errors;
+                                       handler.obtainMessage(TelemetryService.MSG_CRC_ERROR, new Integer(crc_errors)).sendToTarget();
+                               }
+                       }
+               } catch (InterruptedException ee) {
+               } catch (IOException ie) {
+                       AltosDebug.error("IO exception in telemetry reader");
+                       handler.obtainMessage(TelemetryService.MSG_DISCONNECTED, link).sendToTarget();
+               } finally {
+                       close();
+               }
+       }
+
+       public TelemetryReader (AltosLink in_link, Handler in_handler) {
+               AltosDebug.debug("connected TelemetryReader create started");
+               link    = in_link;
+               handler = in_handler;
+
+               telemQueue = new LinkedBlockingQueue<AltosLine>();
+               link.add_monitor(telemQueue);
+               link.set_telemetry(AltosLib.ao_telemetry_standard);
+
+               AltosDebug.debug("connected TelemetryReader created");
+       }
+}
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TelemetryService.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TelemetryService.java
new file mode 100644 (file)
index 0000000..5dba24b
--- /dev/null
@@ -0,0 +1,723 @@
+/*
+ * Copyright © 2012 Mike Beattie <mike@ethernal.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.lang.ref.WeakReference;
+import java.util.concurrent.TimeoutException;
+import java.util.*;
+
+import android.app.*;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothAdapter;
+import android.graphics.Color;
+import android.hardware.usb.*;
+import android.content.Intent;
+import android.content.Context;
+import android.os.*;
+import android.widget.Toast;
+
+import org.altusmetrum.altoslib_13.*;
+
+public class TelemetryService extends Service implements AltosIdleMonitorListener {
+
+       static final int MSG_REGISTER_CLIENT   = 1;
+       static final int MSG_UNREGISTER_CLIENT = 2;
+       static final int MSG_CONNECT           = 3;
+       static final int MSG_OPEN_USB          = 4;
+       static final int MSG_CONNECTED         = 5;
+       static final int MSG_CONNECT_FAILED    = 6;
+       static final int MSG_DISCONNECTED      = 7;
+       static final int MSG_TELEMETRY         = 8;
+       static final int MSG_SETFREQUENCY      = 9;
+       static final int MSG_CRC_ERROR         = 10;
+       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.
+       private int NOTIFICATION = R.string.telemetry_service_label;
+       //private NotificationManager mNM;
+
+       ArrayList<Messenger> clients = new ArrayList<Messenger>(); // Keeps track of all current registered clients.
+       final Handler   handler   = new IncomingHandler(this);
+       final Messenger messenger = new Messenger(handler); // Target we publish for clients to send messages to IncomingHandler.
+
+       // Name of the connected device
+       DeviceAddress address;
+       private AltosDroidLink  altos_link  = null;
+       private TelemetryReader telemetry_reader = null;
+       private TelemetryLogger telemetry_logger = null;
+
+       // Local Bluetooth adapter
+       private BluetoothAdapter bluetooth_adapter = null;
+
+       // 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;
+               IncomingHandler(TelemetryService s) { service = new WeakReference<TelemetryService>(s); }
+
+               @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 */
+                       case MSG_REGISTER_CLIENT:
+                               s.add_client(msg.replyTo);
+                               break;
+                       case MSG_UNREGISTER_CLIENT:
+                               s.remove_client(msg.replyTo);
+                               break;
+                       case MSG_CONNECT:
+                               AltosDebug.debug("Connect command received");
+                               address = (DeviceAddress) msg.obj;
+                               AltosDroidPreferences.set_active_device(address);
+                               s.start_altos_bluetooth(address, false);
+                               break;
+                       case MSG_OPEN_USB:
+                               AltosDebug.debug("Open USB command received");
+                               UsbDevice device = (UsbDevice) msg.obj;
+                               s.start_usb(device);
+                               break;
+                       case MSG_DISCONNECT:
+                               AltosDebug.debug("Disconnect command received");
+                               s.address = null;
+                               if (!(Boolean) msg.obj)
+                                       AltosDroidPreferences.set_active_device(null);
+                               s.disconnect(true);
+                               break;
+                       case MSG_DELETE_SERIAL:
+                               AltosDebug.debug("Delete Serial command received");
+                               s.delete_serial((Integer) msg.obj);
+                               break;
+                       case MSG_SETFREQUENCY:
+                               AltosDebug.debug("MSG_SETFREQUENCY");
+                               s.telemetry_state.frequency = (Double) msg.obj;
+                               if (s.telemetry_state.connect == TelemetryState.CONNECT_CONNECTED) {
+                                       try {
+                                               s.altos_link.set_radio_frequency(s.telemetry_state.frequency);
+                                               s.altos_link.save_frequency();
+                                       } catch (InterruptedException e) {
+                                       } catch (TimeoutException e) {
+                                       }
+                               }
+                               s.send_to_clients();
+                               break;
+                       case MSG_SETBAUD:
+                               AltosDebug.debug("MSG_SETBAUD");
+                               s.telemetry_state.telemetry_rate = (Integer) msg.obj;
+                               if (s.telemetry_state.connect == TelemetryState.CONNECT_CONNECTED) {
+                                       s.altos_link.set_telemetry_rate(s.telemetry_state.telemetry_rate);
+                                       s.altos_link.save_telemetry_rate();
+                               }
+                               s.send_to_clients();
+                               break;
+
+                               /*
+                                *Messages from AltosBluetooth
+                                */
+                       case MSG_CONNECTED:
+                               AltosDebug.debug("MSG_CONNECTED");
+                               bt = (AltosDroidLink) msg.obj;
+
+                               if (bt != s.altos_link) {
+                                       AltosDebug.debug("Stale message");
+                                       break;
+                               }
+                               AltosDebug.debug("Connected to device");
+                               try {
+                                       s.connected();
+                               } catch (InterruptedException ie) {
+                               }
+                               break;
+                       case MSG_CONNECT_FAILED:
+                               AltosDebug.debug("MSG_CONNECT_FAILED");
+                               bt = (AltosDroidLink) msg.obj;
+
+                               if (bt != s.altos_link) {
+                                       AltosDebug.debug("Stale message");
+                                       break;
+                               }
+                               if (s.address != null) {
+                                       AltosDebug.debug("Connection failed... retrying");
+                                       s.start_altos_bluetooth(s.address, true);
+                               } else {
+                                       s.disconnect(true);
+                               }
+                               break;
+                       case MSG_DISCONNECTED:
+
+                               /* This can be sent by either AltosDroidLink or TelemetryReader */
+                               AltosDebug.debug("MSG_DISCONNECTED");
+                               bt = (AltosDroidLink) msg.obj;
+
+                               if (bt != s.altos_link) {
+                                       AltosDebug.debug("Stale message");
+                                       break;
+                               }
+                               if (s.address != null) {
+                                       AltosDebug.debug("Connection lost... retrying");
+                                       s.start_altos_bluetooth(s.address, true);
+                               } else {
+                                       s.disconnect(true);
+                               }
+                               break;
+
+                               /*
+                                * Messages from TelemetryReader
+                                */
+                       case MSG_TELEMETRY:
+                               s.telemetry((AltosTelemetry) msg.obj);
+                               break;
+                       case MSG_CRC_ERROR:
+                               // forward crc error messages
+                               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);
+                       }
+               }
+       }
+
+       /* Handle telemetry packet
+        */
+       private void telemetry(AltosTelemetry telem) {
+               AltosState      state;
+
+               if (telemetry_state.states.containsKey(telem.serial()))
+                       state = telemetry_state.states.get(telem.serial());
+               else
+                       state = new AltosState(new AltosCalData());
+               telem.provide_data(state);
+               telemetry_state.states.put(telem.serial(), state);
+               telemetry_state.quiet = false;
+               if (state != null) {
+                       AltosPreferences.set_state(state,telem.serial());
+               }
+               send_to_clients();
+       }
+
+       /* Construct the message to deliver to clients
+        */
+       private Message message() {
+               if (telemetry_state == null)
+                       AltosDebug.debug("telemetry_state null!");
+               if (telemetry_state.states == null)
+                       AltosDebug.debug("telemetry_state.states null!");
+               return Message.obtain(null, AltosDroid.MSG_STATE, telemetry_state);
+       }
+
+       /* A new friend has connected
+        */
+       private void add_client(Messenger client) {
+
+               clients.add(client);
+               AltosDebug.debug("Client bound to service");
+
+               /* On connect, send the current state to the new client
+                */
+               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
+                */
+               if (address != null && telemetry_state.connect == TelemetryState.CONNECT_DISCONNECTED) {
+                       AltosDebug.debug("Reconnecting now...");
+                       start_altos_bluetooth(address, false);
+               }
+       }
+
+       /* A client has disconnected, clean up
+        */
+       private void remove_client(Messenger client) {
+               clients.remove(client);
+               AltosDebug.debug("Client unbound from service");
+
+               /* When the list of clients is empty, stop the service if
+                * we have no current telemetry source
+                */
+
+                if (clients.isEmpty() && telemetry_state.connect == TelemetryState.CONNECT_DISCONNECTED) {
+                        AltosDebug.debug("No clients, no connection. Stopping\n");
+                        stopSelf();
+                }
+       }
+
+       private void send_to_client(Messenger client) {
+               Message m = message();
+               try {
+                       client.send(m);
+               } catch (RemoteException e) {
+                       AltosDebug.error("Client %s disappeared", client.toString());
+                       remove_client(client);
+               }
+       }
+
+       private void send_to_clients() {
+               for (Messenger client : clients)
+                       send_to_client(client);
+       }
+
+       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);
+               }
+       }
+
+       private void send_idle_mode_to_clients() {
+               for (Messenger client : clients)
+                       send_idle_mode_to_client(client);
+       }
+
+       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();
+                       try {
+                               telemetry_reader.join();
+                       } catch (InterruptedException e) {
+                       }
+                       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();
+                       telemetry_logger = null;
+               }
+               if (altos_link != null) {
+                       AltosDebug.debug("disconnect(): stopping AltosDroidLink");
+                       altos_link.close();
+                       altos_link = null;
+                       ignite = null;
+               }
+               telemetry_state.config = null;
+               if (notify) {
+                       AltosDebug.debug("disconnect(): send message to clients");
+                       send_to_clients();
+                       if (clients.isEmpty()) {
+                               AltosDebug.debug("disconnect(): no clients, terminating");
+                               stopSelf();
+                       }
+               }
+       }
+
+       private void start_usb(UsbDevice device) {
+               AltosUsb        d = new AltosUsb(this, device, handler);
+
+               if (d != null) {
+                       disconnect(false);
+                       altos_link = d;
+                       try {
+                               connected();
+                       } catch (InterruptedException ie) {
+                       }
+               }
+       }
+
+       private void delete_serial(int serial) {
+               telemetry_state.states.remove((Integer) serial);
+               AltosPreferences.remove_state(serial);
+               send_to_clients();
+       }
+
+       private void start_altos_bluetooth(DeviceAddress address, boolean pause) {
+               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);
+               telemetry_state.connect = TelemetryState.CONNECT_CONNECTING;
+               telemetry_state.address = address;
+               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 && idle_monitor == null && !ignite_running) {
+                       try {
+                               double  voltage = altos_link.monitor_battery();
+                               telemetry_state.receiver_battery = voltage;
+                               send_to_clients();
+                       } catch (InterruptedException ie) {
+                       }
+               }
+       }
+
+       private void stop_receiver_voltage_timer() {
+               if (receiver_voltage_timer != null) {
+                       receiver_voltage_timer.cancel();
+                       receiver_voltage_timer.purge();
+                       receiver_voltage_timer = null;
+               }
+       }
+
+       private void start_receiver_voltage_timer() {
+               if (receiver_voltage_timer == null && altos_link.has_monitor_battery()) {
+                       receiver_voltage_timer = new Timer();
+                       receiver_voltage_timer.scheduleAtFixedRate(new TimerTask() { public void run() {update_receiver_voltage();}}, 1000L, 10000L);
+               }
+       }
+
+       private void connected() throws InterruptedException {
+               AltosDebug.debug("connected top");
+               AltosDebug.check_ui("connected\n");
+               try {
+                       if (altos_link == null)
+                               throw new InterruptedException("no bluetooth");
+                       telemetry_state.config = altos_link.config_data();
+                       altos_link.set_radio_frequency(telemetry_state.frequency);
+                       altos_link.set_telemetry_rate(telemetry_state.telemetry_rate);
+               } catch (TimeoutException e) {
+                       // If this timed out, then we really want to retry it, but
+                       // probably safer to just retry the connection from scratch.
+                       AltosDebug.debug("connected timeout");
+                       if (address != null) {
+                               AltosDebug.debug("connected timeout, retrying");
+                               start_altos_bluetooth(address, true);
+                       } else {
+                               handler.obtainMessage(MSG_CONNECT_FAILED).sendToTarget();
+                               disconnect(true);
+                       }
+                       return;
+               }
+
+               AltosDebug.debug("connected bluetooth configured");
+               telemetry_state.connect = TelemetryState.CONNECT_CONNECTED;
+               telemetry_state.address = address;
+
+               telemetry_start();
+
+               AltosDebug.debug("connected TelemetryReader started");
+
+               telemetry_logger = new TelemetryLogger(this, altos_link);
+
+               start_receiver_voltage_timer();
+
+               AltosDebug.debug("Notify UI of connection");
+
+               send_to_clients();
+       }
+
+
+       @Override
+       public void onCreate() {
+
+               AltosDebug.init(this);
+
+               // Initialise preferences
+               AltosDroidPreferences.init(this);
+
+               // Get local Bluetooth adapter
+               bluetooth_adapter = BluetoothAdapter.getDefaultAdapter();
+
+               telemetry_state = new TelemetryState();
+
+               // Create a reference to the NotificationManager so that we can update our notifcation text later
+               //mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
+
+               telemetry_state.connect = TelemetryState.CONNECT_DISCONNECTED;
+               telemetry_state.address = null;
+
+               /* Pull the saved state information out of the preferences database
+                */
+               ArrayList<Integer> serials = AltosPreferences.list_states();
+
+               telemetry_state.latest_serial = AltosPreferences.latest_state();
+
+               telemetry_state.quiet = true;
+
+               AltosDebug.debug("latest serial %d\n", telemetry_state.latest_serial);
+
+               for (int serial : serials) {
+                       AltosState saved_state = AltosPreferences.state(serial);
+                       if (saved_state != null) {
+                               if (telemetry_state.latest_serial == 0)
+                                       telemetry_state.latest_serial = serial;
+
+                               AltosDebug.debug("recovered old state serial %d flight %d",
+                                                serial,
+                                                saved_state.cal_data().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);
+                               AltosPreferences.remove_state(serial);
+                       }
+               }
+       }
+
+
+       private String createNotificationChannel(String channelId, String channelName) {
+               NotificationChannel chan = new NotificationChannel(
+                               channelId, channelName, NotificationManager.IMPORTANCE_NONE);
+               chan.setLightColor(Color.BLUE);
+               chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
+               NotificationManager service = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+               service.createNotificationChannel(chan);
+               return channelId;
+       }
+
+       @Override
+       public int onStartCommand(Intent intent, int flags, int startId) {
+               AltosDebug.debug("Received start id %d: %s", startId, intent);
+
+               // The PendingIntent to launch our activity if the user selects this notification
+               PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
+                               new Intent(this, AltosDroid.class), 0);
+
+               String channelId =
+                               (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
+                                               ? createNotificationChannel("altosdroid_telemetry", "AltosDroid Telemetry Service")
+                                               : "";
+
+               // Create notification to be displayed while the service runs
+               Notification notification = new Notification.Builder(this, channelId)
+                               .setContentTitle(getText(R.string.telemetry_service_label))
+                               .setContentText(getText(R.string.telemetry_service_started))
+                               .setContentIntent(contentIntent)
+                               .setWhen(System.currentTimeMillis())
+                               .setOngoing(true)
+                               .setSmallIcon(R.drawable.am_status_c)
+//                             .setLargeIcon(R.drawable.am_status_c)
+                               .build();
+
+               // Move us into the foreground.
+               startForeground(NOTIFICATION, notification);
+
+               /* Start bluetooth if we don't have a connection already */
+               if (intent != null &&
+                   (telemetry_state.connect == TelemetryState.CONNECT_NONE ||
+                    telemetry_state.connect == TelemetryState.CONNECT_DISCONNECTED))
+               {
+                       String  action = intent.getAction();
+
+                       if (action.equals(AltosDroid.ACTION_BLUETOOTH)) {
+                               DeviceAddress address = AltosDroidPreferences.active_device();
+                               if (address != null && !address.address.startsWith("USB"))
+                                       start_altos_bluetooth(address, false);
+                       }
+               }
+
+               // We want this service to continue running until it is explicitly
+               // stopped, so return sticky.
+               return START_STICKY;
+       }
+
+       @Override
+       public void onDestroy() {
+
+               // Stop the bluetooth Comms threads
+               disconnect(true);
+
+               // Demote us from the foreground, and cancel the persistent notification.
+               stopForeground(true);
+
+               // Tell the user we stopped.
+               Toast.makeText(this, R.string.telemetry_service_stopped, Toast.LENGTH_SHORT).show();
+       }
+
+       @Override
+       public IBinder onBind(Intent intent) {
+               return messenger.getBinder();
+       }
+
+       /* AltosIdleMonitorListener */
+       public void update(AltosState state, AltosListenerState listener_state) {
+               telemetry_state.states.put(state.cal_data().serial, state);
+               telemetry_state.receiver_battery = listener_state.battery;
+               send_to_clients();
+       }
+
+       public void failed() {
+       }
+
+       public void error(String reason) {
+               stop_idle_monitor();
+       }
+}
diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TelemetryState.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TelemetryState.java
new file mode 100644 (file)
index 0000000..d292c7b
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright © 2012 Mike Beattie <mike@ethernal.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.util.*;
+import org.altusmetrum.altoslib_13.*;
+
+public class TelemetryState {
+       public static final int CONNECT_NONE         = 0;
+       public static final int CONNECT_DISCONNECTED = 1;
+       public static final int CONNECT_CONNECTING   = 2;
+       public static final int CONNECT_CONNECTED    = 3;
+
+       int             connect;
+       DeviceAddress   address;
+       AltosConfigData config;
+       int             crc_errors;
+       double          receiver_battery;
+       double          frequency;
+       int             telemetry_rate;
+
+       boolean         quiet;
+
+       HashMap<Integer,AltosState>     states;
+
+       int             latest_serial;
+
+       public TelemetryState() {
+               connect = CONNECT_NONE;
+               config = null;
+               states = new HashMap<Integer,AltosState>();
+               crc_errors = 0;
+               receiver_battery = AltosLib.MISSING;
+               frequency = AltosPreferences.frequency(0);
+               telemetry_rate = AltosPreferences.telemetry_rate(0);
+       }
+}
diff --git a/altosdroid/app/src/main/res/drawable-hdpi/am_status_c.png b/altosdroid/app/src/main/res/drawable-hdpi/am_status_c.png
new file mode 100644 (file)
index 0000000..d439321
Binary files /dev/null and b/altosdroid/app/src/main/res/drawable-hdpi/am_status_c.png differ
diff --git a/altosdroid/app/src/main/res/drawable-hdpi/am_status_g.png b/altosdroid/app/src/main/res/drawable-hdpi/am_status_g.png
new file mode 100644 (file)
index 0000000..03f9dd7
Binary files /dev/null and b/altosdroid/app/src/main/res/drawable-hdpi/am_status_g.png differ
diff --git a/altosdroid/app/src/main/res/drawable-hdpi/app_icon.png b/altosdroid/app/src/main/res/drawable-hdpi/app_icon.png
new file mode 100644 (file)
index 0000000..da2f08a
Binary files /dev/null and b/altosdroid/app/src/main/res/drawable-hdpi/app_icon.png differ
diff --git a/altosdroid/app/src/main/res/drawable-hdpi/ic_maps_indicator_current_position.png b/altosdroid/app/src/main/res/drawable-hdpi/ic_maps_indicator_current_position.png
new file mode 100644 (file)
index 0000000..bc9160d
Binary files /dev/null and b/altosdroid/app/src/main/res/drawable-hdpi/ic_maps_indicator_current_position.png differ
diff --git a/altosdroid/app/src/main/res/drawable-mdpi/am_status_c.png b/altosdroid/app/src/main/res/drawable-mdpi/am_status_c.png
new file mode 100644 (file)
index 0000000..30a8d29
Binary files /dev/null and b/altosdroid/app/src/main/res/drawable-mdpi/am_status_c.png differ
diff --git a/altosdroid/app/src/main/res/drawable-mdpi/am_status_g.png b/altosdroid/app/src/main/res/drawable-mdpi/am_status_g.png
new file mode 100644 (file)
index 0000000..07f7f07
Binary files /dev/null and b/altosdroid/app/src/main/res/drawable-mdpi/am_status_g.png differ
diff --git a/altosdroid/app/src/main/res/drawable-mdpi/ic_maps_indicator_current_position.png b/altosdroid/app/src/main/res/drawable-mdpi/ic_maps_indicator_current_position.png
new file mode 100644 (file)
index 0000000..4e427d8
Binary files /dev/null and b/altosdroid/app/src/main/res/drawable-mdpi/ic_maps_indicator_current_position.png differ
diff --git a/altosdroid/app/src/main/res/drawable/app_icon.png b/altosdroid/app/src/main/res/drawable/app_icon.png
new file mode 100644 (file)
index 0000000..b0a3c9c
Binary files /dev/null and b/altosdroid/app/src/main/res/drawable/app_icon.png differ
diff --git a/altosdroid/app/src/main/res/drawable/pad.png b/altosdroid/app/src/main/res/drawable/pad.png
new file mode 100644 (file)
index 0000000..b2e65c8
Binary files /dev/null and b/altosdroid/app/src/main/res/drawable/pad.png differ
diff --git a/altosdroid/app/src/main/res/drawable/rocket.png b/altosdroid/app/src/main/res/drawable/rocket.png
new file mode 100644 (file)
index 0000000..7e62f6c
Binary files /dev/null and b/altosdroid/app/src/main/res/drawable/rocket.png differ
diff --git a/altosdroid/app/src/main/res/layout/altosdroid.xml b/altosdroid/app/src/main/res/layout/altosdroid.xml
new file mode 100644 (file)
index 0000000..df87067
--- /dev/null
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright © 2012-2013 Mike Beattie <mike@ethernal.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; 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.
+
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+       android:layout_width="fill_parent"
+       android:layout_height="wrap_content"
+       android:layout_weight="0"
+       android:orientation="vertical" >
+
+       <LinearLayout
+               xmlns:android="http://schemas.android.com/apk/res/android"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:layout_weight="0"
+               android:baselineAligned="true"
+               android:orientation="horizontal" >
+
+               <RelativeLayout
+                       android:id="@+id/callsign_container"
+                       android:layout_width="0dp"
+                       android:layout_height="wrap_content"
+                       android:layout_weight="1" >
+
+                       <TextView
+                               android:id="@+id/callsign_label"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:text="@string/callsign_label" />
+
+                       <TextView
+                               android:id="@+id/callsign_value"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:layout_below="@+id/callsign_label"
+                               android:text=""
+                               android:textAppearance="?android:attr/textAppearanceSmall" />
+               </RelativeLayout>
+
+               <RelativeLayout
+                       android:id="@+id/serial_container"
+                       android:layout_width="0dp"
+                       android:layout_height="wrap_content"
+                       android:layout_weight="1" >
+
+                       <TextView
+                               android:id="@+id/serial_label"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:text="@string/serial_label" />
+
+                       <TextView
+                               android:id="@+id/serial_value"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:layout_below="@+id/serial_label"
+                               android:textAppearance="?android:attr/textAppearanceSmall" />
+               </RelativeLayout>
+
+               <RelativeLayout
+                       android:id="@+id/flight_container"
+                       android:layout_width="0dp"
+                       android:layout_height="wrap_content"
+                       android:layout_weight="1" >
+
+                       <TextView
+                               android:id="@+id/flight_label"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:text="@string/flight_label" />
+
+                       <TextView
+                               android:id="@+id/flight_value"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:layout_below="@+id/flight_label"
+                               android:textAppearance="?android:attr/textAppearanceSmall" />
+               </RelativeLayout>
+
+               <RelativeLayout
+                       android:id="@+id/state_container"
+                       android:layout_width="0dp"
+                       android:layout_height="wrap_content"
+                       android:layout_weight="1" >
+
+                       <TextView
+                               android:id="@+id/state_label"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:text="@string/state_label" />
+
+                       <TextView
+                               android:id="@+id/state_value"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:layout_below="@+id/state_label"
+                               android:textAppearance="?android:attr/textAppearanceSmall" />
+               </RelativeLayout>
+
+               <RelativeLayout
+                       android:id="@+id/rssi_container"
+                       android:layout_width="0dp"
+                       android:layout_height="wrap_content"
+                       android:layout_weight="1" >
+
+                       <TextView
+                               android:id="@+id/rssi_label"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:text="@string/rssi_label" />
+
+                       <TextView
+                               android:id="@+id/rssi_value"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:layout_below="@+id/rssi_label"
+                               android:textAppearance="?android:attr/textAppearanceSmall" />
+               </RelativeLayout>
+
+               <RelativeLayout
+                       android:id="@+id/age_container"
+                       android:layout_width="0dp"
+                       android:layout_height="wrap_content"
+                       android:layout_weight="1" >
+
+                       <TextView
+                               android:id="@+id/age_label"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:text="@string/age_label" />
+
+                       <TextView
+                               android:id="@+id/age_value"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:layout_below="@+id/age_label"
+                               android:textAppearance="?android:attr/textAppearanceSmall" />
+               </RelativeLayout>
+       </LinearLayout>
+
+       <TabHost
+               xmlns:android="http://schemas.android.com/apk/res/android"
+               android:id="@android:id/tabhost"
+               android:layout_width="fill_parent"
+               android:layout_height="0dp"
+               android:layout_weight="1" >
+
+               <LinearLayout
+                       android:layout_width="match_parent"
+                       android:layout_height="match_parent"
+                       android:orientation="vertical" >
+
+                       <TabWidget
+                               android:id="@android:id/tabs"
+                               android:layout_width="match_parent"
+                               android:layout_height="wrap_content"
+                               android:layout_weight="0"
+                               android:orientation="horizontal" />
+
+                       <FrameLayout
+                               android:id="@android:id/tabcontent"
+                               android:layout_width="0dp"
+                               android:layout_height="0dp"
+                               android:layout_weight="0" />
+
+                       <org.altusmetrum.AltosDroid.AltosViewPager
+                               android:id="@+id/pager"
+                               android:layout_width="match_parent"
+                               android:layout_height="0dp"
+                               android:layout_weight="1" />
+               </LinearLayout>
+       </TabHost>
+
+       <TextView
+               android:id="@+id/version"
+               android:layout_width="fill_parent"
+               android:layout_height="10dip"
+               android:layout_weight="0"
+               android:gravity="bottom|right"
+               android:textSize="7sp"
+               android:typeface="monospace" />
+
+</LinearLayout>
diff --git a/altosdroid/app/src/main/res/layout/custom_title.xml b/altosdroid/app/src/main/res/layout/custom_title.xml
new file mode 100644 (file)
index 0000000..57eb6b4
--- /dev/null
@@ -0,0 +1,39 @@
+<?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
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     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.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:gravity="center_vertical"
+  >
+  <TextView android:id="@+id/title_left_text"
+      android:layout_alignParentLeft="true"
+      android:ellipsize="end"
+      android:singleLine="true"
+      style="?android:attr/windowTitleStyle"
+      android:layout_width="wrap_content"
+      android:layout_height="match_parent"
+      android:layout_weight="1"
+    />
+    <TextView android:id="@+id/title_right_text"
+        android:layout_alignParentRight="true"
+        android:ellipsize="end"
+        android:singleLine="true"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:textColor="#fff"
+        android:layout_weight="1" 
+    />
+</RelativeLayout>
\ No newline at end of file
diff --git a/altosdroid/app/src/main/res/layout/device_list.xml b/altosdroid/app/src/main/res/layout/device_list.xml
new file mode 100644 (file)
index 0000000..0c103e9
--- /dev/null
@@ -0,0 +1,63 @@
+<?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; 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.
+
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    >
+    <Button android:id="@+id/button_scan"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/button_scan"
+    />
+    <TextView android:id="@+id/title_new_devices"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/title_other_devices"
+        android:visibility="gone"
+        android:background="#666"
+        android:textColor="#fff"
+        android:paddingLeft="5dp"
+    />
+    <ListView android:id="@+id/new_devices"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+       android:fadeScrollbars="false"
+       android:scrollbars="vertical"
+    />
+    <TextView android:id="@+id/title_paired_devices"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/title_paired_devices"
+        android:visibility="gone"
+        android:background="#666"
+        android:textColor="#fff"
+        android:paddingLeft="5dp"
+    />
+    <ListView android:id="@+id/paired_devices"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+       android:fadeScrollbars="false"
+       android:scrollbars="vertical"
+    />
+</LinearLayout>
diff --git a/altosdroid/app/src/main/res/layout/device_name.xml b/altosdroid/app/src/main/res/layout/device_name.xml
new file mode 100644 (file)
index 0000000..8fa358c
--- /dev/null
@@ -0,0 +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
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     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.
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:textSize="18sp"
+    android:padding="5dp"
+/>
\ No newline at end of file
diff --git a/altosdroid/app/src/main/res/layout/frequency.xml b/altosdroid/app/src/main/res/layout/frequency.xml
new file mode 100644 (file)
index 0000000..7adbdc1
--- /dev/null
@@ -0,0 +1,34 @@
+<?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; 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.
+
+-->
+<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/app/src/main/res/layout/idle_mode.xml b/altosdroid/app/src/main/res/layout/idle_mode.xml
new file mode 100644 (file)
index 0000000..6c598c1
--- /dev/null
@@ -0,0 +1,55 @@
+<?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; 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.
+
+-->
+<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/app/src/main/res/layout/igniter_status.xml b/altosdroid/app/src/main/res/layout/igniter_status.xml
new file mode 100644 (file)
index 0000000..931ad62
--- /dev/null
@@ -0,0 +1,39 @@
+<?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; 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.
+
+-->
+<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/app/src/main/res/layout/igniters.xml b/altosdroid/app/src/main/res/layout/igniters.xml
new file mode 100644 (file)
index 0000000..6ce5b24
--- /dev/null
@@ -0,0 +1,49 @@
+<?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; 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.
+
+-->
+<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/app/src/main/res/layout/manage_frequencies.xml b/altosdroid/app/src/main/res/layout/manage_frequencies.xml
new file mode 100644 (file)
index 0000000..afb3310
--- /dev/null
@@ -0,0 +1,97 @@
+<?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; 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.
+
+-->
+<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/app/src/main/res/layout/map_preload.xml b/altosdroid/app/src/main/res/layout/map_preload.xml
new file mode 100644 (file)
index 0000000..4e60df2
--- /dev/null
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright © 2015 Keith Packard <keithp@keithp.com>
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    >
+  <ScrollView android:layout_width="fill_parent"
+             android:layout_height="wrap_content">
+    <LinearLayout android:layout_width="wrap_content"
+                 android:layout_height="wrap_content"
+                  android:orientation="vertical">
+      <TextView android:id="@+id/preload_site_label"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:text="@string/preload_site_label"
+               />
+      <Spinner android:id="@+id/preload_site_list"
+              android:layout_width="fill_parent"
+              android:layout_height="wrap_content"
+              android:prompt="@string/preload_site_label"
+              android:spinnerMode="dropdown"
+              />
+      <TextView android:id="@+id/preload_latitude_label"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:text="@string/preload_latitude_label"
+               />
+      <EditText android:id="@+id/preload_latitude"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:hint="@string/preload_latitude_label"
+               android:inputType="number|numberSigned|numberDecimal"/>
+      <TextView android:id="@+id/preload_longitude_label"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:text="@string/preload_longitude_label"
+               />
+      <EditText android:id="@+id/preload_longitude"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:hint="@string/preload_longitude_label"
+               android:inputType="number|numberSigned|numberDecimal"/>
+      <TextView android:id="@+id/preload_types"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:text="@string/preload_types"
+               />
+<!--
+      <CheckBox android:id="@+id/preload_hybrid"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:text="@string/preload_hybrid"
+               />
+      <CheckBox android:id="@+id/preload_satellite"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:text="@string/preload_satellite"
+               />
+      <CheckBox android:id="@+id/preload_roadmap"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:text="@string/preload_roadmap"
+               />
+      <CheckBox android:id="@+id/preload_terrain"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:text="@string/preload_terrain"
+               />
+-->
+      <TextView android:id="@+id/preload_min_zoom_label"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:text="@string/preload_min_zoom"
+               />
+      <Spinner android:id="@+id/preload_min_zoom"
+              android:layout_width="fill_parent"
+              android:layout_height="wrap_content"
+              android:prompt="@string/preload_min_zoom"
+              android:spinnerMode="dropdown"
+              />
+      <TextView android:id="@+id/preload_max_zoom_label"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:text="@string/preload_max_zoom"
+               />
+      <Spinner android:id="@+id/preload_max_zoom"
+              android:layout_width="fill_parent"
+              android:layout_height="wrap_content"
+              android:prompt="@string/preload_max_zoom"
+              android:spinnerMode="dropdown"
+              />
+      <TextView android:id="@+id/preload_radius_label"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:text="@string/preload_radius"
+               />
+      <Spinner android:id="@+id/preload_radius"
+              android:layout_width="fill_parent"
+              android:layout_height="wrap_content"
+              android:prompt="@string/preload_radius"
+              android:spinnerMode="dropdown"
+              />
+      <Button android:id="@+id/preload_load"
+              android:layout_width="match_parent"
+              android:layout_height="wrap_content"
+              android:text="@string/preload_load"
+             />
+      <ProgressBar android:id="@+id/preload_progress"
+                  android:layout_width="match_parent"
+                  android:layout_height="wrap_content"
+                  style="@android:style/Widget.ProgressBar.Horizontal"
+                  />
+    </LinearLayout>
+  </ScrollView>
+</LinearLayout>
diff --git a/altosdroid/app/src/main/res/layout/map_type.xml b/altosdroid/app/src/main/res/layout/map_type.xml
new file mode 100644 (file)
index 0000000..e5cea22
--- /dev/null
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright © 2015 Keith Packard <keithp@keithp.com>
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    >
+  <Button android:id="@+id/map_type_hybrid"
+          android:layout_width="fill_parent"
+          android:layout_height="wrap_content"
+          android:text="@string/preload_hybrid"
+          android:onClick="selectType"
+          />
+  <Button android:id="@+id/map_type_satellite"
+          android:layout_width="fill_parent"
+          android:layout_height="wrap_content"
+          android:text="@string/preload_satellite"
+          android:onClick="selectType"
+          />
+  <Button android:id="@+id/map_type_roadmap"
+          android:layout_width="fill_parent"
+          android:layout_height="wrap_content"
+          android:text="@string/preload_roadmap"
+          android:onClick="selectType"
+          />
+  <Button android:id="@+id/map_type_terrain"
+          android:layout_width="fill_parent"
+          android:layout_height="wrap_content"
+          android:text="@string/preload_terrain"
+          android:onClick="selectType"
+          />
+</LinearLayout>
diff --git a/altosdroid/app/src/main/res/layout/setup.xml b/altosdroid/app/src/main/res/layout/setup.xml
new file mode 100644 (file)
index 0000000..eeaf60a
--- /dev/null
@@ -0,0 +1,125 @@
+<?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; 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.
+
+-->
+<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>
diff --git a/altosdroid/app/src/main/res/layout/tab_flight.xml b/altosdroid/app/src/main/res/layout/tab_flight.xml
new file mode 100644 (file)
index 0000000..36d277d
--- /dev/null
@@ -0,0 +1,403 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright © 2013 Mike Beattie <mike@ethernal.org>
+
+     This program is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published by
+     the Free Software Foundation; 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.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical" >
+
+  <LinearLayout
+      android:layout_weight="0"
+      android:layout_width="fill_parent"
+      android:layout_height="wrap_content"
+      android:orientation="vertical" >
+
+    <LinearLayout
+       xmlns:android="http://schemas.android.com/apk/res/android"
+       android:layout_width="fill_parent"
+       android:layout_height="wrap_content"
+       android:layout_weight="0"
+       android:baselineAligned="true"
+       android:orientation="horizontal" >
+
+      <RelativeLayout
+         android:layout_width="0dp"
+         android:layout_height="wrap_content"
+         android:layout_weight="1" >
+
+       <TextView
+           android:id="@+id/speed_label"
+           android:layout_width="wrap_content"
+           android:layout_height="wrap_content"
+           android:text="@string/speed_label" />
+
+       <TextView
+           android:id="@+id/speed_value"
+           android:layout_width="wrap_content"
+           android:layout_height="wrap_content"
+           android:layout_alignParentRight="true"
+           android:layout_below="@id/speed_label"
+           android:text=""
+           android:textAppearance="?android:attr/textAppearanceSmall" />
+      </RelativeLayout>
+
+      <RelativeLayout
+         android:layout_width="0dp"
+         android:layout_height="wrap_content"
+         android:layout_weight="1" >
+
+       <TextView
+           android:id="@+id/height_label"
+           android:layout_width="wrap_content"
+           android:layout_height="wrap_content"
+           android:text="@string/height_label" />
+
+       <TextView
+           android:id="@+id/height_value"
+           android:layout_width="wrap_content"
+           android:layout_height="wrap_content"
+           android:layout_alignParentRight="true"
+           android:layout_below="@id/height_label"
+           android:text=""
+           android:textAppearance="?android:attr/textAppearanceSmall" />
+      </RelativeLayout>
+
+    </LinearLayout>
+
+    <LinearLayout
+       xmlns:android="http://schemas.android.com/apk/res/android"
+       android:layout_width="fill_parent"
+       android:layout_height="wrap_content"
+       android:layout_weight="0"
+       android:baselineAligned="true"
+       android:orientation="horizontal" >
+
+      <RelativeLayout
+         android:layout_width="0dp"
+         android:layout_height="wrap_content"
+         android:layout_weight="1" >
+
+       <TextView
+           android:id="@+id/max_speed_label"
+           android:layout_width="wrap_content"
+           android:layout_height="wrap_content"
+           android:text="@string/max_speed_label" />
+
+       <TextView
+           android:id="@+id/max_speed_value"
+           android:layout_width="wrap_content"
+           android:layout_height="wrap_content"
+           android:layout_alignParentRight="true"
+           android:layout_below="@id/max_speed_label"
+           android:text=""
+           android:textAppearance="?android:attr/textAppearanceSmall" />
+      </RelativeLayout>
+
+      <RelativeLayout
+         android:layout_width="0dp"
+         android:layout_height="wrap_content"
+         android:layout_weight="1" >
+
+       <TextView
+           android:id="@+id/max_height_label"
+           android:layout_width="wrap_content"
+           android:layout_height="wrap_content"
+           android:text="@string/max_height_label" />
+
+       <TextView
+           android:id="@+id/max_height_value"
+           android:layout_width="wrap_content"
+           android:layout_height="wrap_content"
+           android:layout_alignParentRight="true"
+           android:layout_below="@id/max_height_label"
+           android:text=""
+           android:textAppearance="?android:attr/textAppearanceSmall" />
+      </RelativeLayout>
+
+    </LinearLayout>
+
+    <LinearLayout
+       xmlns:android="http://schemas.android.com/apk/res/android"
+       android:layout_width="fill_parent"
+       android:layout_height="wrap_content"
+       android:layout_weight="0"
+       android:baselineAligned="true"
+       android:orientation="horizontal"
+       android:paddingTop="5dp" >
+
+      <RelativeLayout
+         android:layout_width="0dp"
+         android:layout_height="wrap_content"
+         android:layout_weight="1" >
+
+       <TextView
+           android:id="@+id/elevation_label"
+           android:layout_width="wrap_content"
+           android:layout_height="wrap_content"
+           android:text="@string/elevation_label" />
+
+       <TextView
+           android:id="@+id/elevation_value"
+           android:layout_width="wrap_content"
+           android:layout_height="wrap_content"
+           android:layout_alignParentRight="true"
+           android:layout_below="@id/elevation_label"
+           android:text=""
+           android:textAppearance="?android:attr/textAppearanceSmall" />
+      </RelativeLayout>
+
+      <RelativeLayout
+         android:layout_width="0dp"
+         android:layout_height="wrap_content"
+         android:layout_weight="1" >
+
+       <TextView
+           android:id="@+id/range_label"
+           android:layout_width="wrap_content"
+           android:layout_height="wrap_content"
+           android:text="@string/range_label" />
+
+       <TextView
+           android:id="@+id/range_value"
+           android:layout_width="wrap_content"
+           android:layout_height="wrap_content"
+           android:layout_alignParentRight="true"
+           android:layout_below="@id/range_label"
+           android:text=""
+           android:textAppearance="?android:attr/textAppearanceSmall" />
+      </RelativeLayout>
+
+    </LinearLayout>
+
+    <LinearLayout
+       xmlns:android="http://schemas.android.com/apk/res/android"
+       android:layout_width="fill_parent"
+       android:layout_height="wrap_content"
+       android:layout_weight="0"
+       android:baselineAligned="true"
+       android:orientation="horizontal"
+       android:paddingTop="5dp" >
+
+      <RelativeLayout
+         android:layout_width="0dp"
+         android:layout_height="wrap_content"
+         android:layout_weight="1" >
+
+       <TextView
+           android:id="@+id/bearing_label"
+           android:layout_width="wrap_content"
+           android:layout_height="wrap_content"
+           android:text="@string/bearing_label" />
+
+       <TextView
+           android:id="@+id/bearing_value"
+           android:layout_width="wrap_content"
+           android:layout_height="wrap_content"
+           android:layout_alignParentRight="true"
+           android:layout_below="@id/bearing_label"
+           android:text=""
+           android:textAppearance="?android:attr/textAppearanceSmall" />
+      </RelativeLayout>
+
+      <RelativeLayout
+         android:layout_width="0dp"
+         android:layout_height="wrap_content"
+         android:layout_weight="1" >
+
+       <TextView
+           android:id="@+id/compass_label"
+           android:layout_width="wrap_content"
+           android:layout_height="wrap_content"
+           android:text="" />
+
+       <TextView
+           android:id="@+id/compass_value"
+           android:layout_width="wrap_content"
+           android:layout_height="wrap_content"
+           android:layout_alignParentRight="true"
+           android:layout_below="@id/compass_label"
+           android:text=""
+           android:textAppearance="?android:attr/textAppearanceSmall" />
+      </RelativeLayout>
+
+    </LinearLayout>
+
+    <LinearLayout
+       xmlns:android="http://schemas.android.com/apk/res/android"
+       android:layout_width="fill_parent"
+       android:layout_height="wrap_content"
+       android:layout_weight="0"
+       android:baselineAligned="true"
+       android:orientation="horizontal"
+       android:paddingTop="5dp" >
+
+      <RelativeLayout
+         android:layout_width="0dp"
+         android:layout_height="wrap_content"
+         android:layout_weight="1" >
+
+       <TextView
+           android:id="@+id/distance_label"
+           android:layout_width="wrap_content"
+           android:layout_height="wrap_content"
+           android:text="@string/gnd_distance_label" />
+
+       <TextView
+           android:id="@+id/distance_value"
+           android:layout_width="wrap_content"
+           android:layout_height="wrap_content"
+           android:layout_alignParentRight="true"
+           android:layout_below="@id/distance_label"
+           android:text=""
+           android:textAppearance="?android:attr/textAppearanceSmall" />
+      </RelativeLayout>
+
+      <TextView
+         android:layout_width="0dp"
+         android:layout_height="wrap_content"
+         android:layout_weight="1" >
+      </TextView>
+
+    </LinearLayout>
+
+    <RelativeLayout
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content"
+       android:paddingTop="5dp" >
+
+      <TextView
+         android:id="@+id/lat_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text="@string/latitude_label" />
+
+      <TextView
+         android:id="@+id/lat_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_alignParentRight="true"
+         android:layout_below="@id/lat_label"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </RelativeLayout>
+
+    <RelativeLayout
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content"
+       android:paddingTop="5dp" >
+
+      <TextView
+         android:id="@+id/lon_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text="@string/longitude_label" />
+
+      <TextView
+         android:id="@+id/lon_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_alignParentRight="true"
+         android:layout_below="@id/lon_label"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </RelativeLayout>
+
+    <RelativeLayout
+       android:id="@+id/apogee_view"
+       android:visibility="gone"
+       android:layout_gravity="fill"
+       android:layout_weight="1"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content"
+       android:paddingTop="5dp" >
+
+      <ImageView
+         android:id="@+id/apogee_redled"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:contentDescription="@string/apogee_voltage_label"
+         android:src="@drawable/grayled" />
+
+      <ImageView
+         android:id="@+id/apogee_greenled"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_toRightOf="@id/apogee_redled"
+         android:contentDescription="@string/apogee_voltage_label"
+         android:paddingRight="5dp"
+         android:src="@drawable/grayled" />
+
+      <TextView
+         android:id="@+id/apogee_voltage_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_toRightOf="@id/apogee_greenled"
+         android:text="@string/apogee_voltage_label" />
+
+      <TextView
+         android:id="@+id/apogee_voltage_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_alignParentRight="true"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </RelativeLayout>
+
+    <RelativeLayout
+       android:id="@+id/main_view"
+       android:visibility="gone"
+       android:layout_gravity="fill"
+       android:layout_weight="1"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content"
+       android:paddingTop="5dp" >
+
+      <ImageView
+         android:id="@+id/main_redled"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:contentDescription="@string/main_voltage_label"
+         android:src="@drawable/grayled" />
+
+      <ImageView
+         android:id="@+id/main_greenled"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_toRightOf="@id/main_redled"
+         android:contentDescription="@string/main_voltage_label"
+         android:paddingRight="5dp"
+         android:src="@drawable/grayled" />
+
+      <TextView
+         android:id="@+id/main_voltage_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_toRightOf="@id/main_greenled"
+         android:text="@string/main_voltage_label" />
+
+      <TextView
+         android:id="@+id/main_voltage_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_alignParentRight="true"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </RelativeLayout>
+  </LinearLayout>
+</LinearLayout>
diff --git a/altosdroid/app/src/main/res/layout/tab_layout.xml b/altosdroid/app/src/main/res/layout/tab_layout.xml
new file mode 100644 (file)
index 0000000..2c21c64
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/customTabLayout"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <TextView
+        android:id="@+id/tabLabel"
+        android:layout_height="wrap_content"
+        android:layout_width="match_parent"
+        android:textSize="13dp"
+        android:textColor="#ffffff"
+       android:gravity="center_horizontal"
+       android:background="#808080"
+        android:layout_centerVertical="true"
+        android:layout_centerHorizontal="true" />
+</RelativeLayout>
diff --git a/altosdroid/app/src/main/res/layout/tab_map.xml b/altosdroid/app/src/main/res/layout/tab_map.xml
new file mode 100644 (file)
index 0000000..25ae3a8
--- /dev/null
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright © 2013 Mike Beattie <mike@ethernal.org>
+
+     This program is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published by
+     the Free Software Foundation; 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+       android:layout_width="match_parent"
+       android:layout_height="match_parent"
+       android:orientation="vertical" >
+
+  <FrameLayout
+      android:layout_width="fill_parent"
+      android:layout_height="wrap_content"
+      android:baselineAligned="true"
+      android:orientation="horizontal"
+      android:layout_weight="1">
+
+    <LinearLayout
+       android:id="@+id/map_online"
+       android:orientation="horizontal"
+       android:layout_width="fill_parent"
+       android:layout_height="fill_parent"
+       android:layout_weight="1">
+    </LinearLayout>
+
+    <org.altusmetrum.AltosDroid.AltosMapOffline
+       android:id="@+id/map_offline"
+       android:layout_width="fill_parent"
+       android:layout_height="wrap_content"
+       android:layout_weight="1"/>
+  </FrameLayout>
+  
+  <LinearLayout
+      xmlns:android="http://schemas.android.com/apk/res/android"
+      android:layout_width="fill_parent"
+      android:layout_height="wrap_content"
+      android:baselineAligned="true"
+      android:orientation="horizontal" >
+
+    <RelativeLayout
+       android:layout_width="0dp"
+       android:layout_height="wrap_content"
+       android:layout_weight="1"
+       android:paddingTop="5dp" >
+
+      <TextView
+         android:id="@+id/distance_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:paddingRight="4dp"
+         android:text="@string/distance_label" />
+
+      <TextView
+         android:id="@+id/distance_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_toRightOf="@id/distance_label"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </RelativeLayout>
+
+    <RelativeLayout
+       android:layout_width="0dp"
+       android:layout_height="wrap_content"
+       android:layout_weight="1"
+       android:paddingTop="5dp" >
+
+      <TextView
+         android:id="@+id/bearing_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:paddingRight="4dp"
+         android:text="@string/bearing_label" />
+
+      <TextView
+         android:id="@+id/bearing_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_toRightOf="@id/bearing_label"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </RelativeLayout>
+
+  </LinearLayout>
+
+  <LinearLayout
+      xmlns:android="http://schemas.android.com/apk/res/android"
+      android:layout_width="fill_parent"
+      android:layout_height="wrap_content"
+      android:baselineAligned="true"
+      android:orientation="horizontal" >
+
+    <RelativeLayout
+       android:layout_width="0dp"
+       android:layout_height="wrap_content"
+       android:layout_weight="1"
+       android:paddingTop="5dp" >
+
+      <TextView
+         android:id="@+id/target_lat_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:paddingRight="4dp"
+         android:text="@string/target_latitude_label" />
+
+      <TextView
+         android:id="@+id/target_lat_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_toRightOf="@id/target_lat_label"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </RelativeLayout>
+
+    <RelativeLayout
+       android:layout_width="0dp"
+       android:layout_height="wrap_content"
+       android:layout_weight="1"
+       android:paddingTop="5dp" >
+
+      <TextView
+         android:id="@+id/target_lon_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:paddingRight="4dp"
+         android:text="@string/target_longitude_label" />
+
+      <TextView
+         android:id="@+id/target_lon_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_toRightOf="@id/target_lon_label"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </RelativeLayout>
+  </LinearLayout>
+
+  <LinearLayout
+      xmlns:android="http://schemas.android.com/apk/res/android"
+      android:layout_width="fill_parent"
+      android:layout_height="wrap_content"
+      android:baselineAligned="true"
+      android:orientation="horizontal" >
+
+    <RelativeLayout
+       android:layout_width="0dp"
+       android:layout_height="wrap_content"
+       android:layout_weight="1"
+       android:paddingTop="5dp" >
+
+      <TextView
+         android:id="@+id/receiver_lat_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:paddingRight="4dp"
+         android:text="@string/receiver_latitude_label" />
+
+      <TextView
+         android:id="@+id/receiver_lat_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_toRightOf="@id/receiver_lat_label"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </RelativeLayout>
+
+    <RelativeLayout
+       android:layout_width="0dp"
+       android:layout_height="wrap_content"
+       android:layout_weight="1"
+       android:paddingTop="5dp" >
+
+      <TextView
+         android:id="@+id/receiver_lon_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:paddingRight="4dp"
+         android:text="@string/receiver_longitude_label" />
+
+      <TextView
+         android:id="@+id/receiver_lon_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_toRightOf="@id/receiver_lon_label"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </RelativeLayout>
+  </LinearLayout>
+</LinearLayout>
diff --git a/altosdroid/app/src/main/res/layout/tab_pad.xml b/altosdroid/app/src/main/res/layout/tab_pad.xml
new file mode 100644 (file)
index 0000000..990a6be
--- /dev/null
@@ -0,0 +1,496 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright © 2013 Mike Beattie <mike@ethernal.org>
+
+     This program is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published by
+     the Free Software Foundation; 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.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content">
+
+  <TableLayout
+      xmlns:android="http://schemas.android.com/apk/res/android"
+      android:stretchColumns="2,3"
+      android:layout_weight="0"
+      android:layout_width="wrap_content"
+      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">
+      
+      <ImageView
+         android:id="@+id/battery_redled"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:contentDescription="@string/battery_voltage_label"
+         android:src="@drawable/grayled"
+         />
+
+      <ImageView
+         android:id="@+id/battery_greenled"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:contentDescription="@string/battery_voltage_label"
+         android:src="@drawable/grayled" />
+
+      <TextView
+         android:id="@+id/battery_voltage_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text="@string/battery_voltage_label" />
+
+      <TextView
+         android:id="@+id/battery_voltage_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall"
+         />
+    </TableRow>
+
+    <TableRow
+       android:id="@+id/receiver_row"
+       android:visibility="gone"
+       android:layout_gravity="center"
+       android:layout_weight="1"
+       android:padding="2dip"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content">
+
+      <ImageView
+         android:id="@+id/receiver_redled"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:contentDescription="@string/receiver_voltage_label"
+         android:src="@drawable/grayled" />
+
+      <ImageView
+         android:id="@+id/receiver_greenled"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:contentDescription="@string/receiver_voltage_label"
+         android:src="@drawable/grayled" />
+
+      <TextView
+         android:id="@+id/receiver_voltage_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text="@string/receiver_voltage_label" />
+
+      <TextView
+         android:id="@+id/receiver_voltage_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </TableRow>
+
+    <TableRow
+       android:layout_gravity="center"
+       android:layout_weight="1"
+       android:padding="2dip"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content" >
+
+      <ImageView
+         android:id="@+id/logging_redled"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:contentDescription="@string/logging_label"
+         android:src="@drawable/grayled" />
+
+      <ImageView
+         android:id="@+id/logging_greenled"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:contentDescription="@string/logging_label"
+         android:src="@drawable/grayled" />
+
+      <TextView
+         android:id="@+id/logging_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text="@string/logging_label" />
+
+      <TextView
+         android:id="@+id/logging_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_below="@id/logging_label"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </TableRow>
+
+    <TableRow
+       android:layout_gravity="center"
+       android:layout_weight="1"
+       android:padding="2dip"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content" >
+
+      <ImageView
+         android:id="@+id/gps_locked_redled"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:contentDescription="@string/gps_locked_label"
+         android:src="@drawable/grayled" />
+
+      <ImageView
+         android:id="@+id/gps_locked_greenled"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:contentDescription="@string/gps_locked_label"
+         android:src="@drawable/grayled" />
+
+      <TextView
+         android:id="@+id/gps_locked_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text="@string/gps_locked_label" />
+
+      <TextView
+         android:id="@+id/gps_locked_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_below="@id/gps_locked_label"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </TableRow>
+
+    <TableRow
+       android:layout_gravity="center"
+       android:layout_weight="1"
+       android:padding="2dip"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content" >
+
+      <ImageView
+         android:id="@+id/gps_ready_redled"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:contentDescription="@string/gps_ready_label"
+         android:src="@drawable/grayled" />
+
+      <ImageView
+         android:id="@+id/gps_ready_greenled"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:contentDescription="@string/gps_ready_label"
+         android:src="@drawable/grayled" />
+
+      <TextView
+         android:id="@+id/gps_ready_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text="@string/gps_ready_label" />
+
+      <TextView
+         android:id="@+id/gps_ready_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_below="@id/gps_ready_label"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </TableRow>
+
+    <TableRow
+       android:id="@+id/apogee_row"
+       android:visibility="gone"
+       android:layout_gravity="center"
+       android:layout_weight="1"
+       android:padding="2dip"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content">
+
+      <ImageView
+         android:id="@+id/apogee_redled"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:contentDescription="@string/apogee_voltage_label"
+         android:src="@drawable/grayled" />
+
+      <ImageView
+         android:id="@+id/apogee_greenled"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:contentDescription="@string/apogee_voltage_label"
+         android:src="@drawable/grayled" />
+
+      <TextView
+         android:id="@+id/apogee_voltage_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text="@string/apogee_voltage_label" />
+
+      <TextView
+         android:id="@+id/apogee_voltage_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </TableRow>
+
+    <TableRow
+       android:id="@+id/main_row"
+       android:visibility="gone"
+       android:layout_gravity="center"
+       android:layout_weight="1"
+       android:padding="2dip"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content" >
+
+      <ImageView
+         android:id="@+id/main_redled"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:contentDescription="@string/main_voltage_label"
+         android:src="@drawable/grayled" />
+
+      <ImageView
+         android:id="@+id/main_greenled"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:contentDescription="@string/main_voltage_label"
+         android:src="@drawable/grayled" />
+
+      <TextView
+         android:id="@+id/main_voltage_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text="@string/main_voltage_label" />
+
+      <TextView
+         android:id="@+id/main_voltage_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </TableRow>
+
+    <TableRow
+       android:id="@+id/ignite_a_row"
+       android:visibility="gone"
+       android:layout_gravity="center"
+       android:layout_weight="1"
+       android:padding="2dip"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content" >
+
+      <ImageView
+         android:id="@+id/ignite_a_redled"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:contentDescription="@string/ignite_a_voltage_label"
+         android:src="@drawable/grayled" />
+
+      <ImageView
+         android:id="@+id/ignite_a_greenled"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:contentDescription="@string/ignite_a_voltage_label"
+         android:src="@drawable/grayled" />
+
+      <TextView
+         android:id="@+id/ignite_a_voltage_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text="@string/ignite_a_voltage_label" />
+
+      <TextView
+         android:id="@+id/ignite_a_voltage_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </TableRow>
+
+    <TableRow
+       android:id="@+id/ignite_b_row"
+       android:visibility="gone"
+       android:layout_gravity="center"
+       android:layout_weight="1"
+       android:padding="2dip"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content" >
+
+      <ImageView
+         android:id="@+id/ignite_b_redled"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:contentDescription="@string/ignite_b_voltage_label"
+         android:src="@drawable/grayled" />
+
+      <ImageView
+         android:id="@+id/ignite_b_greenled"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:contentDescription="@string/ignite_b_voltage_label"
+         android:src="@drawable/grayled" />
+
+      <TextView
+         android:id="@+id/ignite_b_voltage_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text="@string/ignite_b_voltage_label" />
+
+      <TextView
+         android:id="@+id/ignite_b_voltage_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </TableRow>
+
+    <TableRow
+       android:id="@+id/ignite_c_row"
+       android:visibility="gone"
+       android:layout_gravity="center"
+       android:layout_weight="1"
+       android:padding="2dip"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content" >
+
+      <ImageView
+         android:id="@+id/ignite_c_redled"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:contentDescription="@string/ignite_c_voltage_label"
+         android:src="@drawable/grayled" />
+
+      <ImageView
+         android:id="@+id/ignite_c_greenled"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:contentDescription="@string/ignite_c_voltage_label"
+         android:src="@drawable/grayled" />
+
+      <TextView
+         android:id="@+id/ignite_c_voltage_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text="@string/ignite_c_voltage_label" />
+
+      <TextView
+         android:id="@+id/ignite_c_voltage_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </TableRow>
+
+    <TableRow
+       android:id="@+id/ignite_d_row"
+       android:visibility="gone"
+       android:layout_gravity="center"
+       android:layout_weight="1"
+       android:padding="2dip"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content" >
+
+      <ImageView
+         android:id="@+id/ignite_d_redled"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:contentDescription="@string/ignite_d_voltage_label"
+         android:src="@drawable/grayled" />
+
+      <ImageView
+         android:id="@+id/ignite_d_greenled"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:contentDescription="@string/ignite_d_voltage_label"
+         android:src="@drawable/grayled" />
+
+      <TextView
+         android:id="@+id/ignite_d_voltage_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text="@string/ignite_d_voltage_label" />
+
+      <TextView
+         android:id="@+id/ignite_d_voltage_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </TableRow>
+
+    <TableRow
+       android:padding="2dip"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content">
+
+      <TextView
+         android:id="@+id/receiver_lat_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_column="2"
+         android:text="@string/receiver_latitude_label" />
+
+      <TextView
+         android:id="@+id/receiver_lat_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </TableRow>
+
+    <TableRow
+       android:padding="2dip"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content">
+
+      <TextView
+         android:id="@+id/receiver_lon_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_column="2"
+         android:text="@string/receiver_longitude_label" />
+
+      <TextView
+         android:id="@+id/receiver_lon_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </TableRow>
+
+    <TableRow
+       android:padding="2dip"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content">
+
+      <TextView
+         android:id="@+id/receiver_alt_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_column="2"
+         android:text="@string/receiver_altitude_label" />
+
+      <TextView
+         android:id="@+id/receiver_alt_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </TableRow>
+  </TableLayout>
+</LinearLayout>
diff --git a/altosdroid/app/src/main/res/layout/tab_recover.xml b/altosdroid/app/src/main/res/layout/tab_recover.xml
new file mode 100644 (file)
index 0000000..7d1e750
--- /dev/null
@@ -0,0 +1,252 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright © 2013 Mike Beattie <mike@ethernal.org>
+
+     This program is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published by
+     the Free Software Foundation; 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.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical" >
+
+  <LinearLayout
+      xmlns:android="http://schemas.android.com/apk/res/android"
+      android:layout_weight="0"
+      android:layout_width="fill_parent"
+      android:layout_height="wrap_content"
+      android:orientation="vertical" >
+
+    <RelativeLayout
+       android:layout_gravity="fill"
+       android:layout_weight="1"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content" >
+
+      <TextView
+         android:id="@+id/bearing_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text="@string/bearing_label" />
+
+      <TextView
+         android:id="@+id/bearing_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_alignParentRight="true"
+         android:layout_below="@+id/bearing_label"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </RelativeLayout>
+
+    <RelativeLayout
+       android:layout_gravity="fill"
+       android:layout_weight="1"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content" >
+
+      <TextView
+         android:id="@+id/direction_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text="@string/direction_label" />
+
+      <TextView
+         android:id="@+id/direction_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_alignParentRight="true"
+         android:layout_below="@+id/direction_label"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </RelativeLayout>
+
+    <RelativeLayout
+       android:layout_gravity="fill"
+       android:layout_weight="1"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content">
+
+      <TextView
+         android:id="@+id/distance_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text="@string/distance_label" />
+
+      <TextView
+         android:id="@+id/distance_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_alignParentRight="true"
+         android:layout_below="@+id/distance_label"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </RelativeLayout>
+
+    <RelativeLayout
+       android:layout_gravity="fill"
+       android:layout_weight="1"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content">
+
+      <TextView
+         android:id="@+id/target_lat_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text="@string/target_latitude_label" />
+
+      <TextView
+         android:id="@+id/target_lat_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_alignParentRight="true"
+         android:layout_below="@id/target_lat_label"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </RelativeLayout>
+
+    <RelativeLayout
+       android:layout_gravity="fill"
+       android:layout_weight="1"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content">
+
+      <TextView
+         android:id="@+id/target_lon_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text="@string/target_longitude_label" />
+
+      <TextView
+         android:id="@+id/target_lon_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_alignParentRight="true"
+         android:layout_below="@id/target_lon_label"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </RelativeLayout>
+
+    <RelativeLayout
+       android:layout_gravity="fill"
+       android:layout_weight="1"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content">
+
+      <TextView
+         android:id="@+id/receiver_lat_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text="@string/receiver_latitude_label" />
+
+      <TextView
+         android:id="@+id/receiver_lat_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_alignParentRight="true"
+         android:layout_below="@id/receiver_lat_label"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </RelativeLayout>
+
+    <RelativeLayout
+       android:layout_gravity="fill"
+       android:layout_weight="1"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content">
+
+      <TextView
+         android:id="@+id/receiver_lon_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text="@string/receiver_longitude_label" />
+
+      <TextView
+         android:id="@+id/receiver_lon_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_alignParentRight="true"
+         android:layout_below="@id/receiver_lon_label"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </RelativeLayout>
+
+    <RelativeLayout
+       android:layout_gravity="fill"
+       android:layout_weight="1"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content">
+
+      <TextView
+         android:id="@+id/max_height_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text="@string/max_height_label" />
+
+      <TextView
+         android:id="@+id/max_height_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_alignParentRight="true"
+         android:layout_below="@id/max_height_label"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </RelativeLayout>
+
+    <RelativeLayout
+       android:layout_gravity="fill"
+       android:layout_weight="1"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content">
+
+      <TextView
+         android:id="@+id/max_speed_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text="@string/max_speed_label" />
+
+      <TextView
+         android:id="@+id/max_speed_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_alignParentRight="true"
+         android:layout_below="@id/max_speed_label"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </RelativeLayout>
+
+    <RelativeLayout
+       android:layout_gravity="fill"
+       android:layout_weight="1"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content">
+
+      <TextView
+         android:id="@+id/max_accel_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text="@string/max_accel_label" />
+
+      <TextView
+         android:id="@+id/max_accel_value"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_alignParentRight="true"
+         android:layout_below="@id/max_accel_label"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </RelativeLayout>
+  </LinearLayout>
+</LinearLayout>
diff --git a/altosdroid/app/src/main/res/menu/option_menu.xml b/altosdroid/app/src/main/res/menu/option_menu.xml
new file mode 100644 (file)
index 0000000..53a0de0
--- /dev/null
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 
+  Copyright © 2015 Keith Packard <keithp@keithp.com>
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/connect_scan"
+          android:icon="@android:drawable/ic_menu_search"
+          android:title="@string/connect_device" />
+    <item android:id="@+id/disconnect"
+         android:icon="@android:drawable/ic_notification_clear_all"
+         android:title="@string/disconnect_device" />
+    <item android:id="@+id/select_freq"
+          android:icon="@android:drawable/ic_menu_preferences"
+          android:title="@string/select_freq" />
+
+    <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" />
+</menu>
diff --git a/altosdroid/app/src/main/res/values/Colors.xml b/altosdroid/app/src/main/res/values/Colors.xml
new file mode 100644 (file)
index 0000000..8dddae2
--- /dev/null
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+        Copyright © 2015 Keith Packard <keithp@keithp.com>
+
+        This program is free software; you can redistribute it and/or modify
+        it under the terms of the GNU General Public License as published by
+        the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+        This program is distributed in the hope that it will be useful, but
+        WITHOUT ANY WARRANTY; without even the implied warranty of
+        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+        General Public License for more details.
+
+        You should have received a copy of the GNU General Public License along
+        with this program; if not, write to the Free Software Foundation, Inc.,
+        59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+-->
+<resources>
+  <color name="old_color">#ffff4040</color>
+</resources>
diff --git a/altosdroid/app/src/main/res/values/CustomTheme.xml b/altosdroid/app/src/main/res/values/CustomTheme.xml
new file mode 100644 (file)
index 0000000..4358096
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<resources>
+  <style name="CustomTheme" parent="android:Theme.Material.Light">
+  </style>
+</resources>
diff --git a/altosdroid/app/src/main/res/values/strings.xml b/altosdroid/app/src/main/res/values/strings.xml
new file mode 100644 (file)
index 0000000..55dc845
--- /dev/null
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+        Copyright © 2012-2013 Mike Beattie <mike@ethernal.org>
+
+        This program is free software; you can redistribute it and/or modify
+        it under the terms of the GNU General Public License as published by
+        the Free Software Foundation; 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.
+-->
+<resources>
+
+       <string name="app_name">AltosDroid</string>
+
+       <!-- AltosDroid -->
+       <string name="bt_not_enabled">Bluetooth was not enabled.</string>
+       <string name="title_connecting">connecting…</string>
+       <string name="title_connected_to">connected</string>
+       <string name="title_not_connected">not connected</string>
+
+       <!-- Options Menu -->
+       <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_maps">Load Maps</string>
+       <string name="select_tracker">Select Tracker</string>
+       <string name="delete_track">Delete Track</string>
+       <string name="map_type">Map Type</string>
+       <string name="map_source">Toggle Online/Offline maps</string>
+
+       <!-- MapTypeActivity -->
+       <!-- <string name="map_type">Map Type</string> -->
+
+       <!-- DeviceListActivity -->
+       <string name="scanning">scanning for devices…</string>
+       <string name="select_device">select a device to connect</string>
+       <string name="none_paired">No devices have been paired</string>
+       <string name="none_found">No devices found</string>
+       <string name="title_paired_devices">Paired Devices</string>
+       <string name="title_other_devices">Other Available Devices</string>
+       <string name="button_scan">Scan for devices</string>
+
+       <!-- Service -->
+       <string name="telemetry_service_label">AltosDroid Telemetry Service</string>
+       <string name="telemetry_service_started">Telemetry Service Started</string>
+       <string name="telemetry_service_stopped">Telemetry Service Stopped</string>
+
+       <!-- UI fields -->
+       <!-- Header -->
+       <string name="callsign_label">Callsign</string>
+       <string name="serial_label">Serial</string>
+       <string name="flight_label">Flight</string>
+       <string name="state_label">State</string>
+       <string name="rssi_label">RSSI</string>
+       <string name="age_label">Age</string>
+
+       <!-- Tab fields -->
+       <string name="height_label">Height</string>
+       <string name="speed_label">Speed</string>
+       <string name="accel_label">Acceleration</string>
+       <string name="bearing_label">Bearing</string>
+       <string name="direction_label">Direction</string>
+       <string name="elevation_label">Elevation</string>
+       <string name="range_label">Range</string>
+       <string name="distance_label">Distance</string>
+       <string name="gnd_distance_label">Ground Distance</string>
+       <string name="max_height_label">Max Height</string>
+       <string name="max_speed_label">Max Speed</string>
+       <string name="max_accel_label">Max Accel</string>
+       <string name="battery_voltage_label">Battery</string>
+       <string name="receiver_voltage_label">Receiver Battery</string>
+       <string name="apogee_voltage_label">Apogee Igniter</string>
+       <string name="main_voltage_label">Main Igniter</string>
+       <string name="ignite_a_voltage_label">Igniter A</string>
+       <string name="ignite_b_voltage_label">Igniter B</string>
+       <string name="ignite_c_voltage_label">Igniter C</string>
+       <string name="ignite_d_voltage_label">Igniter D</string>
+       <string name="logging_label">Data Logging</string>
+       <string name="gps_locked_label">GPS Locked</string>
+       <string name="gps_ready_label">GPS Ready</string>
+       <string name="latitude_label">Latitude</string>
+       <string name="longitude_label">Longitude</string>
+       <string name="target_latitude_label">Tar Lat</string>
+       <string name="target_longitude_label">Tar Lon</string>
+       <string name="receiver_latitude_label">My Lat</string>
+       <string name="receiver_longitude_label">My Lon</string>
+       <string name="receiver_altitude_label">My Alt</string>
+
+       <!-- Map preload -->
+       <string name="preload_site_label">Known Launch Sites</string>
+       <string name="preload_latitude_label">Latitude</string>
+       <string name="preload_longitude_label">Longitude</string>
+
+       <string name="preload_types">Map Types</string>
+       <string name="preload_hybrid">Hybrid</string>
+       <string name="preload_satellite">Satellite</string>
+       <string name="preload_roadmap">Roadmap</string>
+       <string name="preload_terrain">Terrain</string>
+       <string name="preload_min_zoom">Minimum Zoom</string>
+       <string name="preload_max_zoom">Maximum Zoom</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>
diff --git a/altosdroid/app/src/main/res/xml/device_filter.xml b/altosdroid/app/src/main/res/xml/device_filter.xml
new file mode 100644 (file)
index 0000000..84b09c0
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<resources>
+  <usb-device vendor-id="65534" />
+  <usb-device vendor-id="1027" />
+</resources>
diff --git a/altosdroid/build.gradle b/altosdroid/build.gradle
new file mode 100644 (file)
index 0000000..ff1d838
--- /dev/null
@@ -0,0 +1,27 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+    repositories {
+        google()
+        jcenter()
+    }
+    dependencies {
+        classpath 'com.android.tools.build:gradle:3.4.2'
+        // NOTE: Do not place your application dependencies here; they belong
+        // in the individual module build.gradle files
+    }
+}
+
+allprojects {
+    repositories {
+        google()
+        jcenter()
+    }
+    tasks.withType(JavaCompile) {
+        options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
+    }
+}
+
+task clean(type: Delete) {
+    delete rootProject.buildDir
+}
diff --git a/altosdroid/build.xml b/altosdroid/build.xml
deleted file mode 100644 (file)
index 6a89edb..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project name="AltosDroid" default="help">
-
-    <!-- The local.properties file is created and updated by the 'android' tool.
-         It contains the path to the SDK. It should *NOT* be checked into
-         Version Control Systems. -->
-    <property file="local.properties" />
-
-    <!-- The ant.properties file can be created by you. It is only edited by the
-         'android' tool to add properties to it.
-         This is the place to change some Ant specific build properties.
-         Here are some properties you may want to change/update:
-
-         source.dir
-             The name of the source directory. Default is 'src'.
-         out.dir
-             The name of the output directory. Default is 'bin'.
-
-         For other overridable properties, look at the beginning of the rules
-         files in the SDK, at tools/ant/build.xml
-
-         Properties related to the SDK location or the project target should
-         be updated using the 'android' tool with the 'update' action.
-
-         This file is an integral part of the build system for your
-         application and should be checked into Version Control Systems.
-
-         -->
-    <property file="ant.properties" />
-
-    <!-- The project.properties file is created and updated by the 'android'
-         tool, as well as ADT.
-
-         This contains project specific properties such as project target, and library
-         dependencies. Lower level build properties are stored in ant.properties
-         (or in .classpath for Eclipse projects).
-
-         This file is an integral part of the build system for your
-         application and should be checked into Version Control Systems. -->
-    <loadproperties srcFile="project.properties" />
-
-    <!-- quick check on sdk.dir -->
-    <fail
-            message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through an env var"
-            unless="sdk.dir"
-    />
-
-
-<!-- extension targets. Uncomment the ones where you want to do custom work
-     in between standard targets -->
-<!--
-    <target name="-pre-build">
-    </target>
-    <target name="-pre-compile">
-    </target>
-
-    /* This is typically used for code obfuscation.
-       Compiled code location: ${out.classes.absolute.dir}
-       If this is not done in place, override ${out.dex.input.absolute.dir} */
-    <target name="-post-compile">
-    </target>
--->
-
-    <!-- Import the actual build file.
-
-         To customize existing targets, there are two options:
-         - Customize only one target:
-             - copy/paste the target into this file, *before* the
-               <import> task.
-             - customize it to your needs.
-         - Customize the whole content of build.xml
-             - copy/paste the content of the rules files (minus the top node)
-               into this file, replacing the <import> task.
-             - customize to your needs.
-
-         ***********************
-         ****** IMPORTANT ******
-         ***********************
-         In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
-         in order to avoid having your file be overridden by tools such as "android update project"
-    -->
-    <!-- version-tag: 1 -->
-    <import file="${sdk.dir}/tools/ant/build.xml" />
-
-</project>
index ac97b7bd83b804fe18cfed7eecb8d106afb2307f..1b446b42f31910f35b35e6e121a165a9149ef2a0 100755 (executable)
@@ -7,10 +7,11 @@
 # version and build information, primarily).
 #
 
-infile=src/org/altusmetrum/AltosDroid/BuildInfo.java.in
-outfile=src/org/altusmetrum/AltosDroid/BuildInfo.java
+srcdir=app/src/main/java/org/altusmetrum/AltosDroid
+infile=${srcdir}/BuildInfo.java.in
+outfile=${srcdir}/BuildInfo.java
 
-. ../src/Version
+. ../src/Makedefs
 version=$VERSION
 branch=''
 commitnum=''
diff --git a/altosdroid/default.properties b/altosdroid/default.properties
deleted file mode 100644 (file)
index 3ac2523..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-# This file is automatically generated by Android Tools.
-# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
-#
-# This file must be checked in Version Control Systems.
-#
-# To customize properties used by the Ant build system use,
-# "build.properties", and override values to adapt the script to your
-# project structure.
-
-# Project target.
-target=android-12
diff --git a/altosdroid/gradle.properties b/altosdroid/gradle.properties
new file mode 100644 (file)
index 0000000..9e6fce1
--- /dev/null
@@ -0,0 +1,19 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+android.enableJetifier=true
+android.useAndroidX=true
+org.gradle.jvmargs=-Xmx1536m
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
diff --git a/altosdroid/gradle/wrapper/gradle-wrapper.jar b/altosdroid/gradle/wrapper/gradle-wrapper.jar
new file mode 100644 (file)
index 0000000..87b738c
Binary files /dev/null and b/altosdroid/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/altosdroid/gradle/wrapper/gradle-wrapper.properties b/altosdroid/gradle/wrapper/gradle-wrapper.properties
new file mode 100644 (file)
index 0000000..0c3026a
--- /dev/null
@@ -0,0 +1,6 @@
+#Thu Aug 29 13:53:38 NZST 2019
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
diff --git a/altosdroid/gradlew b/altosdroid/gradlew
new file mode 100755 (executable)
index 0000000..af6708f
--- /dev/null
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+    echo "$*"
+}
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Escape application args
+save () {
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+    echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+  cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/altosdroid/gradlew.bat b/altosdroid/gradlew.bat
new file mode 100644 (file)
index 0000000..0f8d593
--- /dev/null
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off\r
+@rem ##########################################################################\r
+@rem\r
+@rem  Gradle startup script for Windows\r
+@rem\r
+@rem ##########################################################################\r
+\r
+@rem Set local scope for the variables with windows NT shell\r
+if "%OS%"=="Windows_NT" setlocal\r
+\r
+set DIRNAME=%~dp0\r
+if "%DIRNAME%" == "" set DIRNAME=.\r
+set APP_BASE_NAME=%~n0\r
+set APP_HOME=%DIRNAME%\r
+\r
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r
+set DEFAULT_JVM_OPTS="-Xmx64m"\r
+\r
+@rem Find java.exe\r
+if defined JAVA_HOME goto findJavaFromJavaHome\r
+\r
+set JAVA_EXE=java.exe\r
+%JAVA_EXE% -version >NUL 2>&1\r
+if "%ERRORLEVEL%" == "0" goto init\r
+\r
+echo.\r
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r
+echo.\r
+echo Please set the JAVA_HOME variable in your environment to match the\r
+echo location of your Java installation.\r
+\r
+goto fail\r
+\r
+:findJavaFromJavaHome\r
+set JAVA_HOME=%JAVA_HOME:"=%\r
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe\r
+\r
+if exist "%JAVA_EXE%" goto init\r
+\r
+echo.\r
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r
+echo.\r
+echo Please set the JAVA_HOME variable in your environment to match the\r
+echo location of your Java installation.\r
+\r
+goto fail\r
+\r
+:init\r
+@rem Get command-line arguments, handling Windows variants\r
+\r
+if not "%OS%" == "Windows_NT" goto win9xME_args\r
+\r
+:win9xME_args\r
+@rem Slurp the command line arguments.\r
+set CMD_LINE_ARGS=\r
+set _SKIP=2\r
+\r
+:win9xME_args_slurp\r
+if "x%~1" == "x" goto execute\r
+\r
+set CMD_LINE_ARGS=%*\r
+\r
+:execute\r
+@rem Setup the command line\r
+\r
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar\r
+\r
+@rem Execute Gradle\r
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\r
+\r
+:end\r
+@rem End local scope for the variables with windows NT shell\r
+if "%ERRORLEVEL%"=="0" goto mainEnd\r
+\r
+:fail\r
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r
+rem the _cmd.exe /c_ return code!\r
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1\r
+exit /b 1\r
+\r
+:mainEnd\r
+if "%OS%"=="Windows_NT" endlocal\r
+\r
+:omega\r
diff --git a/altosdroid/keystore b/altosdroid/keystore
deleted file mode 100644 (file)
index 00739d0..0000000
Binary files a/altosdroid/keystore and /dev/null differ
diff --git a/altosdroid/project.properties b/altosdroid/project.properties
deleted file mode 100644 (file)
index d178f98..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-# This file is automatically generated by Android Tools.
-# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
-#
-# This file must be checked in Version Control Systems.
-#
-# To customize properties used by the Ant build system use,
-# "ant.properties", and override values to adapt the script to your
-# project structure.
-
-# Project target.
-target=android-12
-android.library.reference.1=google-play-services_lib/
diff --git a/altosdroid/release.keystore b/altosdroid/release.keystore
deleted file mode 100644 (file)
index 53607dc..0000000
Binary files a/altosdroid/release.keystore and /dev/null differ
diff --git a/altosdroid/res/drawable-hdpi/am_status_c.png b/altosdroid/res/drawable-hdpi/am_status_c.png
deleted file mode 100644 (file)
index d439321..0000000
Binary files a/altosdroid/res/drawable-hdpi/am_status_c.png and /dev/null differ
diff --git a/altosdroid/res/drawable-hdpi/am_status_g.png b/altosdroid/res/drawable-hdpi/am_status_g.png
deleted file mode 100644 (file)
index 03f9dd7..0000000
Binary files a/altosdroid/res/drawable-hdpi/am_status_g.png and /dev/null differ
diff --git a/altosdroid/res/drawable-hdpi/app_icon.png b/altosdroid/res/drawable-hdpi/app_icon.png
deleted file mode 100644 (file)
index da2f08a..0000000
Binary files a/altosdroid/res/drawable-hdpi/app_icon.png and /dev/null differ
diff --git a/altosdroid/res/drawable-hdpi/ic_maps_indicator_current_position.png b/altosdroid/res/drawable-hdpi/ic_maps_indicator_current_position.png
deleted file mode 100644 (file)
index bc9160d..0000000
Binary files a/altosdroid/res/drawable-hdpi/ic_maps_indicator_current_position.png and /dev/null differ
diff --git a/altosdroid/res/drawable-mdpi/am_status_c.png b/altosdroid/res/drawable-mdpi/am_status_c.png
deleted file mode 100644 (file)
index 30a8d29..0000000
Binary files a/altosdroid/res/drawable-mdpi/am_status_c.png and /dev/null differ
diff --git a/altosdroid/res/drawable-mdpi/am_status_g.png b/altosdroid/res/drawable-mdpi/am_status_g.png
deleted file mode 100644 (file)
index 07f7f07..0000000
Binary files a/altosdroid/res/drawable-mdpi/am_status_g.png and /dev/null differ
diff --git a/altosdroid/res/drawable-mdpi/ic_maps_indicator_current_position.png b/altosdroid/res/drawable-mdpi/ic_maps_indicator_current_position.png
deleted file mode 100644 (file)
index 4e427d8..0000000
Binary files a/altosdroid/res/drawable-mdpi/ic_maps_indicator_current_position.png and /dev/null differ
diff --git a/altosdroid/res/drawable/app_icon.png b/altosdroid/res/drawable/app_icon.png
deleted file mode 100644 (file)
index b0a3c9c..0000000
Binary files a/altosdroid/res/drawable/app_icon.png and /dev/null differ
diff --git a/altosdroid/res/drawable/pad.png b/altosdroid/res/drawable/pad.png
deleted file mode 100644 (file)
index b2e65c8..0000000
Binary files a/altosdroid/res/drawable/pad.png and /dev/null differ
diff --git a/altosdroid/res/drawable/rocket.png b/altosdroid/res/drawable/rocket.png
deleted file mode 100644 (file)
index 7e62f6c..0000000
Binary files a/altosdroid/res/drawable/rocket.png and /dev/null differ
diff --git a/altosdroid/res/layout/altosdroid.xml b/altosdroid/res/layout/altosdroid.xml
deleted file mode 100644 (file)
index df87067..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-
- Copyright © 2012-2013 Mike Beattie <mike@ethernal.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; 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.
-
--->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-       android:layout_width="fill_parent"
-       android:layout_height="wrap_content"
-       android:layout_weight="0"
-       android:orientation="vertical" >
-
-       <LinearLayout
-               xmlns:android="http://schemas.android.com/apk/res/android"
-               android:layout_width="fill_parent"
-               android:layout_height="wrap_content"
-               android:layout_weight="0"
-               android:baselineAligned="true"
-               android:orientation="horizontal" >
-
-               <RelativeLayout
-                       android:id="@+id/callsign_container"
-                       android:layout_width="0dp"
-                       android:layout_height="wrap_content"
-                       android:layout_weight="1" >
-
-                       <TextView
-                               android:id="@+id/callsign_label"
-                               android:layout_width="wrap_content"
-                               android:layout_height="wrap_content"
-                               android:text="@string/callsign_label" />
-
-                       <TextView
-                               android:id="@+id/callsign_value"
-                               android:layout_width="wrap_content"
-                               android:layout_height="wrap_content"
-                               android:layout_below="@+id/callsign_label"
-                               android:text=""
-                               android:textAppearance="?android:attr/textAppearanceSmall" />
-               </RelativeLayout>
-
-               <RelativeLayout
-                       android:id="@+id/serial_container"
-                       android:layout_width="0dp"
-                       android:layout_height="wrap_content"
-                       android:layout_weight="1" >
-
-                       <TextView
-                               android:id="@+id/serial_label"
-                               android:layout_width="wrap_content"
-                               android:layout_height="wrap_content"
-                               android:text="@string/serial_label" />
-
-                       <TextView
-                               android:id="@+id/serial_value"
-                               android:layout_width="wrap_content"
-                               android:layout_height="wrap_content"
-                               android:layout_below="@+id/serial_label"
-                               android:textAppearance="?android:attr/textAppearanceSmall" />
-               </RelativeLayout>
-
-               <RelativeLayout
-                       android:id="@+id/flight_container"
-                       android:layout_width="0dp"
-                       android:layout_height="wrap_content"
-                       android:layout_weight="1" >
-
-                       <TextView
-                               android:id="@+id/flight_label"
-                               android:layout_width="wrap_content"
-                               android:layout_height="wrap_content"
-                               android:text="@string/flight_label" />
-
-                       <TextView
-                               android:id="@+id/flight_value"
-                               android:layout_width="wrap_content"
-                               android:layout_height="wrap_content"
-                               android:layout_below="@+id/flight_label"
-                               android:textAppearance="?android:attr/textAppearanceSmall" />
-               </RelativeLayout>
-
-               <RelativeLayout
-                       android:id="@+id/state_container"
-                       android:layout_width="0dp"
-                       android:layout_height="wrap_content"
-                       android:layout_weight="1" >
-
-                       <TextView
-                               android:id="@+id/state_label"
-                               android:layout_width="wrap_content"
-                               android:layout_height="wrap_content"
-                               android:text="@string/state_label" />
-
-                       <TextView
-                               android:id="@+id/state_value"
-                               android:layout_width="wrap_content"
-                               android:layout_height="wrap_content"
-                               android:layout_below="@+id/state_label"
-                               android:textAppearance="?android:attr/textAppearanceSmall" />
-               </RelativeLayout>
-
-               <RelativeLayout
-                       android:id="@+id/rssi_container"
-                       android:layout_width="0dp"
-                       android:layout_height="wrap_content"
-                       android:layout_weight="1" >
-
-                       <TextView
-                               android:id="@+id/rssi_label"
-                               android:layout_width="wrap_content"
-                               android:layout_height="wrap_content"
-                               android:text="@string/rssi_label" />
-
-                       <TextView
-                               android:id="@+id/rssi_value"
-                               android:layout_width="wrap_content"
-                               android:layout_height="wrap_content"
-                               android:layout_below="@+id/rssi_label"
-                               android:textAppearance="?android:attr/textAppearanceSmall" />
-               </RelativeLayout>
-
-               <RelativeLayout
-                       android:id="@+id/age_container"
-                       android:layout_width="0dp"
-                       android:layout_height="wrap_content"
-                       android:layout_weight="1" >
-
-                       <TextView
-                               android:id="@+id/age_label"
-                               android:layout_width="wrap_content"
-                               android:layout_height="wrap_content"
-                               android:text="@string/age_label" />
-
-                       <TextView
-                               android:id="@+id/age_value"
-                               android:layout_width="wrap_content"
-                               android:layout_height="wrap_content"
-                               android:layout_below="@+id/age_label"
-                               android:textAppearance="?android:attr/textAppearanceSmall" />
-               </RelativeLayout>
-       </LinearLayout>
-
-       <TabHost
-               xmlns:android="http://schemas.android.com/apk/res/android"
-               android:id="@android:id/tabhost"
-               android:layout_width="fill_parent"
-               android:layout_height="0dp"
-               android:layout_weight="1" >
-
-               <LinearLayout
-                       android:layout_width="match_parent"
-                       android:layout_height="match_parent"
-                       android:orientation="vertical" >
-
-                       <TabWidget
-                               android:id="@android:id/tabs"
-                               android:layout_width="match_parent"
-                               android:layout_height="wrap_content"
-                               android:layout_weight="0"
-                               android:orientation="horizontal" />
-
-                       <FrameLayout
-                               android:id="@android:id/tabcontent"
-                               android:layout_width="0dp"
-                               android:layout_height="0dp"
-                               android:layout_weight="0" />
-
-                       <org.altusmetrum.AltosDroid.AltosViewPager
-                               android:id="@+id/pager"
-                               android:layout_width="match_parent"
-                               android:layout_height="0dp"
-                               android:layout_weight="1" />
-               </LinearLayout>
-       </TabHost>
-
-       <TextView
-               android:id="@+id/version"
-               android:layout_width="fill_parent"
-               android:layout_height="10dip"
-               android:layout_weight="0"
-               android:gravity="bottom|right"
-               android:textSize="7sp"
-               android:typeface="monospace" />
-
-</LinearLayout>
diff --git a/altosdroid/res/layout/custom_title.xml b/altosdroid/res/layout/custom_title.xml
deleted file mode 100644 (file)
index 57eb6b4..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-<?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
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     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.
--->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:gravity="center_vertical"
-  >
-  <TextView android:id="@+id/title_left_text"
-      android:layout_alignParentLeft="true"
-      android:ellipsize="end"
-      android:singleLine="true"
-      style="?android:attr/windowTitleStyle"
-      android:layout_width="wrap_content"
-      android:layout_height="match_parent"
-      android:layout_weight="1"
-    />
-    <TextView android:id="@+id/title_right_text"
-        android:layout_alignParentRight="true"
-        android:ellipsize="end"
-        android:singleLine="true"
-        android:layout_width="wrap_content"
-        android:layout_height="match_parent"
-        android:textColor="#fff"
-        android:layout_weight="1" 
-    />
-</RelativeLayout>
\ No newline at end of file
diff --git a/altosdroid/res/layout/device_list.xml b/altosdroid/res/layout/device_list.xml
deleted file mode 100644 (file)
index 0c103e9..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-<?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; 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.
-
--->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    >
-    <Button android:id="@+id/button_scan"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:text="@string/button_scan"
-    />
-    <TextView android:id="@+id/title_new_devices"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:text="@string/title_other_devices"
-        android:visibility="gone"
-        android:background="#666"
-        android:textColor="#fff"
-        android:paddingLeft="5dp"
-    />
-    <ListView android:id="@+id/new_devices"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_weight="1"
-       android:fadeScrollbars="false"
-       android:scrollbars="vertical"
-    />
-    <TextView android:id="@+id/title_paired_devices"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:text="@string/title_paired_devices"
-        android:visibility="gone"
-        android:background="#666"
-        android:textColor="#fff"
-        android:paddingLeft="5dp"
-    />
-    <ListView android:id="@+id/paired_devices"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_weight="1"
-       android:fadeScrollbars="false"
-       android:scrollbars="vertical"
-    />
-</LinearLayout>
diff --git a/altosdroid/res/layout/device_name.xml b/altosdroid/res/layout/device_name.xml
deleted file mode 100644 (file)
index 8fa358c..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-<?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
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     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.
--->
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:textSize="18sp"
-    android:padding="5dp"
-/>
\ No newline at end of file
diff --git a/altosdroid/res/layout/frequency.xml b/altosdroid/res/layout/frequency.xml
deleted file mode 100644 (file)
index 7adbdc1..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-<?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; 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.
-
--->
-<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
deleted file mode 100644 (file)
index 6c598c1..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-<?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; 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.
-
--->
-<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
deleted file mode 100644 (file)
index 931ad62..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-<?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; 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.
-
--->
-<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
deleted file mode 100644 (file)
index 6ce5b24..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-<?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; 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.
-
--->
-<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
deleted file mode 100644 (file)
index afb3310..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-<?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; 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.
-
--->
-<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/map_preload.xml b/altosdroid/res/layout/map_preload.xml
deleted file mode 100644 (file)
index 4e60df2..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright © 2015 Keith Packard <keithp@keithp.com>
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public License along
-  with this program; if not, write to the Free Software Foundation, Inc.,
-  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
--->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    >
-  <ScrollView android:layout_width="fill_parent"
-             android:layout_height="wrap_content">
-    <LinearLayout android:layout_width="wrap_content"
-                 android:layout_height="wrap_content"
-                  android:orientation="vertical">
-      <TextView android:id="@+id/preload_site_label"
-               android:layout_width="fill_parent"
-               android:layout_height="wrap_content"
-               android:text="@string/preload_site_label"
-               />
-      <Spinner android:id="@+id/preload_site_list"
-              android:layout_width="fill_parent"
-              android:layout_height="wrap_content"
-              android:prompt="@string/preload_site_label"
-              android:spinnerMode="dropdown"
-              />
-      <TextView android:id="@+id/preload_latitude_label"
-               android:layout_width="fill_parent"
-               android:layout_height="wrap_content"
-               android:text="@string/preload_latitude_label"
-               />
-      <EditText android:id="@+id/preload_latitude"
-               android:layout_width="fill_parent"
-               android:layout_height="wrap_content"
-               android:hint="@string/preload_latitude_label"
-               android:inputType="number|numberSigned|numberDecimal"/>
-      <TextView android:id="@+id/preload_longitude_label"
-               android:layout_width="fill_parent"
-               android:layout_height="wrap_content"
-               android:text="@string/preload_longitude_label"
-               />
-      <EditText android:id="@+id/preload_longitude"
-               android:layout_width="fill_parent"
-               android:layout_height="wrap_content"
-               android:hint="@string/preload_longitude_label"
-               android:inputType="number|numberSigned|numberDecimal"/>
-      <TextView android:id="@+id/preload_types"
-               android:layout_width="fill_parent"
-               android:layout_height="wrap_content"
-               android:text="@string/preload_types"
-               />
-<!--
-      <CheckBox android:id="@+id/preload_hybrid"
-               android:layout_width="fill_parent"
-               android:layout_height="wrap_content"
-               android:text="@string/preload_hybrid"
-               />
-      <CheckBox android:id="@+id/preload_satellite"
-               android:layout_width="fill_parent"
-               android:layout_height="wrap_content"
-               android:text="@string/preload_satellite"
-               />
-      <CheckBox android:id="@+id/preload_roadmap"
-               android:layout_width="fill_parent"
-               android:layout_height="wrap_content"
-               android:text="@string/preload_roadmap"
-               />
-      <CheckBox android:id="@+id/preload_terrain"
-               android:layout_width="fill_parent"
-               android:layout_height="wrap_content"
-               android:text="@string/preload_terrain"
-               />
--->
-      <TextView android:id="@+id/preload_min_zoom_label"
-               android:layout_width="fill_parent"
-               android:layout_height="wrap_content"
-               android:text="@string/preload_min_zoom"
-               />
-      <Spinner android:id="@+id/preload_min_zoom"
-              android:layout_width="fill_parent"
-              android:layout_height="wrap_content"
-              android:prompt="@string/preload_min_zoom"
-              android:spinnerMode="dropdown"
-              />
-      <TextView android:id="@+id/preload_max_zoom_label"
-               android:layout_width="fill_parent"
-               android:layout_height="wrap_content"
-               android:text="@string/preload_max_zoom"
-               />
-      <Spinner android:id="@+id/preload_max_zoom"
-              android:layout_width="fill_parent"
-              android:layout_height="wrap_content"
-              android:prompt="@string/preload_max_zoom"
-              android:spinnerMode="dropdown"
-              />
-      <TextView android:id="@+id/preload_radius_label"
-               android:layout_width="fill_parent"
-               android:layout_height="wrap_content"
-               android:text="@string/preload_radius"
-               />
-      <Spinner android:id="@+id/preload_radius"
-              android:layout_width="fill_parent"
-              android:layout_height="wrap_content"
-              android:prompt="@string/preload_radius"
-              android:spinnerMode="dropdown"
-              />
-      <Button android:id="@+id/preload_load"
-              android:layout_width="match_parent"
-              android:layout_height="wrap_content"
-              android:text="@string/preload_load"
-             />
-      <ProgressBar android:id="@+id/preload_progress"
-                  android:layout_width="match_parent"
-                  android:layout_height="wrap_content"
-                  style="@android:style/Widget.ProgressBar.Horizontal"
-                  />
-    </LinearLayout>
-  </ScrollView>
-</LinearLayout>
diff --git a/altosdroid/res/layout/map_type.xml b/altosdroid/res/layout/map_type.xml
deleted file mode 100644 (file)
index e5cea22..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright © 2015 Keith Packard <keithp@keithp.com>
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public License along
-  with this program; if not, write to the Free Software Foundation, Inc.,
-  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
--->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    >
-  <Button android:id="@+id/map_type_hybrid"
-          android:layout_width="fill_parent"
-          android:layout_height="wrap_content"
-          android:text="@string/preload_hybrid"
-          android:onClick="selectType"
-          />
-  <Button android:id="@+id/map_type_satellite"
-          android:layout_width="fill_parent"
-          android:layout_height="wrap_content"
-          android:text="@string/preload_satellite"
-          android:onClick="selectType"
-          />
-  <Button android:id="@+id/map_type_roadmap"
-          android:layout_width="fill_parent"
-          android:layout_height="wrap_content"
-          android:text="@string/preload_roadmap"
-          android:onClick="selectType"
-          />
-  <Button android:id="@+id/map_type_terrain"
-          android:layout_width="fill_parent"
-          android:layout_height="wrap_content"
-          android:text="@string/preload_terrain"
-          android:onClick="selectType"
-          />
-</LinearLayout>
diff --git a/altosdroid/res/layout/setup.xml b/altosdroid/res/layout/setup.xml
deleted file mode 100644 (file)
index eeaf60a..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-<?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; 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.
-
--->
-<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>
diff --git a/altosdroid/res/layout/tab_flight.xml b/altosdroid/res/layout/tab_flight.xml
deleted file mode 100644 (file)
index 36d277d..0000000
+++ /dev/null
@@ -1,403 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright © 2013 Mike Beattie <mike@ethernal.org>
-
-     This program is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published by
-     the Free Software Foundation; 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.
--->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="fill_parent"
-    android:layout_height="wrap_content"
-    android:orientation="vertical" >
-
-  <LinearLayout
-      android:layout_weight="0"
-      android:layout_width="fill_parent"
-      android:layout_height="wrap_content"
-      android:orientation="vertical" >
-
-    <LinearLayout
-       xmlns:android="http://schemas.android.com/apk/res/android"
-       android:layout_width="fill_parent"
-       android:layout_height="wrap_content"
-       android:layout_weight="0"
-       android:baselineAligned="true"
-       android:orientation="horizontal" >
-
-      <RelativeLayout
-         android:layout_width="0dp"
-         android:layout_height="wrap_content"
-         android:layout_weight="1" >
-
-       <TextView
-           android:id="@+id/speed_label"
-           android:layout_width="wrap_content"
-           android:layout_height="wrap_content"
-           android:text="@string/speed_label" />
-
-       <TextView
-           android:id="@+id/speed_value"
-           android:layout_width="wrap_content"
-           android:layout_height="wrap_content"
-           android:layout_alignParentRight="true"
-           android:layout_below="@id/speed_label"
-           android:text=""
-           android:textAppearance="?android:attr/textAppearanceSmall" />
-      </RelativeLayout>
-
-      <RelativeLayout
-         android:layout_width="0dp"
-         android:layout_height="wrap_content"
-         android:layout_weight="1" >
-
-       <TextView
-           android:id="@+id/height_label"
-           android:layout_width="wrap_content"
-           android:layout_height="wrap_content"
-           android:text="@string/height_label" />
-
-       <TextView
-           android:id="@+id/height_value"
-           android:layout_width="wrap_content"
-           android:layout_height="wrap_content"
-           android:layout_alignParentRight="true"
-           android:layout_below="@id/height_label"
-           android:text=""
-           android:textAppearance="?android:attr/textAppearanceSmall" />
-      </RelativeLayout>
-
-    </LinearLayout>
-
-    <LinearLayout
-       xmlns:android="http://schemas.android.com/apk/res/android"
-       android:layout_width="fill_parent"
-       android:layout_height="wrap_content"
-       android:layout_weight="0"
-       android:baselineAligned="true"
-       android:orientation="horizontal" >
-
-      <RelativeLayout
-         android:layout_width="0dp"
-         android:layout_height="wrap_content"
-         android:layout_weight="1" >
-
-       <TextView
-           android:id="@+id/max_speed_label"
-           android:layout_width="wrap_content"
-           android:layout_height="wrap_content"
-           android:text="@string/max_speed_label" />
-
-       <TextView
-           android:id="@+id/max_speed_value"
-           android:layout_width="wrap_content"
-           android:layout_height="wrap_content"
-           android:layout_alignParentRight="true"
-           android:layout_below="@id/max_speed_label"
-           android:text=""
-           android:textAppearance="?android:attr/textAppearanceSmall" />
-      </RelativeLayout>
-
-      <RelativeLayout
-         android:layout_width="0dp"
-         android:layout_height="wrap_content"
-         android:layout_weight="1" >
-
-       <TextView
-           android:id="@+id/max_height_label"
-           android:layout_width="wrap_content"
-           android:layout_height="wrap_content"
-           android:text="@string/max_height_label" />
-
-       <TextView
-           android:id="@+id/max_height_value"
-           android:layout_width="wrap_content"
-           android:layout_height="wrap_content"
-           android:layout_alignParentRight="true"
-           android:layout_below="@id/max_height_label"
-           android:text=""
-           android:textAppearance="?android:attr/textAppearanceSmall" />
-      </RelativeLayout>
-
-    </LinearLayout>
-
-    <LinearLayout
-       xmlns:android="http://schemas.android.com/apk/res/android"
-       android:layout_width="fill_parent"
-       android:layout_height="wrap_content"
-       android:layout_weight="0"
-       android:baselineAligned="true"
-       android:orientation="horizontal"
-       android:paddingTop="5dp" >
-
-      <RelativeLayout
-         android:layout_width="0dp"
-         android:layout_height="wrap_content"
-         android:layout_weight="1" >
-
-       <TextView
-           android:id="@+id/elevation_label"
-           android:layout_width="wrap_content"
-           android:layout_height="wrap_content"
-           android:text="@string/elevation_label" />
-
-       <TextView
-           android:id="@+id/elevation_value"
-           android:layout_width="wrap_content"
-           android:layout_height="wrap_content"
-           android:layout_alignParentRight="true"
-           android:layout_below="@id/elevation_label"
-           android:text=""
-           android:textAppearance="?android:attr/textAppearanceSmall" />
-      </RelativeLayout>
-
-      <RelativeLayout
-         android:layout_width="0dp"
-         android:layout_height="wrap_content"
-         android:layout_weight="1" >
-
-       <TextView
-           android:id="@+id/range_label"
-           android:layout_width="wrap_content"
-           android:layout_height="wrap_content"
-           android:text="@string/range_label" />
-
-       <TextView
-           android:id="@+id/range_value"
-           android:layout_width="wrap_content"
-           android:layout_height="wrap_content"
-           android:layout_alignParentRight="true"
-           android:layout_below="@id/range_label"
-           android:text=""
-           android:textAppearance="?android:attr/textAppearanceSmall" />
-      </RelativeLayout>
-
-    </LinearLayout>
-
-    <LinearLayout
-       xmlns:android="http://schemas.android.com/apk/res/android"
-       android:layout_width="fill_parent"
-       android:layout_height="wrap_content"
-       android:layout_weight="0"
-       android:baselineAligned="true"
-       android:orientation="horizontal"
-       android:paddingTop="5dp" >
-
-      <RelativeLayout
-         android:layout_width="0dp"
-         android:layout_height="wrap_content"
-         android:layout_weight="1" >
-
-       <TextView
-           android:id="@+id/bearing_label"
-           android:layout_width="wrap_content"
-           android:layout_height="wrap_content"
-           android:text="@string/bearing_label" />
-
-       <TextView
-           android:id="@+id/bearing_value"
-           android:layout_width="wrap_content"
-           android:layout_height="wrap_content"
-           android:layout_alignParentRight="true"
-           android:layout_below="@id/bearing_label"
-           android:text=""
-           android:textAppearance="?android:attr/textAppearanceSmall" />
-      </RelativeLayout>
-
-      <RelativeLayout
-         android:layout_width="0dp"
-         android:layout_height="wrap_content"
-         android:layout_weight="1" >
-
-       <TextView
-           android:id="@+id/compass_label"
-           android:layout_width="wrap_content"
-           android:layout_height="wrap_content"
-           android:text="" />
-
-       <TextView
-           android:id="@+id/compass_value"
-           android:layout_width="wrap_content"
-           android:layout_height="wrap_content"
-           android:layout_alignParentRight="true"
-           android:layout_below="@id/compass_label"
-           android:text=""
-           android:textAppearance="?android:attr/textAppearanceSmall" />
-      </RelativeLayout>
-
-    </LinearLayout>
-
-    <LinearLayout
-       xmlns:android="http://schemas.android.com/apk/res/android"
-       android:layout_width="fill_parent"
-       android:layout_height="wrap_content"
-       android:layout_weight="0"
-       android:baselineAligned="true"
-       android:orientation="horizontal"
-       android:paddingTop="5dp" >
-
-      <RelativeLayout
-         android:layout_width="0dp"
-         android:layout_height="wrap_content"
-         android:layout_weight="1" >
-
-       <TextView
-           android:id="@+id/distance_label"
-           android:layout_width="wrap_content"
-           android:layout_height="wrap_content"
-           android:text="@string/gnd_distance_label" />
-
-       <TextView
-           android:id="@+id/distance_value"
-           android:layout_width="wrap_content"
-           android:layout_height="wrap_content"
-           android:layout_alignParentRight="true"
-           android:layout_below="@id/distance_label"
-           android:text=""
-           android:textAppearance="?android:attr/textAppearanceSmall" />
-      </RelativeLayout>
-
-      <TextView
-         android:layout_width="0dp"
-         android:layout_height="wrap_content"
-         android:layout_weight="1" >
-      </TextView>
-
-    </LinearLayout>
-
-    <RelativeLayout
-       android:layout_width="wrap_content"
-       android:layout_height="wrap_content"
-       android:paddingTop="5dp" >
-
-      <TextView
-         android:id="@+id/lat_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text="@string/latitude_label" />
-
-      <TextView
-         android:id="@+id/lat_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:layout_alignParentRight="true"
-         android:layout_below="@id/lat_label"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </RelativeLayout>
-
-    <RelativeLayout
-       android:layout_width="wrap_content"
-       android:layout_height="wrap_content"
-       android:paddingTop="5dp" >
-
-      <TextView
-         android:id="@+id/lon_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text="@string/longitude_label" />
-
-      <TextView
-         android:id="@+id/lon_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:layout_alignParentRight="true"
-         android:layout_below="@id/lon_label"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </RelativeLayout>
-
-    <RelativeLayout
-       android:id="@+id/apogee_view"
-       android:visibility="gone"
-       android:layout_gravity="fill"
-       android:layout_weight="1"
-       android:layout_width="wrap_content"
-       android:layout_height="wrap_content"
-       android:paddingTop="5dp" >
-
-      <ImageView
-         android:id="@+id/apogee_redled"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:contentDescription="@string/apogee_voltage_label"
-         android:src="@drawable/grayled" />
-
-      <ImageView
-         android:id="@+id/apogee_greenled"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:layout_toRightOf="@id/apogee_redled"
-         android:contentDescription="@string/apogee_voltage_label"
-         android:paddingRight="5dp"
-         android:src="@drawable/grayled" />
-
-      <TextView
-         android:id="@+id/apogee_voltage_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:layout_toRightOf="@id/apogee_greenled"
-         android:text="@string/apogee_voltage_label" />
-
-      <TextView
-         android:id="@+id/apogee_voltage_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:layout_alignParentRight="true"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </RelativeLayout>
-
-    <RelativeLayout
-       android:id="@+id/main_view"
-       android:visibility="gone"
-       android:layout_gravity="fill"
-       android:layout_weight="1"
-       android:layout_width="wrap_content"
-       android:layout_height="wrap_content"
-       android:paddingTop="5dp" >
-
-      <ImageView
-         android:id="@+id/main_redled"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:contentDescription="@string/main_voltage_label"
-         android:src="@drawable/grayled" />
-
-      <ImageView
-         android:id="@+id/main_greenled"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:layout_toRightOf="@id/main_redled"
-         android:contentDescription="@string/main_voltage_label"
-         android:paddingRight="5dp"
-         android:src="@drawable/grayled" />
-
-      <TextView
-         android:id="@+id/main_voltage_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:layout_toRightOf="@id/main_greenled"
-         android:text="@string/main_voltage_label" />
-
-      <TextView
-         android:id="@+id/main_voltage_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:layout_alignParentRight="true"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </RelativeLayout>
-  </LinearLayout>
-</LinearLayout>
diff --git a/altosdroid/res/layout/tab_layout.xml b/altosdroid/res/layout/tab_layout.xml
deleted file mode 100644 (file)
index 2c21c64..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/customTabLayout"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-    <TextView
-        android:id="@+id/tabLabel"
-        android:layout_height="wrap_content"
-        android:layout_width="match_parent"
-        android:textSize="13dp"
-        android:textColor="#ffffff"
-       android:gravity="center_horizontal"
-       android:background="#808080"
-        android:layout_centerVertical="true"
-        android:layout_centerHorizontal="true" />
-</RelativeLayout>
diff --git a/altosdroid/res/layout/tab_map.xml b/altosdroid/res/layout/tab_map.xml
deleted file mode 100644 (file)
index 25ae3a8..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright © 2013 Mike Beattie <mike@ethernal.org>
-
-     This program is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published by
-     the Free Software Foundation; 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.
--->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-       android:layout_width="match_parent"
-       android:layout_height="match_parent"
-       android:orientation="vertical" >
-
-  <FrameLayout
-      android:layout_width="fill_parent"
-      android:layout_height="wrap_content"
-      android:baselineAligned="true"
-      android:orientation="horizontal"
-      android:layout_weight="1">
-
-    <LinearLayout
-       android:id="@+id/map_online"
-       android:orientation="horizontal"
-       android:layout_width="fill_parent"
-       android:layout_height="fill_parent"
-       android:layout_weight="1">
-    </LinearLayout>
-
-    <org.altusmetrum.AltosDroid.AltosMapOffline
-       android:id="@+id/map_offline"
-       android:layout_width="fill_parent"
-       android:layout_height="wrap_content"
-       android:layout_weight="1"/>
-  </FrameLayout>
-  
-  <LinearLayout
-      xmlns:android="http://schemas.android.com/apk/res/android"
-      android:layout_width="fill_parent"
-      android:layout_height="wrap_content"
-      android:baselineAligned="true"
-      android:orientation="horizontal" >
-
-    <RelativeLayout
-       android:layout_width="0dp"
-       android:layout_height="wrap_content"
-       android:layout_weight="1"
-       android:paddingTop="5dp" >
-
-      <TextView
-         android:id="@+id/distance_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:paddingRight="4dp"
-         android:text="@string/distance_label" />
-
-      <TextView
-         android:id="@+id/distance_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:layout_toRightOf="@id/distance_label"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </RelativeLayout>
-
-    <RelativeLayout
-       android:layout_width="0dp"
-       android:layout_height="wrap_content"
-       android:layout_weight="1"
-       android:paddingTop="5dp" >
-
-      <TextView
-         android:id="@+id/bearing_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:paddingRight="4dp"
-         android:text="@string/bearing_label" />
-
-      <TextView
-         android:id="@+id/bearing_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:layout_toRightOf="@id/bearing_label"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </RelativeLayout>
-
-  </LinearLayout>
-
-  <LinearLayout
-      xmlns:android="http://schemas.android.com/apk/res/android"
-      android:layout_width="fill_parent"
-      android:layout_height="wrap_content"
-      android:baselineAligned="true"
-      android:orientation="horizontal" >
-
-    <RelativeLayout
-       android:layout_width="0dp"
-       android:layout_height="wrap_content"
-       android:layout_weight="1"
-       android:paddingTop="5dp" >
-
-      <TextView
-         android:id="@+id/target_lat_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:paddingRight="4dp"
-         android:text="@string/target_latitude_label" />
-
-      <TextView
-         android:id="@+id/target_lat_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:layout_toRightOf="@id/target_lat_label"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </RelativeLayout>
-
-    <RelativeLayout
-       android:layout_width="0dp"
-       android:layout_height="wrap_content"
-       android:layout_weight="1"
-       android:paddingTop="5dp" >
-
-      <TextView
-         android:id="@+id/target_lon_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:paddingRight="4dp"
-         android:text="@string/target_longitude_label" />
-
-      <TextView
-         android:id="@+id/target_lon_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:layout_toRightOf="@id/target_lon_label"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </RelativeLayout>
-  </LinearLayout>
-
-  <LinearLayout
-      xmlns:android="http://schemas.android.com/apk/res/android"
-      android:layout_width="fill_parent"
-      android:layout_height="wrap_content"
-      android:baselineAligned="true"
-      android:orientation="horizontal" >
-
-    <RelativeLayout
-       android:layout_width="0dp"
-       android:layout_height="wrap_content"
-       android:layout_weight="1"
-       android:paddingTop="5dp" >
-
-      <TextView
-         android:id="@+id/receiver_lat_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:paddingRight="4dp"
-         android:text="@string/receiver_latitude_label" />
-
-      <TextView
-         android:id="@+id/receiver_lat_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:layout_toRightOf="@id/receiver_lat_label"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </RelativeLayout>
-
-    <RelativeLayout
-       android:layout_width="0dp"
-       android:layout_height="wrap_content"
-       android:layout_weight="1"
-       android:paddingTop="5dp" >
-
-      <TextView
-         android:id="@+id/receiver_lon_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:paddingRight="4dp"
-         android:text="@string/receiver_longitude_label" />
-
-      <TextView
-         android:id="@+id/receiver_lon_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:layout_toRightOf="@id/receiver_lon_label"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </RelativeLayout>
-  </LinearLayout>
-</LinearLayout>
diff --git a/altosdroid/res/layout/tab_pad.xml b/altosdroid/res/layout/tab_pad.xml
deleted file mode 100644 (file)
index 990a6be..0000000
+++ /dev/null
@@ -1,496 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright © 2013 Mike Beattie <mike@ethernal.org>
-
-     This program is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published by
-     the Free Software Foundation; 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.
--->
-
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content">
-
-  <TableLayout
-      xmlns:android="http://schemas.android.com/apk/res/android"
-      android:stretchColumns="2,3"
-      android:layout_weight="0"
-      android:layout_width="wrap_content"
-      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">
-      
-      <ImageView
-         android:id="@+id/battery_redled"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:contentDescription="@string/battery_voltage_label"
-         android:src="@drawable/grayled"
-         />
-
-      <ImageView
-         android:id="@+id/battery_greenled"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:contentDescription="@string/battery_voltage_label"
-         android:src="@drawable/grayled" />
-
-      <TextView
-         android:id="@+id/battery_voltage_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text="@string/battery_voltage_label" />
-
-      <TextView
-         android:id="@+id/battery_voltage_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall"
-         />
-    </TableRow>
-
-    <TableRow
-       android:id="@+id/receiver_row"
-       android:visibility="gone"
-       android:layout_gravity="center"
-       android:layout_weight="1"
-       android:padding="2dip"
-       android:layout_width="wrap_content"
-       android:layout_height="wrap_content">
-
-      <ImageView
-         android:id="@+id/receiver_redled"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:contentDescription="@string/receiver_voltage_label"
-         android:src="@drawable/grayled" />
-
-      <ImageView
-         android:id="@+id/receiver_greenled"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:contentDescription="@string/receiver_voltage_label"
-         android:src="@drawable/grayled" />
-
-      <TextView
-         android:id="@+id/receiver_voltage_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text="@string/receiver_voltage_label" />
-
-      <TextView
-         android:id="@+id/receiver_voltage_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </TableRow>
-
-    <TableRow
-       android:layout_gravity="center"
-       android:layout_weight="1"
-       android:padding="2dip"
-       android:layout_width="wrap_content"
-       android:layout_height="wrap_content" >
-
-      <ImageView
-         android:id="@+id/logging_redled"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:contentDescription="@string/logging_label"
-         android:src="@drawable/grayled" />
-
-      <ImageView
-         android:id="@+id/logging_greenled"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:contentDescription="@string/logging_label"
-         android:src="@drawable/grayled" />
-
-      <TextView
-         android:id="@+id/logging_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text="@string/logging_label" />
-
-      <TextView
-         android:id="@+id/logging_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:layout_below="@id/logging_label"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </TableRow>
-
-    <TableRow
-       android:layout_gravity="center"
-       android:layout_weight="1"
-       android:padding="2dip"
-       android:layout_width="wrap_content"
-       android:layout_height="wrap_content" >
-
-      <ImageView
-         android:id="@+id/gps_locked_redled"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:contentDescription="@string/gps_locked_label"
-         android:src="@drawable/grayled" />
-
-      <ImageView
-         android:id="@+id/gps_locked_greenled"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:contentDescription="@string/gps_locked_label"
-         android:src="@drawable/grayled" />
-
-      <TextView
-         android:id="@+id/gps_locked_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text="@string/gps_locked_label" />
-
-      <TextView
-         android:id="@+id/gps_locked_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:layout_below="@id/gps_locked_label"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </TableRow>
-
-    <TableRow
-       android:layout_gravity="center"
-       android:layout_weight="1"
-       android:padding="2dip"
-       android:layout_width="wrap_content"
-       android:layout_height="wrap_content" >
-
-      <ImageView
-         android:id="@+id/gps_ready_redled"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:contentDescription="@string/gps_ready_label"
-         android:src="@drawable/grayled" />
-
-      <ImageView
-         android:id="@+id/gps_ready_greenled"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:contentDescription="@string/gps_ready_label"
-         android:src="@drawable/grayled" />
-
-      <TextView
-         android:id="@+id/gps_ready_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text="@string/gps_ready_label" />
-
-      <TextView
-         android:id="@+id/gps_ready_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:layout_below="@id/gps_ready_label"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </TableRow>
-
-    <TableRow
-       android:id="@+id/apogee_row"
-       android:visibility="gone"
-       android:layout_gravity="center"
-       android:layout_weight="1"
-       android:padding="2dip"
-       android:layout_width="wrap_content"
-       android:layout_height="wrap_content">
-
-      <ImageView
-         android:id="@+id/apogee_redled"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:contentDescription="@string/apogee_voltage_label"
-         android:src="@drawable/grayled" />
-
-      <ImageView
-         android:id="@+id/apogee_greenled"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:contentDescription="@string/apogee_voltage_label"
-         android:src="@drawable/grayled" />
-
-      <TextView
-         android:id="@+id/apogee_voltage_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text="@string/apogee_voltage_label" />
-
-      <TextView
-         android:id="@+id/apogee_voltage_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </TableRow>
-
-    <TableRow
-       android:id="@+id/main_row"
-       android:visibility="gone"
-       android:layout_gravity="center"
-       android:layout_weight="1"
-       android:padding="2dip"
-       android:layout_width="wrap_content"
-       android:layout_height="wrap_content" >
-
-      <ImageView
-         android:id="@+id/main_redled"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:contentDescription="@string/main_voltage_label"
-         android:src="@drawable/grayled" />
-
-      <ImageView
-         android:id="@+id/main_greenled"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:contentDescription="@string/main_voltage_label"
-         android:src="@drawable/grayled" />
-
-      <TextView
-         android:id="@+id/main_voltage_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text="@string/main_voltage_label" />
-
-      <TextView
-         android:id="@+id/main_voltage_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </TableRow>
-
-    <TableRow
-       android:id="@+id/ignite_a_row"
-       android:visibility="gone"
-       android:layout_gravity="center"
-       android:layout_weight="1"
-       android:padding="2dip"
-       android:layout_width="wrap_content"
-       android:layout_height="wrap_content" >
-
-      <ImageView
-         android:id="@+id/ignite_a_redled"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:contentDescription="@string/ignite_a_voltage_label"
-         android:src="@drawable/grayled" />
-
-      <ImageView
-         android:id="@+id/ignite_a_greenled"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:contentDescription="@string/ignite_a_voltage_label"
-         android:src="@drawable/grayled" />
-
-      <TextView
-         android:id="@+id/ignite_a_voltage_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text="@string/ignite_a_voltage_label" />
-
-      <TextView
-         android:id="@+id/ignite_a_voltage_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </TableRow>
-
-    <TableRow
-       android:id="@+id/ignite_b_row"
-       android:visibility="gone"
-       android:layout_gravity="center"
-       android:layout_weight="1"
-       android:padding="2dip"
-       android:layout_width="wrap_content"
-       android:layout_height="wrap_content" >
-
-      <ImageView
-         android:id="@+id/ignite_b_redled"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:contentDescription="@string/ignite_b_voltage_label"
-         android:src="@drawable/grayled" />
-
-      <ImageView
-         android:id="@+id/ignite_b_greenled"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:contentDescription="@string/ignite_b_voltage_label"
-         android:src="@drawable/grayled" />
-
-      <TextView
-         android:id="@+id/ignite_b_voltage_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text="@string/ignite_b_voltage_label" />
-
-      <TextView
-         android:id="@+id/ignite_b_voltage_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </TableRow>
-
-    <TableRow
-       android:id="@+id/ignite_c_row"
-       android:visibility="gone"
-       android:layout_gravity="center"
-       android:layout_weight="1"
-       android:padding="2dip"
-       android:layout_width="wrap_content"
-       android:layout_height="wrap_content" >
-
-      <ImageView
-         android:id="@+id/ignite_c_redled"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:contentDescription="@string/ignite_c_voltage_label"
-         android:src="@drawable/grayled" />
-
-      <ImageView
-         android:id="@+id/ignite_c_greenled"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:contentDescription="@string/ignite_c_voltage_label"
-         android:src="@drawable/grayled" />
-
-      <TextView
-         android:id="@+id/ignite_c_voltage_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text="@string/ignite_c_voltage_label" />
-
-      <TextView
-         android:id="@+id/ignite_c_voltage_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </TableRow>
-
-    <TableRow
-       android:id="@+id/ignite_d_row"
-       android:visibility="gone"
-       android:layout_gravity="center"
-       android:layout_weight="1"
-       android:padding="2dip"
-       android:layout_width="wrap_content"
-       android:layout_height="wrap_content" >
-
-      <ImageView
-         android:id="@+id/ignite_d_redled"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:contentDescription="@string/ignite_d_voltage_label"
-         android:src="@drawable/grayled" />
-
-      <ImageView
-         android:id="@+id/ignite_d_greenled"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:contentDescription="@string/ignite_d_voltage_label"
-         android:src="@drawable/grayled" />
-
-      <TextView
-         android:id="@+id/ignite_d_voltage_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text="@string/ignite_d_voltage_label" />
-
-      <TextView
-         android:id="@+id/ignite_d_voltage_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </TableRow>
-
-    <TableRow
-       android:padding="2dip"
-       android:layout_width="wrap_content"
-       android:layout_height="wrap_content">
-
-      <TextView
-         android:id="@+id/receiver_lat_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:layout_column="2"
-         android:text="@string/receiver_latitude_label" />
-
-      <TextView
-         android:id="@+id/receiver_lat_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </TableRow>
-
-    <TableRow
-       android:padding="2dip"
-       android:layout_width="wrap_content"
-       android:layout_height="wrap_content">
-
-      <TextView
-         android:id="@+id/receiver_lon_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:layout_column="2"
-         android:text="@string/receiver_longitude_label" />
-
-      <TextView
-         android:id="@+id/receiver_lon_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </TableRow>
-
-    <TableRow
-       android:padding="2dip"
-       android:layout_width="wrap_content"
-       android:layout_height="wrap_content">
-
-      <TextView
-         android:id="@+id/receiver_alt_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:layout_column="2"
-         android:text="@string/receiver_altitude_label" />
-
-      <TextView
-         android:id="@+id/receiver_alt_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </TableRow>
-  </TableLayout>
-</LinearLayout>
diff --git a/altosdroid/res/layout/tab_recover.xml b/altosdroid/res/layout/tab_recover.xml
deleted file mode 100644 (file)
index 7d1e750..0000000
+++ /dev/null
@@ -1,252 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright © 2013 Mike Beattie <mike@ethernal.org>
-
-     This program is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published by
-     the Free Software Foundation; 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.
--->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="fill_parent"
-    android:layout_height="wrap_content"
-    android:orientation="vertical" >
-
-  <LinearLayout
-      xmlns:android="http://schemas.android.com/apk/res/android"
-      android:layout_weight="0"
-      android:layout_width="fill_parent"
-      android:layout_height="wrap_content"
-      android:orientation="vertical" >
-
-    <RelativeLayout
-       android:layout_gravity="fill"
-       android:layout_weight="1"
-       android:layout_width="wrap_content"
-       android:layout_height="wrap_content" >
-
-      <TextView
-         android:id="@+id/bearing_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text="@string/bearing_label" />
-
-      <TextView
-         android:id="@+id/bearing_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:layout_alignParentRight="true"
-         android:layout_below="@+id/bearing_label"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </RelativeLayout>
-
-    <RelativeLayout
-       android:layout_gravity="fill"
-       android:layout_weight="1"
-       android:layout_width="wrap_content"
-       android:layout_height="wrap_content" >
-
-      <TextView
-         android:id="@+id/direction_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text="@string/direction_label" />
-
-      <TextView
-         android:id="@+id/direction_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:layout_alignParentRight="true"
-         android:layout_below="@+id/direction_label"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </RelativeLayout>
-
-    <RelativeLayout
-       android:layout_gravity="fill"
-       android:layout_weight="1"
-       android:layout_width="wrap_content"
-       android:layout_height="wrap_content">
-
-      <TextView
-         android:id="@+id/distance_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text="@string/distance_label" />
-
-      <TextView
-         android:id="@+id/distance_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:layout_alignParentRight="true"
-         android:layout_below="@+id/distance_label"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </RelativeLayout>
-
-    <RelativeLayout
-       android:layout_gravity="fill"
-       android:layout_weight="1"
-       android:layout_width="wrap_content"
-       android:layout_height="wrap_content">
-
-      <TextView
-         android:id="@+id/target_lat_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text="@string/target_latitude_label" />
-
-      <TextView
-         android:id="@+id/target_lat_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:layout_alignParentRight="true"
-         android:layout_below="@id/target_lat_label"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </RelativeLayout>
-
-    <RelativeLayout
-       android:layout_gravity="fill"
-       android:layout_weight="1"
-       android:layout_width="wrap_content"
-       android:layout_height="wrap_content">
-
-      <TextView
-         android:id="@+id/target_lon_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text="@string/target_longitude_label" />
-
-      <TextView
-         android:id="@+id/target_lon_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:layout_alignParentRight="true"
-         android:layout_below="@id/target_lon_label"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </RelativeLayout>
-
-    <RelativeLayout
-       android:layout_gravity="fill"
-       android:layout_weight="1"
-       android:layout_width="wrap_content"
-       android:layout_height="wrap_content">
-
-      <TextView
-         android:id="@+id/receiver_lat_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text="@string/receiver_latitude_label" />
-
-      <TextView
-         android:id="@+id/receiver_lat_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:layout_alignParentRight="true"
-         android:layout_below="@id/receiver_lat_label"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </RelativeLayout>
-
-    <RelativeLayout
-       android:layout_gravity="fill"
-       android:layout_weight="1"
-       android:layout_width="wrap_content"
-       android:layout_height="wrap_content">
-
-      <TextView
-         android:id="@+id/receiver_lon_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text="@string/receiver_longitude_label" />
-
-      <TextView
-         android:id="@+id/receiver_lon_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:layout_alignParentRight="true"
-         android:layout_below="@id/receiver_lon_label"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </RelativeLayout>
-
-    <RelativeLayout
-       android:layout_gravity="fill"
-       android:layout_weight="1"
-       android:layout_width="wrap_content"
-       android:layout_height="wrap_content">
-
-      <TextView
-         android:id="@+id/max_height_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text="@string/max_height_label" />
-
-      <TextView
-         android:id="@+id/max_height_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:layout_alignParentRight="true"
-         android:layout_below="@id/max_height_label"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </RelativeLayout>
-
-    <RelativeLayout
-       android:layout_gravity="fill"
-       android:layout_weight="1"
-       android:layout_width="wrap_content"
-       android:layout_height="wrap_content">
-
-      <TextView
-         android:id="@+id/max_speed_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text="@string/max_speed_label" />
-
-      <TextView
-         android:id="@+id/max_speed_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:layout_alignParentRight="true"
-         android:layout_below="@id/max_speed_label"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </RelativeLayout>
-
-    <RelativeLayout
-       android:layout_gravity="fill"
-       android:layout_weight="1"
-       android:layout_width="wrap_content"
-       android:layout_height="wrap_content">
-
-      <TextView
-         android:id="@+id/max_accel_label"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:text="@string/max_accel_label" />
-
-      <TextView
-         android:id="@+id/max_accel_value"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:layout_alignParentRight="true"
-         android:layout_below="@id/max_accel_label"
-         android:text=""
-         android:textAppearance="?android:attr/textAppearanceSmall" />
-    </RelativeLayout>
-  </LinearLayout>
-</LinearLayout>
diff --git a/altosdroid/res/menu/option_menu.xml b/altosdroid/res/menu/option_menu.xml
deleted file mode 100644 (file)
index 53a0de0..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 
-  Copyright © 2015 Keith Packard <keithp@keithp.com>
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public License along
-  with this program; if not, write to the Free Software Foundation, Inc.,
-  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
--->
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:id="@+id/connect_scan"
-          android:icon="@android:drawable/ic_menu_search"
-          android:title="@string/connect_device" />
-    <item android:id="@+id/disconnect"
-         android:icon="@android:drawable/ic_notification_clear_all"
-         android:title="@string/disconnect_device" />
-    <item android:id="@+id/select_freq"
-          android:icon="@android:drawable/ic_menu_preferences"
-          android:title="@string/select_freq" />
-
-    <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" />
-</menu>
diff --git a/altosdroid/res/values/Colors.xml b/altosdroid/res/values/Colors.xml
deleted file mode 100644 (file)
index 8dddae2..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-        Copyright © 2015 Keith Packard <keithp@keithp.com>
-
-        This program is free software; you can redistribute it and/or modify
-        it under the terms of the GNU General Public License as published by
-        the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-        This program is distributed in the hope that it will be useful, but
-        WITHOUT ANY WARRANTY; without even the implied warranty of
-        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-        General Public License for more details.
-
-        You should have received a copy of the GNU General Public License along
-        with this program; if not, write to the Free Software Foundation, Inc.,
-        59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
--->
-<resources>
-  <color name="old_color">#ffff4040</color>
-</resources>
diff --git a/altosdroid/res/values/CustomTheme.xml b/altosdroid/res/values/CustomTheme.xml
deleted file mode 100644 (file)
index 6c701ea..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<resources>
-  <style name="CustomTheme" parent="android:Theme.Holo">
-  </style>
-</resources>
diff --git a/altosdroid/res/values/strings.xml b/altosdroid/res/values/strings.xml
deleted file mode 100644 (file)
index 6a1d24f..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-        Copyright © 2012-2013 Mike Beattie <mike@ethernal.org>
-
-        This program is free software; you can redistribute it and/or modify
-        it under the terms of the GNU General Public License as published by
-        the Free Software Foundation; 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.
--->
-<resources>
-
-       <string name="app_name">AltosDroid</string>
-
-       <!-- AltosDroid -->
-       <string name="bt_not_enabled">Bluetooth was not enabled.</string>
-       <string name="title_connecting">connecting…</string>
-       <string name="title_connected_to">connected</string>
-       <string name="title_not_connected">not connected</string>
-
-       <!-- Options Menu -->
-       <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_maps">Load Maps</string>
-       <string name="select_tracker">Select Tracker</string>
-       <string name="delete_track">Delete Track</string>
-       <string name="map_type">Map Type</string>
-       <string name="map_source">Toggle Online/Offline maps</string>
-
-       <!-- MapTypeActivity -->
-       <string name="map_type">Map Type</string>
-
-       <!-- DeviceListActivity -->
-       <string name="scanning">scanning for devices…</string>
-       <string name="select_device">select a device to connect</string>
-       <string name="none_paired">No devices have been paired</string>
-       <string name="none_found">No devices found</string>
-       <string name="title_paired_devices">Paired Devices</string>
-       <string name="title_other_devices">Other Available Devices</string>
-       <string name="button_scan">Scan for devices</string>
-
-       <!-- Service -->
-       <string name="telemetry_service_label">AltosDroid Telemetry Service</string>
-       <string name="telemetry_service_started">Telemetry Service Started</string>
-       <string name="telemetry_service_stopped">Telemetry Service Stopped</string>
-
-       <!-- UI fields -->
-       <!-- Header -->
-       <string name="callsign_label">Callsign</string>
-       <string name="serial_label">Serial</string>
-       <string name="flight_label">Flight</string>
-       <string name="state_label">State</string>
-       <string name="rssi_label">RSSI</string>
-       <string name="age_label">Age</string>
-
-       <!-- Tab fields -->
-       <string name="height_label">Height</string>
-       <string name="speed_label">Speed</string>
-       <string name="accel_label">Acceleration</string>
-       <string name="bearing_label">Bearing</string>
-       <string name="direction_label">Direction</string>
-       <string name="elevation_label">Elevation</string>
-       <string name="range_label">Range</string>
-       <string name="distance_label">Distance</string>
-       <string name="gnd_distance_label">Ground Distance</string>
-       <string name="max_height_label">Max Height</string>
-       <string name="max_speed_label">Max Speed</string>
-       <string name="max_accel_label">Max Accel</string>
-       <string name="battery_voltage_label">Battery</string>
-       <string name="receiver_voltage_label">Receiver Battery</string>
-       <string name="apogee_voltage_label">Apogee Igniter</string>
-       <string name="main_voltage_label">Main Igniter</string>
-       <string name="ignite_a_voltage_label">Igniter A</string>
-       <string name="ignite_b_voltage_label">Igniter B</string>
-       <string name="ignite_c_voltage_label">Igniter C</string>
-       <string name="ignite_d_voltage_label">Igniter D</string>
-       <string name="logging_label">Data Logging</string>
-       <string name="gps_locked_label">GPS Locked</string>
-       <string name="gps_ready_label">GPS Ready</string>
-       <string name="latitude_label">Latitude</string>
-       <string name="longitude_label">Longitude</string>
-       <string name="target_latitude_label">Tar Lat</string>
-       <string name="target_longitude_label">Tar Lon</string>
-       <string name="receiver_latitude_label">My Lat</string>
-       <string name="receiver_longitude_label">My Lon</string>
-       <string name="receiver_altitude_label">My Alt</string>
-
-       <!-- Map preload -->
-       <string name="preload_site_label">Known Launch Sites</string>
-       <string name="preload_latitude_label">Latitude</string>
-       <string name="preload_longitude_label">Longitude</string>
-
-       <string name="preload_types">Map Types</string>
-       <string name="preload_hybrid">Hybrid</string>
-       <string name="preload_satellite">Satellite</string>
-       <string name="preload_roadmap">Roadmap</string>
-       <string name="preload_terrain">Terrain</string>
-       <string name="preload_min_zoom">Minimum Zoom</string>
-       <string name="preload_max_zoom">Maximum Zoom</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>
diff --git a/altosdroid/res/xml/device_filter.xml b/altosdroid/res/xml/device_filter.xml
deleted file mode 100644 (file)
index 84b09c0..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<resources>
-  <usb-device vendor-id="65534" />
-  <usb-device vendor-id="1027" />
-</resources>
diff --git a/altosdroid/settings.gradle b/altosdroid/settings.gradle
new file mode 100644 (file)
index 0000000..e7b4def
--- /dev/null
@@ -0,0 +1 @@
+include ':app'
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java
deleted file mode 100644 (file)
index 0d09abd..0000000
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
- * Copyright © 2012 Mike Beattie <mike@ethernal.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.AltosDroid;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.UUID;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothSocket;
-//import android.os.Bundle;
-import android.os.Handler;
-//import android.os.Message;
-
-import org.altusmetrum.altoslib_13.*;
-
-public class AltosBluetooth extends AltosDroidLink {
-
-       private ConnectThread    connect_thread = null;
-
-       private BluetoothDevice  device;
-       private BluetoothSocket  socket;
-       private InputStream      input;
-       private OutputStream     output;
-       private boolean          pause;
-
-       // Constructor
-       public AltosBluetooth(BluetoothDevice device, Handler handler, boolean pause) {
-               super(handler);
-               this.device = device;
-               this.handler = handler;
-               this.pause = pause;
-
-               connect_thread = new ConnectThread();
-               connect_thread.start();
-       }
-
-       void connected() {
-               if (closed()) {
-                       AltosDebug.debug("connected after closed");
-                       return;
-               }
-
-               AltosDebug.check_ui("connected\n");
-               try {
-                       synchronized(this) {
-                               if (socket != null) {
-                                       input = socket.getInputStream();
-                                       output = socket.getOutputStream();
-                                       super.connected();
-                               }
-                       }
-               } catch (InterruptedException ie) {
-                       connect_failed();
-               } catch (IOException io) {
-                       connect_failed();
-               }
-       }
-
-       private void connect_failed() {
-               if (closed()) {
-                       AltosDebug.debug("connect_failed after closed");
-                       return;
-               }
-
-               close_device();
-               input = null;
-               output = null;
-               handler.obtainMessage(TelemetryService.MSG_CONNECT_FAILED, this).sendToTarget();
-               AltosDebug.error("ConnectThread: Failed to establish connection");
-       }
-
-       void close_device() {
-               BluetoothSocket tmp_socket;
-
-               synchronized(this) {
-                       tmp_socket = socket;
-                       socket = null;
-               }
-
-               if (tmp_socket != null) {
-                       try {
-                               tmp_socket.close();
-                       } catch (IOException e) {
-                               AltosDebug.error("close_socket failed");
-                       }
-               }
-       }
-
-       public void close() {
-               super.close();
-               input = null;
-               output = null;
-       }
-
-       private final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
-
-       private void create_socket(BluetoothDevice  device) {
-
-               BluetoothSocket tmp_socket = null;
-
-               AltosDebug.check_ui("create_socket\n");
-               try {
-                       tmp_socket = device.createInsecureRfcommSocketToServiceRecord(SPP_UUID);
-               } catch (IOException e) {
-                       e.printStackTrace();
-               }
-               if (socket != null) {
-                       AltosDebug.debug("Socket already allocated %s", socket.toString());
-                       close_device();
-               }
-               synchronized (this) {
-                       socket = tmp_socket;
-               }
-       }
-
-       private class ConnectThread extends Thread {
-
-               public void run() {
-                       AltosDebug.debug("ConnectThread: BEGIN (pause %b)", pause);
-                       setName("ConnectThread");
-
-                       if (pause) {
-                               try {
-                                       Thread.sleep(4000);
-                               } catch (InterruptedException e) {
-                               }
-                       }
-
-                       create_socket(device);
-                       // Always cancel discovery because it will slow down a connection
-                       try {
-                               BluetoothAdapter.getDefaultAdapter().cancelDiscovery();
-                       } catch (Exception e) {
-                               AltosDebug.debug("cancelDiscovery exception %s", e.toString());
-                       }
-
-                       BluetoothSocket local_socket = null;
-
-                       synchronized (AltosBluetooth.this) {
-                               if (!closed())
-                                       local_socket = socket;
-                       }
-
-                       if (local_socket != null) {
-                               try {
-                                       // Make a connection to the BluetoothSocket
-                                       // This is a blocking call and will only return on a
-                                       // successful connection or an exception
-                                       local_socket.connect();
-                               } catch (Exception e) {
-                                       AltosDebug.debug("Connect exception %s", e.toString());
-                                       try {
-                                               local_socket.close();
-                                       } catch (Exception ce) {
-                                               AltosDebug.debug("Close exception %s", ce.toString());
-                                       }
-                                       local_socket = null;
-                               }
-                       }
-
-                       if (local_socket != null) {
-                               connected();
-                       } else {
-                               connect_failed();
-                       }
-
-                       AltosDebug.debug("ConnectThread: completed");
-               }
-       }
-
-       private synchronized void wait_connected() throws InterruptedException, IOException {
-               AltosDebug.check_ui("wait_connected\n");
-               if (input == null && socket != null) {
-                       AltosDebug.debug("wait_connected...");
-                       wait();
-                       AltosDebug.debug("wait_connected done");
-               }
-               if (socket == null)
-                       throw new IOException();
-       }
-
-       int write(byte[] buffer, int len) {
-               if (output == null)
-                       return -1;
-               try {
-                       output.write(buffer, 0, len);
-               } catch (IOException ie) {
-                       return -1;
-               }
-               return len;
-       }
-
-       int read(byte[] buffer, int len) {
-               if (input == null)
-                       return -1;
-               try {
-                       return input.read(buffer, 0, len);
-               } catch (IOException ie) {
-                       return -1;
-               }
-       }
-
-       // Stubs of required methods when extending AltosLink
-       public boolean can_cancel_reply()   { return false; }
-       public boolean show_reply_timeout() { return true; }
-       public void hide_reply_timeout()    { }
-
-}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDebug.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDebug.java
deleted file mode 100644 (file)
index 2ae0652..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright © 2015 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-package org.altusmetrum.AltosDroid;
-
-import java.util.Arrays;
-import java.io.*;
-import java.lang.*;
-
-import org.altusmetrum.altoslib_13.*;
-
-import android.app.Activity;
-import android.graphics.*;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentTransaction;
-import android.view.*;
-import android.widget.*;
-import android.location.Location;
-import android.content.*;
-import android.util.Log;
-import android.os.*;
-import android.content.pm.*;
-
-public class AltosDebug {
-       // Debugging
-       static final String TAG = "AltosDroid";
-
-       static boolean  D = true;
-
-       static void init(Context context) {
-               ApplicationInfo app_info = context.getApplicationInfo();
-
-               if ((app_info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
-                       Log.d(TAG, "Enable debugging\n");
-                       D = true;
-               } else {
-                       Log.d(TAG, "Disable debugging\n");
-                       D = false;
-               }
-       }
-
-
-       static void info(String format, Object ... arguments) {
-               Log.i(TAG, String.format(format, arguments));
-       }
-
-       static void debug(String format, Object ... arguments) {
-               if (D)
-                       Log.d(TAG, String.format(format, arguments));
-       }
-
-       static void error(String format, Object ... arguments) {
-               Log.e(TAG, String.format(format, arguments));
-       }
-
-       static void check_ui(String format, Object ... arguments) {
-               if (Looper.myLooper() == Looper.getMainLooper()) {
-                       Log.e(TAG, String.format("ON UI THREAD " + format, arguments));
-                       for (StackTraceElement el : Thread.currentThread().getStackTrace())
-                               Log.e(TAG, "\t" + el.toString() + "\n");
-               }
-       }
-}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java
deleted file mode 100644 (file)
index 1bcb67e..0000000
+++ /dev/null
@@ -1,1224 +0,0 @@
-/*
- * Copyright © 2012-2013 Mike Beattie <mike@ethernal.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.AltosDroid;
-
-import java.lang.ref.WeakReference;
-import java.text.*;
-import java.util.*;
-import java.io.*;
-
-import android.app.Activity;
-import android.app.PendingIntent;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.content.Intent;
-import android.content.Context;
-import android.content.ComponentName;
-import android.content.ServiceConnection;
-import android.content.DialogInterface;
-import android.os.IBinder;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.os.Messenger;
-import android.os.RemoteException;
-import android.content.res.Resources;
-import android.support.v4.app.FragmentActivity;
-import android.support.v4.app.FragmentManager;
-import android.util.DisplayMetrics;
-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_13.*;
-
-class SavedState {
-       long    received_time;
-       int     state;
-       boolean locked;
-       String  callsign;
-       int     serial;
-       int     flight;
-       int     rssi;
-
-       SavedState(AltosState state) {
-               received_time = state.received_time;
-               this.state = state.state();
-               if (state.gps != null)
-                       locked = state.gps.locked;
-               else
-                       locked = false;
-               callsign = state.cal_data().callsign;
-               serial = state.cal_data().serial;
-               flight = state.cal_data().flight;
-               rssi = state.rssi;
-       }
-}
-
-class Tracker implements CharSequence, Comparable {
-       int     serial;
-       String  call;
-       double  frequency;
-
-       String  display;
-
-       public Tracker(int serial, String call, double frequency) {
-               if (call == null)
-                       call = "none";
-
-               this.serial = serial;
-               this.call = call;
-               this.frequency = frequency;
-               if (frequency == 0.0)
-                       display = "Auto";
-               else if (frequency == AltosLib.MISSING) {
-                       display = String.format("%-8.8s  %6d", call, serial);
-               } else {
-                       display = String.format("%-8.8s %7.3f %6d", call, frequency, serial);
-               }
-       }
-
-       public Tracker(AltosState s) {
-               this(s == null ? 0 : s.cal_data().serial,
-                    s == null ? null : s.cal_data().callsign,
-                    s == null ? 0.0 : s.frequency);
-       }
-
-       /* CharSequence */
-       public char charAt(int index) {
-               return display.charAt(index);
-       }
-
-       public int length() {
-               return display.length();
-       }
-
-       public CharSequence subSequence(int start, int end) throws IndexOutOfBoundsException {
-               return display.subSequence(start, end);
-       }
-
-       public String toString() {
-               return display.toString();
-       }
-
-       /* Comparable */
-       public int compareTo (Object other) {
-               Tracker o = (Tracker) other;
-               if (frequency == 0.0) {
-                       if (o.frequency == 0.0)
-                               return 0;
-                       return -1;
-               }
-               if (o.frequency == 0.0)
-                       return 1;
-
-               int     a = serial - o.serial;
-               int     b = call.compareTo(o.call);
-               int     c = (int) Math.signum(frequency - o.frequency);
-
-               if (b != 0)
-                       return b;
-               if (c != 0)
-                       return c;
-               return a;
-       }
-}
-
-public class AltosDroid extends FragmentActivity implements AltosUnitsListener, LocationListener {
-
-       // Actions sent to the telemetry server at startup time
-
-       public static final String ACTION_BLUETOOTH = "org.altusmetrum.AltosDroid.BLUETOOTH";
-       public static final String ACTION_USB = "org.altusmetrum.AltosDroid.USB";
-
-       // Message types received by our Handler
-
-       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_IDLE_MODE      = 5;
-       public static final int REQUEST_IGNITERS       = 6;
-       public static final int REQUEST_SETUP          = 7;
-
-       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;
-
-       private BluetoothAdapter mBluetoothAdapter = null;
-
-       // Flight state values
-       private TextView mCallsignView;
-       private TextView mRSSIView;
-       private TextView mSerialView;
-       private TextView mFlightView;
-       private RelativeLayout mStateLayout;
-       private TextView mStateView;
-       private TextView mAgeView;
-       private boolean  mAgeViewOld;
-       private int mAgeNewColor;
-       private int mAgeOldColor;
-
-       public static final String      tab_pad_name = "pad";
-       public static final String      tab_flight_name = "flight";
-       public static final String      tab_recover_name = "recover";
-       public static final String      tab_map_name = "map";
-
-       // field to display the version at the bottom of the screen
-       private TextView mVersion;
-
-       private boolean idle_mode = false;
-
-       public Location location = null;
-
-       private AltosState      state;
-       private SavedState      saved_state;
-
-       // Tabs
-       TabHost         mTabHost;
-       AltosViewPager  mViewPager;
-       TabsAdapter     mTabsAdapter;
-       ArrayList<AltosDroidTab> mTabs = new ArrayList<AltosDroidTab>();
-       int             tabHeight;
-
-       // Timer and Saved flight state for Age calculation
-       private Timer timer;
-
-       TelemetryState  telemetry_state;
-       Tracker[]       trackers;
-
-
-       UsbDevice       pending_usb_device;
-       boolean         start_with_usb;
-
-       // Service
-       private boolean mIsBound   = false;
-       private Messenger mService = null;
-       final Messenger mMessenger = new Messenger(new IncomingHandler(this));
-
-       // Text to Speech
-       private AltosVoice mAltosVoice = null;
-
-       // The Handler that gets information back from the Telemetry Service
-       static class IncomingHandler extends Handler {
-               private final WeakReference<AltosDroid> mAltosDroid;
-               IncomingHandler(AltosDroid ad) { mAltosDroid = new WeakReference<AltosDroid>(ad); }
-
-               @Override
-               public void handleMessage(Message msg) {
-                       AltosDroid ad = mAltosDroid.get();
-
-                       switch (msg.what) {
-                       case MSG_STATE:
-                               if (msg.obj == null) {
-                                       AltosDebug.debug("telemetry_state null!");
-                                       return;
-                               }
-                               ad.update_state((TelemetryState) msg.obj);
-                               break;
-                       case MSG_UPDATE_AGE:
-                               ad.update_age();
-                               break;
-                       case MSG_IDLE_MODE:
-                               ad.idle_mode = (Boolean) msg.obj;
-                               ad.update_state(null);
-                               break;
-                       }
-               }
-       };
-
-
-       private ServiceConnection mConnection = new ServiceConnection() {
-               public void onServiceConnected(ComponentName className, IBinder service) {
-                       mService = new Messenger(service);
-                       try {
-                               Message msg = Message.obtain(null, TelemetryService.MSG_REGISTER_CLIENT);
-                               msg.replyTo = mMessenger;
-                               mService.send(msg);
-                       } catch (RemoteException e) {
-                               // In this case the service has crashed before we could even do anything with it
-                       }
-                       if (pending_usb_device != null) {
-                               try {
-                                       mService.send(Message.obtain(null, TelemetryService.MSG_OPEN_USB, pending_usb_device));
-                                       pending_usb_device = null;
-                               } catch (RemoteException e) {
-                               }
-                       }
-               }
-
-               public void onServiceDisconnected(ComponentName className) {
-                       // This is called when the connection with the service has been unexpectedly disconnected - process crashed.
-                       mService = null;
-               }
-       };
-
-       void doBindService() {
-               bindService(new Intent(this, TelemetryService.class), mConnection, Context.BIND_AUTO_CREATE);
-               mIsBound = true;
-       }
-
-       void doUnbindService() {
-               if (mIsBound) {
-                       // If we have received the service, and hence registered with it, then now is the time to unregister.
-                       if (mService != null) {
-                               try {
-                                       Message msg = Message.obtain(null, TelemetryService.MSG_UNREGISTER_CLIENT);
-                                       msg.replyTo = mMessenger;
-                                       mService.send(msg);
-                               } catch (RemoteException e) {
-                                       // There is nothing special we need to do if the service has crashed.
-                               }
-                       }
-                       // Detach our existing connection.
-                       unbindService(mConnection);
-                       mIsBound = false;
-               }
-       }
-
-       public void registerTab(AltosDroidTab mTab) {
-               mTabs.add(mTab);
-       }
-
-       public void unregisterTab(AltosDroidTab mTab) {
-               mTabs.remove(mTab);
-       }
-
-       public void units_changed(boolean imperial_units) {
-               for (AltosDroidTab mTab : mTabs)
-                       mTab.units_changed(imperial_units);
-       }
-
-       void update_title(TelemetryState telemetry_state) {
-               switch (telemetry_state.connect) {
-               case TelemetryState.CONNECT_CONNECTED:
-                       if (telemetry_state.config != null) {
-                               String str = String.format("S/N %d %6.3f MHz%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]));
-                               setTitle(str);
-                       } else {
-                               setTitle(R.string.title_connected_to);
-                       }
-                       break;
-               case TelemetryState.CONNECT_CONNECTING:
-                       if (telemetry_state.address != null)
-                               setTitle(String.format("Connecting to %s...", telemetry_state.address.name));
-                       else
-                               setTitle("Connecting to something...");
-                       break;
-               case TelemetryState.CONNECT_DISCONNECTED:
-               case TelemetryState.CONNECT_NONE:
-                       setTitle(R.string.title_not_connected);
-                       break;
-               }
-       }
-
-       void start_timer() {
-               if (timer == null) {
-                       timer = new Timer();
-                       timer.scheduleAtFixedRate(new TimerTask(){ public void run() {onTimerTick();}}, 1000L, 1000L);
-               }
-       }
-
-       void stop_timer() {
-               if (timer != null) {
-                       timer.cancel();
-                       timer.purge();
-                       timer = null;
-               }
-       }
-
-       int     selected_serial = 0;
-       int     current_serial;
-       long    switch_time;
-
-       void set_switch_time() {
-               switch_time = System.currentTimeMillis();
-               selected_serial = 0;
-       }
-
-       boolean registered_units_listener;
-
-       void update_state(TelemetryState new_telemetry_state) {
-
-               if (new_telemetry_state != null)
-                       telemetry_state = new_telemetry_state;
-
-               if (selected_serial != 0)
-                       current_serial = selected_serial;
-
-               if (current_serial == 0)
-                       current_serial = telemetry_state.latest_serial;
-
-               if (!registered_units_listener) {
-                       registered_units_listener = true;
-                       AltosPreferences.register_units_listener(this);
-               }
-
-               int     num_trackers = 0;
-               for (AltosState s : telemetry_state.states.values()) {
-                       num_trackers++;
-               }
-
-               trackers = new Tracker[num_trackers + 1];
-
-               int n = 0;
-               trackers[n++] = new Tracker(0, "auto", 0.0);
-
-               for (AltosState s : telemetry_state.states.values())
-                       trackers[n++] = new Tracker(s);
-
-               Arrays.sort(trackers);
-
-               update_title(telemetry_state);
-
-               AltosState      state = null;
-               boolean         aged = true;
-
-               if (telemetry_state.states.containsKey(current_serial)) {
-                       state = telemetry_state.states.get(current_serial);
-                       int age = state_age(state.received_time);
-                       if (age < 20)
-                               aged = false;
-                       if (current_serial == selected_serial)
-                               aged = false;
-                       else if (switch_time != 0 && (switch_time - state.received_time) > 0)
-                               aged = true;
-               }
-
-               if (aged) {
-                       AltosState      newest_state = null;
-                       int             newest_age = 0;
-
-                       for (int serial : telemetry_state.states.keySet()) {
-                               AltosState      existing = telemetry_state.states.get(serial);
-                               int             existing_age = state_age(existing.received_time);
-
-                               if (newest_state == null || existing_age < newest_age) {
-                                       newest_state = existing;
-                                       newest_age = existing_age;
-                               }
-                       }
-
-                       if (newest_state != null)
-                               state = newest_state;
-               }
-
-               update_ui(telemetry_state, state, telemetry_state.quiet);
-
-               start_timer();
-       }
-
-       boolean same_string(String a, String b) {
-               if (a == null) {
-                       if (b == null)
-                               return true;
-                       return false;
-               } else {
-                       if (b == null)
-                               return false;
-                       return a.equals(b);
-               }
-       }
-
-
-       private int blend_component(int a, int b, double r, int shift, int mask) {
-               return ((int) (((a >> shift) & mask) * r + ((b >> shift) & mask) * (1 - r)) & mask) << shift;
-       }
-       private int blend_color(int a, int b, double r) {
-               return (blend_component(a, b, r, 0, 0xff) |
-                       blend_component(a, b, r, 8, 0xff) |
-                       blend_component(a, b, r, 16, 0xff) |
-                       blend_component(a, b, r, 24, 0xff));
-       }
-
-       int state_age(long received_time) {
-               return (int) ((System.currentTimeMillis() - received_time + 500) / 1000);
-       }
-
-       void set_screen_on(int age) {
-               if (age < 60)
-                       getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
-               else
-                       getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
-       }
-
-       void update_age() {
-               if (saved_state != null) {
-                       int age = state_age(saved_state.received_time);
-
-                       double age_scale = age / 100.0;
-
-                       if (age_scale > 1.0)
-                               age_scale = 1.0;
-
-                       mAgeView.setTextColor(blend_color(mAgeOldColor, mAgeNewColor, age_scale));
-
-                       set_screen_on(age);
-
-                       String  text;
-                       if (age < 60)
-                               text = String.format("%ds", age);
-                       else if (age < 60 * 60)
-                               text = String.format("%dm", age / 60);
-                       else if (age < 60 * 60 * 24)
-                               text = String.format("%dh", age / (60 * 60));
-                       else
-                               text = String.format("%dd", age / (24 * 60 * 60));
-                       mAgeView.setText(text);
-               }
-       }
-
-       void update_ui(TelemetryState telem_state, AltosState state, boolean quiet) {
-
-               this.state = state;
-
-               int prev_state = AltosLib.ao_flight_invalid;
-
-               AltosGreatCircle from_receiver = null;
-
-               if (saved_state != null)
-                       prev_state = saved_state.state;
-
-               if (state != null) {
-                       set_screen_on(state_age(state.received_time));
-
-                       if (state.state() == AltosLib.ao_flight_stateless) {
-                               boolean prev_locked = false;
-                               boolean locked = false;
-
-                               if(state.gps != null)
-                                       locked = state.gps.locked;
-                               if (saved_state != null)
-                                       prev_locked = saved_state.locked;
-                               if (prev_locked != locked) {
-                                       String currentTab = mTabHost.getCurrentTabTag();
-                                       if (locked) {
-                                               if (currentTab.equals(tab_pad_name)) mTabHost.setCurrentTabByTag(tab_flight_name);
-                                       } else {
-                                               if (currentTab.equals(tab_flight_name)) mTabHost.setCurrentTabByTag(tab_pad_name);
-                                       }
-                               }
-                       } else {
-                               if (prev_state != state.state()) {
-                                       String currentTab = mTabHost.getCurrentTabTag();
-                                       switch (state.state()) {
-                                       case AltosLib.ao_flight_boost:
-                                               if (currentTab.equals(tab_pad_name)) mTabHost.setCurrentTabByTag(tab_flight_name);
-                                               break;
-                                       case AltosLib.ao_flight_landed:
-                                               if (currentTab.equals(tab_flight_name)) mTabHost.setCurrentTabByTag(tab_recover_name);
-                                               break;
-                                       case AltosLib.ao_flight_stateless:
-                                               if (currentTab.equals(tab_pad_name)) mTabHost.setCurrentTabByTag(tab_flight_name);
-                                               break;
-                                       }
-                               }
-                       }
-
-                       if (location != null && state.gps != null && state.gps.locked) {
-                               double altitude = 0;
-                               if (location.hasAltitude())
-                                       altitude = location.getAltitude();
-                               from_receiver = new AltosGreatCircle(location.getLatitude(),
-                                                                    location.getLongitude(),
-                                                                    altitude,
-                                                                    state.gps.lat,
-                                                                    state.gps.lon,
-                                                                    state.gps.alt);
-                       }
-
-                       if (saved_state == null || !same_string(saved_state.callsign, state.cal_data().callsign)) {
-                               mCallsignView.setText(state.cal_data().callsign);
-                       }
-                       if (saved_state == null || state.cal_data().serial != saved_state.serial) {
-                               if (state.cal_data().serial == AltosLib.MISSING)
-                                       mSerialView.setText("");
-                               else
-                                       mSerialView.setText(String.format("%d", state.cal_data().serial));
-                       }
-                       if (saved_state == null || state.cal_data().flight != saved_state.flight) {
-                               if (state.cal_data().flight == AltosLib.MISSING)
-                                       mFlightView.setText("");
-                               else
-                                       mFlightView.setText(String.format("%d", state.cal_data().flight));
-                       }
-                       if (saved_state == null || state.state() != saved_state.state) {
-                               if (state.state() == AltosLib.ao_flight_stateless) {
-                                       mStateLayout.setVisibility(View.GONE);
-                               } else {
-                                       mStateView.setText(state.state_name());
-                                       mStateLayout.setVisibility(View.VISIBLE);
-                               }
-                       }
-                       if (saved_state == null || state.rssi != saved_state.rssi) {
-                               if (state.rssi == AltosLib.MISSING)
-                                       mRSSIView.setText("");
-                               else
-                                       mRSSIView.setText(String.format("%d", state.rssi));
-                       }
-                       saved_state = new SavedState(state);
-               }
-
-               for (AltosDroidTab mTab : mTabs)
-                       mTab.update_ui(telem_state, state, from_receiver, location, mTab == mTabsAdapter.currentItem());
-
-               AltosDebug.debug("quiet %b\n", quiet);
-               if (mAltosVoice != null)
-                       mAltosVoice.tell(telem_state, state, from_receiver, location, (AltosDroidTab) mTabsAdapter.currentItem(), quiet);
-
-       }
-
-       private void onTimerTick() {
-               try {
-                       mMessenger.send(Message.obtain(null, MSG_UPDATE_AGE));
-               } catch (RemoteException e) {
-               }
-       }
-
-       static String pos(double p, String pos, String neg) {
-               String  h = pos;
-               if (p == AltosLib.MISSING)
-                       return "";
-               if (p < 0) {
-                       h = neg;
-                       p = -p;
-               }
-               int deg = (int) Math.floor(p);
-               double min = (p - Math.floor(p)) * 60.0;
-               return String.format("%d°%9.4f\" %s", deg, min, h);
-       }
-
-       static String number(String format, double value) {
-               if (value == AltosLib.MISSING)
-                       return "";
-               return String.format(format, value);
-       }
-
-       static String integer(String format, int value) {
-               if (value == AltosLib.MISSING)
-                       return "";
-               return String.format(format, value);
-       }
-
-       private View create_tab_view(String label) {
-               LayoutInflater inflater = (LayoutInflater) this.getLayoutInflater();
-               View tab_view = inflater.inflate(R.layout.tab_layout, null);
-               TextView text_view = (TextView) tab_view.findViewById (R.id.tabLabel);
-               text_view.setText(label);
-               return tab_view;
-       }
-
-       @Override
-       public void onCreate(Bundle savedInstanceState) {
-               super.onCreate(savedInstanceState);
-               AltosDebug.init(this);
-               AltosDebug.debug("+++ ON CREATE +++");
-
-               // Initialise preferences
-               AltosDroidPreferences.init(this);
-
-               fm = getSupportFragmentManager();
-
-               // Set up the window layout
-               setContentView(R.layout.altosdroid);
-
-               // Create the Tabs and ViewPager
-               mTabHost = (TabHost)findViewById(android.R.id.tabhost);
-               mTabHost.setup();
-
-               mViewPager = (AltosViewPager)findViewById(R.id.pager);
-               mViewPager.setOffscreenPageLimit(4);
-
-               mTabsAdapter = new TabsAdapter(this, mTabHost, mViewPager);
-
-               mTabsAdapter.addTab(mTabHost.newTabSpec(tab_pad_name).setIndicator(create_tab_view("Pad")), TabPad.class, null);
-               mTabsAdapter.addTab(mTabHost.newTabSpec(tab_flight_name).setIndicator(create_tab_view("Flight")), TabFlight.class, null);
-               mTabsAdapter.addTab(mTabHost.newTabSpec(tab_recover_name).setIndicator(create_tab_view("Recover")), TabRecover.class, null);
-               mTabsAdapter.addTab(mTabHost.newTabSpec(tab_map_name).setIndicator(create_tab_view("Map")), TabMap.class, null);
-
-               // Display the Version
-               mVersion = (TextView) findViewById(R.id.version);
-               mVersion.setText("Version: " + BuildInfo.version +
-                                " Built: " + BuildInfo.builddate + " " + BuildInfo.buildtime + " " + BuildInfo.buildtz +
-                                " (" + BuildInfo.branch + "-" + BuildInfo.commitnum + "-" + BuildInfo.commithash + ")");
-
-               mCallsignView  = (TextView) findViewById(R.id.callsign_value);
-               mRSSIView      = (TextView) findViewById(R.id.rssi_value);
-               mSerialView    = (TextView) findViewById(R.id.serial_value);
-               mFlightView    = (TextView) findViewById(R.id.flight_value);
-               mStateLayout   = (RelativeLayout) findViewById(R.id.state_container);
-               mStateView     = (TextView) findViewById(R.id.state_value);
-               mAgeView       = (TextView) findViewById(R.id.age_value);
-               mAgeNewColor   = mAgeView.getTextColors().getDefaultColor();
-               mAgeOldColor   = getResources().getColor(R.color.old_color);
-       }
-
-       private void ensureBluetooth() {
-               // Get local Bluetooth adapter
-               mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
-
-               /* 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);
-               }
-       }
-
-       private boolean check_usb() {
-               UsbDevice       device = AltosUsb.find_device(this, AltosLib.product_basestation);
-
-               if (device != null) {
-                       Intent          i = new Intent(this, AltosDroid.class);
-                       PendingIntent   pi = PendingIntent.getActivity(this, 0, new Intent("hello world", null, this, AltosDroid.class), 0);
-
-                       if (AltosUsb.request_permission(this, device, pi)) {
-                               connectUsb(device);
-                       }
-                       start_with_usb = true;
-                       return true;
-               }
-
-               start_with_usb = false;
-
-               return false;
-       }
-
-       private void noticeIntent(Intent intent) {
-
-               /* Ok, this is pretty convenient.
-                *
-                * When a USB device is plugged in, and our 'hotplug'
-                * intent registration fires, we get an Intent with
-                * EXTRA_DEVICE set.
-                *
-                * When we start up and see a usb device and request
-                * permission to access it, that queues a
-                * PendingIntent, which has the EXTRA_DEVICE added in,
-                * along with the EXTRA_PERMISSION_GRANTED field as
-                * well.
-                *
-                * So, in both cases, we get the device name using the
-                * same call. We check to see if access was granted,
-                * in which case we ignore the device field and do our
-                * usual startup thing.
-                */
-
-               UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
-               boolean granted = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true);
-
-               AltosDebug.debug("intent %s device %s granted %s", intent, device, granted);
-
-               if (!granted)
-                       device = null;
-
-               if (device != null) {
-                       AltosDebug.debug("intent has usb device " + device.toString());
-                       connectUsb(device);
-               } else {
-
-                       /* 'granted' is only false if this intent came
-                        * from the request_permission call and
-                        * permission was denied. In which case, we
-                        * don't want to loop forever...
-                        */
-                       if (granted) {
-                               AltosDebug.debug("check for a USB device at startup");
-                               if (check_usb())
-                                       return;
-                       }
-                       AltosDebug.debug("Starting by looking for bluetooth devices");
-                       ensureBluetooth();
-               }
-       }
-
-       @Override
-       public void onStart() {
-               super.onStart();
-               AltosDebug.debug("++ ON START ++");
-
-               set_switch_time();
-
-               noticeIntent(getIntent());
-
-               // Start Telemetry Service
-               String  action = start_with_usb ? ACTION_USB : ACTION_BLUETOOTH;
-
-               startService(new Intent(action, null, AltosDroid.this, TelemetryService.class));
-
-               doBindService();
-
-               if (mAltosVoice == null)
-                       mAltosVoice = new AltosVoice(this);
-
-       }
-
-       @Override
-       public void onNewIntent(Intent intent) {
-               super.onNewIntent(intent);
-               AltosDebug.debug("onNewIntent");
-               noticeIntent(intent);
-       }
-
-       @Override
-       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, state, true);
-       }
-
-       @Override
-       public void onPause() {
-               super.onPause();
-               AltosDebug.debug("- ON PAUSE -");
-               // Stop listening for location updates
-               ((LocationManager) getSystemService(Context.LOCATION_SERVICE)).removeUpdates(this);
-       }
-
-       @Override
-       public void onStop() {
-               super.onStop();
-               AltosDebug.debug("-- ON STOP --");
-       }
-
-       @Override
-       public void onDestroy() {
-               super.onDestroy();
-               AltosDebug.debug("--- ON DESTROY ---");
-
-               doUnbindService();
-               if (mAltosVoice != null) {
-                       mAltosVoice.stop();
-                       mAltosVoice = null;
-               }
-               stop_timer();
-       }
-
-       protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-               AltosDebug.debug("onActivityResult " + resultCode);
-               switch (requestCode) {
-               case REQUEST_CONNECT_DEVICE:
-                       // When DeviceListActivity returns with a device to connect to
-                       if (resultCode == Activity.RESULT_OK) {
-                               connectDevice(data);
-                       }
-                       break;
-               case REQUEST_ENABLE_BT:
-                       // When the request to enable Bluetooth returns
-                       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.debug("BT not enabled");
-                       }
-                       break;
-               case REQUEST_IDLE_MODE:
-                       if (resultCode == Activity.RESULT_OK)
-                               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) {
-               if (mService == null)
-                       pending_usb_device = device;
-               else {
-                       // Attempt to connect to the device
-                       try {
-                               mService.send(Message.obtain(null, TelemetryService.MSG_OPEN_USB, device));
-                               AltosDebug.debug("Sent OPEN_USB message");
-                       } catch (RemoteException e) {
-                               AltosDebug.debug("connect device message failed");
-                       }
-               }
-       }
-
-       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 {
-                       String address = data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
-                       String name = data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_NAME);
-
-                       AltosDebug.debug("Connecting to " + address + " " + name);
-                       DeviceAddress   a = new DeviceAddress(address, name);
-                       mService.send(Message.obtain(null, TelemetryService.MSG_CONNECT, a));
-                       AltosDebug.debug("Sent connecting message");
-               } catch (RemoteException e) {
-                       AltosDebug.debug("connect device message failed");
-               }
-       }
-
-       private void disconnectDevice(boolean remember) {
-               try {
-                       mService.send(Message.obtain(null, TelemetryService.MSG_DISCONNECT, (Boolean) remember));
-               } catch (RemoteException e) {
-               }
-       }
-
-       private void idle_mode(Intent data) {
-               int type = data.getIntExtra(IdleModeActivity.EXTRA_IDLE_RESULT, -1);
-               Message msg;
-
-               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;
-               }
-       }
-
-       @Override
-       public boolean onCreateOptionsMenu(Menu menu) {
-               MenuInflater inflater = getMenuInflater();
-               inflater.inflate(R.menu.option_menu, menu);
-               return true;
-       }
-
-       void setFrequency(double freq) {
-               try {
-                       mService.send(Message.obtain(null, TelemetryService.MSG_SETFREQUENCY, freq));
-                       set_switch_time();
-               } catch (RemoteException e) {
-               }
-       }
-
-       void setFrequency(AltosFrequency frequency) {
-               setFrequency (frequency.frequency);
-       }
-
-       void setBaud(int baud) {
-               try {
-                       mService.send(Message.obtain(null, TelemetryService.MSG_SETBAUD, baud));
-                       set_switch_time();
-               } catch (RemoteException e) {
-               }
-       }
-
-       void setBaud(String baud) {
-               try {
-                       int     value = Integer.parseInt(baud);
-                       int     rate = AltosLib.ao_telemetry_rate_38400;
-                       switch (value) {
-                       case 2400:
-                               rate = AltosLib.ao_telemetry_rate_2400;
-                               break;
-                       case 9600:
-                               rate = AltosLib.ao_telemetry_rate_9600;
-                               break;
-                       case 38400:
-                               rate = AltosLib.ao_telemetry_rate_38400;
-                               break;
-                       }
-                       setBaud(rate);
-               } catch (NumberFormatException e) {
-               }
-       }
-
-       void select_tracker(int serial) {
-               int i;
-
-               AltosDebug.debug("select tracker %d\n", serial);
-
-               if (serial == selected_serial) {
-                       AltosDebug.debug("%d already selected\n", serial);
-                       return;
-               }
-
-               if (serial != 0) {
-                       for (i = 0; i < trackers.length; i++)
-                               if (trackers[i].serial == serial)
-                                       break;
-
-                       if (i == trackers.length) {
-                               AltosDebug.debug("attempt to select unknown tracker %d\n", serial);
-                               return;
-                       }
-               }
-
-               current_serial = selected_serial = serial;
-               update_state(null);
-       }
-
-       void touch_trackers(Integer[] serials) {
-               AlertDialog.Builder builder_tracker = new AlertDialog.Builder(this);
-               builder_tracker.setTitle("Select Tracker");
-
-               final Tracker[] my_trackers = new Tracker[serials.length + 1];
-
-               my_trackers[0] = new Tracker(null);
-
-               for (int i = 0; i < serials.length; i++) {
-                       AltosState      s = telemetry_state.states.get(serials[i]);
-                       my_trackers[i+1] = new Tracker(s);
-               }
-               builder_tracker.setItems(my_trackers,
-                                        new DialogInterface.OnClickListener() {
-                                                public void onClick(DialogInterface dialog, int item) {
-                                                        if (item == 0)
-                                                                select_tracker(0);
-                                                        else
-                                                                select_tracker(my_trackers[item].serial);
-                                                }
-                                        });
-               AlertDialog alert_tracker = builder_tracker.create();
-               alert_tracker.show();
-       }
-
-       void delete_track(int serial) {
-               try {
-                       mService.send(Message.obtain(null, TelemetryService.MSG_DELETE_SERIAL, (Integer) serial));
-               } catch (Exception ex) {
-               }
-       }
-
-       @Override
-       public boolean onOptionsItemSelected(MenuItem item) {
-               Intent serverIntent = null;
-               switch (item.getItemId()) {
-               case R.id.connect_scan:
-                       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
-                        */
-                       disconnectDevice(false);
-                       return true;
-               case R.id.quit:
-                       AltosDebug.debug("R.id.quit");
-                       disconnectDevice(true);
-                       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 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(frequency_strings,
-                                        new DialogInterface.OnClickListener() {
-                                                public void onClick(DialogInterface dialog, int item) {
-                                                        setFrequency(frequencies[item]);
-                                                }
-                                        });
-                       AlertDialog alert_freq = builder_freq.create();
-                       alert_freq.show();
-                       return true;
-               case R.id.select_tracker:
-                       if (trackers != null) {
-                               AlertDialog.Builder builder_serial = new AlertDialog.Builder(this);
-                               builder_serial.setTitle("Select a tracker");
-                               builder_serial.setItems(trackers,
-                                                       new DialogInterface.OnClickListener() {
-                                                               public void onClick(DialogInterface dialog, int item) {
-                                                                       System.out.printf("select item %d %s\n", item, trackers[item].display);
-                                                                       if (item == 0)
-                                                                               select_tracker(0);
-                                                                       else
-                                                                               select_tracker(trackers[item].serial);
-                                                               }
-                                                       });
-                               AlertDialog alert_serial = builder_serial.create();
-                               alert_serial.show();
-
-                       }
-                       return true;
-               case R.id.delete_track:
-                       if (trackers != null) {
-                               AlertDialog.Builder builder_serial = new AlertDialog.Builder(this);
-                               builder_serial.setTitle("Delete a track");
-                               final Tracker[] my_trackers = new Tracker[trackers.length - 1];
-                               for (int i = 0; i < trackers.length - 1; i++)
-                                       my_trackers[i] = trackers[i+1];
-                               builder_serial.setItems(my_trackers,
-                                                       new DialogInterface.OnClickListener() {
-                                                               public void onClick(DialogInterface dialog, int item) {
-                                                                       delete_track(my_trackers[item].serial);
-                                                               }
-                                                       });
-                               AlertDialog alert_serial = builder_serial.create();
-                               alert_serial.show();
-
-                       }
-                       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) {
-               if (from_receiver == null)
-                       return null;
-
-               if (receiver == null)
-                       return null;
-
-               if (!receiver.hasBearing())
-                       return null;
-
-               float   bearing = receiver.getBearing();
-               float   heading = (float) from_receiver.bearing - bearing;
-
-               while (heading <= -180.0f)
-                       heading += 360.0f;
-               while (heading > 180.0f)
-                       heading -= 360.0f;
-
-               int iheading = (int) (heading + 0.5f);
-
-               if (-1 < iheading && iheading < 1)
-                       return "ahead";
-               else if (iheading < -179 || 179 < iheading)
-                       return "backwards";
-               else if (iheading < 0)
-                       return String.format("left %d°", -iheading);
-               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, state, false);
-       }
-
-       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);
-       }
-}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidLink.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidLink.java
deleted file mode 100644 (file)
index a443b6e..0000000
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright © 2015 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.AltosDroid;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.UUID;
-
-import android.os.Handler;
-
-import org.altusmetrum.altoslib_13.*;
-
-public abstract class AltosDroidLink extends AltosLink {
-
-       Handler         handler;
-
-       Thread          input_thread   = null;
-
-       public double frequency() {
-               return frequency;
-       }
-
-       public int telemetry_rate() {
-               return telemetry_rate;
-       }
-
-       public void save_frequency() {
-               AltosPreferences.set_frequency(0, frequency);
-       }
-
-       public void save_telemetry_rate() {
-               AltosPreferences.set_telemetry_rate(0, telemetry_rate);
-       }
-
-       Object closed_lock = new Object();
-       boolean closing = false;
-       boolean closed = false;
-
-       public boolean closed() {
-               synchronized(closed_lock) {
-                       return closing;
-               }
-       }
-
-       void connected() throws InterruptedException {
-               input_thread = new Thread(this);
-               input_thread.start();
-
-               // Configure the newly connected device for telemetry
-               print("~\nE 0\n");
-               set_monitor(false);
-               AltosDebug.debug("ConnectThread: connected");
-
-               /* Let TelemetryService know we're connected
-                */
-               handler.obtainMessage(TelemetryService.MSG_CONNECTED, this).sendToTarget();
-
-               /* Notify other waiting threads that we're connected now
-                */
-               notifyAll();
-       }
-
-       public void closing() {
-               synchronized(closed_lock) {
-                       AltosDebug.debug("Marked closing true");
-                       closing = true;
-               }
-       }
-
-       private boolean actually_closed() {
-               synchronized(closed_lock) {
-                       return closed;
-               }
-       }
-
-       abstract void close_device();
-
-       public void close() {
-               AltosDebug.debug("close(): begin");
-
-               closing();
-
-               flush_output();
-
-               synchronized (closed_lock) {
-                       AltosDebug.debug("Marked closed true");
-                       closed = true;
-               }
-
-               close_device();
-
-               synchronized(this) {
-
-                       if (input_thread != null) {
-                               AltosDebug.debug("close(): stopping input_thread");
-                               try {
-                                       AltosDebug.debug("close(): input_thread.interrupt().....");
-                                       input_thread.interrupt();
-                                       AltosDebug.debug("close(): input_thread.join().....");
-                                       input_thread.join();
-                               } catch (Exception e) {}
-                               input_thread = null;
-                       }
-                       notifyAll();
-               }
-       }
-
-       abstract int write(byte[] buffer, int len);
-
-       abstract int read(byte[] buffer, int len);
-
-       private static final int buffer_size = 64;
-
-       private byte[] in_buffer = new byte[buffer_size];
-       private byte[] out_buffer = new byte[buffer_size];
-       private int buffer_len = 0;
-       private int buffer_off = 0;
-       private int out_buffer_off = 0;
-
-       private byte[] debug_chars = new byte[buffer_size];
-       private int debug_off;
-
-       private void debug_input(byte b) {
-               if (b == '\n') {
-                       AltosDebug.debug("            " + new String(debug_chars, 0, debug_off));
-                       debug_off = 0;
-               } else {
-                       if (debug_off < buffer_size)
-                               debug_chars[debug_off++] = b;
-               }
-       }
-
-       private void disconnected() {
-               if (closed()) {
-                       AltosDebug.debug("disconnected after closed");
-                       return;
-               }
-
-               AltosDebug.debug("Sending disconnected message");
-               handler.obtainMessage(TelemetryService.MSG_DISCONNECTED, this).sendToTarget();
-       }
-
-       public int getchar() {
-
-               if (actually_closed())
-                       return ERROR;
-
-               while (buffer_off == buffer_len) {
-                       buffer_len = read(in_buffer, buffer_size);
-                       if (buffer_len < 0) {
-                               AltosDebug.debug("ERROR returned from getchar()");
-                               disconnected();
-                               return ERROR;
-                       }
-                       buffer_off = 0;
-               }
-//             if (AltosDebug.D)
-//                     debug_input(in_buffer[buffer_off]);
-               return in_buffer[buffer_off++];
-       }
-
-       public void flush_output() {
-               super.flush_output();
-
-               if (actually_closed()) {
-                       out_buffer_off = 0;
-                       return;
-               }
-
-               while (out_buffer_off != 0) {
-                       int     sent = write(out_buffer, out_buffer_off);
-
-                       if (sent <= 0) {
-                               AltosDebug.debug("flush_output() failed");
-                               out_buffer_off = 0;
-                               break;
-                       }
-
-                       if (sent < out_buffer_off)
-                               System.arraycopy(out_buffer, 0, out_buffer, sent, out_buffer_off - sent);
-
-                       out_buffer_off -= sent;
-               }
-       }
-
-       public void putchar(byte c) {
-               out_buffer[out_buffer_off++] = c;
-               if (out_buffer_off == buffer_size)
-                       flush_output();
-       }
-
-       public void print(String data) {
-               byte[] bytes = data.getBytes();
-//             AltosDebug.debug(data.replace('\n', '\\'));
-               for (byte b : bytes)
-                       putchar(b);
-       }
-
-       public AltosDroidLink(Handler handler) {
-               this.handler = handler;
-       }
-}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapInterface.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapInterface.java
deleted file mode 100644 (file)
index 6da90a3..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright © 2015 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.AltosDroid;
-
-import java.util.*;
-import java.io.*;
-import android.location.Location;
-import org.altusmetrum.altoslib_13.*;
-
-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);
-
-       public void show(TelemetryState telem_state, AltosState state, AltosGreatCircle from_receiver, Location receiver);
-}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapSourceListener.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapSourceListener.java
deleted file mode 100644 (file)
index 294094c..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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.
- */
-
-package org.altusmetrum.AltosDroid;
-
-public interface AltosDroidMapSourceListener {
-       public void map_source_changed(int map_source);
-}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java
deleted file mode 100644 (file)
index 8bb78c0..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-package org.altusmetrum.AltosDroid;
-
-import java.io.*;
-import java.util.*;
-import java.text.*;
-
-import android.content.Context;
-import org.altusmetrum.altoslib_13.*;
-
-public class AltosDroidPreferences extends AltosPreferences {
-
-       /* Active device preference name */
-       final static String activeDeviceAddressPreference = "ACTIVE-DEVICE-ADDRESS";
-       final static String activeDeviceNamePreference = "ACTIVE-DEVICE-NAME";
-
-       static DeviceAddress    active_device_address;
-
-       /* Map source preference name */
-       final static String mapSourcePreference = "MAP-SOURCE";
-
-       static final int        MAP_SOURCE_OFFLINE = 0;
-       static final int        MAP_SOURCE_ONLINE = 1;
-
-       static int      map_source;
-
-       public static void init(Context context) {
-               if (backend != null)
-                       return;
-
-               AltosPreferences.init(new AltosDroidPreferencesBackend(context));
-
-               String address = backend.getString(activeDeviceAddressPreference, null);
-               String name = backend.getString(activeDeviceNamePreference, null);
-
-               if (address != null && name != null)
-                       active_device_address = new DeviceAddress (address, name);
-
-               map_source = backend.getInt(mapSourcePreference, MAP_SOURCE_ONLINE);
-       }
-
-       public static void set_active_device(DeviceAddress address) {
-               synchronized(backend) {
-                       active_device_address = address;
-                       if (active_device_address != null) {
-                               backend.putString(activeDeviceAddressPreference, active_device_address.address);
-                               backend.putString(activeDeviceNamePreference, active_device_address.name);
-                       } else {
-                               backend.remove(activeDeviceAddressPreference);
-                               backend.remove(activeDeviceNamePreference);
-                       }
-                       flush_preferences();
-               }
-       }
-
-       public static DeviceAddress active_device() {
-               synchronized(backend) {
-                       return active_device_address;
-               }
-       }
-
-       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() {
-               synchronized(backend) {
-                       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);
-               }
-       }
-}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java
deleted file mode 100644 (file)
index 854fe86..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright © 2012 Mike Beattie <mike@ethernal.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.AltosDroid;
-
-import java.io.File;
-import java.util.Map;
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.os.Environment;
-import android.util.*;
-
-import org.altusmetrum.altoslib_13.*;
-
-public class AltosDroidPreferencesBackend extends AltosPreferencesBackend {
-       public final static String        NAME    = "org.altusmetrum.AltosDroid";
-       private Context                   context = null;
-       private SharedPreferences         prefs   = null;
-       private SharedPreferences.Editor  editor  = null;
-
-       public AltosDroidPreferencesBackend(Context in_context) {
-               this(in_context, NAME);
-       }
-
-       public AltosDroidPreferencesBackend(Context in_context, String in_prefs) {
-               context = in_context;
-               prefs   = context.getSharedPreferences(in_prefs, 0);
-               editor  = prefs.edit();
-       }
-
-       public String[] keys() {
-               Map<String, ?> all = prefs.getAll();
-               Object[] ao = all.keySet().toArray();
-
-               String[] as = new String[ao.length];
-               for (int i = 0; i < ao.length; i++)
-                       as[i] = (String) ao[i];
-               return as;
-       }
-
-       public AltosPreferencesBackend node(String key) {
-               if (!nodeExists(key))
-                       putBoolean(key, true);
-               return new AltosDroidPreferencesBackend(context, key);
-       }
-
-       public boolean nodeExists(String key) {
-               return prefs.contains(key);
-       }
-
-       public boolean getBoolean(String key, boolean def) {
-               return prefs.getBoolean(key, def);
-       }
-
-       public double getDouble(String key, double def) {
-               Float f = Float.valueOf(prefs.getFloat(key, (float)def));
-               return f.doubleValue();
-       }
-
-       public int getInt(String key, int def) {
-               return prefs.getInt(key, def);
-       }
-
-       public String getString(String key, String def) {
-               String  ret;
-               ret = prefs.getString(key, def);
-//             AltosDebug.debug("AltosDroidPreferencesBackend get string %s:\n", key);
-//             if (ret == null)
-//                     AltosDebug.debug("      (null)\n");
-//             else {
-//                     String[] lines = ret.split("\n");
-//                     for (String l : lines)
-//                             AltosDebug.debug("        %s\n", l);
-//             }
-               return ret;
-       }
-
-       public byte[] getBytes(String key, byte[] def) {
-               String save = prefs.getString(key, null);
-
-               if (save == null)
-                       return def;
-
-               byte[] bytes = Base64.decode(save, Base64.DEFAULT);
-               return bytes;
-       }
-
-       public void putBoolean(String key, boolean value) {
-               editor.putBoolean(key, value);
-       }
-
-       public void putDouble(String key, double value) {
-               editor.putFloat(key, (float)value);
-       }
-
-       public void putInt(String key, int value) {
-               editor.putInt(key, value);
-       }
-
-       public void putString(String key, String value) {
-//             AltosDebug.debug("AltosDroidPreferencesBackend put string %s:\n", key);
-//             String[] lines = value.split("\n");
-//             for (String l : lines)
-//                     AltosDebug.debug("        %s\n", l);
-               editor.putString(key, value);
-       }
-
-       public void putBytes(String key, byte[] bytes) {
-               String save = Base64.encodeToString(bytes, Base64.DEFAULT);
-               editor.putString(key, save);
-       }
-
-       public void remove(String key) {
-               AltosDebug.debug("remove preference %s\n", key);
-               editor.remove(key);
-       }
-
-       public void flush() {
-               editor.apply();
-       }
-
-       public File homeDirectory() {
-               return Environment.getExternalStorageDirectory();
-       }
-
-       public void debug(String format, Object ... arguments) {
-               AltosDebug.debug(format, arguments);
-       }
-}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java
deleted file mode 100644 (file)
index 9594f85..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright © 2013 Mike Beattie <mike@ethernal.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.AltosDroid;
-
-import org.altusmetrum.altoslib_13.*;
-import android.location.Location;
-import android.app.Activity;
-import android.graphics.Color;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentTransaction;
-import android.support.v4.app.FragmentManager;
-import android.location.Location;
-import android.widget.TextView;
-
-public abstract class AltosDroidTab extends Fragment implements AltosUnitsListener {
-       TelemetryState          last_telem_state;
-       AltosState              last_state;
-       AltosGreatCircle        last_from_receiver;
-       Location                last_receiver;
-       AltosDroid              altos_droid;
-
-       public abstract void show(TelemetryState telem_state, AltosState state, AltosGreatCircle from_receiver, Location receiver);
-
-       public abstract String tab_name();
-
-       public void units_changed(boolean imperial_units) {
-               if (!isHidden())
-                       show(last_telem_state, last_state, last_from_receiver, last_receiver);
-       }
-
-       public void set_value(TextView text_view,
-                             AltosUnits units,
-                             int width,
-                             double value) {
-               if (value == AltosLib.MISSING)
-                       text_view.setText("");
-               else
-                       text_view.setText(units.show(width, value));
-       }
-
-       public void set_visible(boolean visible) {
-               FragmentTransaction     ft = AltosDroid.fm.beginTransaction();
-               AltosDebug.debug("set visible %b %s\n", visible, tab_name());
-               if (visible) {
-                       ft.show(this);
-                       show(last_telem_state, last_state, last_from_receiver, last_receiver);
-               } else
-                       ft.hide(this);
-               try {
-                       ft.commitAllowingStateLoss();
-               } catch (IllegalStateException ie) {
-               }
-       }
-
-       @Override
-       public void onAttach(Activity activity) {
-               super.onAttach(activity);
-               altos_droid = (AltosDroid) activity;
-               altos_droid.registerTab(this);
-       }
-
-       @Override
-       public void onDetach() {
-               super.onDetach();
-               altos_droid.unregisterTab(this);
-               altos_droid = null;
-       }
-
-       @Override
-       public void onResume() {
-               super.onResume();
-               AltosDebug.debug("onResume tab %s\n", tab_name());
-               set_visible(true);
-       }
-
-       public void update_ui(TelemetryState telem_state, AltosState state,
-                             AltosGreatCircle from_receiver, Location receiver, boolean is_current)
-       {
-               last_telem_state = telem_state;
-               last_state = state;
-               last_from_receiver = from_receiver;
-               last_receiver = receiver;
-               if (is_current)
-                       show(telem_state, state, from_receiver, receiver);
-               else
-                       return;
-       }
-}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOffline.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOffline.java
deleted file mode 100644 (file)
index 1aebcd3..0000000
+++ /dev/null
@@ -1,532 +0,0 @@
-/*
- * Copyright © 2015 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.AltosDroid;
-
-import java.util.*;
-import java.io.*;
-
-import org.altusmetrum.altoslib_13.*;
-
-import android.app.Activity;
-import android.graphics.*;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentTransaction;
-import android.view.*;
-import android.widget.*;
-import android.location.Location;
-import android.content.*;
-import android.util.*;
-
-class Rocket implements Comparable {
-       AltosLatLon     position;
-       String          name;
-       int             serial;
-       long            last_packet;
-       boolean         active;
-       AltosMapOffline map_offline;
-
-       void paint() {
-               map_offline.draw_bitmap(position, map_offline.rocket_bitmap, map_offline.rocket_off_x, map_offline.rocket_off_y);
-               map_offline.draw_text(position, name, 0, 3*map_offline.rocket_bitmap.getHeight()/4);
-       }
-
-       void set_position(AltosLatLon position, long last_packet) {
-               this.position = position;
-               this.last_packet = last_packet;
-       }
-
-       void set_active(boolean active) {
-               this.active = active;
-       }
-
-       public int compareTo(Object o) {
-               Rocket other = (Rocket) o;
-
-               if (active && !other.active)
-                       return 1;
-               if (other.active && !active)
-                       return -1;
-
-               long    diff = last_packet - other.last_packet;
-
-               if (diff > 0)
-                       return 1;
-               if (diff < 0)
-                       return -1;
-               return 0;
-       }
-
-       Rocket(int serial, AltosMapOffline map_offline) {
-               this.serial = serial;
-               this.name = String.format("%d", serial);
-               this.map_offline = map_offline;
-       }
-}
-
-public class AltosMapOffline extends View implements ScaleGestureDetector.OnScaleGestureListener, AltosMapInterface, AltosDroidMapInterface, AltosMapTypeListener {
-       ScaleGestureDetector    scale_detector;
-       boolean                 scaling;
-       AltosMap                map;
-       AltosDroid              altos_droid;
-
-       static int scale = 1;
-
-       AltosLatLon     here;
-       AltosLatLon     there;
-       AltosLatLon     pad;
-
-       Canvas  canvas;
-       Paint   paint;
-
-       Bitmap  pad_bitmap;
-       int     pad_off_x, pad_off_y;
-       Bitmap  rocket_bitmap;
-       int     rocket_off_x, rocket_off_y;
-       Bitmap  here_bitmap;
-       int     here_off_x, here_off_y;
-
-       static  final int       WHITE = 0xffffffff;
-       static  final int       RED   = 0xffff0000;
-       static  final int       PINK  = 0xffff8080;
-       static  final int       YELLOW= 0xffffff00;
-       static  final int       CYAN  = 0xff00ffff;
-       static  final int       BLUE  = 0xff0000ff;
-       static  final int       BLACK = 0xff000000;
-
-       public static final int stateColors[] = {
-               WHITE,  // startup
-               WHITE,  // idle
-               WHITE,  // pad
-               RED,    // boost
-               PINK,   // fast
-               YELLOW, // coast
-               CYAN,   // drogue
-               BLUE,   // main
-               BLACK,  // landed
-               BLACK,  // invalid
-               CYAN,   // stateless
-       };
-
-       /* AltosMapInterface */
-       public void debug(String format, Object ... arguments) {
-               AltosDebug.debug(format, arguments);
-       }
-
-       class MapTile extends AltosMapTile {
-               public void paint(AltosMapTransform t) {
-                       AltosPointInt           pt = new AltosPointInt(t.screen(upper_left));
-
-                       if (canvas.quickReject(pt.x, pt.y, pt.x + px_size, pt.y + px_size, Canvas.EdgeType.AA))
-                               return;
-
-                       AltosImage              altos_image = this.get_image();
-
-                       MapImage                map_image = (MapImage) altos_image;
-
-                       Bitmap                  bitmap = null;
-
-                       if (map_image != null)
-                               bitmap = map_image.bitmap;
-
-                       if (bitmap != null) {
-                               canvas.drawBitmap(bitmap, pt.x, pt.y, paint);
-                       } else {
-                               paint.setColor(0xff808080);
-                               canvas.drawRect(pt.x, pt.y, pt.x + px_size, pt.y + px_size, paint);
-                               if (t.has_location()) {
-                                       String  message = null;
-                                       switch (status) {
-                                       case AltosMapTile.fetching:
-                                               message = "Fetching...";
-                                               break;
-                                       case AltosMapTile.bad_request:
-                                               message = "Internal error";
-                                               break;
-                                       case AltosMapTile.failed:
-                                               message = "Network error";
-                                               break;
-                                       case AltosMapTile.forbidden:
-                                               message = "Outside of known launch areas";
-                                               break;
-                                       }
-                                       if (message != null) {
-                                               Rect    bounds = new Rect();
-                                               paint.getTextBounds(message, 0, message.length(), bounds);
-
-                                               int     width = bounds.right - bounds.left;
-                                               int     height = bounds.bottom - bounds.top;
-
-                                               float x = pt.x + px_size / 2.0f;
-                                               float y = pt.y + px_size / 2.0f;
-                                               x = x - width / 2.0f;
-                                               y = y + height / 2.0f;
-                                               paint.setColor(0xff000000);
-                                               canvas.drawText(message, 0, message.length(), x, y, paint);
-                                       }
-                               }
-                       }
-               }
-
-               public MapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size, int scale) {
-                       super(cache, upper_left, center, zoom, maptype, px_size, scale);
-               }
-
-       }
-
-       public AltosMapTile new_tile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size, int scale) {
-               return new MapTile(cache, upper_left, center, zoom, maptype, px_size, scale);
-       }
-
-       public AltosMapPath new_path() {
-               return null;
-       }
-
-       public AltosMapLine new_line() {
-               return null;
-       }
-
-       class MapImage implements AltosImage {
-               public Bitmap   bitmap;
-
-               public void flush() {
-                       if (bitmap != null) {
-                               bitmap.recycle();
-                               bitmap = null;
-                       }
-               }
-
-               public MapImage(File file) {
-                       bitmap = BitmapFactory.decodeFile(file.getPath());
-               }
-       }
-
-       public AltosImage load_image(File file) throws Exception {
-               return new MapImage(file);
-       }
-
-       class MapMark extends AltosMapMark {
-               public void paint(AltosMapTransform t) {
-               }
-
-               MapMark(double lat, double lon, int state) {
-                       super(lat, lon, state);
-               }
-       }
-
-       public AltosMapMark new_mark(double lat, double lon, int state) {
-               return new MapMark(lat, lon, state);
-       }
-
-       public int width() {
-               return getWidth();
-       }
-
-       public int height() {
-               return getHeight();
-       }
-
-       public void repaint() {
-               postInvalidate();
-       }
-
-       public void repaint(AltosRectangle damage) {
-               postInvalidate(damage.x, damage.y, damage.x + damage.width, damage.y + damage.height);
-       }
-
-       public void set_zoom_label(String label) {
-       }
-
-       public void select_object(AltosLatLon latlon) {
-               if (map.transform == null)
-                       return;
-               ArrayList<Integer>      near = new ArrayList<Integer>();
-
-               for (Rocket rocket : sorted_rockets()) {
-                       if (rocket.position == null) {
-                               debug("rocket %d has no position\n", rocket.serial);
-                               continue;
-                       }
-                       double distance = map.transform.hypot(latlon, rocket.position);
-                       debug("check select %d distance %g width %d\n", rocket.serial, distance, rocket_bitmap.getWidth());
-                       if (distance < rocket_bitmap.getWidth() * 2.0) {
-                               debug("selecting %d\n", rocket.serial);
-                               near.add(rocket.serial);
-                       }
-               }
-               if (near.size() != 0)
-                       altos_droid.touch_trackers(near.toArray(new Integer[0]));
-       }
-
-       class Line {
-               AltosLatLon     a, b;
-
-               void paint() {
-                       if (a != null && b != null) {
-                               AltosPointDouble        a_screen = map.transform.screen(a);
-                               AltosPointDouble        b_screen = map.transform.screen(b);
-                               paint.setColor(0xff8080ff);
-                               canvas.drawLine((float) a_screen.x, (float) a_screen.y,
-                                                   (float) b_screen.x, (float) b_screen.y,
-                                                   paint);
-                       }
-               }
-
-               void set_a(AltosLatLon a) {
-                       this.a = a;
-               }
-
-               void set_b(AltosLatLon b) {
-                       this.b = b;
-               }
-
-               Line() {
-               }
-       }
-
-       Line line = new Line();
-
-       int     stroke_width = 20;
-
-       void draw_text(AltosLatLon lat_lon, String text, int off_x, int off_y) {
-               if (lat_lon != null && map != null && map.transform != null) {
-                       AltosPointInt pt = new AltosPointInt(map.transform.screen(lat_lon));
-
-                       Rect    bounds = new Rect();
-                       paint.getTextBounds(text, 0, text.length(), bounds);
-
-                       int     width = bounds.right - bounds.left;
-                       int     height = bounds.bottom - bounds.top;
-
-                       float x = pt.x;
-                       float y = pt.y;
-                       x = x - width / 2.0f - off_x;
-                       y = y + height / 2.0f - off_y;
-                       paint.setColor(0xff000000);
-                       canvas.drawText(text, 0, text.length(), x, y, paint);
-               }
-       }
-
-       HashMap<Integer,Rocket> rockets = new HashMap<Integer,Rocket>();
-
-       void draw_bitmap(AltosLatLon lat_lon, Bitmap bitmap, int off_x, int off_y) {
-               if (lat_lon != null && map != null && map.transform != null) {
-                       AltosPointInt pt = new AltosPointInt(map.transform.screen(lat_lon));
-
-                       canvas.drawBitmap(bitmap, pt.x - off_x, pt.y - off_y, paint);
-               }
-       }
-
-       private Rocket[] sorted_rockets() {
-               Rocket[]        rocket_array = rockets.values().toArray(new Rocket[0]);
-
-               Arrays.sort(rocket_array);
-               return rocket_array;
-       }
-
-       private void draw_positions() {
-               line.set_a(there);
-               line.set_b(here);
-               line.paint();
-               draw_bitmap(pad, pad_bitmap, pad_off_x, pad_off_y);
-
-               for (Rocket rocket : sorted_rockets())
-                       rocket.paint();
-               draw_bitmap(here, here_bitmap, here_off_x, here_off_y);
-       }
-
-       @Override public void invalidate() {
-               Rect r = new Rect();
-               getDrawingRect(r);
-               super.invalidate();
-       }
-
-       @Override public void invalidate(int l, int t, int r, int b) {
-               Rect rect = new Rect();
-               getDrawingRect(rect);
-               super.invalidate();
-       }
-
-       @Override
-       protected void onDraw(Canvas view_canvas) {
-               if (map == null) {
-                       debug("MapView draw without map\n");
-                       return;
-               }
-               canvas = view_canvas;
-               paint = new Paint(Paint.ANTI_ALIAS_FLAG);
-               paint.setStrokeWidth(stroke_width);
-               paint.setStrokeCap(Paint.Cap.ROUND);
-               paint.setStrokeJoin(Paint.Join.ROUND);
-               paint.setTextSize(40);
-               map.paint();
-               draw_positions();
-               canvas = null;
-       }
-
-       public boolean onScale(ScaleGestureDetector detector) {
-               float   f = detector.getScaleFactor();
-
-               if (f <= 0.8) {
-                       map.set_zoom_centre(map.get_zoom() - 1, new AltosPointInt((int) detector.getFocusX(), (int) detector.getFocusY()));
-                       return true;
-               }
-               if (f >= 1.2) {
-                       map.set_zoom_centre(map.get_zoom() + 1, new AltosPointInt((int) detector.getFocusX(), (int) detector.getFocusY()));
-                       return true;
-               }
-               return false;
-       }
-
-       public boolean onScaleBegin(ScaleGestureDetector detector) {
-               return true;
-       }
-
-       public void onScaleEnd(ScaleGestureDetector detector) {
-       }
-
-       @Override
-       public boolean dispatchTouchEvent(MotionEvent event) {
-               scale_detector.onTouchEvent(event);
-
-               if (scale_detector.isInProgress()) {
-                       scaling = true;
-               }
-
-               if (scaling) {
-                       if (event.getAction() == MotionEvent.ACTION_UP) {
-                               scaling = false;
-                       }
-                       return true;
-               }
-
-               if (event.getAction() == MotionEvent.ACTION_DOWN) {
-                       map.touch_start((int) event.getX(), (int) event.getY(), true);
-               } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
-                       map.touch_continue((int) event.getX(), (int) event.getY(), true);
-               } else if (event.getAction() == MotionEvent.ACTION_UP) {
-                       map.touch_stop((int) event.getX(), (int) event.getY(), true);
-               }
-               return true;
-       }
-
-       double  mapAccuracy;
-
-       public void center(double lat, double lon, double accuracy) {
-               if (mapAccuracy <= 0 || accuracy < mapAccuracy/10 || (map != null && !map.has_centre())) {
-                       if (map != null)
-                               map.maybe_centre(lat, lon);
-                       mapAccuracy = accuracy;
-               }
-       }
-
-       public void set_visible(boolean visible) {
-               if (visible)
-                       setVisibility(VISIBLE);
-               else
-                       setVisibility(GONE);
-       }
-
-       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)
-                               pad = new AltosLatLon(state.pad_lat, state.pad_lon);
-               }
-
-               if (telem_state != null) {
-                       Integer[] old_serial = rockets.keySet().toArray(new Integer[0]);
-                       Integer[] new_serial = telem_state.states.keySet().toArray(new Integer[0]);
-
-                       /* remove deleted keys */
-                       for (int serial : old_serial) {
-                               if (!telem_state.states.containsKey(serial))
-                                       rockets.remove(serial);
-                       }
-
-                       /* set remaining keys */
-
-                       for (int serial : new_serial) {
-                               Rocket          rocket;
-                               AltosState      t_state = telem_state.states.get(serial);
-                               if (rockets.containsKey(serial))
-                                       rocket = rockets.get(serial);
-                               else {
-                                       rocket = new Rocket(serial, this);
-                                       rockets.put(serial, rocket);
-                               }
-                               if (t_state.gps != null) {
-                                       AltosLatLon     latlon = new AltosLatLon(t_state.gps.lat, t_state.gps.lon);
-                                       rocket.set_position(latlon, t_state.received_time);
-                                       if (state.cal_data().serial == serial)
-                                               there = latlon;
-                               }
-                               if (state != null)
-                                       rocket.set_active(state.cal_data().serial == serial);
-                       }
-               }
-               if (receiver != null) {
-                       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, scale);
-               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 */
-               pad_off_x = pad_bitmap.getWidth() / 2;
-               pad_off_y = pad_bitmap.getHeight();
-
-               rocket_bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.rocket);
-               /* arrow at the bottom of the rocket image */
-               rocket_off_x = rocket_bitmap.getWidth() / 2;
-               rocket_off_y = rocket_bitmap.getHeight();
-
-               here_bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_maps_indicator_current_position);
-               /* Center of the dot */
-               here_off_x = here_bitmap.getWidth() / 2;
-               here_off_y = here_bitmap.getHeight() / 2;
-       }
-
-       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);
-       }
-
-       public AltosMapOffline(Context context, AttributeSet attrs) {
-               super(context, attrs);
-               this.altos_droid = altos_droid;
-               scale_detector = new ScaleGestureDetector(context, this);
-       }
-}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOnline.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOnline.java
deleted file mode 100644 (file)
index 37e4435..0000000
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Copyright © 2013 Mike Beattie <mike@ethernal.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.AltosDroid;
-
-import java.util.*;
-
-import org.altusmetrum.altoslib_13.*;
-
-import com.google.android.gms.maps.*;
-import com.google.android.gms.maps.model.*;
-
-import android.app.Activity;
-import android.graphics.Color;
-import android.graphics.*;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-//import android.support.v4.app.FragmentTransaction;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.TextView;
-import android.location.Location;
-import android.content.*;
-
-class RocketOnline implements Comparable {
-       Marker          marker;
-       int             serial;
-       long            last_packet;
-       int             size;
-
-       void set_position(AltosLatLon position, long last_packet) {
-               marker.setPosition(new LatLng(position.lat, position.lon));
-               this.last_packet = last_packet;
-       }
-
-       private Bitmap rocket_bitmap(Context context, String text) {
-
-               /* From: http://mapicons.nicolasmollet.com/markers/industry/military/missile-2/
-                */
-               Bitmap orig_bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.rocket);
-               Bitmap bitmap = orig_bitmap.copy(Bitmap.Config.ARGB_8888, true);
-
-               Canvas canvas = new Canvas(bitmap);
-               Paint paint = new Paint();
-               paint.setTextSize(40);
-               paint.setColor(0xff000000);
-
-               Rect    bounds = new Rect();
-               paint.getTextBounds(text, 0, text.length(), bounds);
-
-               int     width = bounds.right - bounds.left;
-               int     height = bounds.bottom - bounds.top;
-
-               float x = bitmap.getWidth() / 2.0f - width / 2.0f;
-               float y = bitmap.getHeight() / 2.0f - height / 2.0f;
-
-               size = bitmap.getWidth();
-
-               canvas.drawText(text, 0, text.length(), x, y, paint);
-               return bitmap;
-       }
-
-       public void remove() {
-               marker.remove();
-       }
-
-       public int compareTo(Object o) {
-               RocketOnline other = (RocketOnline) o;
-
-               long    diff = last_packet - other.last_packet;
-
-               if (diff > 0)
-                       return 1;
-               if (diff < 0)
-                       return -1;
-               return 0;
-       }
-
-       RocketOnline(Context context, int serial, GoogleMap map, double lat, double lon, long last_packet) {
-               this.serial = serial;
-               String name = String.format("%d", serial);
-               this.marker = map.addMarker(new MarkerOptions()
-                                           .icon(BitmapDescriptorFactory.fromBitmap(rocket_bitmap(context, name)))
-                                           .position(new LatLng(lat, lon))
-                                           .visible(true));
-               this.last_packet = last_packet;
-       }
-}
-
-public class AltosMapOnline implements AltosDroidMapInterface, GoogleMap.OnMarkerClickListener, GoogleMap.OnMapClickListener, AltosMapTypeListener {
-       public SupportMapFragment mMapFragment;
-       private GoogleMap mMap;
-       private boolean mapLoaded = false;
-       Context context;
-
-       private HashMap<Integer,RocketOnline> rockets = new HashMap<Integer,RocketOnline>();
-       private Marker mPadMarker;
-       private boolean pad_set;
-       private Polyline mPolyline;
-
-       private View map_view;
-
-       private double mapAccuracy = -1;
-
-       private AltosLatLon my_position = null;
-       private AltosLatLon target_position = null;
-
-       private AltosDroid altos_droid;
-
-       public void onCreateView(AltosDroid altos_droid) {
-               this.altos_droid = altos_droid;
-               final int map_type = AltosPreferences.map_type();
-               AltosPreferences.register_map_type_listener(this);
-               mMapFragment = new SupportMapFragment() {
-                       @Override
-                       public void onActivityCreated(Bundle savedInstanceState) {
-                               super.onActivityCreated(savedInstanceState);
-                               setupMap(map_type);
-                       }
-                       @Override
-                       public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
-                               map_view = super.onCreateView(inflater, container, savedInstanceState);
-                               return map_view;
-                       }
-                       @Override
-                       public void onDestroyView() {
-                               super.onDestroyView();
-                               map_view = null;
-                       }
-               };
-       }
-
-       public void onDestroyView() {
-               AltosPreferences.unregister_map_type_listener(this);
-       }
-
-       private double pixel_distance(LatLng a, LatLng b) {
-               Projection projection = mMap.getProjection();
-
-               Point   a_pt = projection.toScreenLocation(a);
-               Point   b_pt = projection.toScreenLocation(b);
-
-               return Math.hypot((double) (a_pt.x - b_pt.x), (double) (a_pt.y - b_pt.y));
-       }
-
-       private RocketOnline[] sorted_rockets() {
-               RocketOnline[]  rocket_array = rockets.values().toArray(new RocketOnline[0]);
-
-               Arrays.sort(rocket_array);
-               return rocket_array;
-       }
-
-       public void onMapClick(LatLng lat_lng) {
-               ArrayList<Integer>      near = new ArrayList<Integer>();
-
-               for (RocketOnline rocket : sorted_rockets()) {
-                       LatLng  pos = rocket.marker.getPosition();
-
-                       if (pos == null)
-                               continue;
-
-                       double distance = pixel_distance(lat_lng, pos);
-                       if (distance < rocket.size * 2)
-                               near.add(rocket.serial);
-               }
-
-               if (near.size() != 0)
-                       altos_droid.touch_trackers(near.toArray(new Integer[0]));
-       }
-
-       public boolean onMarkerClick(Marker marker) {
-               onMapClick(marker.getPosition());
-               return true;
-       }
-
-       public void setupMap(int map_type) {
-               mMap = mMapFragment.getMap();
-               if (mMap != null) {
-                       map_type_changed(map_type);
-                       mMap.setMyLocationEnabled(true);
-                       mMap.getUiSettings().setTiltGesturesEnabled(false);
-                       mMap.getUiSettings().setZoomControlsEnabled(false);
-                       mMap.setOnMarkerClickListener(this);
-                       mMap.setOnMapClickListener(this);
-
-                       mPadMarker = mMap.addMarker(
-                                       new MarkerOptions().icon(BitmapDescriptorFactory.fromResource(R.drawable.pad))
-                                                          .position(new LatLng(0,0))
-                                                          .visible(false)
-                                       );
-
-                       mPolyline = mMap.addPolyline(
-                                       new PolylineOptions().add(new LatLng(0,0), new LatLng(0,0))
-                                                            .width(20)
-                                                            .color(Color.BLUE)
-                                                            .visible(false)
-                                       );
-
-                       mapLoaded = true;
-               }
-       }
-
-       public void center(double lat, double lon, double accuracy) {
-               if (mMap == null)
-                       return;
-
-               if (mapAccuracy < 0 || accuracy < mapAccuracy/10) {
-                       mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(lat, lon),14));
-                       mapAccuracy = accuracy;
-               }
-       }
-
-       private void set_rocket(int serial, AltosState state) {
-               RocketOnline    rocket;
-
-               if (state.gps == null || state.gps.lat == AltosLib.MISSING)
-                       return;
-
-               if (mMap == null)
-                       return;
-
-               if (rockets.containsKey(serial)) {
-                       rocket = rockets.get(serial);
-                       rocket.set_position(new AltosLatLon(state.gps.lat, state.gps.lon), state.received_time);
-               } else {
-                       rocket = new RocketOnline(context,
-                                                 serial,
-                                                 mMap, state.gps.lat, state.gps.lon,
-                                                 state.received_time);
-                       rockets.put(serial, rocket);
-               }
-       }
-
-       private void remove_rocket(int serial) {
-               RocketOnline rocket = rockets.get(serial);
-               rocket.remove();
-               rockets.remove(serial);
-       }
-
-       public void set_visible(boolean visible) {
-               if (map_view == null)
-                       return;
-               if (visible)
-                       map_view.setVisibility(View.VISIBLE);
-               else
-                       map_view.setVisibility(View.GONE);
-       }
-
-       public void show(TelemetryState telem_state, AltosState state, AltosGreatCircle from_receiver, Location receiver) {
-
-               if (telem_state != null) {
-                       for (int serial : rockets.keySet()) {
-                               if (!telem_state.states.containsKey(serial))
-                                       remove_rocket(serial);
-                       }
-
-                       for (int serial : telem_state.states.keySet()) {
-                               set_rocket(serial, telem_state.states.get(serial));
-                       }
-               }
-
-               if (state != null) {
-                       if (mapLoaded) {
-                               if (!pad_set && state.pad_lat != AltosLib.MISSING) {
-                                       pad_set = true;
-                                       mPadMarker.setPosition(new LatLng(state.pad_lat, state.pad_lon));
-                                       mPadMarker.setVisible(true);
-                               }
-                       }
-                       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)
-                                       center (state.gps.lat, state.gps.lon, 10);
-                       }
-               }
-
-               if (receiver != null) {
-                       double accuracy;
-
-                       if (receiver.hasAccuracy())
-                               accuracy = receiver.getAccuracy();
-                       else
-                               accuracy = 1000;
-
-                       my_position = new AltosLatLon(receiver.getLatitude(), receiver.getLongitude());
-                       center (my_position.lat, my_position.lon, accuracy);
-               }
-
-               if (my_position != null && target_position != null && mPolyline != null) {
-                       mPolyline.setPoints(Arrays.asList(new LatLng(my_position.lat, my_position.lon), new LatLng(target_position.lat, target_position.lon)));
-                       mPolyline.setVisible(true);
-               }
-
-       }
-
-       public void map_type_changed(int map_type) {
-               if (mMap != null) {
-                       if (map_type == AltosMap.maptype_hybrid)
-                               mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
-                       else if (map_type == AltosMap.maptype_satellite)
-                               mMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
-                       else if (map_type == AltosMap.maptype_terrain)
-                               mMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
-                       else
-                               mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
-               }
-       }
-
-       public AltosMapOnline(Context context) {
-               this.context = context;
-       }
-}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosUsb.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosUsb.java
deleted file mode 100644 (file)
index 0b235f2..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright © 2015 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.AltosDroid;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.UUID;
-import java.util.HashMap;
-
-import android.content.Context;
-import android.hardware.usb.*;
-import android.app.*;
-import android.os.Handler;
-
-import org.altusmetrum.altoslib_13.*;
-
-public class AltosUsb extends AltosDroidLink {
-
-       private Thread           input_thread   = null;
-
-       private Handler          handler;
-
-       private UsbManager              manager;
-       private UsbDevice               device;
-       private UsbDeviceConnection     connection;
-       private UsbInterface            iface;
-       private UsbEndpoint             in, out;
-
-       private InputStream      input;
-       private OutputStream     output;
-
-       // Constructor
-       public AltosUsb(Context context, UsbDevice device, Handler handler) {
-               super(handler);
-//             set_debug(D);
-               this.handler = handler;
-
-               iface = null;
-               in = null;
-               out = null;
-
-               int     niface = device.getInterfaceCount();
-
-               for (int i = 0; i < niface; i++) {
-
-                       iface = device.getInterface(i);
-
-                       in = null;
-                       out = null;
-
-                       int nendpoints = iface.getEndpointCount();
-
-                       for (int e = 0; e < nendpoints; e++) {
-                               UsbEndpoint     endpoint = iface.getEndpoint(e);
-
-                               if (endpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
-                                       switch (endpoint.getDirection()) {
-                                       case UsbConstants.USB_DIR_OUT:
-                                               out = endpoint;
-                                               break;
-                                       case UsbConstants.USB_DIR_IN:
-                                               in = endpoint;
-                                               break;
-                                       }
-                               }
-                       }
-
-                       if (in != null && out != null)
-                               break;
-               }
-
-               if (in != null && out != null) {
-                       AltosDebug.debug("\tin %s out %s\n", in.toString(), out.toString());
-
-                       manager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
-
-                       if (manager == null) {
-                               AltosDebug.debug("USB_SERVICE failed");
-                               return;
-                       }
-
-                       connection = manager.openDevice(device);
-
-                       if (connection == null) {
-                               AltosDebug.debug("openDevice failed");
-                               return;
-                       }
-
-                       connection.claimInterface(iface, true);
-
-                       input_thread = new Thread(this);
-                       input_thread.start();
-
-                       // Configure the newly connected device for telemetry
-                       print("~\nE 0\n");
-                       set_monitor(false);
-               }
-       }
-
-       static private boolean isAltusMetrum(UsbDevice device) {
-               if (device.getVendorId() != AltosLib.vendor_altusmetrum)
-                       return false;
-               if (device.getProductId() < AltosLib.product_altusmetrum_min)
-                       return false;
-               if (device.getProductId() > AltosLib.product_altusmetrum_max)
-                       return false;
-               return true;
-       }
-
-       static boolean matchProduct(int want_product, UsbDevice device) {
-
-               if (!isAltusMetrum(device))
-                       return false;
-
-               if (want_product == AltosLib.product_any)
-                       return true;
-
-               int have_product = device.getProductId();
-
-               if (want_product == AltosLib.product_basestation)
-                       return have_product == AltosLib.product_teledongle ||
-                               have_product == AltosLib.product_teleterra ||
-                               have_product == AltosLib.product_telebt ||
-                               have_product == AltosLib.product_megadongle;
-
-               if (want_product == AltosLib.product_altimeter)
-                       return have_product == AltosLib.product_telemetrum ||
-                               have_product == AltosLib.product_telemega ||
-                               have_product == AltosLib.product_easymega ||
-                               have_product == AltosLib.product_telegps ||
-                               have_product == AltosLib.product_easymini ||
-                               have_product == AltosLib.product_telemini;
-
-               if (have_product == AltosLib.product_altusmetrum)       /* old devices match any request */
-                       return true;
-
-               if (want_product == have_product)
-                       return true;
-
-               return false;
-       }
-
-       static public boolean request_permission(Context context, UsbDevice device, PendingIntent pi) {
-               UsbManager      manager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
-
-//             if (manager.hasPermission(device))
-//                     return true;
-
-               AltosDebug.debug("request permission for USB device " + device.toString());
-
-               manager.requestPermission(device, pi);
-               return false;
-       }
-
-       static public UsbDevice find_device(Context context, int match_product) {
-               UsbManager      manager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
-
-               HashMap<String,UsbDevice>       devices = manager.getDeviceList();
-
-               for (UsbDevice  device : devices.values()) {
-                       int     vendor = device.getVendorId();
-                       int     product = device.getProductId();
-
-                       if (matchProduct(match_product, device)) {
-                               AltosDebug.debug("found USB device " + device.toString());
-                               return device;
-                       }
-               }
-
-               return null;
-       }
-
-       private void disconnected() {
-               if (closed()) {
-                       AltosDebug.debug("disconnected after closed");
-                       return;
-               }
-
-               AltosDebug.debug("Sending disconnected message");
-               handler.obtainMessage(TelemetryService.MSG_DISCONNECTED, this).sendToTarget();
-       }
-
-       void close_device() {
-               UsbDeviceConnection     tmp_connection;
-
-               synchronized(this) {
-                       tmp_connection = connection;
-                       connection = null;
-               }
-
-               if (tmp_connection != null) {
-                       AltosDebug.debug("Closing USB device");
-                       tmp_connection.close();
-               }
-       }
-
-       int read(byte[] buffer, int len) {
-               int ret = connection.bulkTransfer(in, buffer, len, -1);
-               AltosDebug.debug("read(%d) = %d\n", len, ret);
-               return ret;
-       }
-
-       int write(byte[] buffer, int len) {
-               int ret = connection.bulkTransfer(out, buffer, len, -1);
-               AltosDebug.debug("write(%d) = %d\n", len, ret);
-               return ret;
-       }
-
-       // Stubs of required methods when extending AltosLink
-       public boolean can_cancel_reply()   { return false; }
-       public boolean show_reply_timeout() { return true; }
-       public void hide_reply_timeout()    { }
-
-}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosViewPager.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosViewPager.java
deleted file mode 100644 (file)
index 039ba14..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright © 2013 Mike Beattie <mike@ethernal.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.AltosDroid;
-
-import android.content.Context;
-import android.support.v4.view.ViewPager;
-import android.util.AttributeSet;
-import android.view.View;
-
-public class AltosViewPager extends ViewPager {
-
-    public AltosViewPager(Context context) {
-        super(context);
-    }
-
-    public AltosViewPager(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    @Override
-    protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
-
-           if (v.getClass() != null &&
-               v.getClass().getName() != null &&
-               v.getClass().getName().endsWith("MapOffline"))
-                   return true;
-
-           if(v.getClass() != null &&
-              v.getClass().getPackage() != null &&
-              v.getClass().getPackage().getName() != null &&
-              v.getClass().getPackage().getName().startsWith("maps."))
-                   return true;
-
-           return super.canScroll(v, checkV, dx, x, y);
-    }
-
-}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java
deleted file mode 100644 (file)
index ae3299f..0000000
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
- * Copyright © 2012 Mike Beattie <mike@ethernal.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.AltosDroid;
-
-import android.speech.tts.TextToSpeech;
-import android.speech.tts.TextToSpeech.OnInitListener;
-import android.location.Location;
-
-import org.altusmetrum.altoslib_13.*;
-
-public class AltosVoice {
-
-       private TextToSpeech tts         = null;
-       private boolean      tts_enabled = false;
-
-       static final int TELL_MODE_NONE = 0;
-       static final int TELL_MODE_PAD = 1;
-       static final int TELL_MODE_FLIGHT = 2;
-       static final int TELL_MODE_RECOVER = 3;
-
-       static final int TELL_FLIGHT_NONE = 0;
-       static final int TELL_FLIGHT_STATE = 1;
-       static final int TELL_FLIGHT_SPEED = 2;
-       static final int TELL_FLIGHT_HEIGHT = 3;
-       static final int TELL_FLIGHT_TRACK = 4;
-
-       private int             last_tell_mode;
-       private int             last_tell_serial = AltosLib.MISSING;
-       private int             last_state;
-       private AltosGPS        last_gps;
-       private double          last_height = AltosLib.MISSING;
-       private Location        last_receiver;
-       private long            last_speak_time;
-       private int             last_flight_tell = TELL_FLIGHT_NONE;
-       private boolean         quiet = false;
-
-       private long now() {
-               return System.currentTimeMillis();
-       }
-
-       private void reset_last() {
-               last_tell_mode = TELL_MODE_NONE;
-               last_speak_time = now() - 100 * 1000;
-               last_gps = null;
-               last_height = AltosLib.MISSING;
-               last_receiver = null;
-               last_state = AltosLib.ao_flight_invalid;
-               last_flight_tell = TELL_FLIGHT_NONE;
-       }
-
-       public AltosVoice(AltosDroid a) {
-               tts = new TextToSpeech(a, new OnInitListener() {
-                       public void onInit(int status) {
-                               if (status == TextToSpeech.SUCCESS) tts_enabled = true;
-                       }
-               });
-               reset_last();
-       }
-
-       public synchronized void set_enable(boolean enable) {
-               tts_enabled = enable;
-       }
-
-       public synchronized void speak(String s) {
-               if (!tts_enabled) return;
-               last_speak_time = now();
-               if (!quiet)
-                       tts.speak(s, TextToSpeech.QUEUE_ADD, null);
-       }
-
-       public synchronized long time_since_speak() {
-               return now() - last_speak_time;
-       }
-
-       public synchronized void speak(String format, Object ... arguments) {
-               speak(String.format(format, arguments));
-       }
-
-       public synchronized boolean is_speaking() {
-               return tts.isSpeaking();
-       }
-
-       public void stop() {
-               if (tts != null) {
-                       tts.stop();
-                       tts.shutdown();
-               }
-       }
-
-       private boolean         last_apogee_good;
-       private boolean         last_main_good;
-       private boolean         last_gps_good;
-
-       private boolean tell_gonogo(String name,
-                                 boolean current,
-                                 boolean previous,
-                                 boolean new_mode) {
-               if (current != previous || new_mode)
-                       speak("%s %s.", name, current ? "ready" : "not ready");
-               return current;
-       }
-
-       private boolean tell_pad(TelemetryState telem_state, AltosState state,
-                             AltosGreatCircle from_receiver, Location receiver) {
-
-               if (state == null)
-                       return false;
-
-               AltosDebug.debug("tell_pad lag %b ltm %d\n", last_apogee_good, last_tell_mode);
-
-               if (state.apogee_voltage != AltosLib.MISSING)
-                       last_apogee_good = tell_gonogo("apogee",
-                                                      state.apogee_voltage >= AltosLib.ao_igniter_good,
-                                                      last_apogee_good,
-                                                      last_tell_mode != TELL_MODE_PAD);
-
-               if (state.main_voltage != AltosLib.MISSING)
-                       last_main_good = tell_gonogo("main",
-                                                    state.main_voltage >= AltosLib.ao_igniter_good,
-                                                    last_main_good,
-                                                    last_tell_mode != TELL_MODE_PAD);
-
-               if (state.gps != null)
-                       last_gps_good = tell_gonogo("G P S",
-                                                   state.gps_ready,
-                                                   last_gps_good,
-                                                   last_tell_mode != TELL_MODE_PAD);
-               return true;
-       }
-
-
-       private boolean descending(int state) {
-               return AltosLib.ao_flight_drogue <= state && state <= AltosLib.ao_flight_landed;
-       }
-
-       private boolean target_moved(AltosState state) {
-               if (last_gps != null && state != null && state.gps != null) {
-                       AltosGreatCircle        moved = new AltosGreatCircle(last_gps.lat, last_gps.lon, last_gps.alt,
-                                                                            state.gps.lat, state.gps.lon, state.gps.alt);
-                       double                  height_change = 0;
-                       double                  height = state.height();
-
-                       if (height != AltosLib.MISSING && last_height != AltosLib.MISSING)
-                               height_change = Math.abs(last_height - height);
-
-                       if (moved.range < 10 && height_change < 10)
-                               return false;
-               }
-               return true;
-       }
-
-       private boolean receiver_moved(Location receiver) {
-               if (last_receiver != null && receiver != null) {
-                       AltosGreatCircle        moved = new AltosGreatCircle(last_receiver.getLatitude(),
-                                                                            last_receiver.getLongitude(),
-                                                                            last_receiver.getAltitude(),
-                                                                            receiver.getLatitude(),
-                                                                            receiver.getLongitude(),
-                                                                            receiver.getAltitude());
-                       if (moved.range < 10)
-                               return false;
-               }
-               return true;
-       }
-
-       private boolean tell_flight(TelemetryState telem_state, AltosState state,
-                                   AltosGreatCircle from_receiver, Location receiver) {
-
-               boolean spoken = false;
-
-               if (state == null)
-                       return false;
-
-               if (last_tell_mode != TELL_MODE_FLIGHT)
-                       last_flight_tell = TELL_FLIGHT_NONE;
-
-               if (state.state() != last_state && AltosLib.ao_flight_boost <= state.state() && state.state() <= AltosLib.ao_flight_landed) {
-                       speak(state.state_name());
-                       if (descending(state.state()) && !descending(last_state)) {
-                               if (state.max_height() != AltosLib.MISSING) {
-                                       speak("max height: %s.",
-                                             AltosConvert.height.say_units(state.max_height()));
-                               }
-                       }
-                       last_flight_tell = TELL_FLIGHT_STATE;
-                       return true;
-               }
-
-               if (last_tell_mode == TELL_MODE_FLIGHT && last_flight_tell == TELL_FLIGHT_TRACK) {
-                       if (time_since_speak() < 10 * 1000)
-                               return false;
-                       if (!target_moved(state) && !receiver_moved(receiver))
-                               return false;
-               }
-
-               double  speed;
-               double  height;
-
-               if (last_flight_tell == TELL_FLIGHT_NONE || last_flight_tell == TELL_FLIGHT_STATE || last_flight_tell == TELL_FLIGHT_TRACK) {
-                       last_flight_tell = TELL_FLIGHT_SPEED;
-
-                       if (state.state() <= AltosLib.ao_flight_coast) {
-                               speed = state.speed();
-                       } else {
-                               speed = state.gps_speed();
-                               if (speed == AltosLib.MISSING)
-                                       speed = state.speed();
-                       }
-
-                       if (speed != AltosLib.MISSING) {
-                               speak("speed: %s.", AltosConvert.speed.say_units(speed));
-                               return true;
-                       }
-               }
-
-               if (last_flight_tell == TELL_FLIGHT_SPEED) {
-                       last_flight_tell = TELL_FLIGHT_HEIGHT;
-                       height = state.height();
-
-                       if (height != AltosLib.MISSING) {
-                               speak("height: %s.", AltosConvert.height.say_units(height));
-                               return true;
-                       }
-               }
-
-               if (last_flight_tell == TELL_FLIGHT_HEIGHT) {
-                       last_flight_tell = TELL_FLIGHT_TRACK;
-                       if (from_receiver != null) {
-                               speak("bearing %s %d, elevation %d, distance %s.",
-                                     from_receiver.bearing_words(
-                                             AltosGreatCircle.BEARING_VOICE),
-                                     (int) (from_receiver.bearing + 0.5),
-                                     (int) (from_receiver.elevation + 0.5),
-                                     AltosConvert.distance.say(from_receiver.distance));
-                               return true;
-                       }
-               }
-
-               return spoken;
-       }
-
-       private boolean tell_recover(TelemetryState telem_state, AltosState state,
-                                    AltosGreatCircle from_receiver, Location receiver) {
-
-               if (from_receiver == null)
-                       return false;
-
-               if (last_tell_mode == TELL_MODE_RECOVER) {
-                       if (!target_moved(state) && !receiver_moved(receiver))
-                               return false;
-                       if (time_since_speak() <= 10 * 1000)
-                               return false;
-               }
-
-               String direction = AltosDroid.direction(from_receiver, receiver);
-               if (direction == null)
-                       direction = String.format("Bearing %d", (int) (from_receiver.bearing + 0.5));
-
-               speak("%s, distance %s.", direction,
-                     AltosConvert.distance.say_units(from_receiver.distance));
-
-               return true;
-       }
-
-       public void tell(TelemetryState telem_state, AltosState state,
-                        AltosGreatCircle from_receiver, Location receiver,
-                        AltosDroidTab tab, boolean quiet) {
-
-               this.quiet = quiet;
-
-               boolean spoken = false;
-
-               if (!tts_enabled) return;
-
-               if (is_speaking()) return;
-
-               int     tell_serial = last_tell_serial;
-
-               if (state != null)
-                       tell_serial = state.cal_data().serial;
-
-               if (tell_serial != last_tell_serial)
-                       reset_last();
-
-               int     tell_mode = TELL_MODE_NONE;
-
-               if (tab.tab_name().equals(AltosDroid.tab_pad_name))
-                       tell_mode = TELL_MODE_PAD;
-               else if (tab.tab_name().equals(AltosDroid.tab_flight_name))
-                       tell_mode = TELL_MODE_FLIGHT;
-               else
-                       tell_mode = TELL_MODE_RECOVER;
-
-               if (tell_mode == TELL_MODE_PAD)
-                       spoken = tell_pad(telem_state, state, from_receiver, receiver);
-               else if (tell_mode == TELL_MODE_FLIGHT)
-                       spoken = tell_flight(telem_state, state, from_receiver, receiver);
-               else
-                       spoken = tell_recover(telem_state, state, from_receiver, receiver);
-
-               if (spoken) {
-                       last_tell_mode = tell_mode;
-                       last_tell_serial = tell_serial;
-                       if (state != null) {
-                               last_state = state.state();
-                               last_height = state.height();
-                               if (state.gps != null)
-                                       last_gps = state.gps;
-                       }
-                       if (receiver != null)
-                               last_receiver = receiver;
-               }
-       }
-}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/BuildInfo.java.in b/altosdroid/src/org/altusmetrum/AltosDroid/BuildInfo.java.in
deleted file mode 100644 (file)
index aa6c9a7..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright © 2012 Mike Beattie <mike@ethernal.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.AltosDroid;
-
-public class BuildInfo {
-       public static final String version      = "@VERSION@";
-       public static final String git_describe = "@DESCRIBE@";
-       public static final String branch       = "@BRANCH@";
-       public static final String commitnum    = "@COMMITNUM@";
-       public static final String commithash   = "@COMMITHASH@";
-       public static final String builddate    = "@BUILDDATE@";
-       public static final String buildtime    = "@BUILDTIME@";
-       public static final String buildtz      = "@BUILDTZ@";
-}
-
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/DeviceAddress.java b/altosdroid/src/org/altusmetrum/AltosDroid/DeviceAddress.java
deleted file mode 100644 (file)
index 6f84556..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright © 2015 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.AltosDroid;
-
-public class DeviceAddress {
-       public String   address;
-       public String   name;
-
-       public DeviceAddress(String address, String name) {
-               this.address = address;
-               this.name = name;
-       }
-}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/DeviceListActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/DeviceListActivity.java
deleted file mode 100644 (file)
index f36ef26..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * 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
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.
- */
-
-package org.altusmetrum.AltosDroid;
-
-import java.util.Set;
-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.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.Button;
-import android.widget.ListView;
-import android.widget.TextView;
-import android.widget.AdapterView.OnItemClickListener;
-
-/**
- * This Activity appears as a dialog. It lists any paired devices and
- * devices detected in the area after discovery. When a device is chosen
- * by the user, the MAC address of the device is sent back to the parent
- * Activity in the result Intent.
- */
-public class DeviceListActivity extends Activity {
-
-       // Return Intent extra
-       public static final String EXTRA_DEVICE_ADDRESS = "device_address";
-       public static final String EXTRA_DEVICE_NAME = "device_name";
-
-       // Member fields
-       private BluetoothAdapter mBtAdapter;
-       private ArrayAdapter<String> mPairedDevicesArrayAdapter;
-       private ArrayAdapter<String> mNewDevicesArrayAdapter;
-
-       @Override
-       protected void onCreate(Bundle savedInstanceState) {
-               super.onCreate(savedInstanceState);
-
-               // Setup the window
-               requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
-               setContentView(R.layout.device_list);
-
-               // Set result CANCELED incase the user backs out
-               setResult(Activity.RESULT_CANCELED);
-
-               // Initialize the button to perform device discovery
-               Button scanButton = (Button) findViewById(R.id.button_scan);
-               scanButton.setOnClickListener(new OnClickListener() {
-                       public void onClick(View v) {
-                               doDiscovery();
-                               v.setVisibility(View.GONE);
-                       }
-               });
-
-               // Initialize array adapters. One for already paired devices and
-               // one for newly discovered devices
-               mPairedDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name);
-               mNewDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name);
-
-               // Find and set up the ListView for paired devices
-               ListView pairedListView = (ListView) findViewById(R.id.paired_devices);
-               pairedListView.setAdapter(mPairedDevicesArrayAdapter);
-               pairedListView.setOnItemClickListener(mDeviceClickListener);
-
-               // Find and set up the ListView for newly discovered devices
-               ListView newDevicesListView = (ListView) findViewById(R.id.new_devices);
-               newDevicesListView.setAdapter(mNewDevicesArrayAdapter);
-               newDevicesListView.setOnItemClickListener(mDeviceClickListener);
-
-               // Register for broadcasts when a device is discovered
-               IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
-               this.registerReceiver(mReceiver, filter);
-
-               // Register for broadcasts when discovery has finished
-               filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
-               this.registerReceiver(mReceiver, filter);
-
-               // Get the local Bluetooth adapter
-               mBtAdapter = BluetoothAdapter.getDefaultAdapter();
-
-               // Get a set of currently paired devices
-               Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices();
-
-               // If there are paired devices, add each one to the ArrayAdapter
-               if (pairedDevices.size() > 0) {
-                       findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE);
-                       for (BluetoothDevice device : pairedDevices)
-                               if (device.getName().startsWith("TeleBT"))
-                                       mPairedDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
-
-               } else {
-                       String noDevices = getResources().getText(R.string.none_paired).toString();
-                       mPairedDevicesArrayAdapter.add(noDevices);
-               }
-       }
-
-       @Override
-       protected void onDestroy() {
-               super.onDestroy();
-
-               // Make sure we're not doing discovery anymore
-               if (mBtAdapter != null) {
-                       mBtAdapter.cancelDiscovery();
-               }
-
-               // Unregister broadcast listeners
-               this.unregisterReceiver(mReceiver);
-       }
-
-       /**
-       * Start device discover with the BluetoothAdapter
-       */
-       private void doDiscovery() {
-               AltosDebug.debug("doDiscovery()");
-
-               // Indicate scanning in the title
-               setProgressBarIndeterminateVisibility(true);
-               setTitle(R.string.scanning);
-
-               // Turn on sub-title for new devices
-               findViewById(R.id.title_new_devices).setVisibility(View.VISIBLE);
-
-               // If we're already discovering, stop it
-               if (mBtAdapter.isDiscovering()) {
-                       mBtAdapter.cancelDiscovery();
-               }
-
-               // Request discover from BluetoothAdapter
-               mBtAdapter.startDiscovery();
-       }
-
-       // The on-click listener for all devices in the ListViews
-       private OnItemClickListener mDeviceClickListener = new OnItemClickListener() {
-               public void onItemClick(AdapterView<?> av, View v, int arg2, long arg3) {
-                       // Cancel discovery because it's costly and we're about to connect
-                       mBtAdapter.cancelDiscovery();
-
-                       // Get the device MAC address, which is the last 17 chars in the View
-                       String info = ((TextView) v).getText().toString();
-                       String address = info.substring(info.length() - 17);
-
-                       int newline = info.indexOf('\n');
-
-                       String name = null;
-                       if (newline > 0)
-                               name = info.substring(0, newline);
-                       else
-                               name = info;
-
-                       AltosDebug.debug("******* selected item '%s'", info);
-
-                       // Create the result Intent and include the MAC address
-                       Intent intent = new Intent();
-                       intent.putExtra(EXTRA_DEVICE_ADDRESS, address);
-                       intent.putExtra(EXTRA_DEVICE_NAME, name);
-
-                       // Set result and finish this Activity
-                       setResult(Activity.RESULT_OK, intent);
-                       finish();
-               }
-       };
-
-       // The BroadcastReceiver that listens for discovered devices and
-       // changes the title when discovery is finished
-       private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
-               @Override
-               public void onReceive(Context context, Intent intent) {
-                       String action = intent.getAction();
-
-                       // When discovery finds a device
-                       if (BluetoothDevice.ACTION_FOUND.equals(action)) {
-
-                               /* Get the BluetoothDevice object from the Intent
-                                */
-                               BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-
-                               /* If it's already paired, skip it, because it's been listed already
-                                */
-                               if (device != null && device.getBondState() != BluetoothDevice.BOND_BONDED)
-                               {
-                                       String  name = device.getName();
-                                       if (name != null && name.startsWith("TeleBT"))
-                                               mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
-                               }
-
-                       /* When discovery is finished, change the Activity title
-                        */
-                       } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
-                               setProgressBarIndeterminateVisibility(false);
-                               setTitle(R.string.select_device);
-                               if (mNewDevicesArrayAdapter.getCount() == 0) {
-                                       String noDevices = getResources().getText(R.string.none_found).toString();
-                                       mNewDevicesArrayAdapter.add(noDevices);
-                               }
-                       }
-               }
-       };
-
-}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/Dumper.java b/altosdroid/src/org/altusmetrum/AltosDroid/Dumper.java
deleted file mode 100644 (file)
index 2797fc5..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-package org.altusmetrum.AltosDroid;
-
-       import java.lang.reflect.Array;
-       import java.lang.reflect.Field;
-       import java.util.HashMap;
-
-       public class Dumper {
-               private static Dumper instance = new Dumper();
-
-               protected static Dumper getInstance() {
-                       return instance;
-               }
-
-               class DumpContext {
-                       int maxDepth = 0;
-                       int maxArrayElements = 0;
-                       int callCount = 0;
-                       HashMap<String, String> ignoreList = new HashMap<String, String>();
-                       HashMap<Object, Integer> visited = new HashMap<Object, Integer>();
-               }
-
-               public static String dump(Object o) {
-                       return dump(o, 0, 0, null);
-               }
-
-               public static String dump(Object o, int maxDepth, int maxArrayElements, String[] ignoreList) {
-                       DumpContext ctx = Dumper.getInstance().new DumpContext();
-                       ctx.maxDepth = maxDepth;
-                       ctx.maxArrayElements = maxArrayElements;
-
-                       if (ignoreList != null) {
-                               for (int i = 0; i < Array.getLength(ignoreList); i++) {
-                                       int colonIdx = ignoreList[i].indexOf(':');
-                                       if (colonIdx == -1)
-                                               ignoreList[i] = ignoreList[i] + ":";
-                                       ctx.ignoreList.put(ignoreList[i], ignoreList[i]);
-                               }
-                       }
-
-                       return dump(o, ctx);
-               }
-
-               protected static String dump(Object o, DumpContext ctx) {
-                       if (o == null) {
-                               return "<null>";
-                       }
-
-                       ctx.callCount++;
-                       StringBuffer tabs = new StringBuffer();
-                       for (int k = 0; k < ctx.callCount; k++) {
-                               tabs.append("\t");
-                       }
-                       StringBuffer buffer = new StringBuffer();
-                       @SuppressWarnings("rawtypes")
-                       Class oClass = o.getClass();
-
-                       String oSimpleName = getSimpleNameWithoutArrayQualifier(oClass);
-
-                       if (ctx.ignoreList.get(oSimpleName + ":") != null)
-                               return "<Ignored>";
-
-                       if (oClass.isArray()) {
-                               buffer.append("\n");
-                               buffer.append(tabs.toString().substring(1));
-                               buffer.append("[\n");
-                               int rowCount = ctx.maxArrayElements == 0 ? Array.getLength(o) : Math.min(ctx.maxArrayElements, Array.getLength(o));
-                               for (int i = 0; i < rowCount; i++) {
-                                       buffer.append(tabs.toString());
-                                       try {
-                                               Object value = Array.get(o, i);
-                                               buffer.append(dumpValue(value, ctx));
-                                       } catch (Exception e) {
-                                               buffer.append(e.getMessage());
-                                       }
-                                       if (i < Array.getLength(o) - 1)
-                                               buffer.append(",");
-                                       buffer.append("\n");
-                               }
-                               if (rowCount < Array.getLength(o)) {
-                                       buffer.append(tabs.toString());
-                                       buffer.append(Array.getLength(o) - rowCount + " more array elements...");
-                                       buffer.append("\n");
-                               }
-                               buffer.append(tabs.toString().substring(1));
-                               buffer.append("]");
-                       } else {
-                               buffer.append("\n");
-                               buffer.append(tabs.toString().substring(1));
-                               buffer.append("{\n");
-                               buffer.append(tabs.toString());
-                               buffer.append("hashCode: " + o.hashCode());
-                               buffer.append("\n");
-                               while (oClass != null && oClass != Object.class) {
-                                       Field[] fields = oClass.getDeclaredFields();
-
-                                       if (ctx.ignoreList.get(oClass.getSimpleName()) == null) {
-                                               if (oClass != o.getClass()) {
-                                                       buffer.append(tabs.toString().substring(1));
-                                                       buffer.append("  Inherited from superclass " + oSimpleName + ":\n");
-                                               }
-
-                                               for (int i = 0; i < fields.length; i++) {
-
-                                                       String fSimpleName = getSimpleNameWithoutArrayQualifier(fields[i].getType());
-                                                       String fName = fields[i].getName();
-
-                                                       fields[i].setAccessible(true);
-                                                       buffer.append(tabs.toString());
-                                                       buffer.append(fName + "(" + fSimpleName + ")");
-                                                       buffer.append("=");
-
-                                                       if (ctx.ignoreList.get(":" + fName) == null &&
-                                                               ctx.ignoreList.get(fSimpleName + ":" + fName) == null &&
-                                                               ctx.ignoreList.get(fSimpleName + ":") == null) {
-
-                                                               try {
-                                                                       Object value = fields[i].get(o);
-                                                                       buffer.append(dumpValue(value, ctx));
-                                                               } catch (Exception e) {
-                                                                       buffer.append(e.getMessage());
-                                                               }
-                                                               buffer.append("\n");
-                                                       } else {
-                                                               buffer.append("<Ignored>");
-                                                               buffer.append("\n");
-                                                       }
-                                               }
-                                               oClass = oClass.getSuperclass();
-                                               oSimpleName = oClass.getSimpleName();
-                                       } else {
-                                               oClass = null;
-                                               oSimpleName = "";
-                                       }
-                               }
-                               buffer.append(tabs.toString().substring(1));
-                               buffer.append("}");
-                       }
-                       ctx.callCount--;
-                       return buffer.toString();
-               }
-
-               protected static String dumpValue(Object value, DumpContext ctx) {
-                       if (value == null) {
-                               return "<null>";
-                       }
-                       if (value.getClass().isPrimitive() ||
-                               value.getClass() == java.lang.Short.class ||
-                               value.getClass() == java.lang.Long.class ||
-                               value.getClass() == java.lang.String.class ||
-                               value.getClass() == java.lang.Integer.class ||
-                               value.getClass() == java.lang.Float.class ||
-                               value.getClass() == java.lang.Byte.class ||
-                               value.getClass() == java.lang.Character.class ||
-                               value.getClass() == java.lang.Double.class ||
-                               value.getClass() == java.lang.Boolean.class) {
-
-                               return value.toString();
-
-                       } else {
-
-                               Integer visitedIndex = ctx.visited.get(value);
-                               if (visitedIndex == null) {
-                                       ctx.visited.put(value, ctx.callCount);
-                                       if (ctx.maxDepth == 0 || ctx.callCount < ctx.maxDepth) {
-                                               return dump(value, ctx);
-                                       } else {
-                                               return "<Reached max recursion depth>";
-                                       }
-                               } else {
-                                       return "<Previously visited - see hashCode " + value.hashCode() + ">";
-                               }
-                       }
-               }
-
-
-               private static String getSimpleNameWithoutArrayQualifier(@SuppressWarnings("rawtypes") Class clazz) {
-                       String simpleName = clazz.getSimpleName();
-                       int indexOfBracket = simpleName.indexOf('['); 
-                       if (indexOfBracket != -1)
-                               return simpleName.substring(0, indexOfBracket);
-                       return simpleName;
-               }
-}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/GoNoGoLights.java b/altosdroid/src/org/altusmetrum/AltosDroid/GoNoGoLights.java
deleted file mode 100644 (file)
index c18d730..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright © 2013 Mike Beattie <mike@ethernal.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.AltosDroid;
-
-import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
-import android.widget.ImageView;
-import android.view.View;
-
-public class GoNoGoLights {
-       private Boolean state;
-       private Boolean missing;
-       private Boolean set;
-
-       private ImageView red;
-       private ImageView green;
-
-       private Drawable dRed;
-       private Drawable dGreen;
-       private Drawable dGray;
-
-       public GoNoGoLights(ImageView in_red, ImageView in_green, Resources r) {
-               red = in_red;
-               green = in_green;
-               state = false;
-               missing = true;
-               set = false;
-
-               dRed   = r.getDrawable(R.drawable.redled);
-               dGreen = r.getDrawable(R.drawable.greenled);
-               dGray  = r.getDrawable(R.drawable.grayled);
-       }
-
-       public void set(Boolean s, Boolean m) {
-               if (set && s == state && m == missing) return;
-               state = s;
-               missing = m;
-               set = true;
-               if (missing) {
-                       red.setImageDrawable(dGray);
-                       green.setImageDrawable(dGray);
-               } else if (state) {
-                       red.setImageDrawable(dGray);
-                       green.setImageDrawable(dGreen);
-               } else {
-                       red.setImageDrawable(dRed);
-                       green.setImageDrawable(dGray);
-               }
-       }
-}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/IdleModeActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/IdleModeActivity.java
deleted file mode 100644 (file)
index 3130d2a..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * 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.
- */
-
-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_13.*;
-
-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
deleted file mode 100644 (file)
index a172451..0000000
+++ /dev/null
@@ -1,414 +0,0 @@
-/*
- * 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.
- */
-
-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_13.*;
-
-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
deleted file mode 100644 (file)
index d510116..0000000
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * 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.
- */
-
-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_13.*;
-
-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() {
-
-               set();
-
-               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 find(AltosFrequency frequency) {
-               for (int pos = 0; pos < frequencies_adapter.getCount(); pos++) {
-                       FrequencyItem   item = frequencies_adapter.getItem(pos);
-                       if (item.frequency.frequency == frequency.frequency &&
-                           item.frequency.description.equals(frequency.description))
-                               return pos;
-               }
-               return -1;
-       }
-
-       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);
-                       AltosFrequency frequency = new AltosFrequency(f, description_text);
-                       int pos;
-
-                       pos = find(frequency);
-                       if (pos < 0) {
-                               pos = insert_item(frequency);
-                               changed = true;
-                       }
-                       frequencies_adapter.selected_item = -1;
-                       select_item(pos);
-               } 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();
-       }
-}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/MapTypeActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/MapTypeActivity.java
deleted file mode 100644 (file)
index ec88d2d..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright © 2015 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.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_13.*;
-
-public class MapTypeActivity extends Activity {
-       private Button hybrid;
-       private Button satellite;
-       private Button roadmap;
-       private Button terrain;
-       private int selected_type;
-
-       public static final String EXTRA_MAP_TYPE = "map_type";
-
-       private void done(int type) {
-
-               Intent intent = new Intent();
-               intent.putExtra(EXTRA_MAP_TYPE, type);
-               setResult(Activity.RESULT_OK, intent);
-               finish();
-       }
-
-       public void selectType(View view) {
-               AltosDebug.debug("selectType %s", view.toString());
-               if (view == hybrid)
-                       done(AltosMap.maptype_hybrid);
-               if (view == satellite)
-                       done(AltosMap.maptype_satellite);
-               if (view == roadmap)
-                       done(AltosMap.maptype_roadmap);
-               if (view == terrain)
-                       done(AltosMap.maptype_terrain);
-       }
-
-       @Override
-       protected void onCreate(Bundle savedInstanceState) {
-               super.onCreate(savedInstanceState);
-
-               // Setup the window
-               requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
-               setContentView(R.layout.map_type);
-
-               hybrid = (Button) findViewById(R.id.map_type_hybrid);
-               satellite = (Button) findViewById(R.id.map_type_satellite);
-               roadmap = (Button) findViewById(R.id.map_type_roadmap);
-               terrain = (Button) findViewById(R.id.map_type_terrain);
-
-               // Set result CANCELED incase the user backs out
-               setResult(Activity.RESULT_CANCELED);
-       }
-}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java
deleted file mode 100644 (file)
index e393b56..0000000
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * Copyright © 2015 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.AltosDroid;
-
-import java.util.*;
-import java.io.*;
-import java.text.*;
-
-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 android.location.Location;
-import android.location.LocationManager;
-import android.location.LocationListener;
-import android.location.Criteria;
-
-import org.altusmetrum.altoslib_13.*;
-
-/**
- * This Activity appears as a dialog. It lists any paired devices and
- * devices detected in the area after discovery. When a device is chosen
- * by the user, the MAC address of the device is sent back to the parent
- * Activity in the result Intent.
- */
-public class PreloadMapActivity extends Activity implements AltosLaunchSiteListener, AltosMapLoaderListener, LocationListener {
-
-       private ArrayAdapter<AltosLaunchSite> known_sites_adapter;
-
-/*
-       private CheckBox        hybrid;
-       private CheckBox        satellite;
-       private CheckBox        roadmap;
-       private CheckBox        terrain;
-*/
-
-       private Spinner         known_sites_spinner;
-       private Spinner         min_zoom;
-       private Spinner         max_zoom;
-       private TextView        radius_label;
-       private Spinner         radius;
-
-       private EditText        latitude;
-       private EditText        longitude;
-
-       private ProgressBar     progress;
-
-       private AltosMapLoader  loader;
-
-       long    loader_notify_time;
-
-       /* AltosMapLoaderListener interfaces */
-       public void loader_start(final int max) {
-               loader_notify_time = System.currentTimeMillis();
-
-               this.runOnUiThread(new Runnable() {
-                               public void run() {
-                                       progress.setMax(max);
-                                       progress.setProgress(0);
-                               }
-                       });
-       }
-
-       public void loader_notify(final int cur, final int max, final String name) {
-               long    now = System.currentTimeMillis();
-
-               if (now - loader_notify_time < 100)
-                       return;
-
-               loader_notify_time = now;
-
-               this.runOnUiThread(new Runnable() {
-                               public void run() {
-                                       progress.setProgress(cur);
-                               }
-                       });
-       }
-
-       public void loader_done(int max) {
-               loader = null;
-               this.runOnUiThread(new Runnable() {
-                               public void run() {
-                                       progress.setProgress(0);
-                                       finish();
-                               }
-                       });
-       }
-
-       public void debug(String format, Object ... arguments) {
-               AltosDebug.debug(format, arguments);
-       }
-
-       /* AltosLaunchSiteListener interface */
-
-       public void notify_launch_sites(final List<AltosLaunchSite> sites) {
-               this.runOnUiThread(new Runnable() {
-                               public void run() {
-                                       for (AltosLaunchSite site : sites)
-                                               known_sites_adapter.add(site);
-                               }
-                       });
-       }
-
-       /* LocationProvider interface */
-
-       AltosLaunchSite current_location_site;
-
-       public void onLocationChanged(Location location) {
-               AltosDebug.debug("location changed");
-               if (current_location_site == null) {
-                       AltosLaunchSite selected_item = (AltosLaunchSite) known_sites_spinner.getSelectedItem();
-
-                       current_location_site = new AltosLaunchSite("Current Location", location.getLatitude(), location.getLongitude());
-                       known_sites_adapter.insert(current_location_site, 0);
-
-                       if (selected_item != null)
-                               known_sites_spinner.setSelection(known_sites_adapter.getPosition(selected_item));
-                       else {
-                               latitude.setText(new StringBuffer(String.format("%12.6f", current_location_site.latitude)));
-                               longitude.setText(new StringBuffer(String.format("%12.6f", current_location_site.longitude)));
-                       }
-               } else {
-                       current_location_site.latitude = location.getLatitude();
-                       current_location_site.longitude = location.getLongitude();
-               }
-       }
-
-       public void onStatusChanged(String provider, int status, Bundle extras) {
-       }
-
-       public void onProviderEnabled(String provider) {
-       }
-
-       public void onProviderDisabled(String provider) {
-       }
-
-       private double text(EditText view) throws ParseException {
-               return AltosParse.parse_double_locale(view.getEditableText().toString());
-       }
-
-       private double latitude() throws ParseException {
-               return text(latitude);
-       }
-
-       private double longitude() throws ParseException {
-               return text(longitude);
-       }
-
-       private int value(Spinner spinner) {
-               return (Integer) spinner.getSelectedItem();
-       }
-
-       private int min_z() {
-               return value(min_zoom);
-       }
-
-       private int max_z() {
-               return value(max_zoom);
-       }
-
-       private double value_distance(Spinner spinner) {
-               return (Double) spinner.getSelectedItem();
-       }
-
-       private double radius() {
-               double r = value_distance(radius);
-               if (AltosPreferences.imperial_units())
-                       r = AltosConvert.miles_to_meters(r);
-               else
-                       r = r * 1000;
-               return r;
-       }
-
-/*
-       private int bit(CheckBox box, int value) {
-               if (box.isChecked())
-                       return 1 << value;
-               return 0;
-       }
-*/
-
-       private int types() {
-/*
-               return (bit(hybrid, AltosMap.maptype_hybrid) |
-                       bit(satellite, AltosMap.maptype_satellite) |
-                       bit(roadmap, AltosMap.maptype_roadmap) |
-                       bit(terrain, AltosMap.maptype_terrain));
-*/
-               return 1 << AltosMap.maptype_hybrid;
-       }
-
-       private void load() {
-               if (loader != null)
-                       return;
-
-               try {
-                       double  lat = latitude();
-                       double  lon = longitude();
-                       int     min = min_z();
-                       int     max = max_z();
-                       double  r = radius();
-                       int     t = types();
-
-                       AltosDebug.debug("PreloadMap load %f %f %d %d %f %d\n",
-                                        lat, lon, min, max, r, t);
-                       loader = new AltosMapLoader(this, lat, lon, min, max, r, t, AltosMapOffline.scale);
-               } catch (ParseException e) {
-                       AltosDebug.debug("PreloadMap load raised exception %s", e.toString());
-               }
-       }
-
-       private void add_numbers(Spinner spinner, int min, int max, int def) {
-
-               ArrayAdapter<Integer> adapter = new ArrayAdapter<Integer>(this, android.R.layout.simple_spinner_item);
-
-               int     spinner_def = 0;
-               int     pos = 0;
-
-               for (int i = min; i <= max; i++) {
-                       adapter.add(new Integer(i));
-                       if (i == def)
-                               spinner_def = pos;
-                       pos++;
-               }
-
-               spinner.setAdapter(adapter);
-               spinner.setSelection(spinner_def);
-       }
-
-
-       private void add_distance(Spinner spinner, double[] distances_km, double def_km, double[] distances_mi, double def_mi) {
-
-               ArrayAdapter<Double> adapter = new ArrayAdapter<Double>(this, android.R.layout.simple_spinner_item);
-
-               int     spinner_def = 0;
-               int     pos = 0;
-
-               double[] distances;
-               double  def;
-               if (AltosPreferences.imperial_units()) {
-                       distances = distances_mi;
-                       def = def_mi;
-               } else {
-                       distances = distances_km;
-                       def = def_km;
-               }
-
-               for (int i = 0; i < distances.length; i++) {
-                       adapter.add(distances[i]);
-                       if (distances[i] == def)
-                               spinner_def = pos;
-                       pos++;
-               }
-
-               spinner.setAdapter(adapter);
-               spinner.setSelection(spinner_def);
-       }
-
-
-
-       class SiteListListener implements OnItemSelectedListener {
-               public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
-                       AltosLaunchSite site = (AltosLaunchSite) parent.getItemAtPosition(pos);
-                       latitude.setText(new StringBuffer(String.format("%12.6f", site.latitude)));
-                       longitude.setText(new StringBuffer(String.format("%12.6f", site.longitude)));
-               }
-               public void onNothingSelected(AdapterView<?> parent) {
-               }
-
-               public SiteListListener() {
-               }
-       }
-
-       double[]        radius_mi = { 1, 2, 5, 10, 20 };
-       double          radius_def_mi = 2;
-       double[]        radius_km = { 1, 2, 5, 10, 20, 30 };
-       double          radius_def_km = 2;
-
-       @Override
-       protected void onCreate(Bundle savedInstanceState) {
-               super.onCreate(savedInstanceState);
-
-               // Setup the window
-               requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
-               setContentView(R.layout.map_preload);
-
-               // Set result CANCELED incase the user backs out
-               setResult(Activity.RESULT_CANCELED);
-
-               // Initialize the button to perform device discovery
-               Button loadButton = (Button) findViewById(R.id.preload_load);
-               loadButton.setOnClickListener(new OnClickListener() {
-                       public void onClick(View v) {
-                               load();
-                       }
-               });
-
-               latitude = (EditText) findViewById(R.id.preload_latitude);
-               longitude = (EditText) findViewById(R.id.preload_longitude);
-
-/*
-               hybrid = (CheckBox) findViewById(R.id.preload_hybrid);
-               satellite = (CheckBox) findViewById(R.id.preload_satellite);
-               roadmap = (CheckBox) findViewById(R.id.preload_roadmap);
-               terrain = (CheckBox) findViewById(R.id.preload_terrain);
-
-               hybrid.setChecked(true);
-*/
-
-               min_zoom = (Spinner) findViewById(R.id.preload_min_zoom);
-               add_numbers(min_zoom,
-                           AltosMap.min_zoom - AltosMap.default_zoom,
-                           AltosMap.max_zoom - AltosMap.default_zoom, -2);
-               max_zoom = (Spinner) findViewById(R.id.preload_max_zoom);
-               add_numbers(max_zoom,
-                           AltosMap.min_zoom - AltosMap.default_zoom,
-                           AltosMap.max_zoom - AltosMap.default_zoom, 2);
-               radius_label = (TextView) findViewById(R.id.preload_radius_label);
-               radius = (Spinner) findViewById(R.id.preload_radius);
-               if (AltosPreferences.imperial_units())
-                       radius_label.setText("Radius (miles)");
-               else
-                       radius_label.setText("Radius (km)");
-               add_distance(radius, radius_km, radius_def_km, radius_mi, radius_def_mi);
-
-               progress = (ProgressBar) findViewById(R.id.preload_progress);
-
-               // Initialize array adapters. One for already paired devices and
-               // one for newly discovered devices
-               known_sites_spinner = (Spinner) findViewById(R.id.preload_site_list);
-
-               known_sites_adapter = new ArrayAdapter<AltosLaunchSite>(this, android.R.layout.simple_spinner_item);
-
-               known_sites_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
-
-               known_sites_spinner.setAdapter(known_sites_adapter);
-               known_sites_spinner.setOnItemSelectedListener(new SiteListListener());
-
-               // Listen for GPS and Network position updates
-               LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
-
-               locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, this);
-
-               new AltosLaunchSites(this);
-       }
-
-       @Override
-       protected void onDestroy() {
-               super.onDestroy();
-
-               if (loader != null)
-                       loader.abort();
-
-               // Stop listening for location updates
-               ((LocationManager) getSystemService(Context.LOCATION_SERVICE)).removeUpdates(this);
-       }
-}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/SetupActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/SetupActivity.java
deleted file mode 100644 (file)
index bad0b82..0000000
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * 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.
- */
-
-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_13.*;
-
-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);
-
-               AltosDebug.init(this);
-               AltosDebug.debug("+++ ON CREATE +++");
-
-               // Initialise preferences
-               AltosDroidPreferences.init(this);
-
-               // 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();
-       }
-}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabFlight.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabFlight.java
deleted file mode 100644 (file)
index 8997d96..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright © 2013 Mike Beattie <mike@ethernal.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.AltosDroid;
-
-import org.altusmetrum.altoslib_13.*;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.view.*;
-import android.widget.*;
-import android.location.Location;
-
-public class TabFlight extends AltosDroidTab {
-       private TextView speed_view;
-       private TextView height_view;
-       private TextView max_speed_view;
-       private TextView max_height_view;
-       private TextView elevation_view;
-       private TextView range_view;
-       private TextView bearing_view;
-       private TextView compass_view;
-       private TextView distance_view;
-       private TextView latitude_view;
-       private TextView longitude_view;
-       private View apogee_view;
-       private TextView apogee_voltage_view;
-       private TextView apogee_voltage_label;
-       private GoNoGoLights apogee_lights;
-       private View main_view;
-       private TextView main_voltage_view;
-       private TextView main_voltage_label;
-       private GoNoGoLights main_lights;
-
-       @Override
-       public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
-               View v = inflater.inflate(R.layout.tab_flight, container, false);
-
-               speed_view     = (TextView) v.findViewById(R.id.speed_value);
-               height_view    = (TextView) v.findViewById(R.id.height_value);
-               max_speed_view = (TextView) v.findViewById(R.id.max_speed_value);
-               max_height_view= (TextView) v.findViewById(R.id.max_height_value);
-               elevation_view = (TextView) v.findViewById(R.id.elevation_value);
-               range_view     = (TextView) v.findViewById(R.id.range_value);
-               bearing_view   = (TextView) v.findViewById(R.id.bearing_value);
-               compass_view   = (TextView) v.findViewById(R.id.compass_value);
-               distance_view  = (TextView) v.findViewById(R.id.distance_value);
-               latitude_view  = (TextView) v.findViewById(R.id.lat_value);
-               longitude_view = (TextView) v.findViewById(R.id.lon_value);
-
-               apogee_view = v.findViewById(R.id.apogee_view);
-               apogee_voltage_view = (TextView) v.findViewById(R.id.apogee_voltage_value);
-               apogee_lights = new GoNoGoLights((ImageView) v.findViewById(R.id.apogee_redled),
-                                                (ImageView) v.findViewById(R.id.apogee_greenled),
-                                                getResources());
-               apogee_voltage_label = (TextView) v.findViewById(R.id.apogee_voltage_label);
-
-               main_view = v.findViewById(R.id.main_view);
-               main_voltage_view = (TextView) v.findViewById(R.id.main_voltage_value);
-               main_lights = new GoNoGoLights((ImageView) v.findViewById(R.id.main_redled),
-                                              (ImageView) v.findViewById(R.id.main_greenled),
-                                              getResources());
-               main_voltage_label = (TextView) v.findViewById(R.id.main_voltage_label);
-
-               return v;
-       }
-
-       public String tab_name() { return AltosDroid.tab_flight_name; }
-
-       public void show(TelemetryState telem_state, AltosState state, AltosGreatCircle from_receiver, Location receiver) {
-               if (state != null) {
-                       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.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);
-                               bearing_view.setText(AltosDroid.number("%3.0f°", from_receiver.bearing));
-                               compass_view.setText(from_receiver.bearing_words(AltosGreatCircle.BEARING_LONG));
-                               set_value(distance_view, AltosConvert.distance, 6, from_receiver.distance);
-                       } else { 
-                               elevation_view.setText("<unknown>");
-                               range_view.setText("<unknown>");
-                               bearing_view.setText("<unknown>");
-                               compass_view.setText("<unknown>");
-                               distance_view.setText("<unknown>");
-                       }
-                       if (state.gps != null) {
-                               latitude_view.setText(AltosDroid.pos(state.gps.lat, "N", "S"));
-                               longitude_view.setText(AltosDroid.pos(state.gps.lon, "E", "W"));
-                       }
-
-                       if (state.apogee_voltage == AltosLib.MISSING) {
-                               apogee_view.setVisibility(View.GONE);
-                       } else {
-                               apogee_voltage_view.setText(AltosDroid.number("%4.2f V", state.apogee_voltage));
-                               apogee_lights.set(state.apogee_voltage > 3.2, state.apogee_voltage == AltosLib.MISSING);
-                               apogee_view.setVisibility(View.VISIBLE);
-                       }
-
-                       if (state.main_voltage == AltosLib.MISSING) {
-                               main_view.setVisibility(View.GONE);
-                       } else {
-                               main_voltage_view.setText(AltosDroid.number("%4.2f V", state.main_voltage));
-                               main_lights.set(state.main_voltage > 3.2, state.main_voltage == AltosLib.MISSING);
-                               main_view.setVisibility(View.VISIBLE);
-                       }
-               }
-       }
-
-}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java
deleted file mode 100644 (file)
index a2f997f..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright © 2013 Mike Beattie <mike@ethernal.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.AltosDroid;
-
-import java.util.*;
-import java.io.*;
-
-import org.altusmetrum.altoslib_13.*;
-
-import android.app.Activity;
-import android.graphics.*;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentTransaction;
-import android.view.*;
-import android.widget.*;
-import android.location.Location;
-import android.content.*;
-
-public class TabMap extends AltosDroidTab implements AltosDroidMapSourceListener {
-
-       AltosLatLon     here;
-
-       private TextView mDistanceView;
-       private TextView mBearingLabel;
-       private TextView mBearingView;
-       private TextView mTargetLatitudeView;
-       private TextView mTargetLongitudeView;
-       private TextView mReceiverLatitudeView;
-       private TextView mReceiverLongitudeView;
-       private AltosMapOffline map_offline;
-       private AltosMapOnline map_online;
-       private View view;
-       private int map_source;
-
-       @Override
-       public void onAttach(Activity activity) {
-               super.onAttach(activity);
-       }
-
-       @Override
-       public void onCreate(Bundle savedInstanceState) {
-               super.onCreate(savedInstanceState);
-       }
-
-       @Override
-       public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
-               view = inflater.inflate(R.layout.tab_map, container, false);
-               int map_source = AltosDroidPreferences.map_source();
-
-               mDistanceView  = (TextView)view.findViewById(R.id.distance_value);
-               mBearingLabel  = (TextView)view.findViewById(R.id.bearing_label);
-               mBearingView   = (TextView)view.findViewById(R.id.bearing_value);
-               mTargetLatitudeView  = (TextView)view.findViewById(R.id.target_lat_value);
-               mTargetLongitudeView = (TextView)view.findViewById(R.id.target_lon_value);
-               mReceiverLatitudeView  = (TextView)view.findViewById(R.id.receiver_lat_value);
-               mReceiverLongitudeView = (TextView)view.findViewById(R.id.receiver_lon_value);
-               map_offline = (AltosMapOffline)view.findViewById(R.id.map_offline);
-               map_offline.onCreateView(altos_droid);
-               map_online = new AltosMapOnline(view.getContext());
-               map_online.onCreateView(altos_droid);
-               map_source_changed(AltosDroidPreferences.map_source());
-               AltosDroidPreferences.register_map_source_listener(this);
-               return view;
-       }
-
-       @Override
-       public void onActivityCreated(Bundle savedInstanceState) {
-               super.onActivityCreated(savedInstanceState);
-               if (map_online != null)
-                       getChildFragmentManager().beginTransaction().add(R.id.map_online, map_online.mMapFragment).commit();
-       }
-
-       @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; }
-
-       private void center(double lat, double lon, double accuracy) {
-               if (map_offline != null)
-                       map_offline.center(lat, lon, accuracy);
-               if (map_online != null)
-                       map_online.center(lat, lon, accuracy);
-       }
-
-       public void show(TelemetryState telem_state, AltosState state, AltosGreatCircle from_receiver, Location receiver) {
-               if (from_receiver != null) {
-                       String  direction = AltosDroid.direction(from_receiver, receiver);
-                       if (direction != null) {
-                               mBearingLabel.setText("Direction");
-                               mBearingView.setText(direction);
-                       } else {
-                               mBearingLabel.setText("Bearing");
-                               mBearingView.setText(String.format("%3.0f°", from_receiver.bearing));
-                       }
-                       set_value(mDistanceView, AltosConvert.distance, 6, from_receiver.distance);
-               } else {
-                       mBearingLabel.setText("Bearing");
-                       mBearingView.setText("");
-                       set_value(mDistanceView, AltosConvert.distance, 6, AltosLib.MISSING);
-               }
-
-               if (state != null) {
-                       if (state.gps != null) {
-                               mTargetLatitudeView.setText(AltosDroid.pos(state.gps.lat, "N", "S"));
-                               mTargetLongitudeView.setText(AltosDroid.pos(state.gps.lon, "E", "W"));
-                       }
-               }
-
-               if (receiver != null) {
-                       double accuracy;
-
-                       here = new AltosLatLon(receiver.getLatitude(), receiver.getLongitude());
-                       if (receiver.hasAccuracy())
-                               accuracy = receiver.getAccuracy();
-                       else
-                               accuracy = 1000;
-                       mReceiverLatitudeView.setText(AltosDroid.pos(here.lat, "N", "S"));
-                       mReceiverLongitudeView.setText(AltosDroid.pos(here.lon, "E", "W"));
-                       center (here.lat, here.lon, accuracy);
-               }
-               if (map_source == AltosDroidPreferences.MAP_SOURCE_OFFLINE) {
-                       if (map_offline != null)
-                               map_offline.show(telem_state, state, from_receiver, receiver);
-               } else {
-                       if (map_online != null)
-                               map_online.show(telem_state, state, from_receiver, receiver);
-               }
-       }
-
-       public void map_source_changed(int map_source) {
-               this.map_source = map_source;
-               if (map_source == AltosDroidPreferences.MAP_SOURCE_OFFLINE) {
-                       if (map_online != null)
-                               map_online.set_visible(false);
-                       if (map_offline != null) {
-                               map_offline.set_visible(true);
-                               map_offline.show(last_telem_state, last_state, last_from_receiver, last_receiver);
-                       }
-               } else {
-                       if (map_offline != null)
-                               map_offline.set_visible(false);
-                       if (map_online != null) {
-                               map_online.set_visible(true);
-                               map_online.show(last_telem_state, last_state, last_from_receiver, last_receiver);
-                       }
-               }
-       }
-
-       public TabMap() {
-       }
-}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java
deleted file mode 100644 (file)
index f317ae9..0000000
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright © 2013 Mike Beattie <mike@ethernal.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.AltosDroid;
-
-import org.altusmetrum.altoslib_13.*;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.view.*;
-import android.widget.*;
-import android.location.Location;
-
-public class TabPad extends AltosDroidTab {
-       private TextView battery_voltage_view;
-       private GoNoGoLights battery_lights;
-
-       private TableRow receiver_row;
-       private TextView receiver_voltage_view;
-       private TextView receiver_voltage_label;
-       private GoNoGoLights receiver_voltage_lights;
-
-       private TableRow apogee_row;
-       private TextView apogee_voltage_view;
-       private TextView apogee_voltage_label;
-       private GoNoGoLights apogee_lights;
-
-       private TableRow main_row;
-       private TextView main_voltage_view;
-       private TextView main_voltage_label;
-       private GoNoGoLights main_lights;
-
-       private TextView data_logging_view;
-       private GoNoGoLights data_logging_lights;
-
-       private TextView gps_locked_view;
-       private GoNoGoLights gps_locked_lights;
-
-       private TextView gps_ready_view;
-       private GoNoGoLights gps_ready_lights;
-
-       private TextView receiver_latitude_view;
-       private TextView receiver_longitude_view;
-       private TextView receiver_altitude_view;
-
-       private TableRow[] ignite_row = new TableRow[4];
-       private TextView[] ignite_voltage_view = new TextView[4];
-       private TextView[] ignite_voltage_label = new TextView[4];
-       private GoNoGoLights[] ignite_lights = new GoNoGoLights[4];
-
-
-       @Override
-       public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
-               View v = inflater.inflate(R.layout.tab_pad, container, false);
-               battery_voltage_view = (TextView) v.findViewById(R.id.battery_voltage_value);
-               battery_lights = new GoNoGoLights((ImageView) v.findViewById(R.id.battery_redled),
-                                                 (ImageView) v.findViewById(R.id.battery_greenled),
-                                                 getResources());
-
-               receiver_row = (TableRow) v.findViewById(R.id.receiver_row);
-               receiver_voltage_view = (TextView) v.findViewById(R.id.receiver_voltage_value);
-               receiver_voltage_label = (TextView) v.findViewById(R.id.receiver_voltage_label);
-               receiver_voltage_lights = new GoNoGoLights((ImageView) v.findViewById(R.id.receiver_redled),
-                                                          (ImageView) v.findViewById(R.id.receiver_greenled),
-                                                          getResources());
-
-               apogee_row = (TableRow) v.findViewById(R.id.apogee_row);
-               apogee_voltage_view = (TextView) v.findViewById(R.id.apogee_voltage_value);
-               apogee_voltage_label = (TextView) v.findViewById(R.id.apogee_voltage_label);
-               apogee_lights = new GoNoGoLights((ImageView) v.findViewById(R.id.apogee_redled),
-                                                (ImageView) v.findViewById(R.id.apogee_greenled),
-                                                getResources());
-
-               main_row = (TableRow) v.findViewById(R.id.main_row);
-               main_voltage_view = (TextView) v.findViewById(R.id.main_voltage_value);
-               main_voltage_label = (TextView) v.findViewById(R.id.main_voltage_label);
-               main_lights = new GoNoGoLights((ImageView) v.findViewById(R.id.main_redled),
-                                              (ImageView) v.findViewById(R.id.main_greenled),
-                                              getResources());
-
-               data_logging_view = (TextView) v.findViewById(R.id.logging_value);
-               data_logging_lights = new GoNoGoLights((ImageView) v.findViewById(R.id.logging_redled),
-                                                     (ImageView) v.findViewById(R.id.logging_greenled),
-                                                     getResources());
-
-               gps_locked_view = (TextView) v.findViewById(R.id.gps_locked_value);
-               gps_locked_lights = new GoNoGoLights((ImageView) v.findViewById(R.id.gps_locked_redled),
-                                                   (ImageView) v.findViewById(R.id.gps_locked_greenled),
-                                                   getResources());
-
-               gps_ready_view = (TextView) v.findViewById(R.id.gps_ready_value);
-               gps_ready_lights = new GoNoGoLights((ImageView) v.findViewById(R.id.gps_ready_redled),
-                                                  (ImageView) v.findViewById(R.id.gps_ready_greenled),
-                                                  getResources());
-
-               for (int i = 0; i < 4; i++) {
-                       int row_id, view_id, label_id, lights_id;
-                       int red_id, green_id;
-                       switch (i) {
-                       case 0:
-                       default:
-                               row_id = R.id.ignite_a_row;
-                               view_id = R.id.ignite_a_voltage_value;
-                               label_id = R.id.ignite_a_voltage_label;
-                               red_id = R.id.ignite_a_redled;
-                               green_id = R.id.ignite_a_greenled;
-                               break;
-                       case 1:
-                               row_id = R.id.ignite_b_row;
-                               view_id = R.id.ignite_b_voltage_value;
-                               label_id = R.id.ignite_b_voltage_label;
-                               red_id = R.id.ignite_b_redled;
-                               green_id = R.id.ignite_b_greenled;
-                               break;
-                       case 2:
-                               row_id = R.id.ignite_c_row;
-                               view_id = R.id.ignite_c_voltage_value;
-                               label_id = R.id.ignite_c_voltage_label;
-                               red_id = R.id.ignite_c_redled;
-                               green_id = R.id.ignite_c_greenled;
-                               break;
-                       case 3:
-                               row_id = R.id.ignite_d_row;
-                               view_id = R.id.ignite_d_voltage_value;
-                               label_id = R.id.ignite_d_voltage_label;
-                               red_id = R.id.ignite_d_redled;
-                               green_id = R.id.ignite_d_greenled;
-                               break;
-                       }
-                       ignite_row[i] = (TableRow) v.findViewById(row_id);
-                       ignite_voltage_view[i] = (TextView) v.findViewById(view_id);
-                       ignite_voltage_label[i] = (TextView) v.findViewById(label_id);
-                       ignite_lights[i] = new GoNoGoLights((ImageView) v.findViewById(red_id),
-                                                            (ImageView) v.findViewById(green_id),
-                                                            getResources());
-               }
-
-               receiver_latitude_view = (TextView) v.findViewById(R.id.receiver_lat_value);
-               receiver_longitude_view = (TextView) v.findViewById(R.id.receiver_lon_value);
-               receiver_altitude_view = (TextView) v.findViewById(R.id.receiver_alt_value);
-        return v;
-       }
-
-       public String tab_name() { return AltosDroid.tab_pad_name; }
-
-       public void show(TelemetryState telem_state, AltosState state, AltosGreatCircle from_receiver, Location receiver) {
-               if (state != null) {
-                       battery_voltage_view.setText(AltosDroid.number(" %4.2f V", state.battery_voltage));
-                       battery_lights.set(state.battery_voltage >= AltosLib.ao_battery_good, state.battery_voltage == AltosLib.MISSING);
-                       if (state.apogee_voltage == AltosLib.MISSING) {
-                               apogee_row.setVisibility(View.GONE);
-                       } else {
-                               apogee_voltage_view.setText(AltosDroid.number(" %4.2f V", state.apogee_voltage));
-                               apogee_row.setVisibility(View.VISIBLE);
-                       }
-                       apogee_lights.set(state.apogee_voltage >= AltosLib.ao_igniter_good, state.apogee_voltage == AltosLib.MISSING);
-                       if (state.main_voltage == AltosLib.MISSING) {
-                               main_row.setVisibility(View.GONE);
-                       } else {
-                               main_voltage_view.setText(AltosDroid.number(" %4.2f V", state.main_voltage));
-                               main_row.setVisibility(View.VISIBLE);
-                       }
-                       main_lights.set(state.main_voltage >= AltosLib.ao_igniter_good, state.main_voltage == AltosLib.MISSING);
-
-                       int num_igniter = state.igniter_voltage == null ? 0 : state.igniter_voltage.length;
-
-                       for (int i = 0; i < 4; i++) {
-                               double voltage = i >= num_igniter ? AltosLib.MISSING : state.igniter_voltage[i];
-                               if (voltage == AltosLib.MISSING) {
-                                       ignite_row[i].setVisibility(View.GONE);
-                               } else {
-                                       ignite_voltage_view[i].setText(AltosDroid.number(" %4.2f V", voltage));
-                                       ignite_row[i].setVisibility(View.VISIBLE);
-                               }
-                               ignite_lights[i].set(voltage >= AltosLib.ao_igniter_good, voltage == AltosLib.MISSING);
-                       }
-
-                       if (state.cal_data().flight != 0) {
-                               if (state.state() <= AltosLib.ao_flight_pad)
-                                       data_logging_view.setText("Ready to record");
-                               else if (state.state() < AltosLib.ao_flight_landed)
-                                       data_logging_view.setText("Recording data");
-                               else
-                                       data_logging_view.setText("Recorded data");
-                       } else {
-                               data_logging_view.setText("Storage full");
-                       }
-                       data_logging_lights.set(state.cal_data().flight != 0, state.cal_data().flight == AltosLib.MISSING);
-
-                       if (state.gps != null) {
-                               int soln = state.gps.nsat;
-                               int nsat = state.gps.cc_gps_sat != null ? state.gps.cc_gps_sat.length : 0;
-                               gps_locked_view.setText(String.format("%d in soln, %d in view", soln, nsat));
-                               gps_locked_lights.set(state.gps.locked && state.gps.nsat >= 4, false);
-                               if (state.gps_ready)
-                                       gps_ready_view.setText("Ready");
-                               else
-                                       gps_ready_view.setText(AltosDroid.integer("Waiting %d", state.gps_waiting));
-                       } else
-                               gps_locked_lights.set(false, true);
-                       gps_ready_lights.set(state.gps_ready, state.gps == null);
-               }
-
-               if (telem_state != null) {
-                       if (telem_state.receiver_battery == AltosLib.MISSING) {
-                               receiver_row.setVisibility(View.GONE);
-                       } else {
-                               receiver_voltage_view.setText(AltosDroid.number(" %4.2f V", telem_state.receiver_battery));
-                               receiver_row.setVisibility(View.VISIBLE);
-                       }
-                       receiver_voltage_lights.set(telem_state.receiver_battery >= AltosLib.ao_battery_good, telem_state.receiver_battery == AltosLib.MISSING);
-               }
-
-               if (receiver != null) {
-                       double altitude = AltosLib.MISSING;
-                       if (receiver.hasAltitude())
-                               altitude = receiver.getAltitude();
-                       receiver_latitude_view.setText(AltosDroid.pos(receiver.getLatitude(), "N", "S"));
-                       receiver_longitude_view.setText(AltosDroid.pos(receiver.getLongitude(), "E", "W"));
-                       set_value(receiver_altitude_view, AltosConvert.height, 1, altitude);
-               }
-       }
-}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabRecover.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabRecover.java
deleted file mode 100644 (file)
index 3df4838..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright © 2013 Mike Beattie <mike@ethernal.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.AltosDroid;
-
-import org.altusmetrum.altoslib_13.*;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.TextView;
-import android.location.Location;
-
-public class TabRecover extends AltosDroidTab {
-       private TextView mBearingView;
-       private TextView mDirectionView;
-       private TextView mDistanceView;
-       private TextView mTargetLatitudeView;
-       private TextView mTargetLongitudeView;
-       private TextView mReceiverLatitudeView;
-       private TextView mReceiverLongitudeView;
-       private TextView mMaxHeightView;
-       private TextView mMaxSpeedView;
-       private TextView mMaxAccelView;
-
-       @Override
-       public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
-               View v = inflater.inflate(R.layout.tab_recover, container, false);
-
-               mBearingView   = (TextView) v.findViewById(R.id.bearing_value);
-               mDirectionView = (TextView) v.findViewById(R.id.direction_value);
-               mDistanceView  = (TextView) v.findViewById(R.id.distance_value);
-               mTargetLatitudeView  = (TextView) v.findViewById(R.id.target_lat_value);
-               mTargetLongitudeView = (TextView) v.findViewById(R.id.target_lon_value);
-               mReceiverLatitudeView  = (TextView) v.findViewById(R.id.receiver_lat_value);
-               mReceiverLongitudeView = (TextView) v.findViewById(R.id.receiver_lon_value);
-               mMaxHeightView = (TextView) v.findViewById(R.id.max_height_value);
-               mMaxSpeedView  = (TextView) v.findViewById(R.id.max_speed_value);
-               mMaxAccelView  = (TextView) v.findViewById(R.id.max_accel_value);
-
-               return v;
-       }
-
-       public String tab_name() { return AltosDroid.tab_recover_name; }
-
-       public void show(TelemetryState telem_state, AltosState state, AltosGreatCircle from_receiver, Location receiver) {
-               if (from_receiver != null) {
-                       mBearingView.setText(String.format("%3.0f°", from_receiver.bearing));
-                       set_value(mDistanceView, AltosConvert.distance, 6, from_receiver.distance);
-                       String direction = AltosDroid.direction(from_receiver, receiver);
-                       if (direction == null)
-                               mDirectionView.setText("");
-                       else
-                               mDirectionView.setText(direction);
-               }
-               if (state != null && state.gps != null) {
-                       mTargetLatitudeView.setText(AltosDroid.pos(state.gps.lat, "N", "S"));
-                       mTargetLongitudeView.setText(AltosDroid.pos(state.gps.lon, "E", "W"));
-               }
-
-               if (receiver != null) {
-                       mReceiverLatitudeView.setText(AltosDroid.pos(receiver.getLatitude(), "N", "S"));
-                       mReceiverLongitudeView.setText(AltosDroid.pos(receiver.getLongitude(), "E", "W"));
-               }
-
-               if (state != null) {
-                       set_value(mMaxHeightView, AltosConvert.height, 6, state.max_height());
-                       set_value(mMaxAccelView, AltosConvert.accel, 6, state.max_acceleration());
-                       set_value(mMaxSpeedView, AltosConvert.speed, 6, state.max_speed());
-               }
-       }
-}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabsAdapter.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabsAdapter.java
deleted file mode 100644 (file)
index b34a25b..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * 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
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.
- */
-
-package org.altusmetrum.AltosDroid;
-
-import java.util.ArrayList;
-
-import android.content.Context;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentTransaction;
-import android.support.v4.app.FragmentActivity;
-import android.support.v4.app.FragmentPagerAdapter;
-import android.support.v4.view.ViewPager;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.TabHost;
-import android.widget.TabWidget;
-
-/**
- * This is a helper class that implements the management of tabs and all
- * details of connecting a ViewPager with associated TabHost.  It relies on a
- * trick.  Normally a tab host has a simple API for supplying a View or
- * Intent that each tab will show.  This is not sufficient for switching
- * between pages.  So instead we make the content part of the tab host
- * 0dp high (it is not shown) and the TabsAdapter supplies its own dummy
- * view to show as the tab content.  It listens to changes in tabs, and takes
- * care of switch to the correct paged in the ViewPager whenever the selected
- * tab changes.
- */
-public class TabsAdapter extends FragmentPagerAdapter
-               implements TabHost.OnTabChangeListener, ViewPager.OnPageChangeListener {
-       private final Context mContext;
-       private final TabHost mTabHost;
-       private final ViewPager mViewPager;
-       private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
-       private int position;
-
-       static class TabInfo {
-               private final String tag;
-               private final Class<?> clss;
-               private final Bundle args;
-               private Fragment fragment;
-
-               TabInfo(String _tag, Class<?> _class, Bundle _args) {
-                       tag = _tag;
-                       clss = _class;
-                       args = _args;
-               }
-       }
-
-       static class DummyTabFactory implements TabHost.TabContentFactory {
-               private final Context mContext;
-
-               public DummyTabFactory(Context context) {
-                       mContext = context;
-               }
-
-               public View createTabContent(String tag) {
-                       View v = new View(mContext);
-                       v.setMinimumWidth(0);
-                       v.setMinimumHeight(0);
-                       return v;
-               }
-       }
-
-       public TabsAdapter(FragmentActivity activity, TabHost tabHost, ViewPager pager) {
-               super(activity.getSupportFragmentManager());
-               mContext = activity;
-               mTabHost = tabHost;
-               mViewPager = pager;
-               mTabHost.setOnTabChangedListener(this);
-               mViewPager.setAdapter(this);
-               mViewPager.setOnPageChangeListener(this);
-       }
-
-       public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) {
-               tabSpec.setContent(new DummyTabFactory(mContext));
-               String tag = tabSpec.getTag();
-
-               TabInfo info = new TabInfo(tag, clss, args);
-               mTabs.add(info);
-               mTabHost.addTab(tabSpec);
-               notifyDataSetChanged();
-       }
-
-       @Override
-       public int getCount() {
-               return mTabs.size();
-       }
-
-       @Override
-       public Fragment getItem(int position) {
-               TabInfo info = mTabs.get(position);
-               AltosDebug.debug("TabsAdapter.getItem(%d)", position);
-               info.fragment = Fragment.instantiate(mContext, info.clss.getName(), info.args);
-               return info.fragment;
-       }
-
-       public Fragment currentItem() {
-               TabInfo info = mTabs.get(position);
-               return info.fragment;
-       }
-
-       public void onTabChanged(String tabId) {
-               AltosDroidTab   prev_frag = (AltosDroidTab) mTabs.get(position).fragment;
-
-               position = mTabHost.getCurrentTab();
-
-               AltosDroidTab   cur_frag = (AltosDroidTab) mTabs.get(position).fragment;
-
-               if (prev_frag != cur_frag) {
-                       if (prev_frag != null) {
-                               prev_frag.set_visible(false);
-                       }
-               }
-               if (cur_frag != null) {
-                       cur_frag.set_visible(true);
-               }
-               AltosDebug.debug("TabsAdapter.onTabChanged(%s) = %d", tabId, position);
-               mViewPager.setCurrentItem(position);
-       }
-
-       public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
-       }
-
-       public void onPageSelected(int position) {
-               // Unfortunately when TabHost changes the current tab, it kindly
-               // also takes care of putting focus on it when not in touch mode.
-               // The jerk.
-               // This hack tries to prevent this from pulling focus out of our
-               // ViewPager.
-               TabWidget widget = mTabHost.getTabWidget();
-               int oldFocusability = widget.getDescendantFocusability();
-               widget.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
-               mTabHost.setCurrentTab(position);
-               widget.setDescendantFocusability(oldFocusability);
-       }
-
-       public void onPageScrollStateChanged(int state) {
-       }
-}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java
deleted file mode 100644 (file)
index 49ba547..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-package org.altusmetrum.AltosDroid;
-
-import org.altusmetrum.altoslib_13.*;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Environment;
-
-public class TelemetryLogger {
-       private Context   context = null;
-       private AltosLink link    = null;
-       private AltosLog  logger  = null;
-
-       private BroadcastReceiver mExternalStorageReceiver;
-
-       public TelemetryLogger(Context in_context, AltosLink in_link) {
-               context = in_context;
-               link    = in_link;
-
-               startWatchingExternalStorage();
-       }
-
-       public void stop() {
-               stopWatchingExternalStorage();
-               close();
-       }
-
-       private void close() {
-               if (logger != null) {
-                       AltosDebug.debug("Shutting down Telemetry Logging");
-                       logger.close();
-                       logger = null;
-               }
-       }
-
-       void handleExternalStorageState() {
-               String state = Environment.getExternalStorageState();
-               if (Environment.MEDIA_MOUNTED.equals(state)) {
-                       if (logger == null) {
-                               AltosDebug.debug("Starting up Telemetry Logging");
-                               logger = new AltosLog(link);
-                       }
-               } else {
-                       AltosDebug.debug("External Storage not present - stopping");
-                       close();
-               }
-       }
-
-       void startWatchingExternalStorage() {
-               mExternalStorageReceiver = new BroadcastReceiver() {
-                       @Override
-                       public void onReceive(Context context, Intent intent) {
-                               handleExternalStorageState();
-                       }
-               };
-               IntentFilter filter = new IntentFilter();
-               filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
-               filter.addAction(Intent.ACTION_MEDIA_REMOVED);
-               context.registerReceiver(mExternalStorageReceiver, filter);
-               handleExternalStorageState();
-       }
-
-       void stopWatchingExternalStorage() {
-               context.unregisterReceiver(mExternalStorageReceiver);
-       }
-
-}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java
deleted file mode 100644 (file)
index 5cfa647..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
- * Copyright © 2012 Mike Beattie <mike@ethernal.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-
-package org.altusmetrum.AltosDroid;
-
-import java.text.*;
-import java.io.*;
-import java.util.*;
-import java.util.concurrent.*;
-import android.os.Handler;
-
-import org.altusmetrum.altoslib_13.*;
-
-
-public class TelemetryReader extends Thread {
-
-       int         crc_errors;
-
-       Handler     handler;
-
-       AltosLink   link;
-
-       LinkedBlockingQueue<AltosLine> telemQueue;
-
-       public AltosTelemetry read() throws ParseException, AltosCRCException, InterruptedException, IOException {
-               AltosLine l = telemQueue.take();
-               if (l.line == null)
-                       throw new IOException("IO error");
-               AltosTelemetry telem = AltosTelemetryLegacy.parse(l.line);
-               return telem;
-       }
-
-       public void close() {
-               link.remove_monitor(telemQueue);
-               link = null;
-               telemQueue.clear();
-               telemQueue = null;
-       }
-
-       public void run() {
-               try {
-                       AltosDebug.debug("starting loop");
-                       while (telemQueue != null) {
-                               try {
-                                       AltosTelemetry  telem = read();
-                                       telem.set_frequency(link.frequency);
-                                       handler.obtainMessage(TelemetryService.MSG_TELEMETRY, telem).sendToTarget();
-                               } catch (ParseException pp) {
-                                       AltosDebug.error("Parse error: %d \"%s\"", pp.getErrorOffset(), pp.getMessage());
-                               } catch (AltosCRCException ce) {
-                                       ++crc_errors;
-                                       handler.obtainMessage(TelemetryService.MSG_CRC_ERROR, new Integer(crc_errors)).sendToTarget();
-                               }
-                       }
-               } catch (InterruptedException ee) {
-               } catch (IOException ie) {
-                       AltosDebug.error("IO exception in telemetry reader");
-                       handler.obtainMessage(TelemetryService.MSG_DISCONNECTED, link).sendToTarget();
-               } finally {
-                       close();
-               }
-       }
-
-       public TelemetryReader (AltosLink in_link, Handler in_handler) {
-               AltosDebug.debug("connected TelemetryReader create started");
-               link    = in_link;
-               handler = in_handler;
-
-               telemQueue = new LinkedBlockingQueue<AltosLine>();
-               link.add_monitor(telemQueue);
-               link.set_telemetry(AltosLib.ao_telemetry_standard);
-
-               AltosDebug.debug("connected TelemetryReader created");
-       }
-}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java
deleted file mode 100644 (file)
index 22a2bbd..0000000
+++ /dev/null
@@ -1,716 +0,0 @@
-/*
- * Copyright © 2012 Mike Beattie <mike@ethernal.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.AltosDroid;
-
-import java.lang.ref.WeakReference;
-import java.util.concurrent.TimeoutException;
-import java.util.*;
-
-import android.app.Notification;
-//import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.app.Service;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothAdapter;
-import android.hardware.usb.*;
-import android.content.Intent;
-import android.content.Context;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.Handler;
-import android.os.Message;
-import android.os.Messenger;
-import android.os.RemoteException;
-import android.os.Looper;
-import android.widget.Toast;
-import android.location.Criteria;
-
-import org.altusmetrum.altoslib_13.*;
-
-public class TelemetryService extends Service implements AltosIdleMonitorListener {
-
-       static final int MSG_REGISTER_CLIENT   = 1;
-       static final int MSG_UNREGISTER_CLIENT = 2;
-       static final int MSG_CONNECT           = 3;
-       static final int MSG_OPEN_USB          = 4;
-       static final int MSG_CONNECTED         = 5;
-       static final int MSG_CONNECT_FAILED    = 6;
-       static final int MSG_DISCONNECTED      = 7;
-       static final int MSG_TELEMETRY         = 8;
-       static final int MSG_SETFREQUENCY      = 9;
-       static final int MSG_CRC_ERROR         = 10;
-       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.
-       private int NOTIFICATION = R.string.telemetry_service_label;
-       //private NotificationManager mNM;
-
-       ArrayList<Messenger> clients = new ArrayList<Messenger>(); // Keeps track of all current registered clients.
-       final Handler   handler   = new IncomingHandler(this);
-       final Messenger messenger = new Messenger(handler); // Target we publish for clients to send messages to IncomingHandler.
-
-       // Name of the connected device
-       DeviceAddress address;
-       private AltosDroidLink  altos_link  = null;
-       private TelemetryReader telemetry_reader = null;
-       private TelemetryLogger telemetry_logger = null;
-
-       // Local Bluetooth adapter
-       private BluetoothAdapter bluetooth_adapter = null;
-
-       // 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;
-               IncomingHandler(TelemetryService s) { service = new WeakReference<TelemetryService>(s); }
-
-               @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 */
-                       case MSG_REGISTER_CLIENT:
-                               s.add_client(msg.replyTo);
-                               break;
-                       case MSG_UNREGISTER_CLIENT:
-                               s.remove_client(msg.replyTo);
-                               break;
-                       case MSG_CONNECT:
-                               AltosDebug.debug("Connect command received");
-                               address = (DeviceAddress) msg.obj;
-                               AltosDroidPreferences.set_active_device(address);
-                               s.start_altos_bluetooth(address, false);
-                               break;
-                       case MSG_OPEN_USB:
-                               AltosDebug.debug("Open USB command received");
-                               UsbDevice device = (UsbDevice) msg.obj;
-                               s.start_usb(device);
-                               break;
-                       case MSG_DISCONNECT:
-                               AltosDebug.debug("Disconnect command received");
-                               s.address = null;
-                               if (!(Boolean) msg.obj)
-                                       AltosDroidPreferences.set_active_device(null);
-                               s.disconnect(true);
-                               break;
-                       case MSG_DELETE_SERIAL:
-                               AltosDebug.debug("Delete Serial command received");
-                               s.delete_serial((Integer) msg.obj);
-                               break;
-                       case MSG_SETFREQUENCY:
-                               AltosDebug.debug("MSG_SETFREQUENCY");
-                               s.telemetry_state.frequency = (Double) msg.obj;
-                               if (s.telemetry_state.connect == TelemetryState.CONNECT_CONNECTED) {
-                                       try {
-                                               s.altos_link.set_radio_frequency(s.telemetry_state.frequency);
-                                               s.altos_link.save_frequency();
-                                       } catch (InterruptedException e) {
-                                       } catch (TimeoutException e) {
-                                       }
-                               }
-                               s.send_to_clients();
-                               break;
-                       case MSG_SETBAUD:
-                               AltosDebug.debug("MSG_SETBAUD");
-                               s.telemetry_state.telemetry_rate = (Integer) msg.obj;
-                               if (s.telemetry_state.connect == TelemetryState.CONNECT_CONNECTED) {
-                                       s.altos_link.set_telemetry_rate(s.telemetry_state.telemetry_rate);
-                                       s.altos_link.save_telemetry_rate();
-                               }
-                               s.send_to_clients();
-                               break;
-
-                               /*
-                                *Messages from AltosBluetooth
-                                */
-                       case MSG_CONNECTED:
-                               AltosDebug.debug("MSG_CONNECTED");
-                               bt = (AltosDroidLink) msg.obj;
-
-                               if (bt != s.altos_link) {
-                                       AltosDebug.debug("Stale message");
-                                       break;
-                               }
-                               AltosDebug.debug("Connected to device");
-                               try {
-                                       s.connected();
-                               } catch (InterruptedException ie) {
-                               }
-                               break;
-                       case MSG_CONNECT_FAILED:
-                               AltosDebug.debug("MSG_CONNECT_FAILED");
-                               bt = (AltosDroidLink) msg.obj;
-
-                               if (bt != s.altos_link) {
-                                       AltosDebug.debug("Stale message");
-                                       break;
-                               }
-                               if (s.address != null) {
-                                       AltosDebug.debug("Connection failed... retrying");
-                                       s.start_altos_bluetooth(s.address, true);
-                               } else {
-                                       s.disconnect(true);
-                               }
-                               break;
-                       case MSG_DISCONNECTED:
-
-                               /* This can be sent by either AltosDroidLink or TelemetryReader */
-                               AltosDebug.debug("MSG_DISCONNECTED");
-                               bt = (AltosDroidLink) msg.obj;
-
-                               if (bt != s.altos_link) {
-                                       AltosDebug.debug("Stale message");
-                                       break;
-                               }
-                               if (s.address != null) {
-                                       AltosDebug.debug("Connection lost... retrying");
-                                       s.start_altos_bluetooth(s.address, true);
-                               } else {
-                                       s.disconnect(true);
-                               }
-                               break;
-
-                               /*
-                                * Messages from TelemetryReader
-                                */
-                       case MSG_TELEMETRY:
-                               s.telemetry((AltosTelemetry) msg.obj);
-                               break;
-                       case MSG_CRC_ERROR:
-                               // forward crc error messages
-                               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);
-                       }
-               }
-       }
-
-       /* Handle telemetry packet
-        */
-       private void telemetry(AltosTelemetry telem) {
-               AltosState      state;
-
-               if (telemetry_state.states.containsKey(telem.serial()))
-                       state = telemetry_state.states.get(telem.serial());
-               else
-                       state = new AltosState(new AltosCalData());
-               telem.provide_data(state);
-               telemetry_state.states.put(telem.serial(), state);
-               telemetry_state.quiet = false;
-               if (state != null) {
-                       AltosPreferences.set_state(state,telem.serial());
-               }
-               send_to_clients();
-       }
-
-       /* Construct the message to deliver to clients
-        */
-       private Message message() {
-               if (telemetry_state == null)
-                       AltosDebug.debug("telemetry_state null!");
-               if (telemetry_state.states == null)
-                       AltosDebug.debug("telemetry_state.states null!");
-               return Message.obtain(null, AltosDroid.MSG_STATE, telemetry_state);
-       }
-
-       /* A new friend has connected
-        */
-       private void add_client(Messenger client) {
-
-               clients.add(client);
-               AltosDebug.debug("Client bound to service");
-
-               /* On connect, send the current state to the new client
-                */
-               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
-                */
-               if (address != null && telemetry_state.connect == TelemetryState.CONNECT_DISCONNECTED) {
-                       AltosDebug.debug("Reconnecting now...");
-                       start_altos_bluetooth(address, false);
-               }
-       }
-
-       /* A client has disconnected, clean up
-        */
-       private void remove_client(Messenger client) {
-               clients.remove(client);
-               AltosDebug.debug("Client unbound from service");
-
-               /* When the list of clients is empty, stop the service if
-                * we have no current telemetry source
-                */
-
-                if (clients.isEmpty() && telemetry_state.connect == TelemetryState.CONNECT_DISCONNECTED) {
-                        AltosDebug.debug("No clients, no connection. Stopping\n");
-                        stopSelf();
-                }
-       }
-
-       private void send_to_client(Messenger client) {
-               Message m = message();
-               try {
-                       client.send(m);
-               } catch (RemoteException e) {
-                       AltosDebug.error("Client %s disappeared", client.toString());
-                       remove_client(client);
-               }
-       }
-
-       private void send_to_clients() {
-               for (Messenger client : clients)
-                       send_to_client(client);
-       }
-
-       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);
-               }
-       }
-
-       private void send_idle_mode_to_clients() {
-               for (Messenger client : clients)
-                       send_idle_mode_to_client(client);
-       }
-
-       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();
-                       try {
-                               telemetry_reader.join();
-                       } catch (InterruptedException e) {
-                       }
-                       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();
-                       telemetry_logger = null;
-               }
-               if (altos_link != null) {
-                       AltosDebug.debug("disconnect(): stopping AltosDroidLink");
-                       altos_link.close();
-                       altos_link = null;
-                       ignite = null;
-               }
-               telemetry_state.config = null;
-               if (notify) {
-                       AltosDebug.debug("disconnect(): send message to clients");
-                       send_to_clients();
-                       if (clients.isEmpty()) {
-                               AltosDebug.debug("disconnect(): no clients, terminating");
-                               stopSelf();
-                       }
-               }
-       }
-
-       private void start_usb(UsbDevice device) {
-               AltosUsb        d = new AltosUsb(this, device, handler);
-
-               if (d != null) {
-                       disconnect(false);
-                       altos_link = d;
-                       try {
-                               connected();
-                       } catch (InterruptedException ie) {
-                       }
-               }
-       }
-
-       private void delete_serial(int serial) {
-               telemetry_state.states.remove((Integer) serial);
-               AltosPreferences.remove_state(serial);
-               send_to_clients();
-       }
-
-       private void start_altos_bluetooth(DeviceAddress address, boolean pause) {
-               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);
-               telemetry_state.connect = TelemetryState.CONNECT_CONNECTING;
-               telemetry_state.address = address;
-               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 && idle_monitor == null && !ignite_running) {
-                       try {
-                               double  voltage = altos_link.monitor_battery();
-                               telemetry_state.receiver_battery = voltage;
-                               send_to_clients();
-                       } catch (InterruptedException ie) {
-                       }
-               }
-       }
-
-       private void stop_receiver_voltage_timer() {
-               if (receiver_voltage_timer != null) {
-                       receiver_voltage_timer.cancel();
-                       receiver_voltage_timer.purge();
-                       receiver_voltage_timer = null;
-               }
-       }
-
-       private void start_receiver_voltage_timer() {
-               if (receiver_voltage_timer == null && altos_link.has_monitor_battery()) {
-                       receiver_voltage_timer = new Timer();
-                       receiver_voltage_timer.scheduleAtFixedRate(new TimerTask() { public void run() {update_receiver_voltage();}}, 1000L, 10000L);
-               }
-       }
-
-       private void connected() throws InterruptedException {
-               AltosDebug.debug("connected top");
-               AltosDebug.check_ui("connected\n");
-               try {
-                       if (altos_link == null)
-                               throw new InterruptedException("no bluetooth");
-                       telemetry_state.config = altos_link.config_data();
-                       altos_link.set_radio_frequency(telemetry_state.frequency);
-                       altos_link.set_telemetry_rate(telemetry_state.telemetry_rate);
-               } catch (TimeoutException e) {
-                       // If this timed out, then we really want to retry it, but
-                       // probably safer to just retry the connection from scratch.
-                       AltosDebug.debug("connected timeout");
-                       if (address != null) {
-                               AltosDebug.debug("connected timeout, retrying");
-                               start_altos_bluetooth(address, true);
-                       } else {
-                               handler.obtainMessage(MSG_CONNECT_FAILED).sendToTarget();
-                               disconnect(true);
-                       }
-                       return;
-               }
-
-               AltosDebug.debug("connected bluetooth configured");
-               telemetry_state.connect = TelemetryState.CONNECT_CONNECTED;
-               telemetry_state.address = address;
-
-               telemetry_start();
-
-               AltosDebug.debug("connected TelemetryReader started");
-
-               telemetry_logger = new TelemetryLogger(this, altos_link);
-
-               start_receiver_voltage_timer();
-
-               AltosDebug.debug("Notify UI of connection");
-
-               send_to_clients();
-       }
-
-
-       @Override
-       public void onCreate() {
-
-               AltosDebug.init(this);
-
-               // Initialise preferences
-               AltosDroidPreferences.init(this);
-
-               // Get local Bluetooth adapter
-               bluetooth_adapter = BluetoothAdapter.getDefaultAdapter();
-
-               telemetry_state = new TelemetryState();
-
-               // Create a reference to the NotificationManager so that we can update our notifcation text later
-               //mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
-
-               telemetry_state.connect = TelemetryState.CONNECT_DISCONNECTED;
-               telemetry_state.address = null;
-
-               /* Pull the saved state information out of the preferences database
-                */
-               ArrayList<Integer> serials = AltosPreferences.list_states();
-
-               telemetry_state.latest_serial = AltosPreferences.latest_state();
-
-               telemetry_state.quiet = true;
-
-               AltosDebug.debug("latest serial %d\n", telemetry_state.latest_serial);
-
-               for (int serial : serials) {
-                       AltosState saved_state = AltosPreferences.state(serial);
-                       if (saved_state != null) {
-                               if (telemetry_state.latest_serial == 0)
-                                       telemetry_state.latest_serial = serial;
-
-                               AltosDebug.debug("recovered old state serial %d flight %d",
-                                                serial,
-                                                saved_state.cal_data().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);
-                               AltosPreferences.remove_state(serial);
-                       }
-               }
-       }
-
-       @Override
-       public int onStartCommand(Intent intent, int flags, int startId) {
-               AltosDebug.debug("Received start id %d: %s", startId, intent);
-
-               CharSequence text = getText(R.string.telemetry_service_started);
-
-               // Create notification to be displayed while the service runs
-               Notification notification = new Notification(R.drawable.am_status_c, text, 0);
-
-               // The PendingIntent to launch our activity if the user selects this notification
-               PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
-                               new Intent(this, AltosDroid.class), 0);
-
-               // Set the info for the views that show in the notification panel.
-               notification.setLatestEventInfo(this, getText(R.string.telemetry_service_label), text, contentIntent);
-
-               // Set the notification to be in the "Ongoing" section.
-               notification.flags |= Notification.FLAG_ONGOING_EVENT;
-
-               // Move us into the foreground.
-               startForeground(NOTIFICATION, notification);
-
-               /* Start bluetooth if we don't have a connection already */
-               if (intent != null &&
-                   (telemetry_state.connect == TelemetryState.CONNECT_NONE ||
-                    telemetry_state.connect == TelemetryState.CONNECT_DISCONNECTED))
-               {
-                       String  action = intent.getAction();
-
-                       if (action.equals(AltosDroid.ACTION_BLUETOOTH)) {
-                               DeviceAddress address = AltosDroidPreferences.active_device();
-                               if (address != null && !address.address.startsWith("USB"))
-                                       start_altos_bluetooth(address, false);
-                       }
-               }
-
-               // We want this service to continue running until it is explicitly
-               // stopped, so return sticky.
-               return START_STICKY;
-       }
-
-       @Override
-       public void onDestroy() {
-
-               // Stop the bluetooth Comms threads
-               disconnect(true);
-
-               // Demote us from the foreground, and cancel the persistent notification.
-               stopForeground(true);
-
-               // Tell the user we stopped.
-               Toast.makeText(this, R.string.telemetry_service_stopped, Toast.LENGTH_SHORT).show();
-       }
-
-       @Override
-       public IBinder onBind(Intent intent) {
-               return messenger.getBinder();
-       }
-
-       /* AltosIdleMonitorListener */
-       public void update(AltosState state, AltosListenerState listener_state) {
-               telemetry_state.states.put(state.cal_data().serial, state);
-               telemetry_state.receiver_battery = listener_state.battery;
-               send_to_clients();
-       }
-
-       public void failed() {
-       }
-
-       public void error(String reason) {
-               stop_idle_monitor();
-       }
-}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryState.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryState.java
deleted file mode 100644 (file)
index 74d5cd2..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright © 2012 Mike Beattie <mike@ethernal.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.AltosDroid;
-
-import java.util.*;
-import org.altusmetrum.altoslib_13.*;
-import android.location.Location;
-
-public class TelemetryState {
-       public static final int CONNECT_NONE         = 0;
-       public static final int CONNECT_DISCONNECTED = 1;
-       public static final int CONNECT_CONNECTING   = 2;
-       public static final int CONNECT_CONNECTED    = 3;
-
-       int             connect;
-       DeviceAddress   address;
-       AltosConfigData config;
-       int             crc_errors;
-       double          receiver_battery;
-       double          frequency;
-       int             telemetry_rate;
-
-       boolean         quiet;
-
-       HashMap<Integer,AltosState>     states;
-
-       int             latest_serial;
-
-       public TelemetryState() {
-               connect = CONNECT_NONE;
-               config = null;
-               states = new HashMap<Integer,AltosState>();
-               crc_errors = 0;
-               receiver_battery = AltosLib.MISSING;
-               frequency = AltosPreferences.frequency(0);
-               telemetry_rate = AltosPreferences.telemetry_rate(0);
-       }
-}
index d315f96ac7fdae2769f59b7f58516a420d9ceb9c..04129c44d456d901d7449fd3d505a521aded2471 100644 (file)
@@ -563,6 +563,8 @@ public class AltosConfigData {
                        return false;
                if (product.startsWith("TeleMetrum-v2"))
                        return false;
+               if (product.startsWith("TeleMetrum-v3"))
+                       return false;
                if (product.startsWith("EasyMega"))
                        return false;
                return true;
@@ -587,6 +589,8 @@ public class AltosConfigData {
                if (product != null) {
                        if (product.startsWith("EasyMega-v2"))
                                return true;
+                       if (product.startsWith("TeleMetrum-v3"))
+                               return true;
                }
                throw new AltosUnknownProduct(product);
        }
@@ -595,6 +599,8 @@ public class AltosConfigData {
                if (product != null) {
                        if (product.startsWith("EasyMega-v2"))
                                return AltosAdxl375.X_AXIS;
+                       if (product.startsWith("TeleMetrum-v3"))
+                               return AltosAdxl375.X_AXIS;
                }
                throw new AltosUnknownProduct(product);
        }
index 709b71b63037f3618add139a5032d0e32260fd8c..496235c3c843fa5f2595a6b74d7f12ced91f35bc 100644 (file)
@@ -86,6 +86,9 @@ public abstract class AltosDataListener {
                this.frequency = frequency;
        }
 
+       public void set_avoid_duplicate_files() {
+       }
+
        /* Called after all records are captured */
        public void finish() {
        }
index 280414f8e9a32d5b81906ec50a7fd6b73c527519..f305ed336ece9d7c9f68bc753deab5107c5dae65 100644 (file)
@@ -26,6 +26,8 @@ import java.util.concurrent.*;
 class AltosEepromNameData extends AltosDataListener {
        AltosGPS        gps = null;
 
+       boolean avoid_duplicate_files = false;
+
        public void set_rssi(int rssi, int status) { }
        public void set_received_time(long received_time) { }
 
@@ -39,6 +41,10 @@ class AltosEepromNameData extends AltosDataListener {
        public void set_apogee_voltage(double volts) { }
        public void set_main_voltage(double volts) { }
 
+       public void set_avoid_duplicate_files() {
+               avoid_duplicate_files = true;
+       }
+
        public void set_gps(AltosGPS gps) {
                super.set_gps(gps);
                if (gps != null &&
@@ -96,12 +102,19 @@ public class AltosEepromDownload implements Runnable {
        private AltosFile MakeFile(int serial, int flight, AltosEepromNameData name_data) throws IOException {
                AltosFile               eeprom_name;
 
-               if (name_data.gps != null) {
-                       AltosGPS                gps = name_data.gps;
-                       eeprom_name = new AltosFile(gps.year, gps.month, gps.day,
-                                                   serial, flight, "eeprom");
-               } else
-                       eeprom_name = new AltosFile(serial, flight, "eeprom");
+               for (;;) {
+                       if (name_data.gps != null) {
+                               AltosGPS                gps = name_data.gps;
+                               eeprom_name = new AltosFile(gps.year, gps.month, gps.day,
+                                                           serial, flight, "eeprom");
+                       } else
+                               eeprom_name = new AltosFile(serial, flight, "eeprom");
+                       if (!name_data.avoid_duplicate_files)
+                               break;
+                       if (!eeprom_name.exists())
+                               break;
+                       flight++;
+               }
 
                return eeprom_name;
        }
index 839f0aa0dff23f35e591b68e1d308933c3452b2a..328a0fabf5f1f277c6e7bbecee2e303b409cd7a7 100644 (file)
@@ -45,6 +45,10 @@ public class AltosEepromFile implements AltosRecordSet {
                return set.cal_data();
        }
 
+       public boolean valid() {
+               return set.valid();
+       }
+
        public void capture_series(AltosDataListener series) {
                set.capture_series(series);
        }
index c37dbfa2ee2ed409f7ae72a408a8f97a5bc3c2b9..ce9dbc109e4955c40766c484b738e1d51aa947f4 100644 (file)
@@ -162,7 +162,7 @@ public class AltosEepromRecordMega extends AltosEepromRecord {
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
                        return mag_y();
                case AltosLib.AO_LOG_FORMAT_EASYMEGA_2:
-                       return mag_y();
+                       return mag_x();
                default:
                        return AltosLib.MISSING;
                }
diff --git a/altoslib/AltosEepromRecordMicroPeak2.java b/altoslib/AltosEepromRecordMicroPeak2.java
new file mode 100644 (file)
index 0000000..06ae71f
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Copyright © 2019 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.
+ */
+
+package org.altusmetrum.altoslib_13;
+
+public class AltosEepromRecordMicroPeak2 extends AltosEepromRecord {
+       public static final int record_length = 2;
+
+       private static final int PA_GROUND_OFFSET = 0;
+       private static final int PA_MIN_OFFSET = 4;
+       private static final int N_SAMPLES_OFFSET = 8;
+       private static final int STARTING_LOG_OFFSET = 10;
+
+       private static final int LOG_ID_MICROPEAK = 0;
+       private static final int LOG_ID_MICROKITE = 1;
+       private static final int LOG_ID_MICROPEAK2 = 2;
+
+       private int value16(int o) {
+               return eeprom.data16(o);
+       }
+
+       private int value32(int o) {
+               return eeprom.data32(o);
+       }
+
+       public int cmd() {
+               if (start == 0)
+                       return AltosLib.AO_LOG_FLIGHT;
+               return AltosLib.AO_LOG_SENSOR;
+       }
+
+       private int pa_ground() {
+               return value32(PA_GROUND_OFFSET);
+       }
+
+       private int pa_min() {
+               return value32(PA_MIN_OFFSET);
+       }
+
+       private int log_id() {
+               return value16(N_SAMPLES_OFFSET) >> 12;
+       }
+
+       private int n_samples() {
+               return value16(N_SAMPLES_OFFSET) & 0xfff;
+       }
+
+       private int ticks_per_sample() {
+               int log_id = log_id();
+
+               if (log_id == LOG_ID_MICROPEAK)
+                       return 2;
+               if (log_id == LOG_ID_MICROKITE)
+                       return 200;
+               if (log_id == LOG_ID_MICROPEAK2)
+                       return 10;
+               return 1;
+       }
+
+       public int tick() {
+               if (start <= STARTING_LOG_OFFSET)
+                       return 0;
+               return ((start - STARTING_LOG_OFFSET) / 2) * ticks_per_sample();
+       }
+
+       public double ticks_per_sec() {
+               int log_id = log_id();
+
+               if (log_id == LOG_ID_MICROPEAK)
+                       return 1000.0/96.0;
+               if (log_id == LOG_ID_MICROKITE)
+                       return 1000 / 96.0;
+               if (log_id == LOG_ID_MICROPEAK2)
+                       return 100.0;
+               return 100.0;
+       }
+
+       int mix_in (int high, int low) {
+               return  high - (high & 0xffff) + low;
+       }
+
+       boolean closer (int target, int a, int b) {
+               return Math.abs (target - a) < Math.abs(target - b);
+       }
+
+       private int pressure() {
+               int cur = value32(PA_GROUND_OFFSET);
+               for (int s = STARTING_LOG_OFFSET; s <= start; s += 2) {
+                       int     k = value16(s);
+                       int     same = mix_in(cur, k);
+                       int     up = mix_in(cur + 0x10000, k);
+                       int     down = mix_in(cur - 0x10000, k);
+
+                       if (closer (cur, same, up)) {
+                               if (closer (cur, same, down))
+                                       cur = same;
+                               else
+                                       cur = down;
+                       } else {
+                               if (closer (cur, up, down))
+                                       cur = up;
+                               else
+                                       cur = down;
+                       }
+               }
+               return cur;
+       }
+
+       public void provide_data(AltosDataListener listener, AltosCalData cal_data) {
+               listener.set_tick(tick());
+               switch (cmd()) {
+               case AltosLib.AO_LOG_FLIGHT:
+                       int pa_ground = pa_ground();
+                       int pa_min = pa_min();
+                       int n_samples = n_samples();
+                       int log_id = log_id();
+                       listener.set_state(AltosLib.ao_flight_pad);
+                       listener.cal_data().set_ground_pressure(pa_ground);
+                       listener.cal_data().set_ticks_per_sec(ticks_per_sec());
+                       listener.cal_data().set_boost_tick();
+                       listener.set_avoid_duplicate_files();
+                       break;
+               case AltosLib.AO_LOG_SENSOR:
+                       listener.set_state(AltosLib.ao_flight_boost);
+                       listener.set_pressure(pressure());
+                       break;
+               }
+       }
+
+       public int next_start() {
+               if (start == 0)
+                       return STARTING_LOG_OFFSET;
+               if (start + 2 >= STARTING_LOG_OFFSET + 2 * n_samples())
+                       return -1;
+               return start + 2;
+       }
+
+       public AltosEepromRecord next() {
+               int     s = next_start();
+               if (s < 0)
+                       return null;
+               return new AltosEepromRecordMicroPeak2(eeprom, s);
+       }
+
+       public AltosEepromRecordMicroPeak2(AltosEeprom eeprom, int start) {
+               super(eeprom, start, record_length);
+       }
+
+       public AltosEepromRecordMicroPeak2(AltosEeprom eeprom) {
+               this(eeprom, 0);
+       }
+}
index e26a1e00205d2c8980f38f08b1bf00948f045169..5e2adba34c00ae9cf4e4a9915f52d8b531d75252 100644 (file)
@@ -21,6 +21,7 @@ public class AltosEepromRecordSet implements AltosRecordSet {
        AltosEeprom                     eeprom;
        TreeSet<AltosEepromRecord>      ordered;
        AltosCalData                    cal_data;
+       boolean                         valid;
 
        public AltosConfigData config_data() {
                return eeprom.config_data();
@@ -52,6 +53,10 @@ public class AltosEepromRecordSet implements AltosRecordSet {
                listener.finish();
        }
 
+       public boolean valid() {
+               return valid;
+       }
+
        public AltosEepromRecordSet(AltosEeprom eeprom) {
                this.eeprom = eeprom;
 
@@ -89,13 +94,20 @@ public class AltosEepromRecordSet implements AltosRecordSet {
                case AltosLib.AO_LOG_FORMAT_TELEFIRETWO:
                        record = new AltosEepromRecordFireTwo(eeprom);
                        break;
+               case AltosLib.AO_LOG_FORMAT_MICROPEAK2:
+                       record = new AltosEepromRecordMicroPeak2(eeprom);
+                       break;
                }
 
+               ordered = new TreeSet<AltosEepromRecord>();
+
                if (record == null) {
                        System.out.printf("failed to parse log format %d\n", config_data.log_format);
+                       valid = false;
                        return;
                }
-               ordered = new TreeSet<AltosEepromRecord>();
+               valid = true;
+
                int     tick = 0;
                boolean first = true;
 
index 58f503c565d16db931668c33e8df2b2e4c7c838a..85e7dbf8dc5a513bf09dcc64f2e84d5d5057c05d 100644 (file)
@@ -27,7 +27,7 @@ public class AltosFrequency {
        public String   description;
 
        public int hashCode() {
-               return new Double(frequency).hashCode();
+               return Double.valueOf(frequency).hashCode();
        }
 
        public boolean equals(Object o) {
index 8037eb93deb37ec63e44b49d5b3975c7e31b8dd8..57ac4061dbadde59678979119add0c6a7aae8adf 100644 (file)
@@ -92,6 +92,10 @@ public class AltosGPS implements Cloneable {
                return odt.toEpochSecond();
        }
 
+       public  AltosLatLon lat_lon() {
+               return new AltosLatLon(lat, lon);
+       }
+
        public AltosGPS(AltosTelemetryMap map) throws ParseException {
                String  state = map.get_string(AltosTelemetryLegacy.AO_TELEM_GPS_STATE,
                                               AltosTelemetryLegacy.AO_TELEM_GPS_STATE_ERROR);
index 609d1bcb366f9f3ae747633f1f0a51e8894d04ad..cf99cded5ade7303fb337b299d2613cfc561021d 100644 (file)
@@ -295,15 +295,20 @@ public class AltosHexfile {
                        return -1;
 
                try {
-                       /* Walk the descriptors looking for the device */
+                       /* The address of this has moved depending on
+                        * padding in the linker script. Look forward
+                        * and backwards two bytes to see if we can find it
+                        */
                        a = usb_descriptors.address;
-                       while (get_u8(a+1) != AO_USB_DESC_DEVICE) {
-                               int delta = get_u8(a);
-                               a += delta;
-                               if (delta == 0 || a >= max_address)
-                                       return -1;
-                       }
-                       return a;
+
+                       if (get_u8(a) == 0x12 && get_u8(a+1) == AO_USB_DESC_DEVICE)
+                               return a;
+                       else if (get_u8(a+1) == 0x12 && get_u8(a+3) == AO_USB_DESC_DEVICE)
+                               return a + 2;
+                       else if (get_u8(a-2) == 0x12 && get_u8(a-1) == AO_USB_DESC_DEVICE)
+                               return a - 2;
+
+                       return -1;
                } catch (ArrayIndexOutOfBoundsException ae) {
                        return -1;
                }
index 114dfcf908624a5905d04ee8b546bb143295ca72..8adf710e028a03f8e401ec4c48de5c1e9138a805 100644 (file)
@@ -88,22 +88,103 @@ public class AltosIMU implements Cloneable {
                return n;
        }
 
-       static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException {
+       public static final int orient_telemega = 0;
+       public static final int orient_easymega_v2 = 1;
+
+       private int accel_across(int orient) {
+               switch (orient) {
+               case orient_telemega:
+                       return accel_x;
+               case orient_easymega_v2:
+                       return -accel_y;
+               default:
+                       return AltosLib.MISSING;
+               }
+       }
+
+       private int accel_along(int orient) {
+               switch (orient) {
+               case orient_telemega:
+                       return accel_y;
+               case orient_easymega_v2:
+                       return accel_x;
+               default:
+                       return AltosLib.MISSING;
+               }
+       }
+
+       private int accel_through(int orient) {
+               return accel_z;
+       }
+
+       private int gyro_roll(int orient) {
+               switch (orient) {
+               case orient_telemega:
+                       return gyro_y;
+               case orient_easymega_v2:
+                       return gyro_x;
+               default:
+                       return AltosLib.MISSING;
+               }
+       }
+
+       private int gyro_pitch(int orient) {
+               switch (orient) {
+               case orient_telemega:
+                       return gyro_x;
+               case orient_easymega_v2:
+                       return -gyro_y;
+               default:
+                       return AltosLib.MISSING;
+               }
+       }
+
+       private int gyro_yaw(int orient) {
+               return gyro_z;
+       }
+
+       private int mag_across(int orient) {
+               switch (orient) {
+               case orient_telemega:
+                       return mag_x;
+               case orient_easymega_v2:
+                       return -mag_y;
+               default:
+                       return AltosLib.MISSING;
+               }
+       }
+
+       private int mag_along(int orient) {
+               switch (orient) {
+               case orient_telemega:
+                       return mag_y;
+               case orient_easymega_v2:
+                       return mag_x;
+               default:
+                       return AltosLib.MISSING;
+               }
+       }
+
+       private int mag_through(int orient) {
+               return mag_z;
+       }
+
+       static public void provide_data(AltosDataListener listener, AltosLink link, int orient) throws InterruptedException {
                try {
                        AltosIMU        imu = new AltosIMU(link);
                        AltosCalData    cal_data = listener.cal_data();
 
                        if (imu != null) {
-                               listener.set_gyro(cal_data.gyro_roll(imu.gyro_y),
-                                                 cal_data.gyro_pitch(imu.gyro_x),
-                                                 cal_data.gyro_yaw(imu.gyro_z));
-                               listener.set_accel_ground(imu.accel_y,
-                                                         imu.accel_x,
-                                                         imu.accel_z);
+                               listener.set_gyro(cal_data.gyro_roll(imu.gyro_roll(orient)),
+                                                 cal_data.gyro_pitch(imu.gyro_pitch(orient)),
+                                                 cal_data.gyro_yaw(imu.gyro_yaw(orient)));
+                               listener.set_accel_ground(imu.accel_along(orient),
+                                                         imu.accel_across(orient),
+                                                         imu.accel_through(orient));
                                if (imu.mag_x != AltosLib.MISSING) {
-                                       listener.set_mag(cal_data.mag_along(imu.mag_y),
-                                                        cal_data.mag_across(imu.mag_x),
-                                                        cal_data.mag_through(imu.mag_z));
+                                       listener.set_mag(cal_data.mag_along(imu.mag_along(orient)),
+                                                        cal_data.mag_across(imu.mag_across(orient)),
+                                                        cal_data.mag_through(imu.mag_through(orient)));
                                }
                        }
                } catch (TimeoutException te) {
index a68ccac70357f3fa8e607826ca33a977b84878d9..4b9a52542241c1cd3a6f1908bb842c80fd97fbe6 100644 (file)
@@ -29,7 +29,8 @@ class AltosIdler {
 
        static final int        idle_gps = 0;
        static final int        idle_imu = 1;
-       static final int        idle_mag = 2;
+       static final int        idle_imu_em_v2 = 2;
+       static final int        idle_mag = 3;
        static final int        idle_mma655x = 4;
        static final int        idle_ms5607 = 5;
        static final int        idle_adxl375 = 6;
@@ -51,7 +52,10 @@ class AltosIdler {
                                AltosGPS.provide_data(listener, link);
                                break;
                        case idle_imu:
-                               AltosIMU.provide_data(listener, link);
+                               AltosIMU.provide_data(listener, link, AltosIMU.orient_telemega);
+                               break;
+                       case idle_imu_em_v2:
+                               AltosIMU.provide_data(listener, link, AltosIMU.orient_easymega_v2);
                                break;
                        case idle_mag:
                                AltosMag.provide_data(listener, link);
@@ -140,6 +144,12 @@ public class AltosIdleFetch implements AltosDataProvider {
                               AltosIdler.idle_ms5607,
                               AltosIdler.idle_sensor_metrum),
 
+               new AltosIdler("TeleMetrum-v3",
+                              AltosIdler.idle_gps,
+                              AltosIdler.idle_adxl375,
+                              AltosIdler.idle_ms5607,
+                              AltosIdler.idle_sensor_metrum),
+
                new AltosIdler("TeleMega-v0",
                               AltosIdler.idle_gps,
                               AltosIdler.idle_mma655x,
@@ -172,7 +182,7 @@ public class AltosIdleFetch implements AltosDataProvider {
                new AltosIdler("EasyMega-v2",
                               AltosIdler.idle_adxl375,
                               AltosIdler.idle_ms5607,
-                              AltosIdler.idle_imu,
+                              AltosIdler.idle_imu_em_v2,
                               AltosIdler.idle_sensor_mega),
                new AltosIdler("TeleGPS-v1",
                               AltosIdler.idle_gps,
index b981c36513939a7de503de3ce111473bf2b13a4e..8f6897bb8efabad56da8a3007b4a081969d75ea6 100644 (file)
@@ -623,7 +623,7 @@ public class AltosJson extends JsonUtil {
                        }
                        break;
                case type_long:
-                       result.append(new Long(l_number).toString());
+                       result.append(Long.valueOf(l_number).toString());
                        break;
                case type_string:
                        quote(result, string);
@@ -1036,6 +1036,7 @@ public class AltosJson extends JsonUtil {
         * all inner classes are only members of their immediate outer
         * class
         */
+       @SuppressWarnings("unchecked")
        private Object make(Class c, Class enclosing_class, Object enclosing_object) {
                Object  ret;
                if (c == Boolean.TYPE) {
@@ -1105,7 +1106,7 @@ public class AltosJson extends JsonUtil {
                                        Constructor<?> ctor = ((Class<?>)c).getDeclaredConstructor((Class<?>) enclosing_class);
                                        object = ctor.newInstance(enclosing_object);
                                } else {
-                                       object = c.newInstance();
+                                       object = c.getDeclaredConstructor().newInstance();
                                }
                                for (; c != Object.class; c = c.getSuperclass()) {
                                        for (Field field : c.getDeclaredFields()) {
index cd7015e3cb363f93cad745a19251803a4afbc0f6..277858ff3b5155c2e1619b6f8f56795136ad20aa 100644 (file)
@@ -23,7 +23,7 @@ public class AltosLatLon {
        public double   lon;
 
        public int hashCode() {
-               return new Double(lat).hashCode() ^ new Double(lon).hashCode();
+               return Double.valueOf(lat).hashCode() ^ Double.valueOf(lon).hashCode();
        }
 
        public boolean equals(Object o) {
index 93567c06b96467a7d016088f8f30561a4febd359..cfc326245049e5eb04758433c97f26c1465a7a70 100644 (file)
@@ -375,6 +375,8 @@ public class AltosLib {
        public static final int AO_LOG_FORMAT_EASYMINI2 = 14;
        public static final int AO_LOG_FORMAT_TELEMEGA_3 = 15;
        public static final int AO_LOG_FORMAT_EASYMEGA_2 = 16;
+       public static final int AO_LOG_FORMAT_TELESTATIC = 17;
+       public static final int AO_LOG_FORMAT_MICROPEAK2 = 18;
        public static final int AO_LOG_FORMAT_NONE = 127;
 
        public static boolean isspace(int c) {
index b033cbff75b59e855f62c42ccca1dc3e3fbd257f..8fc40e8af307057a269e2552271ed09f0a47d060 100644 (file)
@@ -222,8 +222,7 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener {
                return false;
        }
 
-       public void show(AltosGPS gps, int state) {
-
+       public void show(AltosGPS gps, double time, int state, double gps_height) {
                /*
                 * If insufficient gps data, nothing to update
                 */
@@ -250,7 +249,7 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener {
                }
 
                if (path != null) {
-                       AltosMapRectangle       damage = path.add(gps.lat, gps.lon, state);
+                       AltosMapRectangle       damage = path.add(gps, time, state, gps_height);
 
                        if (damage != null)
                                repaint(damage, AltosMapPath.stroke_width);
@@ -262,7 +261,7 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener {
        }
 
        public void show(AltosState state, AltosListenerState listener_state) {
-               show(state.gps, state.state());
+               show(state.gps, state.time, state.state(), state.gps_height());
        }
 
        public void centre(AltosLatLon lat_lon) {
@@ -290,13 +289,19 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener {
                        centre(lat_lon);
        }
 
-       public void add_mark(double lat, double lon, int state) {
+       public AltosMapMark add_mark(double lat, double lon, int state) {
+               AltosMapMark mark;
                synchronized(marks) {
-                       AltosMapMark mark = map_interface.new_mark(lat, lon, state);
+                       mark = map_interface.new_mark(lat, lon, state);
                        if (mark != null)
                                marks.add(mark);
                }
                repaint();
+               return mark;
+       }
+
+       public void del_mark(AltosMapMark mark) {
+               marks.remove(mark);
        }
 
        public void clear_marks() {
@@ -490,6 +495,16 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener {
                        drag_stop(x, y);
        }
 
+       public AltosMapPathPoint nearest(int x, int y) {
+               notice_user_input();
+               if (path == null)
+                       return null;
+               if (transform == null)
+                       return null;
+               AltosLatLon     at = transform.screen_lat_lon(new  AltosPointInt(x, y));
+               return path.nearest(at);
+       }
+
        public AltosMap(AltosMapInterface map_interface, int scale) {
                this.map_interface = map_interface;
                this.scale = scale;
index 7104b2f63767eede8705e61190a1d96a3572f156..bbb6c994aae11833dc9853797c7305ad5204f99c 100644 (file)
@@ -32,19 +32,44 @@ public abstract class AltosMapPath {
 
        public abstract void paint(AltosMapTransform t);
 
-       public AltosMapRectangle add(double lat, double lon, int state) {
-               AltosMapPathPoint               point = new AltosMapPathPoint(new AltosLatLon (lat, lon), state);
+       public AltosMapRectangle add(AltosGPS gps, double time, int state, double gps_height) {
+               AltosMapPathPoint               point = new AltosMapPathPoint(gps, time, state, gps_height);
                AltosMapRectangle       rect = null;
 
                if (!point.equals(last_point)) {
                        if (last_point != null)
-                               rect = new AltosMapRectangle(last_point.lat_lon, point.lat_lon);
+                               rect = new AltosMapRectangle(last_point.gps.lat_lon(), point.gps.lat_lon());
                        points.add (point);
                        last_point = point;
                }
                return rect;
        }
 
+       private double dist(AltosLatLon lat_lon, AltosMapPathPoint point) {
+               return (new AltosGreatCircle(lat_lon.lat,
+                                            lat_lon.lon,
+                                            point.gps.lat,
+                                            point.gps.lon)).distance;
+       }
+
+       public AltosMapPathPoint nearest(AltosLatLon lat_lon) {
+               AltosMapPathPoint nearest = null;
+               double nearest_dist = 0;
+               for (AltosMapPathPoint point : points) {
+                       if (nearest == null) {
+                               nearest = point;
+                               nearest_dist = dist(lat_lon, point);
+                       } else {
+                               double d = dist(lat_lon, point);
+                               if (d < nearest_dist) {
+                                       nearest = point;
+                                       nearest_dist = d;
+                               }
+                       }
+               }
+               return nearest;
+       }
+
        public void clear () {
                points = new LinkedList<AltosMapPathPoint>();
        }
index 9a1edd421c62c0bba375f2b51b45023ab8c2c31e..88a8bfcf28db86706154f397688f647a4845127b 100644 (file)
@@ -24,11 +24,13 @@ import java.util.*;
 import java.util.concurrent.*;
 
 public class AltosMapPathPoint {
-       public AltosLatLon      lat_lon;
+       public AltosGPS         gps;
+       public double           time;
        public int              state;
+       public double           gps_height;
 
        public int hashCode() {
-               return lat_lon.hashCode() ^ state;
+               return Double.valueOf(gps.lat).hashCode() ^ Double.valueOf(gps.lon).hashCode() ^ state;
        }
 
        public boolean equals(Object o) {
@@ -40,12 +42,14 @@ public class AltosMapPathPoint {
 
                AltosMapPathPoint other = (AltosMapPathPoint) o;
 
-               return lat_lon.equals(other.lat_lon) && state == other.state;
+               return gps.lat == other.gps.lat && gps.lon == other.gps.lon && state == other.state;
        }
 
-       public AltosMapPathPoint(AltosLatLon lat_lon, int state) {
-               this.lat_lon = lat_lon;
+       public AltosMapPathPoint(AltosGPS gps, double time, int state, double gps_height) {
+               this.gps = gps;
+               this.time = time;
                this.state = state;
+               this.gps_height = gps_height;
        }
 }
 
index 6bc6c6f809baaa114dcb6928c94f0b49ceea601b..9eac2654220150ac29ea114bf04b23015b41e45a 100644 (file)
@@ -67,13 +67,13 @@ public class AltosMapTransform {
                return lat_lon(screen_point(screen));
        }
 
-       public AltosPointDouble point(AltosLatLon lat_lon) {
+       public  AltosPointDouble point(double lat, double lon) {
                double x, y;
                double e;
 
-               x = lat_lon.lon * scale_x;
+               x = lon * scale_x;
 
-               e = Math.sin(Math.toRadians(lat_lon.lat));
+               e = Math.sin(Math.toRadians(lat));
                e = Math.max(e,-(1-1.0E-15));
                e = Math.min(e,  1-1.0E-15 );
 
@@ -82,6 +82,10 @@ public class AltosMapTransform {
                return new AltosPointDouble(x, y);
        }
 
+       public AltosPointDouble point(AltosLatLon lat_lon) {
+               return point(lat_lon.lat, lat_lon.lon);
+       }
+
        public AltosPointDouble screen(AltosPointDouble point) {
                return new AltosPointDouble(point.x - offset_x, point.y - offset_y);
        }
@@ -102,6 +106,10 @@ public class AltosMapTransform {
                return screen(point(lat_lon));
        }
 
+       public AltosPointDouble screen(double lat, double lon) {
+               return screen(point(lat, lon));
+       }
+
        private boolean has_location;
 
        public boolean has_location() {
index 59e2f76c9fff051508a7f8d246dc3d35b616cca1..f775738a38185a4643892c3923d30e4f56039d1c 100644 (file)
@@ -22,7 +22,7 @@ public class AltosPointDouble {
        public double   x, y;
 
        public int hashCode() {
-               return new Double(x).hashCode() ^ new Double(y).hashCode();
+               return Double.valueOf(x).hashCode() ^ Double.valueOf(y).hashCode();
        }
 
        public boolean equals(Object o) {
index a84cc3f9a5564a96cedde236d63a3612e3f76e97..4c459cba68cb3080963802c09e71df4ea4fe4d5a 100644 (file)
@@ -19,4 +19,5 @@ import java.util.*;
 public interface AltosRecordSet {
        public AltosCalData cal_data();
        public void capture_series(AltosDataListener listener);
+       public boolean valid();
 }
index 679c6809559508a7b7c8719e8255b0d0ac00837a..01d82c242bd3ef7e1915269eee57ad1d40ac0db6 100644 (file)
@@ -117,6 +117,10 @@ public class AltosTelemetryFile implements AltosRecordSet {
                return cal_data;
        }
 
+       public boolean valid() {
+               return true;
+       }
+
        public void capture_series(AltosDataListener listener) {
                AltosCalData    cal_data = cal_data();
 
index 2219088a07fc133fd84067743adfea467562c04c..c0a5e9e34e7c3bee6d2b263662b3c2d5f9468302 100644 (file)
@@ -32,8 +32,8 @@ public class AltosTelemetrySensor extends AltosTelemetryStandard {
        int     speed() { return int16(20); }
        int     height_16() { return int16(22); }
 
-       int     ground_accel() { return int16(24); }
-       int     ground_pres() { return int16(26); }
+       int     ground_pres() { return int16(24); }
+       int     ground_accel() { return int16(26); }
        int     accel_plus_g() { return int16(28); }
        int     accel_minus_g() { return int16(30); }
 
index 9295b8e82410d249e0e7d1b42758fabbceaabdee..6e492149b426744ccd03f1fd268533f4b4f0de2f 100644 (file)
@@ -42,7 +42,7 @@ public abstract class AltosUnits {
        public abstract double inverse(double v, boolean imperial_units);
 
        public String string_value(double v, boolean imperial_units) {
-               return new Double(value(v, imperial_units)).toString();
+               return Double.valueOf(value(v, imperial_units)).toString();
        }
 
        public abstract String show_units(boolean imperial_units);
index 447830e547f242175702bd16c7612e5d0202431c..59a3b2ca89ab3e09a39887108fecc74d2208b9b5 100644 (file)
@@ -1,10 +1,10 @@
-AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked -source 6
+AM_JAVACFLAGS=$(JAVAC_VERSION_FLAGS) -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked
 
 JAVAROOT=bin
 
 VERSION=1
 
-CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH="bin:$(FREETTS)/*:/usr/share/java/*"
+CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=bin
 
 SRC=.
 
@@ -48,6 +48,7 @@ altoslib_JAVA = \
        AltosEepromRecordMini.java \
        AltosEepromRecordGps.java \
        AltosEepromRecordFireTwo.java \
+       AltosEepromRecordMicroPeak2.java \
        AltosEepromRecordSet.java \
        AltosEepromChunk.java \
        AltosEepromDownload.java \
@@ -207,3 +208,6 @@ bin:
 
 $(JAR): classaltoslib.stamp
        jar cf $@ -C bin org
+if STRIP_NONDETERMINISM
+       $(STRIP_NONDETERMINISM) $@
+endif
index b4c37e0bff7143f8163c3df5cc8683a6efa09600..39752b1dd771f8eaa8e67d5cb072768c28c820f8 100644 (file)
@@ -1427,20 +1427,29 @@ public class AltosConfigFCUI
                return pyro_firing_time;
        }
 
+       private String aprs_interval_string(int interval) {
+               if (interval == 0)
+                       return "Disabled";
+               return Integer.toString(interval);
+       }
+
+       private int aprs_interval_value(String interval) throws AltosConfigDataException {
+               if (interval.equalsIgnoreCase("Disabled"))
+                       return 0;
+               return parse_int("aprs interval", interval, false);
+       }
+
        public void set_aprs_interval(int new_aprs_interval) {
                if (new_aprs_interval != AltosLib.MISSING)
-                       aprs_interval_value.setSelectedItem(Integer.toString(new_aprs_interval));
+                       aprs_interval_value.setSelectedItem(aprs_interval_string(new_aprs_interval));
                aprs_interval_value.setVisible(new_aprs_interval != AltosLib.MISSING);
                aprs_interval_label.setVisible(new_aprs_interval != AltosLib.MISSING);
                set_aprs_interval_tool_tip();
        }
 
        public int aprs_interval() throws AltosConfigDataException {
-               if (aprs_interval_value.isVisible()) {
-                       String  s = aprs_interval_value.getSelectedItem().toString();
-
-                       return parse_int("aprs interval", s, false);
-               }
+               if (aprs_interval_value.isVisible())
+                       return aprs_interval_value(aprs_interval_value.getSelectedItem().toString());
                return AltosLib.MISSING;
        }
 
index 59b06c18da42a68a03934df79a0713f528121281..c1fdc3a3f25f46d21f597f6893153e892a034e6e 100644 (file)
@@ -45,6 +45,7 @@ public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, Alt
        void fill_map(AltosFlightSeries flight_series) {
                boolean                 any_gps = false;
                AltosGPSTimeValue       gtv_last = null;
+               double gps_pad_altitude = flight_series.cal_data().gps_pad_altitude;;
 
                if (flight_series.gps_series != null) {
                        for (AltosGPSTimeValue gtv : flight_series.gps_series) {
@@ -54,7 +55,9 @@ public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, Alt
                                    gps.nsat >= 4) {
                                        if (map == null)
                                                map = new AltosUIMap();
-                                       map.show(gps, (int) flight_series.value_before(AltosFlightSeries.state_name, gtv.time));
+                                       double gps_height = gps.alt - gps_pad_altitude;
+                                       int state = (int) flight_series.value_before(AltosFlightSeries.state_name, gtv.time);
+                                       map.show(gps, gtv.time, state, gps_height);
                                        this.gps = gps;
                                        gtv_last = gtv;
                                        has_gps = true;
@@ -63,8 +66,9 @@ public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, Alt
                }
                if (gtv_last != null) {
                        int state = (int) flight_series.value_after(AltosFlightSeries.state_name, gtv_last.time);
+                       double gps_height = gps.alt - gps_pad_altitude;
                        if (state == AltosLib.ao_flight_landed)
-                               map.show(gtv_last.gps, state);
+                               map.show(gtv_last.gps, gtv_last.time, state,gps_height);
                }
        }
 
index 82ec47465f90a30477bd434daafe270ca7631b24..56e46436beaafccc2261cd3438852ce48a61bf74 100644 (file)
@@ -102,7 +102,7 @@ public class AltosUI extends AltosUIFrame implements AltosEepromGrapher {
 
        /* OSXAdapter interfaces */
        public void macosx_file_handler(String path) {
-               process_graph(new File(path));
+               process_graph(null, new File(path));
        }
 
        public void macosx_quit_handler() {
@@ -324,7 +324,7 @@ public class AltosUI extends AltosUIFrame implements AltosEepromGrapher {
        public void graph_flights(AltosEepromList flights) {
                for (AltosEepromLog flight : flights) {
                        if (flight.graph_selected && flight.file != null) {
-                               process_graph(flight.file);
+                               process_graph(this, flight.file);
                        }
                }
        }
@@ -354,6 +354,25 @@ public class AltosUI extends AltosUIFrame implements AltosEepromGrapher {
                new AltosCSVUI(AltosUI.this, series, chooser.file());
        }
 
+       private static boolean graph_file(AltosUI altosui, AltosRecordSet set, File file) {
+               if (set == null)
+                       return false;
+               if (!set.valid()) {
+                       JOptionPane.showMessageDialog(altosui,
+                                                     String.format("Failed to parse file %s", file),
+                                                     "Graph Failed",
+                                                     JOptionPane.ERROR_MESSAGE);
+                       return false;
+               }
+               try {
+                       new AltosGraphUI(set, file);
+                       return true;
+               } catch (InterruptedException ie) {
+               } catch (IOException ie) {
+               }
+               return false;
+       }
+
        /* Load a flight log CSV file and display a pretty graph.
         */
 
@@ -361,13 +380,7 @@ public class AltosUI extends AltosUIFrame implements AltosEepromGrapher {
                AltosDataChooser chooser;
                chooser = new AltosDataChooser(this);
                AltosRecordSet set = chooser.runDialog();
-               if (set == null)
-                       return;
-               try {
-                       new AltosGraphUI(set, chooser.file());
-               } catch (InterruptedException ie) {
-               } catch (IOException ie) {
-               }
+               graph_file(this, set, chooser.file());
        }
 
        private void ConfigureAltosUI() {
@@ -477,17 +490,9 @@ public class AltosUI extends AltosUIFrame implements AltosEepromGrapher {
                return true;
        }
 
-       static boolean process_graph(File file) {
+       static boolean process_graph(AltosUI altosui, File file) {
                AltosRecordSet set = record_set(file);
-               if (set == null)
-                       return false;
-               try {
-                       new AltosGraphUI(set, file);
-                       return true;
-               } catch (InterruptedException ie) {
-               } catch (IOException ie) {
-               }
-               return false;
+               return graph_file(altosui, set, file);
        }
 
        static boolean process_summary(File file) {
@@ -613,7 +618,7 @@ public class AltosUI extends AltosUIFrame implements AltosEepromGrapher {
                                                if (altosui == null)
                                                        altosui = new AltosUI();
                                        case process_graph:
-                                               if (!process_graph(file))
+                                               if (!process_graph(null, file))
                                                        ++errors;
                                                break;
                                        case process_replay:
index 7cc1f4ea0dc462e9124b53fc9726b5ef4be66fbf..eab29cbe7a4c5692d7df09fc3d7ae8d7bf40ae6b 100644 (file)
@@ -1,6 +1,6 @@
 
 JAVAROOT=classes
-AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked -source 6
+AM_JAVACFLAGS=$(JAVAC_VERSION_FLAGS) -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked
 
 man_MANS=altosui.1
 
@@ -122,7 +122,8 @@ FIRMWARE_TD_3_0=$(top_srcdir)/src/teledongle-v3.0/teledongle-v3.0-$(VERSION).ihx
 FIRMWARE_TD=$(FIRMWARE_TD_3_0)
 
 FIRMWARE_TM_2_0=$(top_srcdir)/src/telemetrum-v2.0/telemetrum-v2.0-$(VERSION).ihx
-FIRMWARE_TM=$(FIRMWARE_TM_2_0)
+FIRMWARE_TM_3_0=$(top_srcdir)/src/telemetrum-v3.0/telemetrum-v3.0-$(VERSION).ihx
+FIRMWARE_TM=$(FIRMWARE_TM_2_0) $(FIRMWARE_TM_3_0)
 
 FIRMWARE_TELEMINI_3_0=$(top_srcdir)/src/telemini-v3.0/telemini-v3.0-$(VERSION).ihx
 FIRMWARE_TELEMINI=$(FIRMWARE_TELEMINI_3_0)
@@ -137,7 +138,8 @@ FIRMWARE_TMEGA_3_0=$(top_srcdir)/src/telemega-v3.0/telemega-v3.0-$(VERSION).ihx
 FIRMWARE_TMEGA=$(FIRMWARE_TMEGA_1_0) $(FIRMWARE_TMEGA_2_0) $(FIRMWARE_TMEGA_3_0)
 
 FIRMWARE_EMINI_1_0=$(top_srcdir)/src/easymini-v1.0/easymini-v1.0-$(VERSION).ihx
-FIRMWARE_EMINI=$(FIRMWARE_EMINI_1_0)
+FIRMWARE_EMINI_2_0=$(top_srcdir)/src/easymini-v2.0/easymini-v2.0-$(VERSION).ihx
+FIRMWARE_EMINI=$(FIRMWARE_EMINI_1_0) $(FIRMWARE_EMINI_2_0)
 
 FIRMWARE_EMEGA_1_0=$(top_srcdir)/src/easymega-v1.0/easymega-v1.0-$(VERSION).ihx
 FIRMWARE_EMEGA_2_0=$(top_srcdir)/src/easymega-v2.0/easymega-v2.0-$(VERSION).ihx
@@ -255,12 +257,18 @@ $(JAR): classaltosui.stamp Manifest.txt $(JAVA_ICONS) $(ALTOSLIB_CLASS) $(ALTOSU
                $(ICONJAR) \
                -C classes altosui \
                -C ../libaltos libaltosJNI
+if STRIP_NONDETERMINISM
+       $(STRIP_NONDETERMINISM) $@
+endif
 
 $(FATJAR): classaltosui.stamp Manifest-fat.txt $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) $(FREETTS_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) $(JAVA_ICONS)
        jar cfm $@ Manifest-fat.txt \
                $(ICONJAR) \
                -C classes altosui \
                -C ../libaltos libaltosJNI
+if STRIP_NONDETERMINISM
+       $(STRIP_NONDETERMINISM) $@
+endif
 
 Manifest.txt: Makefile
        echo 'Main-Class: altosui.AltosUI' > $@
index ffb39b8c2aae4e4e7b2035a9e780355114808bf8..7186e91b33024f14fc7c1e21d3c0dda5f99a6cfe 100644 (file)
@@ -319,7 +319,7 @@ public class AltosFlashUI
                                return false;
                }
 
-               if (existing_config.radio_calibration_broken) {
+               if (existing_config != null && existing_config.radio_calibration_broken) {
                        int ret = JOptionPane.showConfirmDialog(this,
                                                                String.format("Radio calibration value %d may be incorrect\nFlash anyways?",
                                                                              existing_config.radio_calibration),
@@ -481,12 +481,24 @@ public class AltosFlashUI
                public void run () {
                        try {
                                AltosLink link = null;
+                               boolean new_device = false;
 
                                for (;;) {
                                        System.out.printf("Attempting to open %s\n", device.toShortString());
 
-                                       link = new AltosSerial(device);
+                                       for (int i = 0; i < 20; i++) {
+                                               link = new AltosSerial(device);
 
+                                               if (link != null)
+                                                       break;
+
+                                               if (!new_device)
+                                                       break;
+
+                                               System.out.printf("Waiting for device to become ready\n");
+
+                                               Thread.sleep(1000);
+                                       }
                                        if (link == null)
                                                throw new IOException(String.format("%s: open failed",
                                                                                    device.toShortString()));
@@ -536,6 +548,7 @@ public class AltosFlashUI
                                                        if (!matched) {
                                                                System.out.printf("Identified new device %s\n", d.toShortString());
                                                                device = (AltosUSBDevice) d;
+                                                               new_device = true;
                                                                break;
                                                        }
                                                }
index fd670d4ec9df439081ee7533662989f9e2223083..eb2e8333d5df9597c2eb767cc0a6be31a7e04441 100644 (file)
@@ -29,9 +29,11 @@ public class AltosRomconfigUI
 {
        Container       pane;
        Box             box;
+       JLabel          product_label;
        JLabel          serial_label;
        JLabel          radio_calibration_label;
 
+       JLabel          product_value;
        JFrame          owner;
        JTextField      serial_value;
        JTextField      radio_calibration_value;
@@ -54,6 +56,29 @@ public class AltosRomconfigUI
 
                int y = 0;
 
+               /* Product name */
+               /* Serial */
+               c = new GridBagConstraints();
+               c.gridx = 0; c.gridy = y;
+               c.gridwidth = 3;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = il;
+               product_label = new JLabel("Product:");
+               pane.add(product_label, c);
+
+               c = new GridBagConstraints();
+               c.gridx = 3; c.gridy = y;
+               c.gridwidth = 3;
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.weightx = 1;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = ir;
+               product_value = new JLabel(config.usb_product);
+               pane.add(product_value, c);
+
+               y++;
+
                /* Serial */
                c = new GridBagConstraints();
                c.gridx = 0; c.gridy = y;
@@ -76,7 +101,7 @@ public class AltosRomconfigUI
 
                y++;
 
-               if (AltosLib.has_radio(config.usb_id.pid)) {
+               if (config == null || AltosLib.has_radio(config.usb_id.pid)) {
                        /* Radio calibration value */
                        c = new GridBagConstraints();
                        c.gridx = 0; c.gridy = y;
index 098e9a52f17ebe28add7f8f3829f10f86279f278..da02451310416c47627a8a1b4251a5110d080f91 100644 (file)
@@ -137,7 +137,8 @@ public class AltosUIGraph implements AltosUnitsListener, AltosShapeListener {
                this.series = null;
                this.axis_index = 0;
 
-               enable.register_shape_listener(this);
+               if (enable != null)
+                       enable.register_shape_listener(this);
 
                axes_added = new Hashtable<Integer,Boolean>();
 
index 8dfdba64c8bca8da70beb0f8462e6c2e3882341c..bd0a855c01ee6468c549bbdafeb3af6ebb0bfe44 100644 (file)
@@ -36,6 +36,7 @@ public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosM
        Graphics2D      g;
        Font            tile_font;
        Font            line_font;
+       AltosMapMark    nearest_mark;
 
        static Point2D.Double point2d(AltosPointDouble pt) {
                return new Point2D.Double(pt.x, pt.y);
@@ -115,7 +116,61 @@ public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosM
                        map.touch_continue(e.getPoint().x, e.getPoint().y, is_drag_event(e));
                }
 
+               String pos(double p, String pos, String neg) {
+                       if (p == AltosLib.MISSING)
+                               return "";
+                       String  h = pos;
+                       if (p < 0) {
+                               h = neg;
+                               p = -p;
+                       }
+                       int deg = (int) Math.floor(p);
+                       double min = (p - Math.floor(p)) * 60.0;
+                       return String.format("%s %4d° %9.6f'", h, deg, min);
+               }
+
+               String height(double h, String label) {
+                       if (h == AltosLib.MISSING)
+                               return "";
+                       return String.format(" %s%s",
+                                            AltosConvert.height.show(6, h),
+                                            label);
+               }
+
+               String speed(double s, String label) {
+                       if (s == AltosLib.MISSING)
+                               return "";
+                       return String.format(" %s%s",
+                                            AltosConvert.speed.show(6, s),
+                                            label);
+               }
+
                public void mouseMoved(MouseEvent e) {
+                       AltosMapPathPoint point = map.nearest(e.getPoint().x, e.getPoint().y);
+
+                       if (point != null) {
+                               if (nearest_mark == null)
+                                       nearest_mark = map.add_mark(point.gps.lat,
+                                                                   point.gps.lon,
+                                                                   point.state);
+                               else {
+                                       nearest_mark.lat_lon.lat = point.gps.lat;
+                                       nearest_mark.lat_lon.lon = point.gps.lon;
+                                       nearest_mark.state = point.state;
+                               }
+                               nearest_label.setText(String.format("%9.2f sec %s%s%s%s",
+                                                                   point.time,
+                                                                   pos(point.gps.lat,
+                                                                       "N", "S"),
+                                                                   pos(point.gps.lon,
+                                                                       "E", "W"),
+                                                                   height(point.gps_height, ""),
+                                                                   speed(point.gps.ground_speed, "(h)"),
+                                                                   speed(point.gps.climb_rate, "(v)")));
+                       } else {
+                               nearest_label.setText("");
+                       }
+                       repaint();
                }
 
                /* MouseListener methods */
@@ -222,7 +277,7 @@ public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosM
                        g.setStroke(new BasicStroke(stroke_width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
 
                        for (AltosMapPathPoint point : points) {
-                               Point2D.Double  cur = point2d(t.screen(point.lat_lon));
+                               Point2D.Double  cur = point2d(t.screen(point.gps.lat, point.gps.lon));
                                if (prev != null) {
                                        Line2D.Double   line = new Line2D.Double (prev, cur);
                                        Rectangle       bounds = line.getBounds();
@@ -387,6 +442,8 @@ public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosM
        public void set_font() {
                tile_font = AltosUILib.value_font;
                line_font = AltosUILib.status_font;
+               if (nearest_label != null)
+                       nearest_label.setFont(AltosUILib.value_font);
        }
 
        public void font_size_changed(int font_size) {
@@ -400,6 +457,8 @@ public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosM
 
        JLabel  zoom_label;
 
+       JLabel  nearest_label;
+
        public void set_maptype(int type) {
 /*
                map.set_maptype(type);
@@ -430,8 +489,8 @@ public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosM
                map.show(state, listener_state);
        }
 
-       public void show(AltosGPS gps, int state) {
-               map.show(gps, state);
+       public void show(AltosGPS gps, double time, int state, double gps_height) {
+               map.show(gps, time, state, gps_height);
        }
 
        public String getName() {
@@ -541,6 +600,20 @@ public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosM
                c.weighty = 0;
                add(zoom_out, c);
 
+
+               nearest_label = new JLabel("", JLabel.LEFT);
+               nearest_label.setFont(tile_font);
+
+               c = new GridBagConstraints();
+               c.anchor = GridBagConstraints.CENTER;
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.gridx = 0;
+               c.gridy = 11;
+               c.weightx = 0;
+               c.weighty = 0;
+               c.gridwidth = 1;
+               c.gridheight = 1;
+               add(nearest_label, c);
 /*
                maptype_combo = new JComboBox<String>(map.maptype_labels);
 
index c00144f8cfb9ef99b745669ec315699aac0b7aaa..10a5b494d3883477f3030aaeeaaebab22cb491d8 100644 (file)
@@ -1,4 +1,4 @@
-AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked -source 6
+AM_JAVACFLAGS=$(JAVAC_VERSION_FLAGS) -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked
 
 JAVAROOT=bin
 
@@ -101,3 +101,6 @@ $(JAVAROOT):
 
 $(JAR): classaltosuilib.stamp $(ICONS)
        jar cf $@ $(ICONJAR) -C $(JAVAROOT) .
+if STRIP_NONDETERMINISM
+       $(STRIP_NONDETERMINISM) $@
+endif
index 266848754700fdb24a9dad96bb3a9228c68298d7..3d510971ffc84307d3a6a3a32b89e37df03c3d40 100755 (executable)
@@ -37,7 +37,7 @@ tests="0:100 1:100 2:100 3:100 12:10 13:100 15:10000 16:250 202:1000 203:100 204
 PASS=0
 FAIL=0
 WEAK=0
-../ao-tools/ao-chaosread/ao-chaosread $serial --infinite --bytes | for test in $tests done; do
+chaosread $serial --infinite --bytes | for test in $tests done; do
     case $test in
        *:*:*)
            dnum=`echo $test | sed 's/:.*$//'`
index 13407e8675f38f1dd5ac7efc8eda262a1f8b9a0b..8fa1d1d3d0fde2302770e4eeff1ea93e86d0d925 100755 (executable)
@@ -1,11 +1,11 @@
 #!/bin/sh
 
-VERSION=2.0
+VERSION=3.0
 PRODUCT=TeleMetrum
 BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
 
 echo "$PRODUCT-v$VERSION Test Program"
-echo "Copyright 2014 by Keith Packard.  Released under GPL v2"
+echo "Copyright 2019 by Bdale Garbee.  Released under GPL v2"
 echo
 echo "Expectations:"
 echo "\t$PRODUCT v$VERSION powered from USB"
diff --git a/ao-bringup/test-telemetrum-v2.0 b/ao-bringup/test-telemetrum-v2.0
new file mode 100755 (executable)
index 0000000..13407e8
--- /dev/null
@@ -0,0 +1,68 @@
+#!/bin/sh
+
+VERSION=2.0
+PRODUCT=TeleMetrum
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+
+echo "$PRODUCT-v$VERSION Test Program"
+echo "Copyright 2014 by Keith Packard.  Released under GPL v2"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo
+
+ret=1
+ao-list | while read product serial dev; do
+    case "$product" in
+       "$PRODUCT-v$VERSION")
+
+           echo "Testing $product $serial $dev"
+           echo ""
+
+           ./test-igniters "$dev" drogue main
+           echo ""
+
+           echo "Testing baro sensor"
+           ../ao-tools/ao-test-baro/ao-test-baro --tty="$dev"
+
+           case $? in
+               0)
+                   ;;
+               *)
+                   echo "failed"
+                   exit 1
+           esac
+           echo""
+
+           FLASHSIZE=8388608
+
+           echo "Testing flash"
+           ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE"
+
+           case $? in
+               0)
+                   ;;
+               *)
+                   echo "failed"
+                   exit 1
+           esac
+           echo""
+
+           echo "Testing GPS"
+           ../ao-tools/ao-test-gps/ao-test-gps --tty="$dev"
+
+           case $? in
+               0)
+                   ;;
+               *)
+                   echo "failed"
+                   exit 1
+           esac
+           echo""
+
+           echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
+           echo "\007"
+           ret=0
+           ;;
+    esac
+done
diff --git a/ao-bringup/turnon_telefireeight b/ao-bringup/turnon_telefireeight
new file mode 100755 (executable)
index 0000000..871c357
--- /dev/null
@@ -0,0 +1,74 @@
+#!/bin/sh
+
+PRODUCT=TeleFireEight
+VERSION=2.0
+REPO=~/altusmetrumllc/Binaries
+
+if [ -x /usr/bin/ao-flash-stm ]; then
+       FLASH_STM=/usr/bin/ao-flash-stm
+else
+       echo "Can't find ao-flash-stm!  Aborting."
+       exit 1
+fi
+
+if [ -x /usr/bin/ao-usbload ]; then
+       USBLOAD=/usr/bin/ao-usbload
+else
+       echo "Can't find ao-usbload!  Aborting."
+       exit 1
+fi
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2019 by Bdale Garbee.  Released under GPL v2"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION"
+echo "\t\twith USB cable attached"
+echo "\t\twith ST-Link-V2 cabled to debug header"
+echo
+
+case $# in
+    1)
+       SERIAL="$1"
+       echo "$PRODUCT-$VERSION serial number: $SERIAL" 
+       ;;
+    0)
+       echo -n "$PRODUCT-$VERSION serial number: "
+       read SERIAL
+       ;;
+    *)
+       echo "Usage: $0 <serial-number>" 1>&2
+       exit 1;
+       ;;
+esac
+
+echo $FLASH_STM
+
+$FLASH_STM $REPO/loaders/telefireeight-v$VERSION*.elf
+
+sleep 3
+
+$USBLOAD --serial=$SERIAL $REPO/telefireeight-v$VERSION*.elf || exit 1
+
+sleep 5
+
+dev=`ao-list | awk '/'"$PRODUCT"'-v'"$VERSION"'/ { print $3; exit(0); }'`
+
+case "$dev" in
+/dev/tty*)
+       echo "$PRODUCT found on $dev"
+       ;;
+*)
+       echo 'No '"$PRODUCT"'-v'"$VERSION"' found'
+       exit 1
+       ;;
+esac
+
+echo 'E 0' > $dev
+SERIAL=$SERIAL ./cal-freq $dev
+echo 'E 1' > $dev
+
+echo "$PRODUCT-v$VERSION" serial "$SERIAL" is ready for integration and testing
+echo "\007"
+
+exit $?
index dd30378a01a649eeead9db44e6d9e8c39571326a..9d8f18964968ca9f2a4e885a34c44ac44d80938d 100755 (executable)
@@ -14,7 +14,7 @@ else
        exit 1
 fi
 
-VERSION=2.0
+VERSION=3.0
 PRODUCT=TeleMetrum
 
 echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
diff --git a/ao-bringup/turnon_telemetrum_v2.0 b/ao-bringup/turnon_telemetrum_v2.0
new file mode 100755 (executable)
index 0000000..dd30378
--- /dev/null
@@ -0,0 +1,81 @@
+#!/bin/sh
+
+if [ -x /usr/bin/ao-flash-stm ]; then
+       FLASH_STM=/usr/bin/ao-flash-stm
+else
+       echo "Can't find ao-flash-stm!  Aborting."
+       exit 1
+fi
+
+if [ -x /usr/bin/ao-usbload ]; then
+       USBLOAD=/usr/bin/ao-usbload
+else
+       echo "Can't find ao-usbload!  Aborting."
+       exit 1
+fi
+
+VERSION=2.0
+PRODUCT=TeleMetrum
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2014 by Bdale Garbee.  Released under GPL v2"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo "\t\twith ST-Link-V2 cabled to debug header"
+echo "\t\twith coax from UHF to frequency counter"
+echo
+echo -n "$PRODUCT-$VERSION serial number: "
+
+case $# in
+    1)
+       SERIAL="$1"
+       echo "$PRODUCT-$VERSION serial number: $SERIAL" 
+       ;;
+    0)
+       echo -n "$PRODUCT-$VERSION serial number: "
+       read SERIAL
+       ;;
+    *)
+       echo "Usage: $0 <serial-number>" 1>&2
+       exit 1;
+       ;;
+esac
+
+echo $FLASH_STM
+
+$FLASH_STM ~/altusmetrumllc/Binaries/loaders/telemetrum-v$VERSION-*.elf || exit 1
+
+sleep 3
+
+$USBLOAD --serial=$SERIAL ~/altusmetrumllc/Binaries/telemetrum-v$VERSION-*.elf || exit 1
+
+sleep 5
+
+dev=`ao-list | awk '/TeleMetrum-v'"$VERSION"'/ { print $3; exit(0); }'`
+
+case "$dev" in
+/dev/tty*)
+       echo "TeleMetrum found on $dev"
+       ;;
+*)
+       echo 'No TeleMetrum-v'"$VERSION"' found'
+       exit 1
+       ;;
+esac
+
+echo 'E 0' > $dev
+
+SERIAL=$SERIAL ./cal-freq $dev
+
+failed=1
+while [ $failed = 1 ]; do
+    ../ao-tools/ao-cal-accel/ao-cal-accel $dev
+    failed=$?
+done
+
+echo 'E 1' > $dev
+
+./test-telemetrum
+
+exit $?
index fb5548576e0fb1a5be5d9e930294d2a6305a6410..e2425c99efb4d1aa5f6d4ece74aeb445f29dafe1 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-chaosread ao-makebin
+       ao-cal-freq ao-makebin
 if LIBSTLINK
 SUBDIRS += ao-stmload
 endif
index f01cddd47d5e940f34d6efcbda9194cff7452838..b42885a40d0f8fd6a3f70e850dc6edbf8b60e205 100644 (file)
@@ -1,6 +1,6 @@
 bin_PROGRAMS=ao-bitbang
 
-AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AM_CFLAGS=$(WARN_CFLAGS) -I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
 AO_BITBANG_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
 
 ao_bitbang_DEPENDENCIES = $(AO_BITBANG_LIBS)
diff --git a/ao-tools/ao-bm70/Makefile.am b/ao-tools/ao-bm70/Makefile.am
new file mode 100644 (file)
index 0000000..f13ce0f
--- /dev/null
@@ -0,0 +1,7 @@
+bin_PROGRAMS=ao-bm70
+
+AM_CFLAGS=-O0 -g
+
+ao_bm70_SOURCES = ao-bm70.c
+
+man_MANS=ao-bm70.1
diff --git a/ao-tools/ao-boot-stm32/Makefile.am b/ao-tools/ao-boot-stm32/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
index d278097a27e434f6315c00ca03c801363b6e05a2..49997252d941c6513b7a1df4715700352f2d2658 100644 (file)
@@ -1,6 +1,6 @@
 bin_PROGRAMS=ao-cal-accel
 
-AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AM_CFLAGS=$(WARN_CFLAGS) -I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
 
 ao_cal_accel_DEPENDENCIES = $(top_builddir)/ao-tools/lib/libao-tools.a
 
index 8a9e634727e842e70912eda45775d8d6d2ce7466..671e4ba53925b9e6f05a9c398c45a22fe855da57 100644 (file)
@@ -48,35 +48,13 @@ static void usage(char *program)
        exit(1);
 }
 
-void
+static void
 done(struct cc_usb *cc, int code)
 {
        cc_usb_close(cc);
        exit (code);
 }
 
-static int
-ends_with(char *whole, char *suffix)
-{
-       int whole_len = strlen(whole);
-       int suffix_len = strlen(suffix);
-
-       if (suffix_len > whole_len)
-               return 0;
-       return strcmp(whole + whole_len - suffix_len, suffix) == 0;
-}
-
-static int
-starts_with(char *whole, char *prefix)
-{
-       int whole_len = strlen(whole);
-       int prefix_len = strlen(prefix);
-
-       if (prefix_len > whole_len)
-               return 0;
-       return strncmp(whole, prefix, prefix_len) == 0;
-}
-
 static char **
 tok(char *line) {
        char    **strs = malloc (sizeof (char *)), *str;
@@ -92,16 +70,6 @@ tok(char *line) {
        return strs;
 }
 
-static void
-free_strs(char **strs) {
-       char    *str;
-       int     i;
-
-       for (i = 0; (str = strs[i]) != NULL; i++)
-               free(str);
-       free(strs);
-}
-
 struct flash {
        struct flash    *next;
        char            line[512];
@@ -130,21 +98,8 @@ flash(struct cc_usb *usb)
        return head;
 }
 
-static void
-free_flash(struct flash *b) {
-       struct flash *n;
-
-       while (b) {
-               n = b->next;
-               free_strs(b->strs);
-               free(b);
-               b = n;
-       }
-}
-
-char **
+static char **
 find_flash(struct flash *b, char *word0) {
-       int i;
        for (;b; b = b->next) {
                if (strstr(b->line, word0))
                        return b->strs;
@@ -152,7 +107,7 @@ find_flash(struct flash *b, char *word0) {
        return NULL;
 }
 
-void
+static void
 await_key(void)
 {
        struct termios  termios, termios_save;
@@ -166,12 +121,12 @@ await_key(void)
        tcsetattr(0, TCSAFLUSH, &termios_save);
 }
 
-int
+static int
 do_cal(struct cc_usb *usb) {
        struct flash    *b;
        char    **accel;
        char    line[1024];
-       int     l;
+       int     l = 0;
        int     running = 0;
        int     worked = 1;
 
@@ -230,18 +185,11 @@ int
 main (int argc, char **argv)
 {
        char                    *device = NULL;
-       char                    *filename;
-       Elf                     *e;
-       unsigned int            s;
-       int                     i;
        int                     c;
-       int                     tries;
        struct cc_usb           *cc = NULL;
        char                    *tty = NULL;
-       int                     success;
        int                     verbose = 0;
        int                     ret = 0;
-       int                     expected_size;
 
        while ((c = getopt_long(argc, argv, "rT:D:c:s:v:", options, NULL)) != -1) {
                switch (c) {
index e11c2b0aa50cdcc33f65a985eb62f86015945805..eccfde242bc1b2aad9bf135dfa969a40407397c5 100644 (file)
@@ -1,6 +1,6 @@
 bin_PROGRAMS=ao-cal-freq
 
-AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AM_CFLAGS=$(WARN_CFLAGS) -I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
 
 ao_cal_freq_DEPENDENCIES = $(top_builddir)/ao-tools/lib/libao-tools.a
 
index 838fbab3a6f6947844a97e692d58515b75093b44..b9efb8f68a46e55539400754c8a2959fcd3dbb74 100644 (file)
@@ -50,35 +50,6 @@ static void usage(char *program)
        exit(1);
 }
 
-void
-done(struct cc_usb *cc, int code)
-{
-       cc_usb_close(cc);
-       exit (code);
-}
-
-static int
-ends_with(char *whole, char *suffix)
-{
-       int whole_len = strlen(whole);
-       int suffix_len = strlen(suffix);
-
-       if (suffix_len > whole_len)
-               return 0;
-       return strcmp(whole + whole_len - suffix_len, suffix) == 0;
-}
-
-static int
-starts_with(char *whole, char *prefix)
-{
-       int whole_len = strlen(whole);
-       int prefix_len = strlen(prefix);
-
-       if (prefix_len > whole_len)
-               return 0;
-       return strncmp(whole, prefix, prefix_len) == 0;
-}
-
 static char **
 tok(char *line) {
        char    **strs = malloc (sizeof (char *)), *str;
@@ -94,16 +65,6 @@ tok(char *line) {
        return strs;
 }
 
-static void
-free_strs(char **strs) {
-       char    *str;
-       int     i;
-
-       for (i = 0; (str = strs[i]) != NULL; i++)
-               free(str);
-       free(strs);
-}
-
 struct flash {
        struct flash    *next;
        char            line[512];
@@ -132,21 +93,8 @@ flash(struct cc_usb *usb)
        return head;
 }
 
-static void
-free_flash(struct flash *b) {
-       struct flash *n;
-
-       while (b) {
-               n = b->next;
-               free_strs(b->strs);
-               free(b);
-               b = n;
-       }
-}
-
-char **
+static char **
 find_flash(struct flash *b, char *word0) {
-       int i;
        for (;b; b = b->next) {
                if (strstr(b->line, word0))
                        return b->strs;
@@ -154,21 +102,7 @@ find_flash(struct flash *b, char *word0) {
        return NULL;
 }
 
-void
-await_key(void)
-{
-       struct termios  termios, termios_save;
-       char    buf[512];
-
-       tcgetattr(0, &termios);
-       termios_save = termios;
-       cfmakeraw(&termios);
-       tcsetattr(0, TCSAFLUSH, &termios);
-       read(0, buf, sizeof (buf));
-       tcsetattr(0, TCSAFLUSH, &termios_save);
-}
-
-int
+static int
 do_save(struct cc_usb *usb)
 {
        int ret = 0;
@@ -192,7 +126,7 @@ do_save(struct cc_usb *usb)
        return ret;
 }
 
-int
+static int
 do_output(char *output, int cur_cal)
 {
        printf ("Saving calibration value to file \"%s\"\n", output);
@@ -220,7 +154,7 @@ do_output(char *output, int cur_cal)
        return ret;
 }
 
-int
+static int
 do_cal(char *tty, int save, char *output)
 {
        struct cc_usb *usb = NULL;
@@ -313,18 +247,11 @@ int
 main (int argc, char **argv)
 {
        char                    *device = NULL;
-       char                    *filename;
-       Elf                     *e;
-       unsigned int            s;
-       int                     i;
        int                     c;
-       int                     tries;
        char                    *tty = NULL;
-       int                     success;
        int                     verbose = 0;
        int                     save = 1;
        int                     ret = 0;
-       int                     expected_size;
        char                    *output = NULL;
 
        while ((c = getopt_long(argc, argv, "vnT:D:o:", options, NULL)) != -1) {
diff --git a/ao-tools/ao-chaosread/.gitignore b/ao-tools/ao-chaosread/.gitignore
deleted file mode 100644 (file)
index b944387..0000000
+++ /dev/null
@@ -1 +0,0 @@
-ao-chaosread
diff --git a/ao-tools/ao-chaosread/Makefile.am b/ao-tools/ao-chaosread/Makefile.am
deleted file mode 100644 (file)
index 6ba8885..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-bin_PROGRAMS=ao-chaosread
-
-AM_CFLAGS=$(LIBUSB_CFLAGS) -Wall -Wextra
-
-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
deleted file mode 100644 (file)
index 94ca5ce..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-.\"
-.\" 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.
-.TP
-\-l length | --length length
-Set the amount of data to read. Suffixes 'k', 'M' and 'G' are
-supported. The default is 1k.
-.TP
-\-i | --infinite
-Read an unlimited amount of data.
-.TP
-\-b | --bytes
-For each 16-bit value read, output bits 1-8 as a byte, don't output
-bit 0 or bits 9-15 at all.
-.TP
-\-c | --cooked
-Read whitened data from the device. The default is to read raw data
-from the noise source.
-.TP
-\-r | --raw
-Read raw data from the noise source. This is the default.
-.TP
-\-f | --flash
-Read the contents of flash memory on the device. This loops through
-flash memory, so you can read the contents more than once, but there's
-no way to reset the pointer back to the start other than making sure
-you read the whole contents.
-.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
deleted file mode 100644 (file)
index 5c0de12..0000000
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * Copyright © 2016 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include <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, (unsigned char *) 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:
-       if (handle)
-               libusb_close(handle);
-       return 0;
-}
-
-struct chaoskey *
-chaoskey_open(char *serial)
-{
-       struct chaoskey *ck;
-       int             ret;
-       ssize_t         num;
-       libusb_device   **list;
-       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);
-}
-
-#define COOKED_ENDPOINT        0x85
-#define RAW_ENDPOINT   0x86
-#define FLASH_ENDPOINT 0x87
-
-int
-chaoskey_read(struct chaoskey *ck, int endpoint, void *buffer, int len)
-{
-       uint8_t *buf = buffer;
-       int     total = 0;
-
-       while (len) {
-               int     ret;
-               int     transferred;
-
-               ret = libusb_bulk_transfer(ck->handle, endpoint, buf, len, &transferred, 10000);
-               if (ret) {
-                       if (total)
-                               return total;
-                       else {
-                               errno = EIO;
-                               return -1;
-                       }
-               }
-               len -= transferred;
-               buf += transferred;
-               total += transferred;
-       }
-       return total;
-}
-
-static const struct option options[] = {
-       { .name = "serial", .has_arg = 1, .val = 's' },
-       { .name = "length", .has_arg = 1, .val = 'l' },
-       { .name = "infinite", .has_arg = 0, .val = 'i' },
-       { .name = "bytes", .has_arg = 0, .val = 'b' },
-       { .name = "cooked", .has_arg = 0, .val = 'c' },
-       { .name = "raw", .has_arg = 0, .val = 'r' },
-       { .name = "flash", .has_arg = 0, .val = 'f' },
-       { 0, 0, 0, 0},
-};
-
-static void usage(char *program)
-{
-       fprintf(stderr, "usage: %s [--serial=<serial>] [--length=<length>[kMG]] [--infinite] [--bytes] [--cooked] [--raw] [--flash]\n", program);
-       exit(1);
-}
-
-int
-main (int argc, char **argv)
-{
-       struct chaoskey *ck;
-       uint16_t        buf[512];
-       int     got;
-       int     c;
-       char    *serial = NULL;
-       char    *length_string;
-       char    *length_end;
-       unsigned long   length = sizeof(buf);
-       int     this_time;
-       int     infinite = 0;
-       int     bytes = 0;
-       int     endpoint = RAW_ENDPOINT;
-
-       while ((c = getopt_long(argc, argv, "s:l:ibcrf", 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;
-               case 'i':
-                       infinite = 1;
-                       break;
-               case 'b':
-                       bytes = 1;
-                       break;
-               case 'c':
-                       endpoint = COOKED_ENDPOINT;
-                       break;
-               case 'r':
-                       endpoint = RAW_ENDPOINT;
-                       break;
-               case 'f':
-                       endpoint = FLASH_ENDPOINT;
-                       break;
-               default:
-                       usage(argv[0]);
-                       break;
-               }
-       }
-
-       ck = chaoskey_open(serial);
-       if (!ck)
-               exit(1);
-
-       if (bytes)
-               length *= 2;
-
-       while (length || infinite) {
-               this_time = sizeof(buf);
-               if (!infinite && length < sizeof(buf))
-                       this_time = (int) length;
-               got = chaoskey_read(ck, endpoint, buf, this_time);
-               if (got < 0) {
-                       perror("read");
-                       exit(1);
-               }
-               if (bytes) {
-                       int i;
-                       for (i = 0; i < got / 2; i++)
-                               putchar((buf[i] >> 1 & 0xff));
-               } else {
-                       int i;
-                       int ret;
-                       for (i = 0; i < got; i += ret) {
-                               ret = write(1, ((char *) buf) + i, got - i);
-                               if (ret <= 0) {
-                                       perror("write");
-                                       exit(1);
-                               }
-                       }
-               }
-               length -= got;
-       }
-       exit(0);
-}
index 2c33cf0677cee345151df0716a580971c4454be2..e2fe65421a23c08c7114bd9256e40eaaad34ba08 100644 (file)
@@ -1,6 +1,6 @@
 bin_PROGRAMS=ao-dbg
 
-AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AM_CFLAGS=$(WARN_CFLAGS) -I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
 AO_DBG_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
 
 man_MANS = ao-dbg.1
index 11c521e88d5a47614137a651f4ac6a02a7a252fa..f0e6b6cec51049e657a716e1fcc2a5586be312f8 100644 (file)
@@ -106,6 +106,7 @@ command_di (int argc, char **argv)
                return command_error;
        length = (int) end - (int) start + 1;
        status = ccdbg_read_memory(s51_dbg, start + 0xff00, memory, length);
+       (void) status;
        dump_bytes(memory, length, start, "0x%02x ");
        return command_success;
 }
@@ -126,6 +127,7 @@ command_ds (int argc, char **argv)
                return command_error;
        length = (int) end - (int) start + 1;
        status = ccdbg_read_sfr(s51_dbg, start, memory, length);
+       (void) status;
        dump_bytes(memory, length, start, "0x%02x ");
        return command_success;
 }
@@ -146,6 +148,7 @@ command_dx (int argc, char **argv)
                return command_error;
        length = (int) end - (int) start + 1;
        status = ccdbg_read_memory(s51_dbg, start, memory, length);
+       (void) status;
        dump_bytes(memory, length, start, "0x%04x ");
        return command_success;
 }
@@ -282,11 +285,10 @@ enable_breakpoints(void)
                        enable_breakpoint(b);
 }
 
-enum command_result
+static enum command_result
 set_breakpoint(uint16_t address, int temporary)
 {
        int b;
-       uint8_t status;
        for (b = 0; b < CC_NUM_BREAKPOINTS; b++) {
                if (breakpoints[b].enabled == 0)
                        break;
@@ -307,11 +309,10 @@ set_breakpoint(uint16_t address, int temporary)
        return command_success;
 }
 
-enum command_result
+static enum command_result
 clear_breakpoint(uint16_t address, int temporary)
 {
        int b;
-       uint8_t status;
 
        for (b = 0; b < CC_NUM_BREAKPOINTS; b++) {
                if (breakpoints[b].enabled != 0 &&
@@ -333,7 +334,7 @@ clear_breakpoint(uint16_t address, int temporary)
 }
 
 
-int
+static int
 find_breakpoint(uint16_t address)
 {
        int b;
@@ -372,7 +373,6 @@ command_break (int argc, char **argv)
 enum command_result
 command_clear (int argc, char **argv)
 {
-       int b;
        uint16_t address;
        enum command_result result;
 
@@ -384,7 +384,7 @@ command_clear (int argc, char **argv)
        return clear_breakpoint(address, 0);
 }
 
-void
+static void
 cc_stopped(uint8_t status)
 {
        uint16_t pc;
@@ -411,7 +411,7 @@ cc_stopped(uint8_t status)
        }
 }
 
-uint8_t
+static uint8_t
 cc_step(uint16_t pc)
 {
        int b;
@@ -585,8 +585,6 @@ static enum command_result
 info_breakpoints(int argc, char **argv)
 {
        int b;
-       uint16_t address;
-       enum command_result result;
 
        if (argc == 1) {
                s51_printf("Num Type       Disp Hit   Cnt   Address  What\n");
@@ -599,7 +597,7 @@ info_breakpoints(int argc, char **argv)
                        }
                return command_success;
        }
-
+       return command_syntax;
 }
 
 static enum command_result
index 8c87903510b5a325297afca854a1944a4cccbdaf..772701a94315543260b101747021a63ea213930e 100644 (file)
@@ -50,7 +50,8 @@ usage(void)
        exit(1);
 }
 
-void s51_sigint()
+static void
+s51_sigint(int signum)
 {
        s51_interrupted = 1;
 }
@@ -64,7 +65,7 @@ static const struct option options[] = {
 int
 main(int argc, char **argv)
 {
-       int flags, opt;
+       int opt;
        char *endptr;
 
        while ((opt = getopt_long(argc, argv, "PVvHhmt:X:c:r:Z:s:S:p:T:", options, NULL)) != -1) {
@@ -242,7 +243,6 @@ s51_check_input(void)
 {
        struct pollfd   input;
        int r;
-       int c;
 
        input.fd = fileno(s51_input);
        input.events = POLLIN;
index ba69183431c823f508bb318afff89c291ee77abc..b61d68b8db7266cf1696cda57a1162c92a6a3851 100644 (file)
@@ -68,41 +68,6 @@ static struct command_function functions[] = {
 #define TRUE 1
 #endif
 
-static int
-string_to_int(char *s, int *v)
-{
-       char *endptr;
-
-       if (isdigit(s[0]) || s[0] == '-' || s[0] == '+') {
-               *v = strtol(s, &endptr, 0);
-               if (endptr == s)
-                       return FALSE;
-       } else if (*s == '\'') {
-               s++;
-               if (*s == '\\') {
-                       s++;
-                       switch (*s) {
-                       case 'n':
-                               *v = '\n';
-                               break;
-                       case 't':
-                               *v = '\t';
-                               break;
-                       default:
-                               *v = (int) *s;
-                               break;
-                       }
-               } else
-                       *v = (int) *s;
-               s++;
-               if (*s != '\'')
-                       return FALSE;
-       }
-       else
-               return FALSE;
-    return TRUE;
-}
-
 struct command_function *
 command_string_to_function(struct command_function *functions, char *name)
 {
index edc650a506c8d99c2c2a20de7ba43443a0726b3e..2ced54b5a8d815585c98bdb0b66899ebd58ba183 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <ccdbg.h>
 #include <cc.h>
+#include <ctype.h>
 
 extern char *s51_prompt;
 extern struct ccdbg *s51_dbg;
index 94bb94a909b02c7f5004f604a130900b64f5727b..a5395a42222d7651caa8d3b5e903af3ea1a739a9 100644 (file)
@@ -1,6 +1,6 @@
 bin_PROGRAMS=ao-dump-up
 
-AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS) $(GNOME_CFLAGS)
+AM_CFLAGS=$(WARN_CFLAGS) -I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS) $(GNOME_CFLAGS)
 AO_DUMP_LOG_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
 
 ao_dump_up_DEPENDENCIES = $(AO_DUMP_LOG_LIBS)
index cfa81b465a565e663491976104c13addfe89f222..a3d8ef622bbfbc247d0049aa6f3ee1e381aa8cb5 100644 (file)
@@ -25,6 +25,7 @@ ao-dump-up \- Dump flight log from MicroPeak flight computer
 [\--tty \fItty-device\fP]
 [\-D \fIaltos-device\fP]
 [\--device \fIaltos-device\fP]
+[\--wait]
 .SH OPTIONS
 .TP
 \-T tty-device | --tty tty-device
@@ -34,6 +35,9 @@ the target device.
 \-D AltOS-device | --device AltOS-device
 Search for a connected device. This forces the program to look
 for a specific USB device name.
+.TP
+\--wait
+Wait for a device to appear instead of exiting when no device is found.
 .SH DESCRIPTION
 .I ao-dump-up
 downloads a MicroPeak flight log from a connected MicroPeak USB adapter.
index df05088cadaf2e4cb33d0b61482eac66f5210a5e..6866ef592997e7fe24bf9954d5c6fa81c3b56faa 100644 (file)
@@ -21,6 +21,7 @@
 #include <unistd.h>
 #include <getopt.h>
 #include <string.h>
+#include <ctype.h>
 #include "cc-usb.h"
 #include "cc.h"
 
@@ -39,17 +40,6 @@ static void usage(char *program)
        exit(1);
 }
 
-static uint8_t
-log_checksum(int d[8])
-{
-       uint8_t sum = 0x5a;
-       int     i;
-
-       for (i = 0; i < 8; i++)
-               sum += (uint8_t) d[i];
-       return -sum;
-}
-
 static int get_nonwhite(struct cc_usb *cc, int timeout)
 {
        int     c;
@@ -147,7 +137,6 @@ main (int argc, char **argv)
        char            *tty = NULL;
        char            *device = NULL;
        int             c;
-       char            line[8192];
        int             nsamples;
        int             i;
        int             crc;
index db99f5aedebd078c97ff6c205a3c107d942efc00..2b134f94e522f5bc603ae3bb00bb8842022fb584 100644 (file)
@@ -1,6 +1,6 @@
 bin_PROGRAMS=ao-dumpflash
 
-AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AM_CFLAGS=$(WARN_CFLAGS) -I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
 AO_DUMPLOG_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
 
 ao_dumpflash_DEPENDENCIES = $(AO_DUMPLOG_LIBS)
index 3cd21e66ac83ed0e8c228c5b38ec03e13dcbec86..5c789fb934fecb8b7582cdc4cbe0c7688521114c 100644 (file)
@@ -51,24 +51,17 @@ main (int argc, char **argv)
        int             c;
        char            line[8192];
        FILE            *out;
-       char            *filename;
        int             serial_number = 0;
        int             freq = 434550;
        char            *call = "N0CALL";
-       int             flight = 0;
-       char            cmd;
        int             block;
        int             addr;
        int             received_addr;
        int             data[8];
-       int             done;
        int             i;
-       int             column;
        int             remote = 0;
-       int             any_valid;
-       int             invalid;
        int             storage_size = 0;
-       char            *out_name;
+       char            *out_name = NULL;
 
        while ((c = getopt_long(argc, argv, "T:D:F:C:o:R", options, NULL)) != -1) {
                switch (c) {
index a80cac33f6196a64ed4a8f9d9284cec658b8b39a..bd4a8707bd2c230640525e639d861196a7690b88 100644 (file)
@@ -1,6 +1,6 @@
 bin_PROGRAMS=ao-dumplog
 
-AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS) $(GNOME_CFLAGS)
+AM_CFLAGS=$(WARN_CFLAGS) -I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS) $(GNOME_CFLAGS)
 AO_DUMPLOG_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
 
 ao_dumplog_DEPENDENCIES = $(AO_DUMPLOG_LIBS)
index c5965c4707b852c79ec5e8345ba18f3f0b5d633a..154d6395db0bc2f893f4dffed60b06c411e75949 100644 (file)
@@ -1,6 +1,6 @@
 bin_PROGRAMS=ao-edit-telem
 
-AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AM_CFLAGS=$(WARN_CFLAGS) -I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
 AO_POSTFLIGHT_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
 
 ao_edit_telem_DEPENDENCIES = $(AO_POSTFLIGHT_LIBS)
index e2795ede180908ac11acb1b2ff93c4e24ba80660..92cde3dc73ee88be3532550bff301a6bd5e241ee 100644 (file)
@@ -73,7 +73,7 @@ int pending = 1;
 static void
 dump_saved(void);
 
-void
+static void
 doit(union ao_telemetry_all *telem)
 {
        double lat, lon;
@@ -142,10 +142,9 @@ int
 main (int argc, char **argv)
 {
        char    line[80];
-       int c, i, ret;
-       char *s;
+       int c, i, ret = 0;
        FILE *file;
-       int serial;
+
        while ((c = getopt_long(argc, argv, "l:L:", options, NULL)) != -1) {
                switch (c) {
                case 'L':
@@ -166,11 +165,6 @@ main (int argc, char **argv)
                        ret++;
                        continue;
                }
-               s = strstr(argv[i], "-serial-");
-               if (s)
-                       serial = atoi(s + 8);
-               else
-                       serial = 0;
                while (fgets(line, sizeof (line), file)) {
                        union ao_telemetry_all telem;
 
index efeed97689d40c832d7b4c4a249c4f973a023b7d..1e38ebade5b5b1d7ec47c53a69e192aeedb2d9f2 100644 (file)
@@ -1,11 +1,11 @@
 bin_PROGRAMS=ao-eeprom
 
-AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AM_CFLAGS=$(WARN_CFLAGS) -I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
 AO_EEPROM_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
 
 ao_eeprom_DEPENDENCIES = $(AO_EEPROM_LIBS)
 
-ao_eeprom_LDADD=$(AO_EEPROM_LIBS) $(LIBUSB_LIBS)
+ao_eeprom_LDADD=$(AO_EEPROM_LIBS) -ljson-c -lm
 
 ao_eeprom_SOURCES = ao-eeprom.c
 
index 728f11ed2ffbb1bff79c956bd9ae195e81efa592..6257e125b3095b3c50991f5409de3ddee5332985 100644 (file)
 .\"
 .TH AO-EEPROM 1 "ao-eeprom" ""
 .SH NAME
-ao-eeprom \- Fetch eeprom contents from TeleMetrum device
+ao-eeprom \- Analyze an eeprom log
 .SH SYNOPSIS
 .B "ao-eeprom"
-[\-T \fItty-device\fP]
-[\--tty \fItty-device\fP]
-[\-D \fIaltos-device\fP]
-[\--device \fIaltos-device\fP]
+[\--raw]
+[\--csum]
+[\--verbose]
+[\--len <record-len>]
+{flight.eeprom} ...
 .SH OPTIONS
 .TP
-\-T tty-device | --tty tty-device
-This selects which tty device the debugger uses to communicate with
-the target device. The special name 'BITBANG' directs ao-dbg to use
-the cp2103 connection, otherwise this should be a usb serial port
-connected to a suitable cc1111 debug node.
+\-r | --raw
+This option makes ao-eeprom dump the raw bytes of each
+log record in hex format.
 .TP
-\-D AltOS-device | --device AltOS-device
-Search for a connected device. This requires an argument of one of the
-following forms:
-.IP
-TeleMetrum:2
-.br
-TeleMetrum
-.br
-2
-.IP
-Leaving out the product name will cause the tool to select a suitable
-product, leaving out the serial number will cause the tool to match
-one of the available devices.
+\-c | --csum
+This option makes ao-eeprom dump records that have checksum errors. By default,
+ao-eeprom skips such records.
+\-v | --verbose
+This option makes ao-eeprom report when records are skipped due to
+checksum errors.
+\-l <record-len> | --len <record-len
+Specify the eeprom record length rather than letting ao-eeprom
+automatically determine it based on the file contents.
 .SH DESCRIPTION
 .I ao-eeprom
-downloads the eeprom contents from a connected TeleMetrum device.
-.SH USAGE
-.I ao-eeprom
-connects to the specified target device and dumps each block of the
-eeprom to stdout in hexadecimal bytes.
+reads the specified eeprom log and display the contents of each
+record.
 .SH AUTHOR
 Keith Packard
index b865e298d2e01b6a499c6a7e270e46a682d31e2b..91a6ccb352ac1740da8f89280dcdbc3c2769cfeb 100644 (file)
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdbool.h>
 #include <unistd.h>
 #include <getopt.h>
-#include "cc-usb.h"
-#include "cc.h"
-
-#define NUM_BLOCK      512
+#include <ao-eeprom-read.h>
+#include <ao-atmosphere.h>
 
 static const struct option options[] = {
-       { .name = "tty", .has_arg = 1, .val = 'T' },
-       { .name = "device", .has_arg = 1, .val = 'D' },
+       { .name = "raw", .has_arg = 0, .val = 'r' },
+       { .name = "csum", .has_arg = 0, .val = 'c' },
+       { .name = "verbose", .has_arg = 0, .val = 'v' },
+       { .name = "len", .has_arg = 1, .val = 'l' },
        { 0, 0, 0, 0},
 };
 
 static void usage(char *program)
 {
-       fprintf(stderr, "usage: %s [--tty <tty-name>] [--device <device-name>\n", program);
+       fprintf(stderr, "usage: %s [--raw] [--csum] [--verbose] [--len <record-len>] {flight.eeprom} ...\n", program);
        exit(1);
 }
 
+static bool
+ao_csum_valid(uint8_t *d, int len)
+{
+       uint8_t sum = 0x5a;
+       int i;
+       for (i = 0; i < len; i++)
+               sum += d[i];
+       return sum == 0;
+}
+
+static void
+ao_ms5607(uint32_t pres, uint32_t temp, struct ao_eeprom *eeprom, bool is_ms5611)
+{
+       struct ao_ms5607_sample ms5607_sample = { .pres = pres, .temp = temp };
+       struct ao_ms5607_value ms5607_value;
+
+       ao_ms5607_convert(&ms5607_sample, &ms5607_value,
+                         &eeprom->ms5607_prom, is_ms5611);
+       printf(" pres %9u %7.3f kPa  %7.1f m temp %9u %6.2f °C",
+              pres,
+              ms5607_value.pres / 1000.0,
+              ao_pressure_to_altitude(ms5607_value.pres),
+              temp,
+              ms5607_value.temp / 100.0);
+}
+
+#define GRAVITY 9.80665
+
+static void
+ao_accel(int16_t accel, struct ao_eeprom *eeprom)
+{
+       double accel_2g = eeprom->config.accel_minus_g - eeprom->config.accel_plus_g;
+       double accel_scale = GRAVITY * 2.0 / accel_2g;
+       printf(" accel %6d %7.2f m/s²",
+              accel, (eeprom->config.accel_plus_g - accel) * accel_scale);
+}
+
+static const char *state_names[] = {
+       "startup",
+       "idle",
+       "pad",
+       "boost",
+       "fast",
+       "coast",
+       "drogue",
+       "main",
+       "landed",
+       "invalid"
+};
+
+#define NUM_STATE      (sizeof state_names/sizeof state_names[0])
+
+static const char *
+ao_state_name(uint16_t state)
+{
+       if (state < NUM_STATE)
+               return state_names[state];
+       return "UNKNOWN";
+}
+
+static void
+ao_state(uint16_t state, uint16_t reason)
+{
+       printf(" state %5u %s reason %5u",
+              state, ao_state_name(state), reason);
+}
+
+static double
+ao_adc_to_volts(int16_t value, int16_t max_adc, double ref, double r1, double r2)
+{
+       return ref * ((double) value / max_adc) * (r1 + r2) / r2;
+}
+
+static void
+ao_volts(const char *name, int16_t value, int16_t max_adc, double ref, double r1, double r2)
+{
+       printf(" %s %5d",
+              name, value);
+       if (r1 && r2 && ref)
+               printf(" %6.3f V", ao_adc_to_volts(value, max_adc, ref, r1, r2));
+}
+
+static double lb_to_n(double lb)
+{
+       return lb / 0.22480894;
+}
+
+static double psi_to_pa(double psi)
+{
+       return psi * 6894.76;
+}
+
+static double
+ao_volts_to_newtons(double volts)
+{
+       /* this is a total guess */
+       return lb_to_n(volts * 57.88645 * GRAVITY);
+}
+
+static void
+ao_thrust(int16_t value, int16_t max_adc, double ref, double r1, double r2)
+{
+       printf(" thrust %5d", value);
+       if (r1 && r2 && ref) {
+               double volts = ao_adc_to_volts(value, max_adc, ref, r1, r2);
+               printf(" %6.3f V %8.1f N", volts, ao_volts_to_newtons(volts));
+       }
+}
+
+static void
+ao_pressure(int16_t value, int16_t max_adc, double ref, double r1, double r2)
+{
+       printf(" pressure %5d", value);
+       if (r1 && r2 && ref) {
+               double volts = ao_adc_to_volts(value, max_adc, ref, r1, r2);
+               if (volts < 0.5) volts = 0.5;
+               if (volts > 4.5) volts = 4.5;
+
+               double psi = (volts - 0.5) / 4.0 * 2500.0;
+               double pa = psi_to_pa(psi);
+               printf(" %9.3f kPa", pa / 1000.0);
+       }
+}
+
+#if 0
+static uint16_t
+uint16(uint8_t *bytes, int off)
+{
+       return (uint16_t) bytes[off] | (((uint16_t) bytes[off+1]) << 8);
+}
+
+static int16_t
+int16(uint8_t *bytes, int off)
+{
+       return (int16_t) uint16(bytes, off);
+}
+
+static uint32_t
+uint32(uint8_t *bytes, int off)
+{
+       return (uint32_t) bytes[off] | (((uint32_t) bytes[off+1]) << 8) |
+               (((uint32_t) bytes[off+2]) << 16) |
+               (((uint32_t) bytes[off+3]) << 24);
+}
+
+static int32_t
+int32(uint8_t *bytes, int off)
+{
+       return (int32_t) uint32(bytes, off);
+}
+#endif
+
+static uint32_t
+uint24(uint8_t *bytes, int off)
+{
+       return (uint32_t) bytes[off] | (((uint32_t) bytes[off+1]) << 8) |
+               (((uint32_t) bytes[off+2]) << 16);
+}
+
+static int32_t
+int24(uint8_t *bytes, int off)
+{
+       return (int32_t) uint24(bytes, off);
+}
+
 int
 main (int argc, char **argv)
 {
-       struct cc_usb   *cc;
-       int             block;
-       uint8_t         bytes[2 * 32 * (2 + 8)];
-       uint8_t         *b;
-       int             i, j;
-       uint32_t        addr;
-       char            *tty = NULL;
-       char            *device = NULL;
-       int             c;
-
-       while ((c = getopt_long(argc, argv, "T:D:", options, NULL)) != -1) {
+       struct ao_eeprom        *eeprom;
+       FILE                    *file;
+       int                     c;
+       bool                    raw = false;
+       bool                    csum = false;
+       bool                    verbose = false;
+       int                     arg_len = 0;
+       char                    *end;
+       int                     ret = 0;
+       int                     i;
+
+       while ((c = getopt_long(argc, argv, "rcvl:", options, NULL)) != -1) {
                switch (c) {
-               case 'T':
-                       tty = optarg;
+               case 'r':
+                       raw = true;
                        break;
-               case 'D':
-                       device = optarg;
+               case 'c':
+                       csum = true;
+                       break;
+               case 'v':
+                       verbose = true;
+                       break;
+               case 'l':
+                       arg_len = strtol(optarg, &end, 0);
+                       if (!*optarg || *end)
+                               usage(argv[0]);
                        break;
                default:
                        usage(argv[0]);
                        break;
                }
        }
-       if (!tty)
-               tty = cc_usbdevs_find_by_arg(device, "TeleMetrum");
-       if (!tty)
-               tty = getenv("ALTOS_TTY");
-       if (!tty)
-               tty="/dev/ttyACM0";
-       cc = cc_usb_open(tty);
-       if (!cc)
-               exit(1);
-       for (block = 0; block < NUM_BLOCK; block += 2) {
-               cc_queue_read(cc, bytes, sizeof (bytes));
-               cc_usb_printf(cc, "e %x\ne %x\n", block, block + 1);
-               cc_usb_sync(cc);
-               for (i = 0; i < 32 * 2; i++) {
-                       b = bytes + (i * 10);
-                       addr = block * 256 + i * 8;
-                       printf ("%06x", addr);
-                       for (j = 0; j < 8; j++) {
-                               printf (" %02x", b[j+2]);
+       for (i = optind; i < argc; i++) {
+               file = fopen(argv[i], "r");
+               if (!file) {
+                       perror(argv[i]);
+                       ret++;
+                       continue;
+               }
+               eeprom = ao_eeprom_read(file);
+               fclose(file);
+               if (!eeprom) {
+                       perror(argv[i]);
+                       ret++;
+                       continue;
+               }
+               int     len = 0;
+               bool    is_ms5611 = false;
+
+               int64_t current_tick = 0;
+               int64_t first_tick = 0x7fffffffffffffffLL;
+
+               double  sense_r1 = 0.0, sense_r2 = 0.0;
+               double  batt_r1 = 0.0, batt_r2 = 0.0;
+               double  adc_ref = 0.0;
+               int16_t max_adc = 0;
+
+               switch (eeprom->log_format) {
+               case AO_LOG_FORMAT_TELEMEGA_OLD:
+                       len = 32;
+                       break;
+               case AO_LOG_FORMAT_EASYMINI1:
+                       len = 16;
+                       max_adc = 32767;
+                       if (eeprom->serial_number < 1000)
+                               adc_ref = 3.0;
+                       else
+                               adc_ref = 3.3;
+                       batt_r1 = sense_r1 = 100e3;
+                       batt_r2 = sense_r2 = 27e3;
+                       break;
+               case AO_LOG_FORMAT_TELEMETRUM:
+                       len = 16;
+                       max_adc = 4095;
+                       adc_ref = 3.3;
+                       batt_r1 = 5600;
+                       batt_r2 = 10000;
+                       sense_r1 = 100e3;
+                       sense_r2 = 27e3;
+                       break;
+               case AO_LOG_FORMAT_TELEMINI2:
+                       len = 16;
+                       break;
+               case AO_LOG_FORMAT_TELEGPS:
+                       len = 32;
+                       break;
+               case AO_LOG_FORMAT_TELEMEGA:
+                       len = 32;
+                       max_adc = 4095;
+                       adc_ref = 3.3;
+                       batt_r1 = 5600;
+                       batt_r2 = 10000;
+                       sense_r1 = 100e3;
+                       sense_r2 = 27e3;
+                       break;
+               case AO_LOG_FORMAT_DETHERM:
+                       len = 16;
+                       break;
+               case AO_LOG_FORMAT_TELEMINI3:
+                       len = 16;
+                       max_adc = 4095;
+                       adc_ref = 3.3;
+                       batt_r1 = 5600;
+                       batt_r2 = 10000;
+                       sense_r1 = 100e3;
+                       sense_r2 = 27e3;
+                       break;
+               case AO_LOG_FORMAT_TELEFIRETWO:
+                       len = 32;
+                       max_adc = 4095;
+                       adc_ref = 3.3;
+                       sense_r1 = batt_r1 = 5600;
+                       sense_r2 = batt_r2 = 10000;
+                       break;
+               case AO_LOG_FORMAT_EASYMINI2:
+                       len = 16;
+                       max_adc = 4095;
+                       adc_ref = 3.3;
+                       batt_r1 = sense_r1 = 100e3;
+                       batt_r2 = sense_r2 = 27e3;
+                       break;
+               case AO_LOG_FORMAT_TELEMEGA_3:
+                       len = 32;
+                       max_adc = 4095;
+                       adc_ref = 3.3;
+                       batt_r1 = 5600;
+                       batt_r2 = 10000;
+                       sense_r1 = 100e3;
+                       sense_r2 = 27e3;
+                       break;
+               case AO_LOG_FORMAT_EASYMEGA_2:
+                       len = 32;
+                       max_adc = 4095;
+                       adc_ref = 3.3;
+                       batt_r1 = 5600;
+                       batt_r2 = 10000;
+                       sense_r1 = 100e3;
+                       sense_r2 = 27e3;
+                       break;
+               case AO_LOG_FORMAT_TELESTATIC:
+                       len = 32;
+                       break;
+               case AO_LOG_FORMAT_MICROPEAK2:
+                       len = 2;
+                       break;
+               }
+               if (arg_len)
+                       len = arg_len;
+               if (verbose)
+                       printf("config major %d minor %d log format %d total %u len %d\n",
+                              eeprom->config.major,
+                              eeprom->config.minor,
+                              eeprom->log_format,
+                              eeprom->len,
+                              len);
+
+               uint32_t        pos;
+               for (pos = 0; pos < eeprom->len; pos += len) {
+                       int i;
+                       if (raw) {
+                               printf("%9u", pos);
+                               for (i = 0; i < len; i++)
+                                       printf(" %02x", eeprom->data[pos + i]);
+                       } else {
+                               struct ao_log_mega *log_mega;
+                               struct ao_log_mini *log_mini;
+                               struct ao_log_metrum *log_metrum;
+                               struct ao_log_gps *log_gps;
+                               struct ao_log_firetwo *log_firetwo;
+
+                               if (!csum && !ao_csum_valid(&eeprom->data[pos], len)) {
+                                       if (verbose)
+                                               printf("\tchecksum error at %d\n", pos);
+                                       continue;
+                               }
+
+                               struct ao_log_header *log_header = (struct ao_log_header *) &eeprom->data[pos];
+
+                               if (first_tick == 0x7fffffffffffffffLL) {
+                                       current_tick = first_tick = log_header->tick;
+                               } else {
+                                       int16_t diff = (int16_t) (log_header->tick - (uint16_t) current_tick);
+
+                                       current_tick += diff;
+                               }
+                               printf("type %c tick %5u %6.2f S", log_header->type, log_header->tick, (current_tick - first_tick) / 100.0);
+
+                               switch (eeprom->log_format) {
+                               case AO_LOG_FORMAT_TELEMEGA_OLD:
+                               case AO_LOG_FORMAT_TELEMEGA:
+                               case AO_LOG_FORMAT_TELEMEGA_3:
+                               case AO_LOG_FORMAT_EASYMEGA_2:
+                                       log_mega = (struct ao_log_mega *) &eeprom->data[pos];
+                                       switch (log_mega->type) {
+                                       case AO_LOG_FLIGHT:
+                                               printf(" serial %5u flight %5u ground_accel %6d ground_pres %9u",
+                                                      eeprom->serial_number,
+                                                      log_mega->u.flight.flight,
+                                                      log_mega->u.flight.ground_accel,
+                                                      log_mega->u.flight.ground_pres);
+                                               printf(" along %6d aross %6d through %6d",
+                                                      log_mega->u.flight.ground_accel_along,
+                                                      log_mega->u.flight.ground_accel_across,
+                                                      log_mega->u.flight.ground_accel_through);
+                                               printf(" roll %6d pitch %6d yaw %6d",
+                                                      log_mega->u.flight.ground_roll,
+                                                      log_mega->u.flight.ground_pitch,
+                                                      log_mega->u.flight.ground_yaw);
+                                               break;
+                                       case AO_LOG_STATE:
+                                               ao_state(log_mega->u.state.state,
+                                                        log_mega->u.state.reason);
+                                               break;
+                                       case AO_LOG_SENSOR:
+                                               ao_ms5607(log_mega->u.sensor.pres,
+                                                         log_mega->u.sensor.temp,
+                                                         eeprom, is_ms5611);
+                                               printf(" accel_x %6d accel_y %6d accel_z %6d",
+                                                      log_mega->u.sensor.accel_x,
+                                                      log_mega->u.sensor.accel_y,
+                                                      log_mega->u.sensor.accel_z);
+                                               printf (" gyro_x %6d gyro_y %6d gyro_z %6d",
+                                                      log_mega->u.sensor.gyro_x,
+                                                      log_mega->u.sensor.gyro_y,
+                                                      log_mega->u.sensor.gyro_z);
+                                               printf (" mag_x %6d mag_y %6d mag_z %6d",
+                                                      log_mega->u.sensor.mag_x,
+                                                      log_mega->u.sensor.mag_y,
+                                                      log_mega->u.sensor.mag_z);
+                                               ao_accel(log_mega->u.sensor.accel, eeprom);
+                                               break;
+                                       case AO_LOG_TEMP_VOLT:
+                                               ao_volts("v_batt",
+                                                        log_mega->u.volt.v_batt,
+                                                        max_adc,
+                                                        adc_ref,
+                                                        batt_r1, batt_r2);
+                                               ao_volts("v_pbatt",
+                                                        log_mega->u.volt.v_pbatt,
+                                                        max_adc,
+                                                        adc_ref,
+                                                        sense_r1, sense_r2);
+                                               printf(" n_sense %1d",
+                                                      log_mega->u.volt.n_sense);
+                                               for (i = 0; i < log_mega->u.volt.n_sense; i++) {
+                                                       char name[10];
+                                                       sprintf(name, "sense%d", i);
+                                                       ao_volts(name,
+                                                                log_mega->u.volt.sense[i],
+                                                                max_adc,
+                                                                adc_ref,
+                                                                sense_r1, sense_r2);
+                                               }
+                                               printf(" pyro %04x", log_mega->u.volt.pyro);
+                                               break;
+                                       case AO_LOG_GPS_TIME:
+                                               printf(" lat %10.7f ° lon %10.7f ° alt %8d m",
+                                                      log_mega->u.gps.latitude / 10000000.0,
+                                                      log_mega->u.gps.longitude/ 10000000.0,
+                                                      (int32_t) (log_mega->u.gps.altitude_low |
+                                                                 (log_mega->u.gps.altitude_high << 16)));
+                                               printf(" time %02d:%02d:%02d %04d-%02d-%02d flags %02x",
+                                                      log_mega->u.gps.hour,
+                                                      log_mega->u.gps.minute,
+                                                      log_mega->u.gps.second,
+                                                      log_mega->u.gps.year + 2000,
+                                                      log_mega->u.gps.month,
+                                                      log_mega->u.gps.day,
+                                                      log_mega->u.gps.flags);
+                                               printf(" course %3d ground_speed %5u climb_rate %6d pdop %3d hdop %3d vdop %3d mode %3d",
+                                                      log_mega->u.gps.course,
+                                                      log_mega->u.gps.ground_speed,
+                                                      log_mega->u.gps.climb_rate,
+                                                      log_mega->u.gps.pdop,
+                                                      log_mega->u.gps.hdop,
+                                                      log_mega->u.gps.vdop,
+                                                      log_mega->u.gps.mode);
+                                               break;
+                                       case AO_LOG_GPS_SAT:
+                                               printf(" channels %2d",
+                                                      log_mega->u.gps_sat.channels);
+                                               for (i = 0; i < 12; i++) {
+                                                       printf(" svid %3d c_n %2d",
+                                                              log_mega->u.gps_sat.sats[i].svid,
+                                                              log_mega->u.gps_sat.sats[i].c_n);
+                                               }
+                                               break;
+                                       }
+                                       break;
+                               case AO_LOG_FORMAT_EASYMINI1:
+                               case AO_LOG_FORMAT_EASYMINI2:
+                               case AO_LOG_FORMAT_TELEMINI2:
+                               case AO_LOG_FORMAT_TELEMINI3:
+                                       log_mini = (struct ao_log_mini *) &eeprom->data[pos];
+                                       switch (log_mini->type) {
+                                       case AO_LOG_FLIGHT:
+                                               printf(" serial %5u flight %5u ground_pres %9u",
+                                                      eeprom->serial_number,
+                                                      log_mini->u.flight.flight,
+                                                      log_mini->u.flight.ground_pres);
+                                               break;
+                                       case AO_LOG_STATE:
+                                               ao_state(log_mini->u.state.state,
+                                                        log_mini->u.state.reason);
+                                               break;
+                                       case AO_LOG_SENSOR:
+                                               ao_ms5607(int24(log_mini->u.sensor.pres, 0),
+                                                         int24(log_mini->u.sensor.temp, 0),
+                                                         eeprom, is_ms5611);
+                                               ao_volts("sense_a",
+                                                        log_mini->u.sensor.sense_a, max_adc,
+                                                        adc_ref, sense_r1, sense_r2);
+                                               ao_volts("sense_m",
+                                                        log_mini->u.sensor.sense_m, max_adc,
+                                                        adc_ref, sense_r1, sense_r2);
+                                               ao_volts("v_batt",
+                                                        log_mini->u.sensor.v_batt, max_adc,
+                                                        adc_ref, batt_r1, batt_r2);
+                                               break;
+                                       } /*  */
+                                       break;
+                               case AO_LOG_FORMAT_TELEMETRUM:
+                                       log_metrum = (struct ao_log_metrum *) &eeprom->data[pos];
+                                       switch (log_metrum->type) {
+                                       case AO_LOG_FLIGHT:
+                                               printf(" serial %5u flight %5u ground_accel %6d ground_pres %9u ground_temp %9u",
+                                                      eeprom->serial_number,
+                                                      log_metrum->u.flight.flight,
+                                                      log_metrum->u.flight.ground_accel,
+                                                      log_metrum->u.flight.ground_pres,
+                                                      log_metrum->u.flight.ground_temp);
+                                               break;
+                                       case AO_LOG_SENSOR:
+                                               ao_ms5607(log_metrum->u.sensor.pres,
+                                                         log_metrum->u.sensor.temp,
+                                                         eeprom, is_ms5611);
+                                               ao_accel(log_metrum->u.sensor.accel, eeprom);
+                                               break;
+                                       case AO_LOG_TEMP_VOLT:
+                                               ao_volts("v_batt",
+                                                        log_metrum->u.volt.v_batt, max_adc,
+                                                        adc_ref, batt_r1, batt_r2);
+                                               ao_volts("sense_a",
+                                                        log_metrum->u.volt.sense_a, max_adc,
+                                                        adc_ref, sense_r1, sense_r2);
+                                               ao_volts("sense_m",
+                                                        log_metrum->u.volt.sense_m, max_adc,
+                                                        adc_ref, sense_r1, sense_r2);
+                                               break;
+                                       case AO_LOG_DEPLOY:
+                                               break;
+                                       case AO_LOG_STATE:
+                                               ao_state(log_metrum->u.state.state,
+                                                        log_metrum->u.state.reason);
+                                               break;
+                                       case AO_LOG_GPS_TIME:
+                                               printf(" time %02d:%02d:%02d 20%02d-%02d-%02d flags %02x pdop %3u",
+                                                      log_metrum->u.gps_time.hour,
+                                                      log_metrum->u.gps_time.minute,
+                                                      log_metrum->u.gps_time.second,
+                                                      log_metrum->u.gps_time.year,
+                                                      log_metrum->u.gps_time.month,
+                                                      log_metrum->u.gps_time.day,
+                                                      log_metrum->u.gps_time.flags,
+                                                      log_metrum->u.gps_time.pdop);
+                                               break;
+                                       case AO_LOG_GPS_SAT:
+                                               printf(" channels %2d more %1d",
+                                                      log_metrum->u.gps_sat.channels,
+                                                      log_metrum->u.gps_sat.more);
+                                               for (i = 0; i < 4; i++) {
+                                                       printf(" svid %3d c_n %2d",
+                                                              log_metrum->u.gps_sat.sats[i].svid,
+                                                              log_metrum->u.gps_sat.sats[i].c_n);
+                                               }
+                                               break;
+                                       case AO_LOG_GPS_POS:
+                                               printf(" lat %10.7f° lon %10.7f° alt %8d m",
+                                                      log_metrum->u.gps.latitude / 10000000.0,
+                                                      log_metrum->u.gps.longitude/ 10000000.0,
+                                                      (int32_t) (log_metrum->u.gps.altitude_low |
+                                                                 (log_metrum->u.gps.altitude_high << 16)));
+                                               break;
+                                       default:
+                                               printf(" unknown");
+                                       }
+                                       break;
+                               case AO_LOG_FORMAT_TELEFIRETWO:
+                                       log_firetwo = (struct ao_log_firetwo *) &eeprom->data[pos];
+                                       switch (log_firetwo->type) {
+                                       case AO_LOG_FLIGHT:
+                                               printf(" serial %5u flight %5u",
+                                                      eeprom->serial_number,
+                                                      log_firetwo->u.flight.flight);
+                                               break;
+                                       case AO_LOG_STATE:
+                                               ao_state(log_firetwo->u.state.state,
+                                                        log_firetwo->u.state.reason);
+                                               break;
+                                       case AO_LOG_SENSOR:
+                                               ao_pressure(log_firetwo->u.sensor.pressure,
+                                                           max_adc, adc_ref,
+                                                           sense_r1, sense_r2);
+                                               ao_thrust(log_firetwo->u.sensor.thrust,
+                                                         max_adc, adc_ref,
+                                                         sense_r1, sense_r2);
+                                               for (i = 0; i < 4; i++) {
+                                                       char name[20];
+                                                       sprintf(name, "thermistor%d", i);
+                                                       ao_volts(name,
+                                                                log_firetwo->u.sensor.thermistor[i],
+                                                                max_adc, adc_ref,
+                                                                sense_r1, sense_r2);
+                                               }
+                                               break;
+                                       }
+                                       break;
+                               case AO_LOG_FORMAT_TELEGPS:
+                                       log_gps = (struct ao_log_gps *) &eeprom->data[pos];
+                                       (void) log_gps;
+                                       break;
+                               case AO_LOG_FORMAT_DETHERM:
+                                       break;
+                               }
                        }
-                       printf ("\n");
+                       printf("\n");
                }
        }
-       cc_usb_close(cc);
-       exit (0);
+       return ret;
 }
index dd0046d7b04bfbb56c26c5e5283776dae66d3d0b..5e1975e742b7bbf672c6a3c71d4a565391177f14 100644 (file)
@@ -1,6 +1,6 @@
 bin_PROGRAMS=ao-elftohex
 
-AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AM_CFLAGS=$(WARN_CFLAGS) -I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
 AO_ELFTOHEX_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
 
 ao_elftohex_DEPENDENCIES = $(AO_ELFTOHEX_LIBS)
index de3c4deb8dc051c74c1853d4757c1940cd2835a5..a3fbfa83a423941caa8a27b4c329b99c6de23e88 100644 (file)
@@ -1,6 +1,6 @@
 bin_PROGRAMS=ao-list
 
-AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AM_CFLAGS=$(WARN_CFLAGS) -I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
 AO_LIST_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
 
 ao_list_DEPENDENCIES = $(AO_LIST_LIBS)
index 3c48dc27eb4a70ed1801d1c3ac125043a2f80499..b92a9c8723a79005505cf72a43b959c8204f7be0 100644 (file)
@@ -1,6 +1,6 @@
 bin_PROGRAMS=ao-load
 
-AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AM_CFLAGS=$(WARN_CFLAGS) -I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
 AO_LOAD_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
 
 ao_load_DEPENDENCIES = $(AO_LOAD_LIBS)
index 0cf03772073c5a503ea5e8364547b42e143e8115..a2de42bc02b3d0672907795c3dae0183dda5f511 100644 (file)
@@ -93,6 +93,7 @@ rewrite(struct ao_hex_image *image, unsigned addr, char *data, int len)
                printf (" %02x", data[i]);
        printf("\n");
        memcpy(image->data + addr - image->address, data, len);
+       return 1;
 }
 
 static const struct option options[] = {
@@ -112,8 +113,6 @@ int
 main (int argc, char **argv)
 {
        struct ccdbg    *dbg;
-       uint8_t         status;
-       uint16_t        pc;
        struct ao_hex_file      *hex;
        struct ao_hex_image *image;
        char            *filename;
index 758097a4c297e12cc498da96b26765cb65311b7c..0946fb23225fb951e8bc83f8012854b56e5b857d 100644 (file)
@@ -1,6 +1,6 @@
 bin_PROGRAMS=ao-makebin
 
-AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AM_CFLAGS=$(WARN_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)
index 22b62608f471b41e2cd3c369db5c6a9129964f26..1a221b681e38bf65613da3a33b032ecea1bfc641 100644 (file)
@@ -1,6 +1,6 @@
 bin_PROGRAMS=ao-mega
 
-AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AM_CFLAGS=$(WARN_CFLAGS) -I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
 AO_POSTFLIGHT_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
 
 ao_mega_DEPENDENCIES = $(AO_POSTFLIGHT_LIBS)
index 589d164a40616746755dc3e357e12146cb693d74..892c62c6b04edcec08a0355a6208438e3831e930 100644 (file)
@@ -1,6 +1,6 @@
 bin_PROGRAMS=ao-postflight
 
-AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS) $(GNOME_CFLAGS) $(PLPLOT_CFLAGS)
+AM_CFLAGS=$(WARN_CFLAGS) -I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS) $(GNOME_CFLAGS) $(PLPLOT_CFLAGS)
 AO_POSTFLIGHT_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
 
 ao_postflight_DEPENDENCIES = $(AO_POSTFLIGHT_LIBS)
index d2c55658804419875bf31d8fa1e668185c5e5055..64880549dee222f9b5c0bc5f0ea80c0ea5a593e1 100644 (file)
@@ -1,6 +1,6 @@
 bin_PROGRAMS=ao-rawload
 
-AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AM_CFLAGS=$(WARN_CFLAGS) -I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
 AO_RAWLOAD_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
 
 ao_rawload_DEPENDENCIES = $(AO_RAWLOAD_LIBS)
index 17ed73cae20e5ac58a7176ba8583459da22b7e07..c139cda1b46876fb03db2b3b2bfc27efd9044ee6 100644 (file)
@@ -38,8 +38,6 @@ int
 main (int argc, char **argv)
 {
        struct ccdbg    *dbg;
-       uint8_t         status;
-       uint16_t        pc;
        struct ao_hex_file      *hex;
        struct ao_hex_image *image;
        char            *filename;
index bfddf131c895e0414cfaae9bb1b29475c7ec2b44..227e714f39fd86f2095d483963b0c5a2d52be1cb 100644 (file)
@@ -1,6 +1,6 @@
 bin_PROGRAMS=ao-send-telem
 
-AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AM_CFLAGS=$(WARN_CFLAGS) -I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
 AO_POSTFLIGHT_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
 
 ao_send_telem_DEPENDENCIES = $(AO_POSTFLIGHT_LIBS)
index a4fc85b7300d8f15b4e6483dd26ca02c16f7e05a..4b8f3c4f2639c182a70d1a2f0b2b266cfe0c1e6b 100644 (file)
@@ -114,7 +114,6 @@ static const char *state_names[] = {
 static void
 send_telem(struct cc_usb *cc, union ao_telemetry_all *telem)
 {
-       int     rssi = (int8_t) telem->generic.rssi / 2 - 74;
        int     i;
        uint8_t *b;
 
@@ -170,9 +169,7 @@ main (int argc, char **argv)
        char            line[80];
        int             c, i, ret = 0;
        int             freq = 434550;
-       char            *s;
        FILE            *file;
-       int             serial;
        uint16_t        last_tick;
        int             started;
        int             realtime = 0;
@@ -239,7 +236,6 @@ main (int argc, char **argv)
 
        if (fake) {
                union ao_telemetry_all  telem;
-               uint16_t                tick;
                int                     i;
 
                memset(&telem, '\0', sizeof (telem));
index f6c5089a0ddf150d49ff7fcdb5ffa474807e20f8..9e3f2c1216eacb5a1f04a181d061dcbe574c0420 100644 (file)
@@ -1,6 +1,6 @@
 bin_PROGRAMS=ao-sky-flash
 
-AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AM_CFLAGS=$(WARN_CFLAGS) -I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
 AO_SKY_FLASH_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
 
 ao_sky_flash_DEPENDENCIES = $(AO_SKY_FLASH_LIBS)
index d728d0c22413cb30dde726b1e8309cb5417e7d48..2f7719ff97fc4913013b22ebacb099f943ea28f7 100644 (file)
@@ -48,7 +48,7 @@ skytraq_send_bin(int fd, const char *filename)
        size = ftell(file);
        rewind(file);
 
-       sprintf(message, "BINSIZE = %d Checksum = %d Loopnumber = %d ", size, cksum, 1);
+       sprintf(message, "BINSIZE = %ld Checksum = %d Loopnumber = %d ", size, cksum, 1);
 
        ret = skytraq_cmd_wait(fd, message, strlen(message) + 1, "OK", 20000);
        if (ret < 0)
index 7dbb69548b92cf7b259d8a42c8f180f75918f012..16c6ee424d8394205d946b7e5b15bfa52b8a1c23 100644 (file)
 #include <stdint.h>
 #include <stdarg.h>
 #include <getopt.h>
+#include <unistd.h>
 #include "cc.h"
 
 static const struct option options[] = {
        { .name = "tty", .has_arg = 1, .val = 'T' },
        { .name = "device", .has_arg = 1, .val = 'D' },
-       { .name = "loader", .has_arg = 1, .val = 'l' },
        { .name = "firmware", .has_arg = 1, .val = 'f' },
        { .name = "query", .has_arg = 0, .val = 'q' },
        { .name = "raw", .has_arg = 0, .val = 'r' },
@@ -46,7 +46,6 @@ usage(char *program)
        fprintf(stderr,
                "usage: %s [--tty <tty-name>]\n"
                "          [--device <device-name>]\n"
-               "          [--loader <srec bootloader file>]\n"
                "          [--firmware <binary firmware file>]\n"
                "          [--query]\n"
                "          [--quiet]\n"
@@ -54,7 +53,7 @@ usage(char *program)
        exit(1);
 }
 
-int
+static int
 skytraq_expect(int fd, uint8_t want, int timeout) {
        int     c;
 
@@ -66,12 +65,12 @@ skytraq_expect(int fd, uint8_t want, int timeout) {
        return 0;
 }
 
-int
+static int
 skytraq_wait_reply(int fd, uint8_t reply, uint8_t *buf, uint8_t reply_len) {
 
        for(;;) {
                uint8_t a, b;
-               uint8_t cksum_computed, cksum_read;
+               uint8_t cksum_computed;
                int     len;
                switch (skytraq_expect(fd, 0xa0, 10000)) {
                case -1:
@@ -135,16 +134,10 @@ int
 main(int argc, char **argv)
 {
        int     fd;
-       char    buf[512];
        int     ret;
-       FILE    *input;
-       long    size;
-       unsigned char   cksum;
        int     c;
-       char    message[1024];
        char    *tty = NULL;
        char    *device = NULL;
-       char    *loader = "srec_115200.bin";
        char    *file = NULL;
        int     query = 0;
        int     raw = 0;
@@ -157,9 +150,6 @@ main(int argc, char **argv)
                case 'D':
                        device = optarg;
                        break;
-               case 'l':
-                       loader = optarg;
-                       break;
                case 'f':
                        file = optarg;
                        break;
index 6dcbbf7242e2df334b77f554d7a2b76fbd5e3dec..1a8dfb9e48330bd5312ab58ec3052d0fbd0960b1 100644 (file)
@@ -31,7 +31,7 @@ int
 skytraq_setcomm(int fd, int baudrate);
 
 int
-skytraq_write(int fd, const char *data, int len);
+skytraq_write(int fd, const void *data, int len);
 
 int
 skytraq_waitchar(int fd, int timeout);
@@ -42,6 +42,12 @@ skytraq_waitstatus(int fd, const char *status, int timeout);
 void
 skytraq_flush(int fd);
 
+int
+skytraq_millis(void);
+
+void
+skytraq_dbg_newline(void);
+
 int
 skytraq_cmd_wait(int fd, const char *message, int len, const char *status, int timeout);
 
index 94b0b156502149e171f041258e50de764cc733ae..e56ab9238176b45047a8b0dd4345f8641ad93b54 100644 (file)
@@ -16,7 +16,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-#define _BSD_SOURCE
+#define _DEFAULT_SOURCE 1
 #include <termios.h>
 #include <unistd.h>
 #include <sys/types.h>
@@ -98,11 +98,10 @@ skytraq_open(const char *path)
 #define US_PER_CHAR    (1000000 / BPS)
 
 int
-skytraq_write(int fd, const char *data, int len)
+skytraq_write(int fd, const void *d, int len)
 {
-       const char *d = data;
+       const char *data = d;
        int             r;
-       int             us;
 
        skytraq_dbg_printf (0, "%4d: ", len);
        if (len < 70)
@@ -116,7 +115,6 @@ skytraq_write(int fd, const char *data, int len)
                r = write(fd, data, this_time);
                if (r <= 0)
                        return r;
-               us = r * US_PER_CHAR;
                usleep(r * US_PER_CHAR);
                data += r;
                len -= r;
@@ -132,7 +130,7 @@ skytraq_setcomm(int fd, int baudrate)
        int     i;
        uint8_t cksum;
 
-       int target_baudrate;
+       int target_baudrate = 0;
        switch(baudrate)
        {
        case 4800:
index 45eb6216787f5afe2d50e68f497eb9b34744c914..a049f275ffe07812926a20af3ee826b7d385942c 100644 (file)
@@ -2,7 +2,7 @@ if LIBSTLINK
 
 bin_PROGRAMS=ao-stmload
 
-AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(STLINK_CFLAGS) $(LIBUSB_CFLAGS)
+AM_CFLAGS=$(WARN_CFLAGS) -I$(top_srcdir)/ao-tools/lib $(STLINK_CFLAGS) $(LIBUSB_CFLAGS)
 AO_STMLOAD_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
 
 ao_stmload_DEPENDENCIES = $(AO_STMLOAD_LIBS)
index 3436443ebb346872b8ab79c913dc151c378f1f8a..8cc05ce315c23788003c1c9a83d92e18d755655c 100644 (file)
@@ -1,6 +1,6 @@
 bin_PROGRAMS=ao-telem
 
-AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AM_CFLAGS=$(WARN_CFLAGS) -I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
 AO_POSTFLIGHT_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
 
 ao_telem_DEPENDENCIES = $(AO_POSTFLIGHT_LIBS)
index 8e6699d5ad3c87090906be32d6eedae7c58535a6..83a27c242819fdd866b01c90c3d581f9d087f299 100644 (file)
 .\"
 .TH AO-TELEM 1 "ao-telem" ""
 .SH NAME
-ao-telem \- Analyse a flight log (either telemetry or eeprom)
+ao-telem \- Analyze a telemetry log
 .SH SYNOPSIS
 .B "ao-telem"
-[\-s <summary-file>]
-[\--summary=<summary-file>]
-[\-d <detail-file>]
-[\--detail=<detail-file>]
-[\-r <raw-file>]
-[\--raw=<raw-file>]
-[\-p <plot-file>]
-[\--plot=<plot-file>]
-[\-g <gps-file]
-[\--gps=<gps-file]
-[\-k <kml-file]
-[\--kml=<kml-file]
-{flight.eeprom|flight.telem}
+[\--crc]
+{flight.telem} ...
+.SH OPTIONS
+.TP
+\-c | --crc
+This option makes ao-telem analyze records with CRC errors. By
+default, these records are skipped.
 .SH DESCRIPTION
 .I ao-telem
-reads the specified flight log and produces several different kinds of
-output.
-.IP Summary
-By default, summary information is shown on stdout. With the --summary
-option, it can be redirected to a file.
-.IP Detail
-When requested with the --detail option, a filtered version of the
-flight position, speed and acceleration are written to the specified
-file.
-.IP Raw
-The --raw option writes the unfiltered, but converted acceleration
-and height data to the specified file.
-.IP Plot
-The --plot option writes plots of height, speed and acceleration to
-the specified file in .svg format
-.IP GPS
-The --gps option writes the recorded GPS data to the specified file in
-three columns.
-.IP KML
-The --kml option writes the recorded GPS data to the specified file in
-Keyhole Markup Language format, which can be displayed in Googleearth.
+reads the specified telemetry log and display the contents of each
+record.
 .SH AUTHOR
 Keith Packard
index aa54a1b9a4ffe5b0a1906ff211e659197118d463..02d53ff32cacf571bb0e25474cb27ed3227cc895 100644 (file)
@@ -31,8 +31,7 @@ static const struct option options[] = {
 
 static void usage(char *program)
 {
-       fprintf(stderr, "usage: %s\n"
-               "\t{flight-log} ...\n", program);
+       fprintf(stderr, "usage: %s [--crc] {flight.telem} ...\n",program);
        exit(1);
 }
 
@@ -42,10 +41,8 @@ int
 main (int argc, char **argv)
 {
        char    line[80];
-       int c, i, ret;
-       char *s;
+       int c, i, ret = 0;
        FILE *file;
-       int serial;
        int ignore_crc = 0;
        while ((c = getopt_long(argc, argv, "c", options, NULL)) != -1) {
                switch (c) {
@@ -64,11 +61,6 @@ main (int argc, char **argv)
                        ret++;
                        continue;
                }
-               s = strstr(argv[i], "-serial-");
-               if (s)
-                       serial = atoi(s + 8);
-               else
-                       serial = 0;
                while (fgets(line, sizeof (line), file)) {
                        union ao_telemetry_all telem;
                        char call[AO_MAX_CALLSIGN+1];
@@ -105,7 +97,7 @@ main (int argc, char **argv)
                                        memcpy(version, telem.configuration.version, AO_MAX_VERSION);
                                        call[AO_MAX_CALLSIGN] = '\0';
                                        version[AO_MAX_CALLSIGN] = '\0';
-                                       printf ("device %3d flight %5d config %3d.%03d delay %2d main %4d",
+                                       printf ("device %3d flight %5d config %3d.%03d delay %2d main %4d log_max %5d",
                                                telem.configuration.device,
                                                telem.configuration.flight,
                                                telem.configuration.config_major,
@@ -123,7 +115,7 @@ main (int argc, char **argv)
                                                (telem.location.flags & (1 << 6)) ? ",date" : "",
                                                (telem.location.flags & (1 << 7)) ? ",course" : "");
                                        printf (" alt %5d lat %12.7f lon %12.7f",
-                                               telem.location.altitude,
+                                               AO_TELEMETRY_LOCATION_ALTITUDE(&telem.location),
                                                telem.location.latitude / 1e7,
                                                telem.location.longitude / 1e7);
                                        if ((telem.location.flags & (1 << 6)) != 0) {
index 69e47529cb5613c8602873d972040d018b77cc6b..c4d8cf252c120f08a97c167c468f95858438367b 100644 (file)
@@ -1,6 +1,6 @@
 bin_PROGRAMS=ao-test-baro
 
-AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AM_CFLAGS=$(WARN_CFLAGS) -I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
 
 ao_test_baro_DEPENDENCIES = $(top_builddir)/ao-tools/lib/libao-tools.a
 
index 36c805c201bdb34181bd719b7c85b828eeccce00..d617a83aa876d4c95c7cbfcca513cd21bf6fd04d 100644 (file)
@@ -47,7 +47,7 @@ static void usage(char *program)
        exit(1);
 }
 
-void
+static void
 done(struct cc_usb *cc, int code)
 {
 /*     cc_usb_printf(cc, "a\n"); */
@@ -55,28 +55,6 @@ done(struct cc_usb *cc, int code)
        exit (code);
 }
 
-static int
-ends_with(char *whole, char *suffix)
-{
-       int whole_len = strlen(whole);
-       int suffix_len = strlen(suffix);
-
-       if (suffix_len > whole_len)
-               return 0;
-       return strcmp(whole + whole_len - suffix_len, suffix) == 0;
-}
-
-static int
-starts_with(char *whole, char *prefix)
-{
-       int whole_len = strlen(whole);
-       int prefix_len = strlen(prefix);
-
-       if (prefix_len > whole_len)
-               return 0;
-       return strncmp(whole, prefix, prefix_len) == 0;
-}
-
 static char **
 tok(char *line) {
        char    **strs = malloc (sizeof (char *)), *str;
@@ -140,16 +118,15 @@ free_baro(struct baro *b) {
        }
 }
 
-char **
+static char **
 find_baro(struct baro *b, char *word0) {
-       int i;
        for (;b; b = b->next)
                if (b->strs[0] && !strcmp(b->strs[0], word0))
                        return b->strs;
        return NULL;
 }
 
-int
+static int
 do_baro(struct cc_usb *usb) {
        struct baro *b = baro(usb);
        char **temp = find_baro(b, "Temperature:");
@@ -185,15 +162,9 @@ int
 main (int argc, char **argv)
 {
        char                    *device = NULL;
-       char                    *filename;
-       Elf                     *e;
-       unsigned int            s;
-       int                     i;
        int                     c;
-       int                     tries;
        struct cc_usb           *cc = NULL;
        char                    *tty = NULL;
-       int                     success;
        int                     verbose = 0;
        int                     ret = 0;
 
index 0323c28240f6c8eefc995c22313546fedc39ca6f..e01c7a63e304b6949e4dc3d6cff968bc4b91a89c 100644 (file)
@@ -1,6 +1,6 @@
 bin_PROGRAMS=ao-test-flash
 
-AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AM_CFLAGS=$(WARN_CFLAGS) -I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
 
 ao_test_flash_DEPENDENCIES = $(top_builddir)/ao-tools/lib/libao-tools.a
 
index 5cbc56d750ae6f4b6e19da8c1cf6562b3d71e6a6..dc5d8ebcded8835f9b273b09bb7cf904ab52c12d 100644 (file)
@@ -47,35 +47,13 @@ static void usage(char *program)
        exit(1);
 }
 
-void
+static void
 done(struct cc_usb *cc, int code)
 {
        cc_usb_close(cc);
        exit (code);
 }
 
-static int
-ends_with(char *whole, char *suffix)
-{
-       int whole_len = strlen(whole);
-       int suffix_len = strlen(suffix);
-
-       if (suffix_len > whole_len)
-               return 0;
-       return strcmp(whole + whole_len - suffix_len, suffix) == 0;
-}
-
-static int
-starts_with(char *whole, char *prefix)
-{
-       int whole_len = strlen(whole);
-       int prefix_len = strlen(prefix);
-
-       if (prefix_len > whole_len)
-               return 0;
-       return strncmp(whole, prefix, prefix_len) == 0;
-}
-
 static char **
 tok(char *line) {
        char    **strs = malloc (sizeof (char *)), *str;
@@ -141,9 +119,8 @@ free_flash(struct flash *b) {
        }
 }
 
-char **
+static char **
 find_flash(struct flash *b, char *word0) {
-       int i;
        for (;b; b = b->next) {
                if (strstr(b->line, word0))
                        return b->strs;
@@ -151,7 +128,7 @@ find_flash(struct flash *b, char *word0) {
        return NULL;
 }
 
-int
+static int
 do_flash(struct cc_usb *usb, int expected_size) {
        struct flash *b = flash(usb);
        char **size = find_flash(b, "Storage size:");
@@ -188,18 +165,11 @@ int
 main (int argc, char **argv)
 {
        char                    *device = NULL;
-       char                    *filename;
-       Elf                     *e;
-       unsigned int            s;
-       int                     i;
        int                     c;
-       int                     tries;
        struct cc_usb           *cc = NULL;
        char                    *tty = NULL;
-       int                     success;
        int                     verbose = 0;
        int                     ret = 0;
-       int                     expected_size;
 
        while ((c = getopt_long(argc, argv, "rT:D:c:s:v:", options, NULL)) != -1) {
                switch (c) {
index d89ddddd61e5f4f4773e60d757b06959178e532e..db28891dda2eaf6ee437bfa282e2756961386dd8 100644 (file)
@@ -1,6 +1,6 @@
 bin_PROGRAMS=ao-test-gps
 
-AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AM_CFLAGS=$(WARN_CFLAGS) -I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
 
 ao_test_gps_DEPENDENCIES = $(top_builddir)/ao-tools/lib/libao-tools.a
 
index 5012028c15bfe088bf67aad2a6ed9ccf5962f05c..09ad3e8cb18bc38b888c9de69812d8bf78a086a0 100644 (file)
@@ -47,7 +47,7 @@ static void usage(char *program)
        exit(1);
 }
 
-void
+static void
 done(struct cc_usb *cc, int code)
 {
 /*     cc_usb_printf(cc, "a\n"); */
@@ -55,28 +55,6 @@ done(struct cc_usb *cc, int code)
        exit (code);
 }
 
-static int
-ends_with(char *whole, char *suffix)
-{
-       int whole_len = strlen(whole);
-       int suffix_len = strlen(suffix);
-
-       if (suffix_len > whole_len)
-               return 0;
-       return strcmp(whole + whole_len - suffix_len, suffix) == 0;
-}
-
-static int
-starts_with(char *whole, char *prefix)
-{
-       int whole_len = strlen(whole);
-       int prefix_len = strlen(prefix);
-
-       if (prefix_len > whole_len)
-               return 0;
-       return strncmp(whole, prefix, prefix_len) == 0;
-}
-
 static char **
 tok(char *line) {
        char    **strs = malloc (sizeof (char *)), *str;
@@ -140,16 +118,15 @@ free_gps(struct gps *b) {
        }
 }
 
-char **
+static char **
 find_gps(struct gps *b, char *word0) {
-       int i;
        for (;b; b = b->next)
                if (b->strs[0] && !strcmp(b->strs[0], word0))
                        return b->strs;
        return NULL;
 }
 
-int
+static int
 do_gps(struct cc_usb *usb) {
        int     count = 0;
 
@@ -186,15 +163,9 @@ int
 main (int argc, char **argv)
 {
        char                    *device = NULL;
-       char                    *filename;
-       Elf                     *e;
-       unsigned int            s;
-       int                     i;
        int                     c;
-       int                     tries;
        struct cc_usb           *cc = NULL;
        char                    *tty = NULL;
-       int                     success;
        int                     verbose = 0;
        int                     ret = 0;
 
index e24ed469fb283686af98e5a68f1d4e8d63c20c77..6c9efddba76570108a395a418cbc8e116dd066a5 100644 (file)
@@ -1,6 +1,6 @@
 bin_PROGRAMS=ao-test-igniter
 
-AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AM_CFLAGS=$(WARN_CFLAGS) -I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
 
 ao_test_igniter_DEPENDENCIES = $(top_builddir)/ao-tools/lib/libao-tools.a
 
index c426e1bd28d34742e6034308f5c75ee9d79eac34..62e6c702c1c14d80a0d67327d90df1bca7e5ee5c 100644 (file)
@@ -47,7 +47,7 @@ static void usage(char *program)
        exit(1);
 }
 
-void
+static void
 done(struct cc_usb *cc, int code)
 {
 /*     cc_usb_printf(cc, "a\n"); */
@@ -55,28 +55,6 @@ done(struct cc_usb *cc, int code)
        exit (code);
 }
 
-static int
-ends_with(char *whole, char *suffix)
-{
-       int whole_len = strlen(whole);
-       int suffix_len = strlen(suffix);
-
-       if (suffix_len > whole_len)
-               return 0;
-       return strcmp(whole + whole_len - suffix_len, suffix) == 0;
-}
-
-static int
-starts_with(char *whole, char *prefix)
-{
-       int whole_len = strlen(whole);
-       int prefix_len = strlen(prefix);
-
-       if (prefix_len > whole_len)
-               return 0;
-       return strncmp(whole, prefix, prefix_len) == 0;
-}
-
 struct igniter {
        struct igniter  *next;
        char            name[512];
@@ -96,7 +74,7 @@ igniters(struct cc_usb *usb)
                cc_usb_getline(usb, line, sizeof (line));
                if (strstr(line, "software-version"))
                        break;
-               if (sscanf(line, "Igniter: %s Status: %s", &name, &status) == 2) {
+               if (sscanf(line, "Igniter: %s Status: %s", name, status) == 2) {
                        struct igniter  *i = malloc (sizeof (struct igniter));
                        strcpy(i->name, name);
                        strcpy(i->status, status);
@@ -125,6 +103,7 @@ find_igniter(struct igniter *i, char *name)
        for (; i; i = i->next)
                if (strcmp(i->name, name) == 0)
                        return i;
+       return NULL;
 }
 
 static int
@@ -134,7 +113,7 @@ do_igniter(struct cc_usb *usb, char *name)
        struct igniter  *this = find_igniter(all, name);
        if (!this) {
                struct igniter  *i;
-               printf("no igniter %s found in");
+               printf("no igniter %s found in", name);
                for (i = all; i; i = i->next)
                        printf(" %s", i->name);
                printf("\n");
@@ -157,15 +136,10 @@ int
 main (int argc, char **argv)
 {
        char                    *device = NULL;
-       char                    *filename;
-       Elf                     *e;
-       unsigned int            s;
        int                     i;
        int                     c;
-       int                     tries;
        struct cc_usb           *cc = NULL;
        char                    *tty = NULL;
-       int                     success;
        int                     verbose = 0;
        int                     ret = 0;
 
index e3b63a85f6fffeb01c0451a3bac4946397f16292..9a05d5c40352fc25168dfa9d38234100d0ae1255 100644 (file)
@@ -1,6 +1,6 @@
 bin_PROGRAMS=ao-usbload
 
-AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AM_CFLAGS=$(WARN_CFLAGS) -I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
 AO_STMLOAD_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
 
 ao_usbload_DEPENDENCIES = $(AO_STMLOAD_LIBS)
index 31ee138a3679584779eeda813997667b8ba3ffd9..6da57bace36b6b53ad6ff51bf0b078373311ebf9 100644 (file)
@@ -96,7 +96,7 @@ static void usage(char *program)
        exit(1);
 }
 
-void
+static void
 done(struct cc_usb *cc, int code)
 {
 /*     cc_usb_printf(cc, "a\n"); */
@@ -124,7 +124,7 @@ ucs2len(uint16_t *ucs2)
        return len;
 }
 
-int
+static int
 putucs4(uint32_t c, FILE *file)
 {
        char d;
@@ -162,23 +162,14 @@ main (int argc, char **argv)
 {
        char                    *device = NULL;
        char                    *filename;
-       Elf                     *e;
        int                     raw = 0;
        char                    *serial_end;
        unsigned int            serial = 0;
-       char                    *serial_ucs2;
-       int                     serial_ucs2_len;
-       char                    serial_int[2];
-       unsigned int            s;
-       int                     i;
-       int                     string_num;
        uint32_t                cal = 0;
-       char                    cal_int[4];
        char                    *cal_end;
        int                     c;
        int                     was_flashed = 0;
        struct ao_hex_image     *load;
-       int                     tries;
        struct cc_usb           *cc = NULL;
        char                    *tty = NULL;
        int                     success;
index 5cbab5cf48da64219164ea9dea96072d43cde86f..14113a8225f5b185cfcf99862a62fbfb8e855f0c 100644 (file)
@@ -1,6 +1,6 @@
 bin_PROGRAMS=ao-usbtrng
 
-AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AM_CFLAGS=$(WARN_CFLAGS) -I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
 
 ao_usbtrng_DEPENDENCIES = $(top_builddir)/ao-tools/lib/libao-tools.a
 
index 0362f1b46af98560dc220181e36afa64392b9f3d..46bdbeb23edd61b21a711d2e2dc0948977056e6b 100644 (file)
@@ -46,7 +46,7 @@ static void usage(char *program)
        exit(1);
 }
 
-void
+static void
 done(struct cc_usb *cc, int code)
 {
        cc_usb_close(cc);
@@ -57,7 +57,6 @@ int
 main (int argc, char **argv)
 {
        char                    *device = NULL;
-       char                    *filename;
        int                     i;
        int                     c;
        struct cc_usb           *cc = NULL;
index 7a288417b10f161d874a607fc2764191e40c25a7..3cdf1dddf01aa16b8c4eaaef09e69d3e12bb0696 100644 (file)
@@ -2,7 +2,7 @@ VERSION=$(shell git describe)
 
 AO_VIEW_CFLAGS=-I$(top_srcdir)/ao-tools/lib
 AO_VIEW_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
-AM_CFLAGS=$(AO_VIEW_CFLAGS) $(GNOME_CFLAGS) $(ALSA_CFLAGS) -I$(top_srcdir)/src -DAOVIEW_VERSION=\"$(VERSION)\" @FLITE_INCS@
+AM_CFLAGS=$(WARN_CFLAGS) $(AO_VIEW_CFLAGS) $(GNOME_CFLAGS) $(ALSA_CFLAGS) -I$(top_srcdir)/src -DAOVIEW_VERSION=\"$(VERSION)\" @FLITE_INCS@
 
 bin_PROGRAMS=ao-view
 
index a33d682d054992018df9e5264b602d0411b8d401..47f9d30ccdb412670be5727068fd48074c017f94 100644 (file)
@@ -40,6 +40,8 @@ libao_tools_a_SOURCES = \
        chbevl.c \
        mconf.h \
        cephes.h \
+       ao-atmosphere.c \
+       ao-atmosphere.h \
        ao-hex.c \
        ao-hex.h \
        ao-editaltos.c \
@@ -50,5 +52,9 @@ libao_tools_a_SOURCES = \
        ao-dfu.h \
        ao-selfload.c \
        ao-selfload.h \
+       ao-eeprom-read.c \
+       ao-eeprom-read.h \
+       ao-ms5607-convert.c \
+       ao-ms5607.h \
        ao-verbose.c \
        ao-verbose.h
diff --git a/ao-tools/lib/ao-atmosphere.c b/ao-tools/lib/ao-atmosphere.c
new file mode 100644 (file)
index 0000000..f11ca7f
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * Copyright © 2019 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.
+ */
+
+#include <math.h>
+#include "ao-atmosphere.h"
+
+#define GRAVITY 9.80665
+
+/*
+ * Pressure Sensor Model, version 1.1
+ *
+ * written by Holly Grimes
+ *
+ * Uses the International Standard Atmosphere as described in
+ *   "A Quick Derivation relating altitude to air pressure" (version 1.03)
+ *    from the Portland State Aerospace Society, except that the atmosphere
+ *    is divided into layers with each layer having a different lapse rate.
+ *
+ * Lapse rate data for each layer was obtained from Wikipedia on Sept. 1, 2007
+ *    at site <http://en.wikipedia.org/wiki/International_Standard_Atmosphere
+ *
+ * Height measurements use the local tangent plane.  The postive z-direction is up.
+ *
+ * All measurements are given in SI units (Kelvin, Pascal, meter, meters/second^2).
+ *   The lapse rate is given in Kelvin/meter, the gas constant for air is given
+ *   in Joules/(kilogram-Kelvin).
+ */
+
+#define GRAVITATIONAL_ACCELERATION     (-GRAVITY)
+#define AIR_GAS_CONSTANT               287.053
+#define NUMBER_OF_LAYERS               7
+#define MAXIMUM_ALTITUDE               84852.0
+#define MINIMUM_PRESSURE               0.3734
+#define LAYER0_BASE_TEMPERATURE                288.15
+#define LAYER0_BASE_PRESSURE           101325
+
+       /* lapse rate and base altitude for each layer in the atmosphere */
+static const double lapse_rate[] = {
+       -0.0065, 0.0, 0.001, 0.0028, 0.0, -0.0028, -0.002
+};
+
+static const double base_altitude[] = {
+       0, 11000, 20000, 32000, 47000, 51000, 71000
+};
+
+/* outputs atmospheric pressure associated with the given altitude.
+ * altitudes are measured with respect to the mean sea level
+ */
+double
+ao_altitude_to_pressure(double altitude)
+{
+       double base_temperature = LAYER0_BASE_TEMPERATURE;
+       double base_pressure = LAYER0_BASE_PRESSURE;
+
+       double pressure;
+       double base; /* base for function to determine pressure */
+       double exponent; /* exponent for function to determine pressure */
+       int layer_number; /* identifies layer in the atmosphere */
+       double delta_z; /* difference between two altitudes */
+
+       if (altitude > MAXIMUM_ALTITUDE) /* FIX ME: use sensor data to improve model */
+               return 0;
+
+       /* calculate the base temperature and pressure for the atmospheric layer
+          associated with the inputted altitude */
+       for(layer_number = 0; layer_number < NUMBER_OF_LAYERS - 1 && altitude > base_altitude[layer_number + 1]; layer_number++) {
+               delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number];
+               if (lapse_rate[layer_number] == 0.0) {
+                       exponent = GRAVITATIONAL_ACCELERATION * delta_z
+                               / AIR_GAS_CONSTANT / base_temperature;
+                       base_pressure *= exp(exponent);
+               }
+               else {
+                       base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0;
+                       exponent = GRAVITATIONAL_ACCELERATION /
+                               (AIR_GAS_CONSTANT * lapse_rate[layer_number]);
+                       base_pressure *= pow(base, exponent);
+               }
+               base_temperature += delta_z * lapse_rate[layer_number];
+       }
+
+       /* calculate the pressure at the inputted altitude */
+       delta_z = altitude - base_altitude[layer_number];
+       if (lapse_rate[layer_number] == 0.0) {
+               exponent = GRAVITATIONAL_ACCELERATION * delta_z
+                       / AIR_GAS_CONSTANT / base_temperature;
+               pressure = base_pressure * exp(exponent);
+       }
+       else {
+               base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0;
+               exponent = GRAVITATIONAL_ACCELERATION /
+                       (AIR_GAS_CONSTANT * lapse_rate[layer_number]);
+               pressure = base_pressure * pow(base, exponent);
+       }
+
+       return pressure;
+}
+
+
+/* outputs the altitude associated with the given pressure. the altitude
+   returned is measured with respect to the mean sea level */
+double
+ao_pressure_to_altitude(double pressure)
+{
+
+       double next_base_temperature = LAYER0_BASE_TEMPERATURE;
+       double next_base_pressure = LAYER0_BASE_PRESSURE;
+
+       double altitude;
+       double base_pressure;
+       double base_temperature;
+       double base; /* base for function to determine base pressure of next layer */
+       double exponent; /* exponent for function to determine base pressure
+                           of next layer */
+       double coefficient;
+       int layer_number; /* identifies layer in the atmosphere */
+       int delta_z; /* difference between two altitudes */
+
+       if (pressure < 0)  /* illegal pressure */
+               return -1;
+       if (pressure < MINIMUM_PRESSURE) /* FIX ME: use sensor data to improve model */
+               return MAXIMUM_ALTITUDE;
+
+       /* calculate the base temperature and pressure for the atmospheric layer
+          associated with the inputted pressure. */
+       layer_number = -1;
+       do {
+               layer_number++;
+               base_pressure = next_base_pressure;
+               base_temperature = next_base_temperature;
+               delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number];
+               if (lapse_rate[layer_number] == 0.0) {
+                       exponent = GRAVITATIONAL_ACCELERATION * delta_z
+                               / AIR_GAS_CONSTANT / base_temperature;
+                       next_base_pressure *= exp(exponent);
+               }
+               else {
+                       base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0;
+                       exponent = GRAVITATIONAL_ACCELERATION /
+                               (AIR_GAS_CONSTANT * lapse_rate[layer_number]);
+                       next_base_pressure *= pow(base, exponent);
+               }
+               next_base_temperature += delta_z * lapse_rate[layer_number];
+       }
+       while(layer_number < NUMBER_OF_LAYERS - 1 && pressure < next_base_pressure);
+
+       /* calculate the altitude associated with the inputted pressure */
+       if (lapse_rate[layer_number] == 0.0) {
+               coefficient = (AIR_GAS_CONSTANT / GRAVITATIONAL_ACCELERATION)
+                       * base_temperature;
+               altitude = base_altitude[layer_number]
+                       + coefficient * log(pressure / base_pressure);
+       }
+       else {
+               base = pressure / base_pressure;
+               exponent = AIR_GAS_CONSTANT * lapse_rate[layer_number]
+                       / GRAVITATIONAL_ACCELERATION;
+               coefficient = base_temperature / lapse_rate[layer_number];
+               altitude = base_altitude[layer_number]
+                       + coefficient * (pow(base, exponent) - 1);
+       }
+
+       return altitude;
+}
diff --git a/ao-tools/lib/ao-atmosphere.h b/ao-tools/lib/ao-atmosphere.h
new file mode 100644 (file)
index 0000000..0a24cb0
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright © 2019 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.
+ */
+
+#ifndef _AO_ATMOSPHERE_H_
+#define _AO_ATMOSPHERE_H_
+
+double
+ao_altitude_to_pressure(double altitude);
+
+double
+ao_pressure_to_altitude(double pressure);
+
+#endif /* _AO_ATMOSPHERE_H_ */
index 0600965309834527964843bedd596821ae93d40a..a51b7dbe8a129b2635bf26085edcb5cd1ca19dd6 100644 (file)
@@ -53,8 +53,6 @@ int ao_num_symbols = NUM_SYMBOLS;
 static bool
 rewrite(struct ao_hex_image *load, unsigned address, uint8_t *data, int length)
 {
-       int             i;
-
        if (address < load->address || load->address + load->length < address + length)
                return false;
 
diff --git a/ao-tools/lib/ao-eeprom-read.c b/ao-tools/lib/ao-eeprom-read.c
new file mode 100644 (file)
index 0000000..7ed4715
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+ * Copyright © 2017 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include "ao-eeprom-read.h"
+#include <json-c/json.h>
+#include <string.h>
+#include <errno.h>
+
+static struct json_object *
+ao_eeprom_read_config(FILE *file)
+{
+       char                    line[1024];
+       struct json_tokener     *tok;
+       struct json_object      *obj = NULL;
+       enum json_tokener_error err;
+
+       tok = json_tokener_new();
+       if (!tok)
+               goto fail_tok;
+
+       for (;;) {
+               if (fgets(line, sizeof(line), file) == NULL)
+                       goto fail_read;
+               obj = json_tokener_parse_ex(tok, line, strlen(line));
+               err = json_tokener_get_error(tok);
+               if (err == json_tokener_success)
+                       break;
+               if (err != json_tokener_continue)
+                       goto fail_read;
+       }
+       json_tokener_free(tok);
+       return obj;
+fail_read:
+       json_tokener_free(tok);
+fail_tok:
+       return NULL;
+}
+
+static int
+ao_eeprom_read_byte(FILE *file)
+{
+       int     byte;
+       if (fscanf(file, "%x", &byte) != 1)
+               return EOF;
+       return byte;
+}
+
+static int
+ao_eeprom_read_data(FILE *file, struct ao_eeprom *eeprom)
+{
+       uint8_t *data = NULL, *ndata;
+       int     len = 0;
+       int     size = 0;
+       int     byte;
+
+       data = malloc(size = 64);
+       if (!data)
+               goto fail_alloc;
+       while ((byte = ao_eeprom_read_byte(file)) != EOF) {
+               if (len == size) {
+                       ndata = realloc(data, size *= 2);
+                       if (!ndata)
+                               goto fail_realloc;
+                       data = ndata;
+               }
+               data[len++] = (uint8_t) byte;
+       }
+       eeprom->data = data;
+       eeprom->len = len;
+       return 1;
+fail_realloc:
+       free(data);
+fail_alloc:
+       return 0;
+}
+
+static int
+ao_json_get_int(struct json_object *obj, const char *key, int def)
+{
+       struct json_object *value;
+       int i;
+
+       if (!json_object_object_get_ex(obj, key, &value))
+               return def;
+       errno = 0;
+       i = (int) json_object_get_int(value);
+       if (errno != 0)
+               return def;
+       return i;
+}
+
+static const char *
+ao_json_get_string(struct json_object *obj, const char *key, const char *def)
+{
+       struct json_object *value;
+       const char *str;
+
+       if (!json_object_object_get_ex(obj, key, &value))
+               return def;
+       errno = 0;
+       str = json_object_get_string(value);
+       if (errno)
+               return def;
+       if (!str)
+               return def;
+       return str;
+}
+
+static int
+ao_eeprom_get_pyro(struct ao_config *config, struct json_object *obj)
+{
+       struct json_object      *pyros;
+       struct json_object      *pyro;
+       int                     i, p;
+
+       if (!json_object_object_get_ex(obj, "pyros", &pyros))
+               return 1;
+
+       if (json_object_get_type(pyros) != json_type_array)
+               return 0;
+
+       for (i = 0; i < json_object_array_length(pyros); i++) {
+               pyro = json_object_array_get_idx(pyros, i);
+               if (pyro) {
+                       p = ao_json_get_int(pyro, "channel", -1);
+                       if (0 <= p && p < AO_PYRO_NUM) {
+                               config->pyro[p].flags           = ao_json_get_int(pyro, "flags", 0);
+                               config->pyro[p].accel_less      = ao_json_get_int(pyro, "accel_less", 0);
+                               config->pyro[p].accel_greater   = ao_json_get_int(pyro, "accel_greater", 0);
+                               config->pyro[p].speed_less      = ao_json_get_int(pyro, "speed_less", 0);
+                               config->pyro[p].speed_greater   = ao_json_get_int(pyro, "speed_greater", 0);
+                               config->pyro[p].height_less     = ao_json_get_int(pyro, "height_less", 0);
+                               config->pyro[p].height_greater  = ao_json_get_int(pyro, "height_greater", 0);
+                               config->pyro[p].orient_less     = ao_json_get_int(pyro, "orient_less", 0);
+                               config->pyro[p].orient_greater  = ao_json_get_int(pyro, "orient_greater", 0);
+                               config->pyro[p].time_less       = ao_json_get_int(pyro, "time_less", 0);
+                               config->pyro[p].time_greater    = ao_json_get_int(pyro, "time_greater", 0);
+                               config->pyro[p].delay           = ao_json_get_int(pyro, "delay", 0);
+                               config->pyro[p].state_less      = ao_json_get_int(pyro, "state_less", 0);
+                               config->pyro[p].state_greater_or_equal  = ao_json_get_int(pyro, "state_greater_or_equal", 0);
+                               config->pyro[p].motor           = ao_json_get_int(pyro, "motor", 0);
+                       }
+               }
+       }
+       return 1;
+}
+
+static int
+ao_eeprom_get_ms5607(struct ao_ms5607_prom *ms5607_prom, struct json_object *obj)
+{
+       struct json_object      *ms5607;
+
+       if (!json_object_object_get_ex(obj, "ms5607", &ms5607))
+               return 1;
+
+       if (json_object_get_type(ms5607) != json_type_object)
+               return 0;
+
+       ms5607_prom->reserved = ao_json_get_int(ms5607, "reserved", 0);
+       ms5607_prom->sens =     ao_json_get_int(ms5607, "sens", 0);
+       ms5607_prom->off =      ao_json_get_int(ms5607, "off", 0);
+       ms5607_prom->tcs =      ao_json_get_int(ms5607, "tcs", 0);
+       ms5607_prom->tco =      ao_json_get_int(ms5607, "tco", 0);
+       ms5607_prom->tref =     ao_json_get_int(ms5607, "tref", 0);
+       ms5607_prom->tempsens = ao_json_get_int(ms5607, "tempsens", 0);
+       ms5607_prom->crc =      ao_json_get_int(ms5607, "crc", 0);
+       return 1;
+}
+
+static int
+ao_eeprom_get_config(struct ao_eeprom *ao_eeprom, struct json_object *obj)
+{
+       struct ao_config        *config = &ao_eeprom->config;
+       const char              *s;
+
+       if (json_object_get_type(obj) != json_type_object)
+               return 0;
+
+       ao_eeprom->log_format =         ao_json_get_int(obj, "log_format", 0);
+       ao_eeprom->serial_number =      ao_json_get_int(obj, "serial", 0);
+
+       config->major =                 ao_json_get_int(obj, "config_major", 0);
+       config->minor =                 ao_json_get_int(obj, "config_minor", 0);
+       if (config->major == 0 || config->minor == 0)
+               return 0;
+
+       config->main_deploy =           ao_json_get_int(obj, "main_deploy", 250);
+       config->accel_plus_g =          ao_json_get_int(obj, "accel_cal_plus", 0);
+
+       s = ao_json_get_string(obj, "callsign", "N0CALL");
+       strncpy(config->callsign, s, sizeof(config->callsign)-1);
+
+       config->apogee_delay =          ao_json_get_int(obj, "apogee_delay", 0);
+       config->accel_minus_g =         ao_json_get_int(obj, "accel_cal_minus", 0);
+       config->radio_cal =             ao_json_get_int(obj, "radio_calibration", 0);
+       config->flight_log_max =        ao_json_get_int(obj, "flight_log_max", 0);
+       config->ignite_mode =           ao_json_get_int(obj, "ignite_mode", 0);
+       config->pad_orientation =       ao_json_get_int(obj, "pad_orientation", 0);
+       config->radio_setting =         ao_json_get_int(obj, "radio_setting", 0);
+       config->radio_enable =          ao_json_get_int(obj, "radio_enable", 1);
+       config->frequency =             ao_json_get_int(obj, "frequency", 434550);
+       config->apogee_lockout =        ao_json_get_int(obj, "apogee_lockout", 0);
+       if (!ao_eeprom_get_pyro(config, obj))
+               return 0;
+       config->ignite_mode =           ao_json_get_int(obj, "ignite_mode", 0);
+       config->ignite_mode =           ao_json_get_int(obj, "ignite_mode", 0);
+       config->ignite_mode =           ao_json_get_int(obj, "ignite_mode", 0);
+       config->ignite_mode =           ao_json_get_int(obj, "ignite_mode", 0);
+       config->ignite_mode =           ao_json_get_int(obj, "ignite_mode", 0);
+       config->ignite_mode =           ao_json_get_int(obj, "ignite_mode", 0);
+
+       if (!ao_eeprom_get_ms5607(&ao_eeprom->ms5607_prom, obj))
+               return 0;
+
+       return 1;
+}
+
+struct ao_eeprom *
+ao_eeprom_read(FILE *file)
+{
+       struct ao_eeprom        *ao_eeprom;
+       struct json_object      *obj;
+       int                     ret;
+
+       ao_eeprom = calloc(1, sizeof (struct ao_eeprom));
+       if (!ao_eeprom)
+               goto fail_ao_eeprom;
+
+       obj = ao_eeprom_read_config(file);
+       if (!obj)
+               goto fail_config;
+
+       ret = ao_eeprom_get_config(ao_eeprom, obj);
+       json_object_put(obj);
+       if (!ret)
+               goto fail_config;
+
+       if (!ao_eeprom_read_data(file, ao_eeprom))
+               goto fail_data;
+
+       return ao_eeprom;
+fail_data:
+fail_config:
+       free(ao_eeprom);
+fail_ao_eeprom:
+       return NULL;
+}
diff --git a/ao-tools/lib/ao-eeprom-read.h b/ao-tools/lib/ao-eeprom-read.h
new file mode 100644 (file)
index 0000000..82893f2
--- /dev/null
@@ -0,0 +1,532 @@
+/*
+ * Copyright © 2017 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef _AO_EEPROM_READ_H_
+#define _AO_EEPROM_READ_H_
+
+#include <stdint.h>
+#include <stdio.h>
+#include <ao-ms5607.h>
+
+#define AO_MAX_CALLSIGN        8
+#define AO_AES_LEN     16
+#define AO_PYRO_NUM    8
+
+/* required functions from the underlying log system */
+
+#define AO_LOG_FORMAT_UNKNOWN          0       /* unknown; altosui will have to guess */
+#define AO_LOG_FORMAT_FULL             1       /* 8 byte typed log records */
+#define AO_LOG_FORMAT_TINY             2       /* two byte state/baro records */
+#define AO_LOG_FORMAT_TELEMETRY                3       /* 32 byte ao_telemetry records */
+#define AO_LOG_FORMAT_TELESCIENCE      4       /* 32 byte typed telescience records */
+#define AO_LOG_FORMAT_TELEMEGA_OLD     5       /* 32 byte typed telemega records */
+#define AO_LOG_FORMAT_EASYMINI1                6       /* 16-byte MS5607 baro only, 3.0V supply */
+#define AO_LOG_FORMAT_TELEMETRUM       7       /* 16-byte typed telemetrum records */
+#define AO_LOG_FORMAT_TELEMINI2                8       /* 16-byte MS5607 baro only, 3.3V supply, cc1111 SoC */
+#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_TELEMINI3                12      /* 16-byte MS5607 baro only, 3.3V supply, stm32f042 SoC */
+#define AO_LOG_FORMAT_TELEFIRETWO      13      /* 32-byte test stand data */
+#define AO_LOG_FORMAT_EASYMINI2                14      /* 16-byte MS5607 baro only, 3.3V supply, stm32f042 SoC */
+#define AO_LOG_FORMAT_TELEMEGA_3       15      /* 32 byte typed telemega records with 32 bit gyro cal and mpu9250 */
+#define AO_LOG_FORMAT_EASYMEGA_2       16      /* 32 byte typed telemega records with 32 bit gyro cal, mpu9250 rotated 90° and adxl375 */
+#define AO_LOG_FORMAT_TELESTATIC       17      /* 32 byte typed telestatic records */
+#define AO_LOG_FORMAT_MICROPEAK2       18      /* 2-byte baro values with header */
+#define AO_LOG_FORMAT_NONE             127     /* No log at all */
+
+enum ao_pyro_flag {
+       ao_pyro_none                    = 0x00000000,
+
+       ao_pyro_accel_less              = 0x00000001,
+       ao_pyro_accel_greater           = 0x00000002,
+
+       ao_pyro_speed_less              = 0x00000004,
+       ao_pyro_speed_greater           = 0x00000008,
+
+       ao_pyro_height_less             = 0x00000010,
+       ao_pyro_height_greater          = 0x00000020,
+
+       ao_pyro_orient_less             = 0x00000040,
+       ao_pyro_orient_greater          = 0x00000080,
+
+       ao_pyro_time_less               = 0x00000100,
+       ao_pyro_time_greater            = 0x00000200,
+
+       ao_pyro_ascending               = 0x00000400,
+       ao_pyro_descending              = 0x00000800,
+
+       ao_pyro_after_motor             = 0x00001000,
+
+       ao_pyro_delay                   = 0x00002000,
+
+       ao_pyro_state_less              = 0x00004000,
+       ao_pyro_state_greater_or_equal  = 0x00008000,
+};
+
+struct ao_pyro {
+       enum ao_pyro_flag       flags;
+       int16_t                 accel_less, accel_greater;
+       int16_t                 speed_less, speed_greater;
+       int16_t                 height_less, height_greater;
+       int16_t                 orient_less, orient_greater;
+       int16_t                 time_less, time_greater;
+       int16_t                 delay;
+       uint8_t                 state_less, state_greater_or_equal;
+       int16_t                 motor;
+       uint16_t                delay_done;
+       uint8_t                 _unused;        /* was 'fired' */
+};
+
+struct ao_config {
+       uint8_t         major;
+       uint8_t         minor;
+       uint16_t        main_deploy;
+       int16_t         accel_plus_g;           /* changed for minor version 2 */
+       uint8_t         _legacy_radio_channel;
+       char            callsign[AO_MAX_CALLSIGN + 1];
+       uint8_t         apogee_delay;           /* minor version 1 */
+       int16_t         accel_minus_g;          /* minor version 2 */
+       uint32_t        radio_cal;              /* minor version 3 */
+       uint32_t        flight_log_max;         /* minor version 4 */
+       uint8_t         ignite_mode;            /* minor version 5 */
+       uint8_t         pad_orientation;        /* minor version 6 */
+       uint32_t        radio_setting;          /* minor version 7 */
+       uint8_t         radio_enable;           /* minor version 8 */
+       uint8_t         aes_key[AO_AES_LEN];    /* minor version 9 */
+       uint32_t        frequency;              /* minor version 10 */
+       uint16_t        apogee_lockout;         /* minor version 11 */
+       struct ao_pyro  pyro[AO_PYRO_NUM];      /* minor version 12 */
+       uint16_t        aprs_interval;          /* minor version 13 */
+       uint8_t         radio_power;            /* minor version 14 */
+       uint8_t         radio_amp;              /* minor version 14 */
+       int16_t         accel_zero_along;       /* minor version 15 */
+       int16_t         accel_zero_across;      /* minor version 15 */
+       int16_t         accel_zero_through;     /* minor version 15 */
+       uint8_t         mid_beep;               /* minor version 16 */
+       uint16_t        tracker_motion;         /* minor version 17 */
+       uint8_t         tracker_interval;       /* minor version 17 */
+       uint16_t        pyro_time;              /* minor version 18 */
+       uint8_t         aprs_ssid;              /* minor version 19 */
+       uint8_t         radio_rate;             /* minor version 20 */
+       uint32_t        send_frequency;         /* minor version 21 */
+       uint8_t         aprs_format;            /* minor version 22 */
+       uint8_t         pad_box;                /* minor version 22 */
+       uint8_t         pad_idle;               /* minor version 23 */
+};
+
+/*
+ * ao_log_big.c
+ */
+
+/*
+ * The data log is recorded in the eeprom as a sequence
+ * of data packets.
+ *
+ * Each packet starts with a 4-byte header that has the
+ * packet type, the packet checksum and the tick count. Then
+ * they all contain 2 16 bit values which hold packet-specific
+ * data.
+ *
+ * For each flight, the first packet
+ * is FLIGHT packet, indicating the serial number of the
+ * device and a unique number marking the number of flights
+ * recorded by this device.
+ *
+ * During flight, data from the accelerometer and barometer
+ * are recorded in SENSOR packets, using the raw 16-bit values
+ * read from the A/D converter.
+ *
+ * Also during flight, but at a lower rate, the deployment
+ * sensors are recorded in DEPLOY packets. The goal here is to
+ * detect failure in the deployment circuits.
+ *
+ * STATE packets hold state transitions as the flight computer
+ * transitions through different stages of the flight.
+ */
+#define AO_LOG_FLIGHT          'F'
+#define AO_LOG_SENSOR          'A'
+#define AO_LOG_TEMP_VOLT       'T'
+#define AO_LOG_DEPLOY          'D'
+#define AO_LOG_STATE           'S'
+#define AO_LOG_GPS_TIME                'G'
+#define AO_LOG_GPS_LAT         'N'
+#define AO_LOG_GPS_LON         'W'
+#define AO_LOG_GPS_ALT         'H'
+#define AO_LOG_GPS_SAT         'V'
+#define AO_LOG_GPS_DATE                'Y'
+#define AO_LOG_GPS_POS         'P'
+
+#define AO_LOG_POS_NONE                (~0UL)
+
+/* Common header in all log formats */
+struct ao_log_header {
+       char                    type;                           /* 0 */
+       uint8_t                 csum;                           /* 1 */
+       uint16_t                tick;                           /* 2 */
+};
+
+struct ao_log_record {
+       char                    type;                           /* 0 */
+       uint8_t                 csum;                           /* 1 */
+       uint16_t                tick;                           /* 2 */
+       union {
+               struct {
+                       int16_t         ground_accel;           /* 4 */
+                       uint16_t        flight;                 /* 6 */
+               } flight;
+               struct {
+                       int16_t         accel;                  /* 4 */
+                       int16_t         pres;                   /* 6 */
+               } sensor;
+               struct {
+                       int16_t         temp;
+                       int16_t         v_batt;
+               } temp_volt;
+               struct {
+                       int16_t         drogue;
+                       int16_t         main;
+               } deploy;
+               struct {
+                       uint16_t        state;
+                       uint16_t        reason;
+               } state;
+               struct {
+                       uint8_t         hour;
+                       uint8_t         minute;
+                       uint8_t         second;
+                       uint8_t         flags;
+               } gps_time;
+               int32_t         gps_latitude;
+               int32_t         gps_longitude;
+               struct {
+                       uint16_t        altitude_low;
+                       int16_t         altitude_high;
+               } gps_altitude;
+               struct {
+                       uint16_t        svid;
+                       uint8_t         unused;
+                       uint8_t         c_n;
+               } gps_sat;
+               struct {
+                       uint8_t         year;
+                       uint8_t         month;
+                       uint8_t         day;
+                       uint8_t         extra;
+               } gps_date;
+               struct {
+                       uint16_t        d0;
+                       uint16_t        d1;
+               } anon;
+       } u;
+};
+
+struct ao_log_mega {
+       char                    type;                   /* 0 */
+       uint8_t                 csum;                   /* 1 */
+       uint16_t                tick;                   /* 2 */
+       union {                                         /* 4 */
+               /* AO_LOG_FLIGHT */
+               struct {
+                       uint16_t        flight;                 /* 4 */
+                       int16_t         ground_accel;           /* 6 */
+                       uint32_t        ground_pres;            /* 8 */
+                       int16_t         ground_accel_along;     /* 12 */
+                       int16_t         ground_accel_across;    /* 14 */
+                       int16_t         ground_accel_through;   /* 16 */
+                       int16_t         pad_18;                 /* 18 */
+                       int32_t         ground_roll;            /* 20 */
+                       int32_t         ground_pitch;           /* 24 */
+                       int32_t         ground_yaw;             /* 28 */
+               } flight;                                       /* 32 */
+               struct {
+                       uint16_t        flight;                 /* 4 */
+                       int16_t         ground_accel;           /* 6 */
+                       uint32_t        ground_pres;            /* 8 */
+                       int16_t         ground_accel_along;     /* 12 */
+                       int16_t         ground_accel_across;    /* 14 */
+                       int16_t         ground_accel_through;   /* 16 */
+                       int16_t         ground_roll;            /* 18 */
+                       int16_t         ground_pitch;           /* 20 */
+                       int16_t         ground_yaw;             /* 22 */
+               } flight_old;                                   /* 24 */
+               /* AO_LOG_STATE */
+               struct {
+                       uint16_t        state;
+                       uint16_t        reason;
+               } state;
+               /* AO_LOG_SENSOR */
+               struct {
+                       uint32_t        pres;           /* 4 */
+                       uint32_t        temp;           /* 8 */
+                       int16_t         accel_x;        /* 12 */
+                       int16_t         accel_y;        /* 14 */
+                       int16_t         accel_z;        /* 16 */
+                       int16_t         gyro_x;         /* 18 */
+                       int16_t         gyro_y;         /* 20 */
+                       int16_t         gyro_z;         /* 22 */
+                       int16_t         mag_x;          /* 24 */
+                       int16_t         mag_z;          /* 26 */
+                       int16_t         mag_y;          /* 28 */
+                       int16_t         accel;          /* 30 */
+               } sensor;       /* 32 */
+               /* AO_LOG_TEMP_VOLT */
+               struct {
+                       int16_t         v_batt;         /* 4 */
+                       int16_t         v_pbatt;        /* 6 */
+                       int16_t         n_sense;        /* 8 */
+                       int16_t         sense[10];      /* 10 */
+                       uint16_t        pyro;           /* 30 */
+               } volt;                                 /* 32 */
+               /* AO_LOG_GPS_TIME */
+               struct {
+                       int32_t         latitude;       /* 4 */
+                       int32_t         longitude;      /* 8 */
+                       uint16_t        altitude_low;   /* 12 */
+                       uint8_t         hour;           /* 14 */
+                       uint8_t         minute;         /* 15 */
+                       uint8_t         second;         /* 16 */
+                       uint8_t         flags;          /* 17 */
+                       uint8_t         year;           /* 18 */
+                       uint8_t         month;          /* 19 */
+                       uint8_t         day;            /* 20 */
+                       uint8_t         course;         /* 21 */
+                       uint16_t        ground_speed;   /* 22 */
+                       int16_t         climb_rate;     /* 24 */
+                       uint8_t         pdop;           /* 26 */
+                       uint8_t         hdop;           /* 27 */
+                       uint8_t         vdop;           /* 28 */
+                       uint8_t         mode;           /* 29 */
+                       int16_t         altitude_high;  /* 30 */
+               } gps;  /* 32 */
+               /* AO_LOG_GPS_SAT */
+               struct {
+                       uint16_t        channels;       /* 4 */
+                       struct {
+                               uint8_t svid;
+                               uint8_t c_n;
+                       } sats[12];                     /* 6 */
+               } gps_sat;                              /* 30 */
+       } u;
+};
+
+#define AO_LOG_MEGA_GPS_ALTITUDE(l)    ((int32_t) ((l)->u.gps.altitude_high << 16) | ((l)->u.gps.altitude_low))
+#define AO_LOG_MEGA_SET_GPS_ALTITUDE(l,a)      (((l)->u.gps.mode |= AO_GPS_MODE_ALTITUDE_24), \
+                                                ((l)->u.gps.altitude_high = (a) >> 16), \
+                                                (l)->u.gps.altitude_low = (a))
+
+struct ao_log_firetwo {
+       char                    type;                   /* 0 */
+       uint8_t                 csum;                   /* 1 */
+       uint16_t                tick;                   /* 2 */
+       union {                                         /* 4 */
+               /* AO_LOG_FLIGHT */
+               struct {
+                       uint16_t        flight;         /* 4 */
+               } flight;       /* 6 */
+               /* AO_LOG_STATE */
+               struct {
+                       uint16_t        state;          /* 4 */
+                       uint16_t        reason;         /* 6 */
+               } state;        /* 8 */
+               /* AO_LOG_SENSOR */
+               struct {
+                       uint16_t        pressure;       /* 4 */
+                       uint16_t        thrust;         /* 6 */
+                       uint16_t        thermistor[4];  /* 8 */
+               } sensor;       /* 24 */
+               uint8_t         align[28];              /* 4 */
+       } u;    /* 32 */
+};
+
+struct ao_log_telestatic {
+       char                    type;                   /* 0 */
+       uint8_t                 csum;                   /* 1 */
+       uint16_t                tick;                   /* 2 */
+       union {                                         /* 4 */
+               /* AO_LOG_FLIGHT */
+               struct {
+                       uint16_t        flight;         /* 4 */
+               } flight;       /* 6 */
+               /* AO_LOG_STATE */
+               struct {
+                       uint16_t        state;          /* 4 */
+                       uint16_t        reason;         /* 6 */
+               } state;        /* 8 */
+               /* AO_LOG_SENSOR */
+               struct {
+                       uint32_t        pressure;       /* 4 */
+                       uint32_t        pressure2;      /* 8 */
+                       uint32_t        thrust;         /* 12 */
+                       uint32_t        mass;           /* 16 */
+                       uint16_t        t_low;          /* 20 */
+                       uint16_t        t_high[4];      /* 22 */
+               } sensor;       /* 30 */
+               uint8_t         align[28];              /* 4 */
+       } u;    /* 32 */
+};
+
+struct ao_log_metrum {
+       char                    type;                   /* 0 */
+       uint8_t                 csum;                   /* 1 */
+       uint16_t                tick;                   /* 2 */
+       union {                                         /* 4 */
+               /* AO_LOG_FLIGHT */
+               struct {
+                       uint16_t        flight;         /* 4 */
+                       int16_t         ground_accel;   /* 6 */
+                       uint32_t        ground_pres;    /* 8 */
+                       uint32_t        ground_temp;    /* 12 */
+               } flight;       /* 16 */
+               /* AO_LOG_STATE */
+               struct {
+                       uint16_t        state;          /* 4 */
+                       uint16_t        reason;         /* 6 */
+               } state;        /* 8 */
+               /* AO_LOG_SENSOR */
+               struct {
+                       uint32_t        pres;           /* 4 */
+                       uint32_t        temp;           /* 8 */
+                       int16_t         accel;          /* 12 */
+               } sensor;       /* 14 */
+               /* AO_LOG_TEMP_VOLT */
+               struct {
+                       int16_t         v_batt;         /* 4 */
+                       int16_t         sense_a;        /* 6 */
+                       int16_t         sense_m;        /* 8 */
+               } volt;         /* 10 */
+               /* AO_LOG_GPS_POS */
+               struct {
+                       int32_t         latitude;       /* 4 */
+                       int32_t         longitude;      /* 8 */
+                       uint16_t        altitude_low;   /* 12 */
+                       int16_t         altitude_high;  /* 14 */
+               } gps;          /* 16 */
+               /* AO_LOG_GPS_TIME */
+               struct {
+                       uint8_t         hour;           /* 4 */
+                       uint8_t         minute;         /* 5 */
+                       uint8_t         second;         /* 6 */
+                       uint8_t         flags;          /* 7 */
+                       uint8_t         year;           /* 8 */
+                       uint8_t         month;          /* 9 */
+                       uint8_t         day;            /* 10 */
+                       uint8_t         pdop;           /* 11 */
+               } gps_time;     /* 12 */
+               /* AO_LOG_GPS_SAT (up to three packets) */
+               struct {
+                       uint8_t channels;               /* 4 */
+                       uint8_t more;                   /* 5 */
+                       struct {
+                               uint8_t svid;
+                               uint8_t c_n;
+                       } sats[4];                      /* 6 */
+               } gps_sat;                              /* 14 */
+               uint8_t         raw[12];                /* 4 */
+       } u;    /* 16 */
+};
+
+struct ao_log_mini {
+       char            type;                           /* 0 */
+       uint8_t         csum;                           /* 1 */
+       uint16_t        tick;                           /* 2 */
+       union {                                         /* 4 */
+               /* AO_LOG_FLIGHT */
+               struct {
+                       uint16_t        flight;         /* 4 */
+                       uint16_t        r6;
+                       uint32_t        ground_pres;    /* 8 */
+               } flight;
+               /* AO_LOG_STATE */
+               struct {
+                       uint16_t        state;          /* 4 */
+                       uint16_t        reason;         /* 6 */
+               } state;
+               /* AO_LOG_SENSOR */
+               struct {
+                       uint8_t         pres[3];        /* 4 */
+                       uint8_t         temp[3];        /* 7 */
+                       int16_t         sense_a;        /* 10 */
+                       int16_t         sense_m;        /* 12 */
+                       int16_t         v_batt;         /* 14 */
+               } sensor;                               /* 16 */
+       } u;                                            /* 16 */
+};                                                     /* 16 */
+
+#define ao_log_pack24(dst,value) do {          \
+               (dst)[0] = (value);             \
+               (dst)[1] = (value) >> 8;        \
+               (dst)[2] = (value) >> 16;       \
+       } while (0)
+
+struct ao_log_gps {
+       char                    type;                   /* 0 */
+       uint8_t                 csum;                   /* 1 */
+       uint16_t                tick;                   /* 2 */
+       union {                                         /* 4 */
+               /* AO_LOG_FLIGHT */
+               struct {
+                       uint16_t        flight;                 /* 4 */
+                       int16_t         start_altitude;         /* 6 */
+                       int32_t         start_latitude;         /* 8 */
+                       int32_t         start_longitude;        /* 12 */
+               } flight;                                       /* 16 */
+               /* AO_LOG_GPS_TIME */
+               struct {
+                       int32_t         latitude;       /* 4 */
+                       int32_t         longitude;      /* 8 */
+                       uint16_t        altitude_low;   /* 12 */
+                       uint8_t         hour;           /* 14 */
+                       uint8_t         minute;         /* 15 */
+                       uint8_t         second;         /* 16 */
+                       uint8_t         flags;          /* 17 */
+                       uint8_t         year;           /* 18 */
+                       uint8_t         month;          /* 19 */
+                       uint8_t         day;            /* 20 */
+                       uint8_t         course;         /* 21 */
+                       uint16_t        ground_speed;   /* 22 */
+                       int16_t         climb_rate;     /* 24 */
+                       uint8_t         pdop;           /* 26 */
+                       uint8_t         hdop;           /* 27 */
+                       uint8_t         vdop;           /* 28 */
+                       uint8_t         mode;           /* 29 */
+                       int16_t         altitude_high;  /* 30 */
+               } gps;  /* 31 */
+               /* AO_LOG_GPS_SAT */
+               struct {
+                       uint16_t        channels;       /* 4 */
+                       struct {
+                               uint8_t svid;
+                               uint8_t c_n;
+                       } sats[12];                     /* 6 */
+               } gps_sat;                              /* 30 */
+       } u;
+};
+
+struct ao_eeprom {
+       struct ao_config        config;
+       struct ao_ms5607_prom   ms5607_prom;
+       int                     log_format;
+       uint16_t                serial_number;
+       uint8_t                 *data;
+       uint32_t                len;
+};
+
+struct ao_eeprom *ao_eeprom_read(FILE *file);
+
+struct ao_eeprom *ao_eeprom_read_old(FILE *file);
+
+void ao_eeprom_free_data(struct ao_eeprom *ao_eeprom);
+
+#endif /* _AO_EEPROM_READ_H_ */
index 2ceed7ab4f2ba9e1791c3283e23b735e93a2aaea..73f3d7bed61dde5534fe03631ff62e4b563f49c9 100644 (file)
@@ -113,9 +113,9 @@ ao_hex_read_record(struct ao_hex_input *input)
        struct ao_hex_record *record = NULL;
        enum ao_hex_read_state state = read_marker;
        char c;
-       int nhexbytes;
-       uint32_t hex;
-       uint32_t ndata;
+       int nhexbytes = 0;
+       uint32_t hex = 0;
+       uint32_t ndata = 0;
        uint8_t checksum;
 
        while (state != read_done) {
@@ -451,8 +451,8 @@ 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; }
+static uint32_t min(uint32_t a, uint32_t b) { return a < b ? a : b; }
+static 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)
diff --git a/ao-tools/lib/ao-ms5607-convert.c b/ao-tools/lib/ao-ms5607-convert.c
new file mode 100644 (file)
index 0000000..cc0eee3
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao-ms5607.h>
+
+void
+ao_ms5607_convert(struct ao_ms5607_sample *sample, struct ao_ms5607_value *value,
+                 struct ao_ms5607_prom *prom, bool is_ms5611)
+{
+       int32_t dT;
+       int32_t TEMP;
+       int64_t OFF;
+       int64_t SENS;
+
+       dT = sample->temp - ((int32_t) prom->tref << 8);
+
+       TEMP = 2000 + (((int64_t) dT * prom->tempsens) >> 23);
+
+       if (is_ms5611) {
+               OFF = ((int64_t) prom->off << 16) + (((int64_t) prom->tco * dT) >> 7);
+               SENS = ((int64_t) prom->sens << 15) + (((int64_t) prom->tcs * dT) >> 8);
+       } else {
+               OFF = ((int64_t) prom->off << 17) + (((int64_t) prom->tco * dT) >> 6);
+               SENS = ((int64_t) prom->sens << 16) + (((int64_t) prom->tcs * dT) >> 7);
+       }
+
+       if (TEMP < 2000) {
+               int32_t T2 = ((int64_t) dT * (int64_t) dT) >> 31;
+               int32_t TEMPM = TEMP - 2000;
+               int64_t OFF2 = (61 * (int64_t) TEMPM * (int64_t) TEMPM) >> 4;
+               int64_t SENS2 = 2 * (int64_t) TEMPM * (int64_t) TEMPM;
+               if (TEMP < -1500) {
+                       int32_t TEMPP = TEMP + 1500;
+                       /* You'd think this would need a 64-bit int, but
+                        * that would imply a temperature below -327.67°C...
+                        */
+                       int32_t TEMPP2 = TEMPP * TEMPP;
+                       OFF2 = OFF2 + (int64_t) 15 * TEMPP2;
+                       SENS2 = SENS2 + (int64_t) 8 * TEMPP2;
+               }
+               TEMP -= T2;
+               OFF -= OFF2;
+               SENS -= SENS2;
+       }
+
+       value->pres = ((((int64_t) sample->pres * SENS) >> 21) - OFF) >> 15;
+       value->temp = TEMP;
+}
diff --git a/ao-tools/lib/ao-ms5607.h b/ao-tools/lib/ao-ms5607.h
new file mode 100644 (file)
index 0000000..a23bb3c
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_MS5607_H_
+#define _AO_MS5607_H_
+
+#include <stdint.h>
+#include <stdbool.h>
+
+struct ao_ms5607_prom {
+       uint16_t        reserved;
+       uint16_t        sens;
+       uint16_t        off;
+       uint16_t        tcs;
+       uint16_t        tco;
+       uint16_t        tref;
+       uint16_t        tempsens;
+       uint16_t        crc;
+};
+
+struct ao_ms5607_sample {
+       uint32_t        pres;   /* raw 24 bit sensor */
+       uint32_t        temp;   /* raw 24 bit sensor */
+};
+
+struct ao_ms5607_value {
+       int32_t         pres;   /* in Pa * 10 */
+       int32_t         temp;   /* in °C * 100 */
+};
+
+void
+ao_ms5607_convert(struct ao_ms5607_sample *sample, struct ao_ms5607_value *value,
+                 struct ao_ms5607_prom *prom, bool is_ms5611);
+
+#endif /* _AO_MS5607_H_ */
index 0f7fa809ecd77864be20d5b866529f7c1c082308..4a7e52fc8d3fa55ec1ebb14e38f3e28ac04909a5 100644 (file)
@@ -213,9 +213,6 @@ cc_pressure_to_altitude(double pressure)
  * 2.82V * 2047 / 3.3 counts/V = 1749 counts/115 kPa
  */
 
-static const double counts_per_kPa = 27 * 2047 / 3300;
-static const double counts_at_101_3kPa = 1674.0;
-
 double
 cc_barometer_to_pressure(double count)
 {
index 88ddda58822ee487da4a7b07a6620bc3b914bb9c..c193b1c7f5ec4f3a3120dfa392898b1d42d90b21 100644 (file)
@@ -306,8 +306,8 @@ cc_log_read(FILE *file)
 {
        struct cc_flightraw     *f;
        char                    line[8192];
-       double                  ground_pres;
-       int                     ground_pres_count;
+       double                  ground_pres = 0.0;
+       int                     ground_pres_count = 0;
 
        f = calloc(1, sizeof (struct cc_flightraw));
        if (!f)
index 74b02a74b53af644707d816aca2c40c453456b37..f2307a8207818436391dd6560f18699424d4aba5 100644 (file)
@@ -46,8 +46,8 @@ struct cc_flightcooked *
 cc_flight_cook(struct cc_flightraw *raw)
 {
        struct cc_flightcooked *cooked;
-       double                  flight_start;
-       double                  flight_stop;
+       double                  flight_start = 0;
+       double                  flight_stop = 0;
        int                     start_set = 0;
        int                     stop_set = 0;
        int                     i;
index 500de96c30391d79f703b8ed81f3b5fa7946fbd7..256af3a116532b12af68e5537c44c78cf655d44e 100644 (file)
@@ -91,13 +91,15 @@ struct ao_telemetry_configuration {
 #define AO_GPS_MODE_MANUAL             'M'
 #define AO_GPS_MODE_SIMULATED          'S'
 
+#define AO_GPS_MODE_ALTITUDE_24                (1 << 0)        /* reports 24-bits of altitude */
+
 struct ao_telemetry_location {
        uint16_t        serial;         /*  0 */
        uint16_t        tick;           /*  2 */
        uint8_t         type;           /*  4 */
 
        uint8_t         flags;          /*  5 Number of sats and other flags */
-       int16_t         altitude;       /*  6 GPS reported altitude (m) */
+       int16_t         altitude_low;   /*  6 GPS reported altitude (m) */
        int32_t         latitude;       /*  8 latitude (degrees * 10⁷) */
        int32_t         longitude;      /* 12 longitude (degrees * 10⁷) */
        uint8_t         year;           /* 16 (- 2000) */
@@ -113,10 +115,15 @@ struct ao_telemetry_location {
        uint16_t        ground_speed;   /* 26 cm/s */
        int16_t         climb_rate;     /* 28 cm/s */
        uint8_t         course;         /* 30 degrees / 2 */
-       uint8_t         unused[1];      /* 31 */
+       int8_t          altitude_high;  /* 31 */
        /* 32 */
 };
 
+typedef int32_t gps_alt_t;
+#define AO_TELEMETRY_LOCATION_ALTITUDE(l) \
+       ((l)->altitude_low | (((l)->mode & AO_GPS_MODE_ALTITUDE_24) ? \
+                             ((gps_alt_t) (l)->altitude_high << 16) : 0))
+
 #define AO_TELEMETRY_SATELLITE         0x06
 
 struct ao_telemetry_satellite_info {
@@ -124,13 +131,16 @@ struct ao_telemetry_satellite_info {
        uint8_t         c_n_1;
 };
 
+#define AO_TELEMETRY_SATELLITE_MAX_SAT 12
+
+
 struct ao_telemetry_satellite {
        uint16_t                                serial;         /*  0 */
        uint16_t                                tick;           /*  2 */
        uint8_t                                 type;           /*  4 */
        uint8_t                                 channels;       /*  5 number of reported sats */
 
-       struct ao_telemetry_satellite_info      sats[12];       /* 6 */
+       struct ao_telemetry_satellite_info      sats[AO_TELEMETRY_SATELLITE_MAX_SAT];   /* 6 */
        uint8_t                                 unused[2];      /* 30 */
        /* 32 */
 };
@@ -173,8 +183,8 @@ struct ao_telemetry_mega_sensor {
        int16_t         gyro_z;         /* 24 */
 
        int16_t         mag_x;          /* 26 */
-       int16_t         mag_y;          /* 28 */
        int16_t         mag_z;          /* 30 */
+       int16_t         mag_y;          /* 28 */
        /* 32 */
 };
        
@@ -233,17 +243,19 @@ struct ao_telemetry_metrum_data {
        uint16_t        serial;         /*  0 */
        uint16_t        tick;           /*  2 */
        uint8_t         type;           /*  4 */
+       uint8_t         pad5[3];        /*  5 */
 
        int32_t         ground_pres;    /* 8 average pres on pad */
        int16_t         ground_accel;   /* 12 average accel on pad */
        int16_t         accel_plus_g;   /* 14 accel calibration at +1g */
        int16_t         accel_minus_g;  /* 16 accel calibration at -1g */
 
-       uint8_t         pad[14];        /* 18 */
+       uint8_t         pad18[14];      /* 18 */
        /* 32 */
 };
 
 #define AO_TELEMETRY_MINI              0x10
+#define AO_TELEMETRY_MINI3             0x11
 
 struct ao_telemetry_mini {
        uint16_t        serial;         /*  0 */
index 6c3ba5910b3602465e918dc38f7bcec04d700e9f..b176170013574dbfcbb0324f1781c4d5ef1ef469 100644 (file)
@@ -102,7 +102,7 @@ usb_tty(char *sys)
        struct dirent **namelist;
        int interface;
        int num_interfaces;
-       char endpoint_base[20];
+       char endpoint_base[64];
        char *endpoint_full;
        char *tty_dir;
        int ntty;
index abaec2cdb7d25df3c1240755438babf8f8cfa39f..76b5e57ac913e1d0555dfcf96b67a8995ef79e28 100644 (file)
@@ -18,13 +18,13 @@ dnl
 dnl Process this file with autoconf to create configure.
 
 AC_PREREQ(2.57)
-AC_INIT([altos], 1.9)
+AC_INIT([altos], 1.9.1)
 ANDROID_VERSION=18
 AC_CONFIG_SRCDIR([src/kernel/ao.h])
 AM_INIT_AUTOMAKE([foreign dist-bzip2])
 AM_MAINTAINER_MODE
 
-RELEASE_DATE=2018-12-31
+RELEASE_DATE=2019-12-05
 AC_SUBST(RELEASE_DATE)
 
 VERSION_DASH=`echo $VERSION | sed 's/\./-/g'`
@@ -64,27 +64,41 @@ AC_ARG_WITH(jcommon, AS_HELP_STRING([--with-jcommon=PATH],
 
 AC_SUBST(JCOMMON)
 
-AC_ARG_WITH(jvm, AS_HELP_STRING([--with-jvm-include=PATH],
-       [Set jvm include path for jni builds (default searches in /usr/lib/jvm)]),
-       [JVM_INCLUDE=$withval], [JVM_INCLUDE=auto])
+AC_ARG_WITH(jvm, AS_HELP_STRING([--with-jvm=PATH],
+       [Set jvm path for java builds (default searches in /usr/lib/jvm)]),
+       [JVM=$withval], [JVM=auto])
 
-if test "x$JVM_INCLUDE" = "xauto"; then
-       AC_MSG_CHECKING([JVM include files])
-       for jvm in default-java java-6-openjdk java-6-sun; do
-               if test "x$JVM_INCLUDE" = "xauto"; then
+if test "x$JVM" = "xauto"; then
+       AC_MSG_CHECKING([JVM])
+       for jvm in default-java java-6-openjdk java-7-openjdk java-8-openjdk java-9-openjdk java-10-openjdk java-11-openjdk java-12-openjdk java-13-openjdk java-6-sun java-8-openjdk-amd64; do
+               if test "x$JVM" = "xauto"; then
                        INCLUDE="/usr/lib/jvm/$jvm/include"
                        if test -f "$INCLUDE"/jni.h; then
-                               JVM_INCLUDE="$INCLUDE"
+                               JVM=/usr/lib/jvm/"$jvm"
                        fi
                fi
        done
-       if test "x$JVM_INCLUDE" = "xauto"; then
-               AC_MSG_ERROR([no JVM include files found])
+       if test "x$JVM" = "xauto"; then
+               AC_MSG_ERROR([no JVM files found])
        fi
-       AC_MSG_RESULT([$JVM_INCLUDE])
+       AC_MSG_RESULT([$JVM])
 fi
 
+AC_ARG_WITH(java-version, AS_HELP_STRING([--with-java-version=7],
+                                        [Set java language compatibility version (default is 7)]),
+          [JAVA_VERSION=$withval], [JAVA_VERSION=7])
+
+JAVAC="$JVM"/bin/javac
+JAVA="$JVM"/bin/java
+JVM_INCLUDE="$JVM"/include
+JAVAC_VERSION_FLAGS="-target 1.$JAVA_VERSION -source 1.$JAVA_VERSION"
+
+AC_SUBST(JAVAC)
+AC_SUBST(JAVA)
+AC_SUBST(JVM)
 AC_SUBST(JVM_INCLUDE)
+AC_SUBST(JAVAC_VERSION_FLAGS)
+
 
 AC_ARG_WITH(android, AS_HELP_STRING([--with-android=PATH],
        [Set android SDK path (default searches in a variety of places)]),
@@ -184,6 +198,9 @@ else
        HAVE_GOOGLE_KEY="no"
 fi
 
+WARN_CFLAGS="-Wall -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs"
+AC_SUBST(WARN_CFLAGS)
+
 AC_ARG_ENABLE(faketime, AS_HELP_STRING([--enable-faketime],
               [Use faketime program to ensure pdf files are reproducible (default=no)]),
              [FAKETIME=$enableval], [FAKETIME=no])
@@ -392,6 +409,25 @@ if test "x$HAVE_ASCIIDOCTOR_PDF" = "xno"; then
 fi
 AM_CONDITIONAL([ASCIIDOCTOR_PDF], [test x$HAVE_ASCIIDOCTOR_PDF != xno])
 
+AC_ARG_WITH([strip-nondeterminism],
+           [AS_HELP_STRING([--with-strip-nondeterminism],
+                           [Name of non-deterministic build data stripping tool])],
+           [],
+           [with_strip_nondeterminism=auto])
+
+if test "x$with_strip_nondeterminism" != "xno"; then
+       if test "x$with_strip_nondeterminism" = "xauto"; then
+               with_strip_nondeterminism="strip-nondeterminism"
+               AC_CHECK_PROG([HAVE_STRIP_NONDETERMINISM],[$with_strip_nondeterminism], yes, no)
+       else
+               HAVE_STRIP_NONDETERMINISM=yes
+       fi
+else
+       HAVE_STRIP_NONDETERMINISM=no
+fi
+AM_CONDITIONAL([STRIP_NONDETERMINISM], [test x$HAVE_STRIP_NONDETERMINISM != xno])
+AC_SUBST(STRIP_NONDETERMINISM, "$with_strip_nondeterminism")
+
 PKG_CHECK_MODULES([JANSSON], [jansson])
 
 AC_ARG_WITH([readline],
@@ -519,7 +555,7 @@ telegps/Info.plist
 telegps/telegps-windows.nsi
 altosdroid/Makefile
 altosdroid/local.properties
-altosdroid/AndroidManifest.xml
+altosdroid/app/src/main/AndroidManifest.xml
 ao-tools/Makefile
 ao-tools/lib/Makefile
 ao-tools/ao-rawload/Makefile
@@ -545,14 +581,12 @@ 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
 map-server/Makefile
 map-server/altos-mapd/Makefile
 map-server/altos-map/Makefile
 map-server/altos-mapj/Makefile
-src/Version
 ])
 
 echo ""
@@ -570,6 +604,7 @@ echo "    STlink support..............: ${HAVE_STLINK}"
 echo "    Newlib-nano support.........: ${NEWLIB_NANO}"
 echo "    i386 and amd64 libaltos.....: ${MULTI_ARCH}"
 echo "    install shared mime info....: ${INSTALL_SHARED_MIME_INFO}"
+echo "    Strip jar timestamps........: ${STRIP_NONDETERMINISM}"
 echo ""
 echo "  Java"
 echo "    freetts.....................: ${FREETTS}"
index 4dfb309431a11e92c396ddb4cb44201b7c7b3afe..5bf3c0ef5d9fbdd7fee9926e1b5ee480f34a754d 100644 (file)
@@ -17,6 +17,7 @@ FAKETIME=TZ=UTC faketime -f '$(RELEASE_DATE) 00:00:00 i0'
 endif
 
 RELNOTES_INC=\
+       release-notes-1.9.1.inc \
        release-notes-1.9.inc \
        release-notes-1.8.7.inc \
        release-notes-1.8.6.inc \
@@ -155,6 +156,21 @@ INC_FILES=\
 
 ADOC_FILES=$(TXT_FILES:.txt=.adoc) $(INC_FILES:.inc=.adoc)
 
+TELELAUNCH_TXT_FILES=altusmetrum.txt
+
+TELELAUNCH_INC_FILES=\
+       header.inc \
+       telelaunch-acknowledgements.inc \
+       telelaunch-intro.inc \
+       telelaunch-configuration.inc \
+       telelaunch-operation.inc \
+       telelaunch-specs.inc \
+       telelaunch-updating-firmware.inc \
+       telelaunch-cables.inc \
+       telelaunch-troubleshooting.inc 
+
+TELELAUNCH_ADOC_FILES=$(TELELAUNCH_TXT_FILES:.txt=.adoc) $(TELELAUNCH_INC_FILES:.inc=.adoc)
+
 TELEGPS_INC_FILES=\
        telegps-dedication.inc \
        telegps-quick-start.inc \
@@ -221,12 +237,12 @@ ONEFILE_HTML_FILES=$(ONEFILE_TXT_FILES:.txt=.html)
 
 AM_HTML=am.html
 
-PUBLISH_HTML=altusmetrum.html micropeak.html telegps.html easymini.html $(ONEFILE_HTML_FILES)
+PUBLISH_HTML=altusmetrum.html micropeak.html telegps.html easymini.html telelaunch.html $(ONEFILE_HTML_FILES)
 
 HTML=$(PUBLISH_HTML) $(RELNOTES_HTML)
 
 if ASCIIDOCTOR_PDF
-PDF=altusmetrum.pdf micropeak.pdf telegps.pdf easymini.pdf $(ONEFILE_PDF_FILES) \
+PDF=altusmetrum.pdf micropeak.pdf telegps.pdf easymini.pdf telelaunch.pdf $(ONEFILE_PDF_FILES) \
        $(OUTLINE_PDF_FILES)
 endif
 
@@ -283,6 +299,8 @@ map-loading.adoc: $(MAP_SVG_FILES)
 
 altusmetrum.pdf altusmetrum.html: $(ADOC_FILES) $(IMAGES)
 
+telelaunch.pdf telelaunch.html: $(TELELAUNCH_ADOC_FILES) $(IMAGES)
+
 telegps.html telegps.pdf: $(TELEGPS_ADOC_FILES) $(IMAGES)
 
 micropeak.pdf micropeak.html: $(MICROPEAK_ADOC_FILES) $(IMAGES)
@@ -318,7 +336,7 @@ publish-keithp:     am.html $(DOC) $(FONTS)
        scp -p $(ICONS) keithp.com:~keithp/public_html/altos/images/icons
 
 clean:
-       rm -f am.html $(HTML) $(PDF) $(ADOC_FILES) $(TELEGPS_ADOC_FILES) $(MICROPEAK_ADOC_FILES)
+       rm -f am.html $(HTML) $(PDF) $(ADOC_FILES) $(TELEGPS_ADOC_FILES) $(MICROPEAK_ADOC_FILES) $(TELELAUNCH_ADOC_FILES)
 
 distclean: clean
        rm -f $(HTML) $(PDF)
index db81297c5392135f2554560ee095f38e5d407724..bd47f0b2a452e02fc0d63eec3c80206cfa6fd4f3 100644 (file)
@@ -13,6 +13,14 @@ Creating documentation for a new release of AltOS
        easymini-release-notes.inc
        telegps-release-notes.inc
 
+* Update version in main docs
+
+       altusmetrum.txt
+       easymini.txt
+       micropeak.txt
+       telegps.txt
+       telemetry.txt
+
 * Add release-notes-${version}.inc to git
 
 * Make sure new hardware specs are documented in specs.inc
index 44f77acad47384b667557fc529790ab78cfc4df0..d497ad2fc9ec42f064459d233e20d57805980899 100644 (file)
                        .Flight Map
                        image::graph-map.png[width=400]
 
-                       Shows a satellite image of the flight area overlaid
-                       with the path of the flight. The red concentric
-                       circles mark the launch pad, the black concentric
-                       circles mark the landing location.
+                       Shows a satellite image of the flight area
+                       overlaid with the path of the flight. The
+                       flight path will have different colored
+                       sections for each state of the flight (just
+                       like the Site Map in Monitor Flight mode):
+                       white for pad, red for boost, pink for fast,
+                       yellow for coast, light blue for drogue, dark
+                       blue for main, and black for landed.
+
+                       The red concentric circles mark the launch
+                       pad, the black concentric circles mark the
+                       landing location. Data for the point along the
+                       along the flight path nearest the cursor will
+                       be displayed at the bottom of the window. This
+                       data includes flight time (so you can
+                       correlate data in the graph window), latitude,
+                       longitude, height above ground and vertical
+                       speed. The selected point will be highlighted
+                       with concentric circles in the same color as
+                       the flight path at that point.
+
                endif::gps[]
 
        === Export Data
                        programming).
                endif::telemetrum,telemini[]
                ifdef::telemega,easymega,telemetrum[]
-                       TeleMega, EasyMega, TeleMetrum v2,
-                       EasyMini and TeleDongle v3 are all
+                       TeleMega, EasyMega, TeleMetrum v2 or newer,
+                       EasyMini, TeleBT v3 or newer and TeleDongle v3
+                       or newer are all
                endif::telemega,easymega,telemetrum[]
                ifndef::telemega,easymega,telemetrum[]
                        EasyMini is
index f13fa5978a25d259e8577285bd324d9d7a725a5c..433f33d4cb2e6e09a583ac64cf9c1a8ab86625a7 100644 (file)
@@ -59,3 +59,5 @@ footer:
       content: '{page-number}'
 literal:
   font_family: DejaVu Sans Mono
+code:
+  font_family: DejaVu Sans Mono
index 17b2a53fabf3659ac6e86ba5f2f7bb06b335caae..408f8a7479c6cd9a2a2e0bf05137e0956f8b9e0f 100644 (file)
@@ -1,12 +1,11 @@
 = The Altus Metrum System: An Owner's Manual for Altus Metrum Rocketry Electronics
 Keith Packard <keithp@keithp.com>; Bdale Garbee <bdale@gag.com>; Bob Finch; Anthony Towns
 :title-logo-image: image:../themes/background.png[]
-:revnumber: v1.9
-:revdate: 31 Dec 2018
+:revnumber: v1.9.1
+:revdate: 5 Dec 2019
 :icons:
 :icontype: svg
-:revremark: Add EasyMega v2.0 support
-:copyright: Bdale Garbee and Keith Packard 2018
+:copyright: Bdale Garbee and Keith Packard 2019
 :doctype: book
 :numbered:
 :stylesheet: am.css
index 144b1e8fc9fd2704cefc91136e3ecea62361d1c8..5e3bdbf0b561b79bbbd704afbde1c47ab50566d4 100644 (file)
@@ -90,7 +90,7 @@ ifdef::radio[]
                transmission is disabled.
                ifdef::altusmetrum[]
                This option is
-               available on TeleMetrum v2 and TeleMega
+               available on TeleMetrum v2 or newer and TeleMega
                boards. TeleMetrum v1 boards cannot transmit
                APRS packets.
                endif::altusmetrum[]
index 67ba0f4dc07e422720e9608164eb53571c157c14..6fc6f035ef727d698eb51d8fcc388b16364c2fa3 100644 (file)
@@ -1,5 +1,17 @@
 [appendix]
 == Release Notes
+       :leveloffset: 2
+       include::release-notes-1.9.1.adoc[]
+
+       <<<<
+       :leveloffset: 2
+       include::release-notes-1.9.adoc[]
+
+       <<<<
+       :leveloffset: 2
+       include::release-notes-1.8.7.adoc[]
+
+       <<<<
        :leveloffset: 2
        include::release-notes-1.8.6.adoc[]
 
index e3d3fae843cd770dcfbaa3cea47d8f4ff4fec82f..7810b4fac60b1417c8b58870c6f189f802eb32f8 100644 (file)
@@ -1,9 +1,9 @@
 = EasyMini Owner's Manual
 Keith Packard <keithp@keithp.com>; Bdale Garbee <bdale@gag.com>
 :title-logo-image: image:../themes/background.png[]
-:revnumber: v1.8.7
-:revdate: 8 Oct 2018
-:copyright: Bdale Garbee and Keith Packard 2018
+:revnumber: v1.9.1
+:revdate: 5 Dec 2019
+:copyright: Bdale Garbee and Keith Packard 2019
 :doctype: book
 :numbered:
 :toc:
index 392289083e1323d39070793ee3e19085199fd547..af79d532d05608bbd65bc27b0cd21c7f16c0f514 100644 (file)
@@ -22,6 +22,7 @@
        |TeleMetrum v1.0        |8      |1MB    |20
        |TeleMetrum v1.1 v1.2   |8      |2MB    |40
        |TeleMetrum v2.0        |16     |8MB    |80
+       |TeleMetrum v3.0        |16     |8MB    |80
        endif::telemetrum[]
        ifdef::telemini[]
        |TeleMini v1.0          |2      |5kB    |4
@@ -52,7 +53,7 @@
        for storing flight log data.
 
        ifdef::telemetrum,telemega,easymega[]
-       TeleMetrum v2.0, TeleMega and EasyMega
+       TeleMetrum v2 or newer, TeleMega and EasyMega
        store configuration data in a bit of eeprom available within
        the processor chip, leaving that space available in flash for
        more flight data.
@@ -65,7 +66,7 @@
        together. That will slightly under-estimate the storage (in
        bytes) needed for the flight.
        ifdef::telemetrum[]
-       For instance, a TeleMetrum v2.0 flight spending
+       For instance, a TeleMetrum v2 or newer flight spending
        20 seconds in ascent and 150 seconds in descent will take
        about (20 * 1600) + (150 * 160) = 56000 bytes of storage. You
        could store dozens of these flights in the on-board flash.
index decaf4d43203fe0600c48a49e4b0707d4890a7b1..5e60986ad1e6baecc1e8005348790f39711be4ff 100644 (file)
                to trickle charge. It can take several hours to fully recharge a
                deeply discharged battery.
 
-               TeleMetrum v2.0, TeleMega and EasyMega use a higher power battery charger,
-               allowing them to charge the battery while running the board at
-               maximum power. When the battery is charging, or when the board
-               is consuming a lot of power, the red LED will be lit. When the
-               battery is fully charged, the green LED will be lit. When the
-               battery is damaged or missing, both LEDs will be lit, which
-               appears yellow.
+               TeleMetrum v2 or newer, TeleMega and EasyMega use a
+               higher power battery charger, allowing them to charge
+               the battery while running the board at maximum
+               power. When the battery is charging, or when the board
+               is consuming a lot of power, the red LED will be
+               lit. When the battery is fully charged, the green LED
+               will be lit. When the battery is damaged or missing,
+               both LEDs will be lit, which appears yellow.
                ====
                endif::telemetrum,telemega,easymega[]
 
index 2363d2511dee984cb41e76777eadbbb5ef0af679..f57135593b6d72858d3dba051a32482681cbc568 100644 (file)
Binary files a/doc/graph-map.png and b/doc/graph-map.png differ
index bff009c0c087166bdda1a06445096e1de15c8232..a95247a2ff81c1723ec1170e086418329770e3dc 100644 (file)
@@ -20,8 +20,8 @@
        The first device created for our community was TeleMetrum, a dual
        deploy altimeter with fully integrated GPS and radio telemetry
        as standard features, and a “companion interface” that will
-       support optional capabilities in the future. The latest version
-       of TeleMetrum, v2.0, has all of the same features but with
+       support optional capabilities in the future. The later versions
+       of TeleMetrum, v2 and newer, have all of the same features but with
        improved sensors and radio to offer increased performance.
 
        Our second device was TeleMini, a dual deploy altimeter with
diff --git a/doc/micropeak-flight-foam.png b/doc/micropeak-flight-foam.png
new file mode 100644 (file)
index 0000000..c7d37e3
Binary files /dev/null and b/doc/micropeak-flight-foam.png differ
diff --git a/doc/micropeak-flight-nofoam.png b/doc/micropeak-flight-nofoam.png
new file mode 100644 (file)
index 0000000..ecf83f7
Binary files /dev/null and b/doc/micropeak-flight-nofoam.png differ
diff --git a/doc/micropeak-foam.jpg b/doc/micropeak-foam.jpg
new file mode 100644 (file)
index 0000000..73a4040
Binary files /dev/null and b/doc/micropeak-foam.jpg differ
index 9569194ee8b25312f20a8cf48c891061f78d31d3..e4d8aa989acd5828508dee47d36779e2183d5345 100644 (file)
@@ -1,8 +1,8 @@
 = MicroPeak Owner's Manual
 Keith Packard <keithp@keithp.com>; Bdale Garbee <bdale@gag.com>
-:revnumber: v1.8.7
-:revdate: 8 Oct 2018
-:copyright: Bdale Garbee and Keith Packard 2018
+:revnumber: v1.9.1
+:revdate: 5 Dec 2019
+:copyright: Bdale Garbee and Keith Packard 2019
 :stylesheet: am.css
 :linkcss:
 :toc:
@@ -299,6 +299,43 @@ Keith Packard <keithp@keithp.com>; Bdale Garbee <bdale@gag.com>
                        these applications, change in one application
                        will affect the other.
 
+== Protecting MicroPeak from Sunlight
+
+       The MS5607 barometric sensor is sensitive to direct light. When light
+       shines through the holes in the cover to the components inside, the
+       reported pressure can vary wildly from the actual pressure. This
+       causes the reported altitude to have errors of thousands of
+       feet.
+
+       MicroPeak should be installed in an opaque compartment in the airframe
+       and not subjected to sunlight. Alternatively, a small piece of
+       adhesive-backed open-cell foam can be attached to the device so that
+       it covers the barometric sensor and protects it from direct light.
+
+       Here's what happens when MicroPeak is exposed to sunlight. At apogee,
+       I exposed MicroPeak to varying amounts of sunlight and you can see the
+       wild swings in altitude resulting from that:
+
+       .MicroPeak in Sunlight
+       image::micropeak-flight-nofoam.png[width=430]
+
+       You can carefully cutting a piece of adhesive-backed open-cell foam
+       and attach it to MicroPeak. It's important to press the adhesive to
+       the circuit board and not to the top of the barometric sensor or the
+       sensor may become blocked and not operate at all. Once you've attached
+       the foam, you should test MicroPeak on the ground to make sure it's
+       still working.
+
+       .MicroPeak with Foam
+       image::micropeak-foam.jpg[width=430]
+
+       That MicroPeak was in the same barometric chamber as the one which
+       generated the above results and the resulting flight data looks
+       correct:
+
+       .MicroPeak in Sunlight with Foam
+       image::micropeak-flight-foam.png[width=430]
+
 [appendix]
 == Handling Precautions
 
@@ -327,10 +364,16 @@ Keith Packard <keithp@keithp.com>; Bdale Garbee <bdale@gag.com>
        sensor out of direct sunlight.
 
        The barometric sensor sampling ports must be able to
-       "breathe", both by not being covered by foam or tape or other
-       materials that might directly block the hole on the top of the
-       sensor, and also by having a suitable static vent to outside
-       air.
+       "breathe", both by not being covered by solid foam or tape or 
+       other materials that might directly block the hole on the top 
+       of the sensor, and also by having a suitable static vent to 
+       outside air.
+
+       One good solution is to use a small rectangle of Poron 
+       50-30031-12X12P or equivalent to cover the sensor.  This is an
+       open cell foam in 1/32" thickness with an adhesive backing.  It
+       seems to do a good job of blocking sun while still allowing
+       airflow to and from the sensor internals.
 
        As with all other rocketry electronics, Altus Metrum
        altimeters must be protected from exposure to corrosive motor
diff --git a/doc/release-notes-1.9.1.inc b/doc/release-notes-1.9.1.inc
new file mode 100644 (file)
index 0000000..be54d3b
--- /dev/null
@@ -0,0 +1,30 @@
+= Release Notes for Version 1.9.1
+include::release-head.adoc[]
+:doctype: article
+
+       Version 1.9.1
+
+       == AltOS
+
+       * Add support for TeleMetrum v3.0
+
+       * Fix accel cal value when changing EasyMega v2.0 pad orientation
+
+       * Correct EasyMega v2.0 magnetometer data axes
+
+       * Fix EasyMega v2.0 idle monitor display of IMU data
+
+       * Report all sensor failures at power-up time.
+       
+       == AltosUI, TeleGPS, MicroPeak
+
+       * Display error message when attempting to graph unknown format file.
+
+       * Make it possible to disable APRS once enabled.
+
+       * Display some data for point near cursor in map tab.
+
+       * Support upgrading devices from pre-1.8 firmware
+
+       * Wait for Windows to prepare new devices during firmware
+         upgrade. This should avoid the “COMxx: open failed” message.
index 3ff1942b4a9ccd8279a9d957dddbbbe2ee40da8c..a51c6b04e529fa59e7a7e0e2541ef6385e1b9ec2 100644 (file)
@@ -1,5 +1,9 @@
 [appendix]
 == Release Notes
+       :leveloffset: 2
+       include::release-notes-1.9.1.adoc[]
+
+       <<<<
        :leveloffset: 2
        include::release-notes-1.9.adoc[]
 
index 48d73f96475c63cba38d61a45f45d1bf01ba3a81..e6310e52e23f6a9aab9f10386b2f42c10ecc0675 100644 (file)
        |40mW
        |3.7V
 
+       |TeleMetrum v3.0
+       |MS5607 30km (100k')
+       |ADXL375 200g
+       |uBlox Max-8Q
+       |-
+       |8MB
+       |40mW
+       |3.7V
+
        endif::telemetrum[]
        ifdef::telemini[]
        |TeleMini v1.0
index 1e130976bcfc38ce33d88b1dd1e3ba529fd34744..6cc9986b150556a283289369c22a5466bf4f3aa2 100644 (file)
        endif::radio[]
 
        ifdef::gps+radio[]
-       :aprsdevices: TeleMetrum v2.0 and TeleMega
+       :aprsdevices: TeleMetrum v2 and newer and TeleMega
        :configure_section: _configure_altimeter
        include::aprs-operation.adoc[]
        endif::gps+radio[]
index ec1135cbd0d83bcc7a174ed603f1281eca0f4c99..af6317024455f2853f66fe8c3803a2e77c4088a8 100644 (file)
@@ -1,6 +1,18 @@
 [appendix]
 == Release Notes
 
+       :leveloffset: 2
+       include::release-notes-1.9.1.adoc[]
+
+       <<<<
+       :leveloffset: 2
+       include::release-notes-1.9.adoc[]
+
+       <<<<
+       :leveloffset: 2
+       include::release-notes-1.8.7.adoc[]
+
+       <<<<
        :leveloffset: 2
        include::release-notes-1.8.6.adoc[]
 
index 1dd889cda8b37e0f6d8234f89ef2298f02f2fd3f..b21445fce6e92931d266714409ea2d51a1d623a1 100644 (file)
                onboard flash before it fills up. TeleGPS will still
                report telemetry even if memory is full, so the only
                thing you will lose is the on-board data log.
-      
+
+       === LEDs
+
+               TeleGPS v1.0 has a dual greed/red LED along the edge
+               towards the USB connector end of the board. This
+               indicates battery charging status while connected to
+               power over USB. When the red LED is lit, the battery
+               is charging. Once the battery is fully charged, the
+               red LED goes out and the green LED turns on. If both
+               LEDs are lit, something is probably wrong with the battery.
+
+               TeleGPS v2.0 has the same green/red battery charging
+               status LED and adds another green LED along the same
+               edge, towards end of the board with the 70cm
+               antenna. This green LED indicates GPS lock status — it
+               blinks once every three seconds when the GPS receiver
+               is locked and tracking position.
+
        === Installation
 
                The battery connectors are a standard 2-pin JST
index 8b558dbd27a7a3606b93da731f9f21e48f4efd46..dd21f5ecd43b1d275cebc6b9e9e6c8f471edb592 100644 (file)
@@ -1,10 +1,9 @@
 = TeleGPS Owner's Manual
 Keith Packard <keithp@keithp.com>; Bdale Garbee <bdale@gag.com>
 :title-logo-image: image:../themes/background.png[]
-:revnumber: v1.8.7
-:revdate: 8 Oct 2018
-:revremark: Fix TeleBT v4.0 RF calibration to factory value when reflashing. Fix map images. Fix Mac OS X support.
-:copyright: Bdale Garbee and Keith Packard 2018
+:revnumber: v1.9.1
+:revdate: 5 Dec 2019
+:copyright: Bdale Garbee and Keith Packard 2019
 :stylesheet: am.css
 :linkcss:
 :toc:
diff --git a/doc/telelaunch-acknowledgements.inc b/doc/telelaunch-acknowledgements.inc
new file mode 100644 (file)
index 0000000..3296624
--- /dev/null
@@ -0,0 +1,26 @@
+[dedication]
+== Acknowledgments
+
+       Our profound thanks to Terry Lee for major contributions to making 
+       the TeleLaunch system something we could actually package and sell!
+
+       Tripoli Colorado, Oregon Rocketry, New River Valley Rocketry, and 
+       the National Association of Rocketry helped instigate this work, 
+       and/or were early adopters of TeleLaunch.  We learned a lot working
+       with each organization.  Thank you!
+
+       Thanks also to our friends in the Kloudbusters, both for helping 
+       us understand what it takes to run truly great large-scale launches, 
+       and for providing some completely deserved, scathing feedback on 
+       an early prototype of TeleLCO.
+
+       Have fun using these products, and we hope to meet all of you
+       out on a rocket flight line somewhere.
+
+       [verse]
+       Bdale Garbee, KB0G
+       NAR #87103, TRA #12201
+
+       [verse]
+       Keith Packard, KD7SQG
+       NAR #88757, TRA #12200
diff --git a/doc/telelaunch-cables.inc b/doc/telelaunch-cables.inc
new file mode 100644 (file)
index 0000000..6c6cc40
--- /dev/null
@@ -0,0 +1,5 @@
+[appendix]
+== Making Pad Cables
+
+       Pad cables can be made from standard AC extension cords and alligator
+       clips...
diff --git a/doc/telelaunch-configuration.inc b/doc/telelaunch-configuration.inc
new file mode 100644 (file)
index 0000000..f5199cc
--- /dev/null
@@ -0,0 +1,133 @@
+== Configuration
+
+       There are three things you need to configure identically in each unit
+       that is part of a TeleLaunch system for wireless communications to
+       succeed.  Those are the operating frequency, the callsign, and a key
+       for the AES encryption algorithm.  Additionally, each TeleFire unit
+       also needs to be configured with a unique bank number.
+
+       Please note that these values must match exactly, or the system will
+       not operate as expected.  That means the callsign needs to have the
+       same choices of upper or lower case, no trailing spaces, etc.  And
+       the operating frequency and AES key must match.
+
+       === Connecting to a Unit
+
+               Configuring each unit of a TeleLaunch system requires use of 
+               a micro USB cable, and a computer with a suitable terminal
+               emulation program.  Connect a suitable cable, open your
+               favoriate terminal emulation program, and power up the unit.
+               By pressing <enter> you should see a command prompt.
+
+               === TeleLCO
+
+                       The USB connector on TeleLCO is accessible without
+                       opening the lid of the Pelican box.  Look for the
+                       blue dust cap over the connector under the handle.
+
+               === TeleFireEight
+
+                       The USB connector on TeleFireEight is located on the
+                       circuit board.  To access it, open the box and flip
+                       the lid up.  you should be able to spot a vertical
+                       micro USB connector on the board near the DIP switch.
+
+                       [WARNING]
+                       Please take care when closing the TeleFireEight lid
+                       not to pinch any wires.
+
+       === Operating Frequency
+
+               The TeleLaunch system supports operation over much of the 
+               "70cm" Amateur Radio band, with the filters optimized for a
+               center frequency of 435 MHz.  For each system, a single
+               operating frequency should be selected and programmed into
+               each unit.
+
+               The default frequency for units leaving the factory is 
+               435.750 MHz.  Since Altus Metrum flight computers operate
+               by default on 10 100khz channels from 434.550 to 435.450 MHz,
+               we chose this frequency to be far enough away from flight
+               computers to avoid any interference, but still close enough
+               to the radio subsystem design center frequency for great
+               performance.
+
+               To configure the frequency, use your terminal emulator to
+               issue two commands.  First, use 'c F xxxxxx' where the xxxxxx
+               is replaced with the desired operating frequency in kHz.  Then
+               use the 'c w' command to save this value into non-volatile
+               memory.  For example, the default 435.750 MHz would be 
+               configured using
+
+                       c f 435750 +
+                       c w
+
+
+       === Callsign
+
+               In the US, you need an
+               link:http://www.altusmetrum.org/Radio/[amateur radio license]
+               or other authorization to legally operate the radio
+               transmitters that are part of TeleLaunch.
+
+               The default callsign shipped from the factory is "N0CALL",
+               which is not a valid callsign and meant to humorously point
+               out that the callsign hasn't been configured yet.
+
+               Individual owners of a TeleLaunch system should use their
+               own callsign.  
+
+               Club owners of a TeleLaunch system should pick the callsign
+               of one club member who is willing to be designated as the 
+               control operator of the system.  Under FCC Part 97 rules,
+               being the control operator does not mean you have to be LCO
+               all the time, it just means taking responsibility for ensuring
+               the system is being operated in compliance with the rules.
+
+               To configure the callsign, use your terminal emulator to 
+               issue two commands.  First, use 'c c callsign' to set the
+               callsign, then use 'c w' to write to non-volatile memory.
+               For example, to set the default N0CALL, the commands would
+               be
+
+                       c c N0CALL +
+                       c w
+
+       === AES Key
+
+               For safety, TeleLaunch uses cryptographic checksums to help 
+               prevent interference, intentional or un-intentional.  This
+               means each system must have a shared AES encryption key
+               identically configured into each unit.
+
+               The key size required is 128 bits, which must be expressed
+               as a 32-digit hexadecimal number.
+
+               To configure the AES key, use 'c a key' followed by 'c w'
+               to write the key to non-volatile memory.  For example, to
+               configure your system with a key that is the answer to life,
+               the universe, and everything, the commands would be
+
+                       c a 00000000000000000000000000000042 +
+                       c w
+
+       === Bank Number
+
+               Each TeleFire unit needs to be configured with a bank number,
+               and bank numbers should be unique within a given system.  For
+               most systems with 8 or fewer banks, just use the DIP switch
+               on the circuit board inside the TeleFire unit to select the
+               desired bank.  Only one switch should be turned on.  Switch
+               one means bank one, etc.
+
+               To allow systems to have more than 8 banks, if all the DIP
+               switches are "off", the unit will use the bank configured in 
+               non-volatile memory.
+
+               To configure the bank number, use 'c B bank' followed by
+               'c w' to write to non-volatile memory.  For example, to
+               set the bank to 42, the commands would be:
+
+                       c B 42 +
+                       c w
+
diff --git a/doc/telelaunch-intro.inc b/doc/telelaunch-intro.inc
new file mode 100644 (file)
index 0000000..bfd67a4
--- /dev/null
@@ -0,0 +1,27 @@
+== Introduction and Overview
+
+Welcome to the Altus Metrum community!  Our circuits and software reflect
+our passion for both hobby rocketry and Free Software.  We hope their
+capabilities and performance will delight you in every way, but by
+releasing all of our hardware and software designs under open licenses,
+we also hope to empower you to take as active a role in our collective
+future as you wish!
+
+Thank you for your interest in TeleLaunch, a wireless control system for
+launching hobby rockets.  Each TeleLaunch system contains at least two units,
+a launch control box (TeleLCO) and one or more launch initiation boxes 
+(TeleFire).  In this manual, we hope to provide all the information required
+to configure and successfully operate a TeleLaunch system.
+
+Unlike other Altus Metrum products, that are usually provided as circuit
+boards that the user must arrange to mount and wire up, all products in the
+TeleLaunch system are sold as fully packaged, almost-ready-to-use units.  This
+means that with only minimal one-time configuration of each unit, a TeleLaunch
+system can be made ready for use very quickly.
+
+Because documentation is just as prone as software to contain "bugs", and
+can always be improved...  If you have questions that aren't answered in this 
+manual, or just need a little help figuring things out, we strongly suggest 
+joining the Altus Metrum user email list, which you can do by visiting 
+https://lists.gag.com/mailman/listinfo/altusmetrum.
+
diff --git a/doc/telelaunch-operation.inc b/doc/telelaunch-operation.inc
new file mode 100644 (file)
index 0000000..db71d91
--- /dev/null
@@ -0,0 +1,161 @@
+== Operation
+
+       Operating a TeleLaunch system is pretty easy, and we hope fairly
+       intuitive for anyone who has ever launched rockets before.  Basic 
+       instructions are printed on a decal inside the lid of each TeleLCO
+       unit, which early customers (before this manual was even written)
+       reported were sufficient to successfully use the system.
+
+       The remainder of this section assumes the system has already been
+       properly configured with callsign, AES key, and bank numbers for each
+       TeleFire box.
+
+       === Charging Batteries
+
+               TeleLCO has an internal Lithium Polymer battery that is 
+               charged over USB.  A weather-tight micro USB connector is
+               installed with a blue cap under the handle.  This position
+               was chosen so that TeleLCO can be charged while the lid is
+               closed and standing handle-up.  Attach a micro USB cable
+               to a computer or other source of USB power.  There are two
+               charge indicators on the panel that will illuminate during
+               charging, red for charge in progress and green for charge
+               complete.
+       
+               TeleFire has an internal sealed lead acid 12V battery, and
+               is provided with an external AC charger.  Connect this charger
+               to the PowerPole connector on the back face of the box to
+               charge the battery.  Other sources of charging current for
+               a nominal 12V sealed battery may be used.  The charge 
+               connector can also be used to attach an external battery if
+               needed.
+       
+       === Setting Up
+
+               Each unit in the TeleLaunch system needs a suitable antenna
+               attached.  A typical configuration would involve the provided
+               omni-directional antenna or optional directional antenna aimed 
+               at the field mounted on a pole attached to TeleLCO at the 
+               launch control station, and the provided rubber whip antennas
+               on each TeleFire box.  
+
+               If deploying the system in rough terrain, on a field with 
+               dense vegetation, or at great distances (some away cells), you
+               may need a better antenna or at least to mount the antenna 
+               higher off the ground.  All units in the TeleLaunch system
+               have tri-color RF signal strength indicators.  A system should
+               show green on all units during normal operation.  An occasional
+               dip to amber is ok, but frequent amber or any red indicates a
+               need to improve the antenna situation.
+
+               Antenna made for use near 435 Mhz in the ham radio "70cm band" 
+               should work, and there are many online sources of information
+               on making inexpensive, highly effective antennas at home.
+
+               The TeleLCO unit should be placed on a table at the Launch
+               Control position.  It can be helpful for the LCO (the human(s)
+               too, not just the electronics!) to be provided with some 
+               shade, but the use of reflective LCDs for the digit 
+               displays and ultri-bright LEDs make TeleLCO operation 
+               reasonable even in direct sunlight.
+
+               Each TeleFire box should be placed in proximity to the launch
+               rails it will service.  Whip clips made from AC power cords
+               (not provided) should be attached to TeleFire and routed to
+               each launch rail.  The pyro output on each channel is 
+               connected to the "line" and "neutral" pins on the outlet,
+               while the ground pin is attached to chassis ground.
+
+       === Turning System On
+
+               Turn on all TeleFire pad boxes in the system.  At power-on,
+               all LEDs will turn on briefly so you can verify they're all 
+               working.  The radio signal strength indicators will show red
+               until TeleLCO is turned on.
+
+               Turn on TeleLCO.  All LCD segments and LEDs will turn on
+               briefly so you can verify they're all working.  An exception
+               are the two battery charger LEDs, which only illuminate when
+               the battery is charging.  The LCD displays will then briefly
+               display the internal battery voltage, which should be at least
+               3.9V for normal operation.  TeleLCO then scans to locate all 
+               TeleFire boxes that are in range and configured for the same 
+               frequency, callsign, and AES key.  During this process, the 
+               Bank LCD diplays will appear to be counting up from 1 to 99.
+               When the search is complete, the Pad display will show the
+               number of TeleFire devices found.  TeleLCO beeps when ready.
+
+       === Launch One Rocket
+
+               Switch the TeleFire to 'Safe' and confirm it is silent.
+
+               Put a rocket on a launch rail / rod, and connect whip clips
+               from a pad output on a TeleFire unit to the motor igniter.
+               Verify igniter continuity using the LED associated with that
+               output.  Green is good.
+
+               Switch the TeleFire unit from 'Safe' to 'Arm', at which point
+               it will start "chirping" to indicate that it is "armed and 
+               dangerous".  Move to the TeleLCO at a safe distance away.
+
+               Ensure the TeleLCO blue Drag Race switch is on Normal and 
+               the blue Drag Race LED is extinguished.
+
+               Select the desired TeleFire unit by pushing the TeleLCO 
+               selector knob until the "Bank" LED is lit, then rotating the 
+               knob until the 
+               desired box is selected.  Then push the knob until the Pad 
+               LED is lit and rotate the knob until the desired pad is 
+               selected.  Verify the Remote Armed LED is lit, and that the
+               selected pad's Igniter Continuity LED is lit.
+
+               Perform range safety checks.
+
+               Move the TeleLCO SAFE/ARM switch to ARM.  This will cause
+               the selected TeleFire unit's strobe to start flashing and
+               siren to become more insistent. 
+
+               Perform count-down.
+
+               Depress the LAUNCH button and hold until the rocket launches.
+
+               Move the TeleLCO SAFE/ARM switch back to SAFE.
+
+       === Launch A Multi-Rocket "Drag Race"
+
+               To enable drag race mode, move the TeleLCO blue switch to
+               Drag Race.  The blue Drag Race LED should illuminate.
+
+               Select pads to include in the drag race by using the same
+               process as for a single rocket to select each Bank and Pad,
+               then press Add/Remove to toggle the currently selected pad
+               in the race.  The continuity LEDs blink ON/off for selected,
+               and on/OFF for deselected (long ON means in the race).
+
+               A drag race can be configured to include pads on multiple
+               TeleFire boxes, but the blinking continuity indicators to
+               show which pads are included can only indicate the currently
+               selected bank.
+
+               Verify remotes are ready and armed by using the Remote Armed
+               and Igniter Continuity LEDs.
+
+               Perform range safety checks.
+
+               Move the TeleLCO SAFE/ARM switch to ARM.  This will cause
+               the selected TeleFire units strobes to start flashing and
+               sirens to become more insistent. 
+
+               Perform count-down.
+
+               Depress the LAUNCH button and hold until rockets launch.
+
+               Move the TeleLCO SAFE/ARM switch back to SAFE.
+
+               Move Drag Race switch back to Normal.
+
+               Note that if there is a mis-fire in a drag race and you want
+               to fix igniters and try again, the current drag configuration
+               is preserved as long as you stay in Drag Race mode.  So you
+               can SAFE the system, fix igniters, and try again before leaving
+               Drag Race mode if desired.
diff --git a/doc/telelaunch-specs.inc b/doc/telelaunch-specs.inc
new file mode 100644 (file)
index 0000000..7d48014
--- /dev/null
@@ -0,0 +1,36 @@
+== Specifications
+
+       The TeleLaunch system can handle up to 99 banks with each bank
+       having up to 8 pads, for a total of 792 pads.
+
+       Each unit in the TeleLaunch system is water-resistant, but is not
+       intended to be directly immersed in water.  Brief rain showers during
+       a launch should pose no problem, but it's recommended to cover units
+       or bring them inside when not in use or during extended periods of 
+       bad weather.
+
+       TeleLCO uses an internal single-cell 2Ah Lithium Polymer battery,
+       which is sufficient for multiple days of typical operation.  This
+       battery is charged over USB.
+
+       TeleFire uses an internal sealed lead-acid 12V battery, which is
+       charged by an external charger attached through the PowerPole
+       connector on the rear panel.
+
+       Pyro initiation uses the 12V sealed lead-acid battery.  Current
+       to any pad can exceed 30A, and with typical igniters every pad on
+       a TeleFire can be successfully included in a drag race.  The system
+       controls current flow to prevent damage, and has a self-resetting 
+       circuit breaker for ultimate protection should something go badly 
+       wrong.
+
+       TeleLaunch uses AES encryption with a shared key between each unit
+       in the system to ensure the integrity of safe launch operations.
+
+       The TeleLaunch system uses radio frequency communications in the
+       vicinity of 435 Mhz.  A US amateur radio license or equivalent
+       authorization is required to legally use the system.  The operating
+       frequency should be chosen to avoid conflict with other devices, or
+       put differently, nothing else should be operating on the same 
+       frequency while TeleLaunch is in use.
+
diff --git a/doc/telelaunch-troubleshooting.inc b/doc/telelaunch-troubleshooting.inc
new file mode 100644 (file)
index 0000000..d44d043
--- /dev/null
@@ -0,0 +1,50 @@
+[appendix]
+== Troubleshooting
+
+       === TeleFire Fails to Arm
+
+               If turning the TeleLCO key switch from "SAFE" to "ARM" does
+               not cause the selected TeleFire box to start flashing and
+               sounding its siren, the most likely cause is that the 
+               TeleFire box was left with the local safe/arm switch in the
+               safe position.  The Remote Arm LED on TeleLCO shows the state
+               of the safe/arm switch on the currently selected TeleFire box
+               and can be used to confirm this situation.
+
+               Note that in a cross-bank drag race configuration, any TeleFire
+               boxes involved in the drag race that are fully armed will
+               launch, while any TeleFire boxes involved in the drag race
+               that are not fully armed will not launch.  Pay attention to
+               make sure all involved TeleFire boxes are flashing their
+               strobe lights and sounding their sirens before launch to
+               ensure all desired rockets will actually participate in such
+               a drag race.
+
+       === Radio Signal Strength
+
+               Each unit in the TeleLaunch system has a debugging feature
+               that can be used to view the actual received radio signal 
+               strength of each packet.  To use this feature, connect to the
+               desired unit (TeleLCO is probably the most useful place to
+               start) with a laptop and terminal program as explained in the
+               configuration section of the manual.  Then, you can enable
+               debug tracing using 'D 1' command.
+
+               Debug mode is fairly chatty, but each time the TeleLCO unit
+               queries the currently selected TeleFire unit for igniter
+               status, the return packet will print out the RSSI value.
+               RSSI is "received signal strength indicated" and is expressed
+               in decibel units relative to a milliwatt, or "dBm".  
+
+               Observing the RSSI is a great way to compare antennas, antenna
+               mounting arrangements, and so forth with more granularity than
+               provided by the red/amber/green operational LED indicators.
+
+               The system is good down to below -100dBm, and it takes about 
+               6dB to double the range.  So a reading of -80dBm means that you
+               could extend the distance between the units by a factor of
+               10 before losing the link.  Note, however, that real world
+               range is affected by terrain, vegetation, etc.  And you really
+               don't ever want to be operating close to the minimum signal
+               threshold!  Keep the RF signal indicators green with good
+               antenna choices and installations for maximum satisfaction.
diff --git a/doc/telelaunch-updating-firmware.inc b/doc/telelaunch-updating-firmware.inc
new file mode 100644 (file)
index 0000000..a785abd
--- /dev/null
@@ -0,0 +1,4 @@
+== Updating Firmware
+
+       The firmware for each unit can be updated over USB.  More details
+       will be forthcoming if/when a firmware update is required.
diff --git a/doc/telelaunch.txt b/doc/telelaunch.txt
new file mode 100644 (file)
index 0000000..bca8cb6
--- /dev/null
@@ -0,0 +1,38 @@
+= TeleLaunch: The Altus Metrum Wireless Launch Control System
+Bdale Garbee <bdale@gag.com>
+:title-logo-image: image:../themes/background.png[]
+:revnumber: v0.1
+:revdate: 16 Feb 2019
+:icons:
+:icontype: svg
+:revremark: initial draft
+:copyright: Bdale Garbee 2019
+:doctype: book
+:numbered:
+:stylesheet: am.css
+:linkcss:
+:toc:
+:telelaunch: 1
+:application: TeleLaunch
+:pdf-stylesdir: .
+:pdf-style: altusmetrum
+:pdf-fontsdir: fonts
+
+       include::header.adoc[]
+
+       include::telelaunch-acknowledgements.adoc[]
+
+       include::telelaunch-intro.adoc[]
+
+       include::telelaunch-configuration.adoc[]
+
+       include::telelaunch-operation.adoc[]
+
+       include::telelaunch-specs.adoc[]
+
+       include::telelaunch-updating-firmware.adoc[]
+
+       include::telelaunch-cables.adoc[]
+
+       include::telelaunch-troubleshooting.adoc[]
+
index 35aec6cc9fd0a3d99d1bb840392eecadbfb9892e..3247db9553e214dd3d00c15966433380ba29788f 100644 (file)
@@ -18,7 +18,7 @@
        bay for TeleMetrum should have at least 10 inches of interior length.
 
        There are two generations of the TeleMetrum design. The
-       major changes in the v2 generation are:
+       major changes after v1 generation are:
 
        * uBlox GPS chip certified for altitude records
 
index ae9c7f9f191d8cfe02e095b24cd24017d602fbd1..b7a0ce4890f71e061cf24f749128fe1bfcc024d9 100644 (file)
@@ -1,8 +1,8 @@
 = AltOS Telemetry
 Keith Packard <keithp@keithp.com>; Bdale Garbee <bdale@gag.com>
-:revnumber: v1.8.7
-:revdate: 8 Oct 2018
-:copyright: Bdale Garbee and Keith Packard 2018
+:revnumber: v1.9.1
+:revdate: 5 Dec 2019
+:copyright: Bdale Garbee and Keith Packard 2019
 :stylesheet: am.css
 :linkcss:
 :doctype: article
@@ -173,7 +173,7 @@ Keith Packard <keithp@keithp.com>; Bdale Garbee <bdale@gag.com>
                |32
                |====
 
-       === TeleMetrum v2 Sensor Data
+       === TeleMetrum v2 and newer Sensor Data
 
                .TeleMetrum v2 Packet Type
                [options="border",cols="1,3"]
@@ -183,17 +183,17 @@ Keith Packard <keithp@keithp.com>; Bdale Garbee <bdale@gag.com>
                |0x0B   |TeleMetrum v2 Calibration Data
                |====
 
-               TeleMetrum v2 has higher resolution barometric data than
+               TeleMetrum v2 and newer have higher resolution barometric data than
                TeleMetrum v1, and so the constant calibration data is
                split out into a separate packet.
 
-               TeleMetrum v2 Sensor Data packets are transmitted once per second on the
+               TeleMetrum v2 and newer Sensor Data packets are transmitted once per second on the
                ground, 10 times per second during ascent and once per second
                during descent and landing
 
-               TeleMetrum v2 Calibration Data packets are always transmitted once per second.
+               TeleMetrum v2 and newer Calibration Data packets are always transmitted once per second.
 
-               .TeleMetrum v2 Sensor Packet Contents
+               .TeleMetrum v2 and newer Sensor Packet Contents
                [options="border",cols="2,3,3,9"]
                |====
                |Offset |Data Type      |Name           |Description
@@ -211,7 +211,7 @@ Keith Packard <keithp@keithp.com>; Bdale Garbee <bdale@gag.com>
                |32
                |====
 
-               .TeleMetrum v2 Calibration Data Packet Contents
+               .TeleMetrum v2 and newer Calibration Data Packet Contents
                [options="border",cols="2,3,3,9"]
                |====
                |Offset |Data Type      |Name           |Description
@@ -461,19 +461,19 @@ Keith Packard <keithp@keithp.com>; Bdale Garbee <bdale@gag.com>
 
        |CC1111
        |10mW transceiver with integrated SoC
-       |TeleDongle v0.2, TeleBT v1.0, TeleMetrum v1.x, TeleMini
+       |TeleDongle v0.2, TeleBT v1.0, TeleMetrum v1.x, TeleMini v1
 
        |CC1120
        |35mW transceiver with SW FEC
-       |TeleMetrum v2, TeleMega
+       |TeleMetrum v2, TeleMega v1
 
        |CC1200
        |35mW transceiver with HW FEC
-       |TeleDongle v3.0, TeleBT v3.0
+       |TeleMetrum v3, TeleMega v2, TeleDongle v3.0, TeleMini v3, TeleBT v3.0, TeleGPS v2
 
        |CC115L
        |14mW transmitter with SW FEC
-       |TeleGPS
+       |TeleGPS v1
 
        |====
 
index ee2f5e9a340b8fb83ed5876bd4141eb19470fdb3..b1047ffa645db07bb20ce7536905f82d6207b6b4 100644 (file)
@@ -2,7 +2,7 @@
 == Updating Device Firmware
 
        ifdef::telemega[]
-       TeleMega, TeleMetrum v2, EasyMega, EasyMini and TeleDongle v3
+       TeleMega, TeleMetrum v2 and newer, EasyMega, EasyMini and TeleDongle v3
        are all
        endif::telemega[]
        ifndef::telemega[]
@@ -28,7 +28,7 @@
 
        ifdef::telemega[]
 
-       === Updating TeleMega, TeleMetrum v2, EasyMega, EasyMini or TeleDongle v3 Firmware
+       === Updating TeleMega, TeleMetrum v2 or newer, EasyMega, EasyMini, TeleDongle v3 or TeleBT v3 Firmware
 
        endif::telemega[]
        ifndef::telemega[]
                        endif::easymega[]
 
                        ifdef::telemetrum[]
-                       TeleMetrum v2::
+                       TeleMetrum v2 and newer::
 
                        Connect pin 6 and pin 1 of the companion
                        connector. Pin 1 can be identified by the square pad
                        the one on the other end of the row.
                        endif::easymini[]
 
+                       TeleGPS v1::
+
+                       Connect pin 32 on the CPU to ground.  Pin 32 is the
+                       right-most pin on the bottom edge of the CPU when the
+                       board is oriented with the USB and battery connectors
+                       to the right.
+
+                       TeleGPS v2::
+
+                       Connect together pins 1 and 5 of the Debug connector.
+                       Pin 1 is the pin with the square pad around the hole.
+
                        ifdef::telemetrum[]
                        TeleDongle v3::
 
                        of the board. Ground is available on the capacitor
                        next to it, on the end towards the USB wires.
                        
+                       TeleBT v3::
+
+                       Connect pin 4 on the CPU to 3.3V, which can be done by
+                       connecting pin 1 to pin 4.  Pin 1 is the left pin on
+                       the lower edge of the chip when the unit is oriented
+                       such that the SMA is at the top.
+
                        TeleBT v4::
 
                        Connect pin 30 on the CPU to ground. Pin 30 is the 6th
index 3122511d01ff7b10c64eaac853fe475de346e9a9..381132b2faeb09d3bf2c3f5f67269969b366ff47 100644 (file)
@@ -7,3 +7,9 @@ application-vnd.altusmetrum.micropeak.svg
 *.icns
 *.build
 *.exe
+*led.png
+*on.png
+*off.png
+*led.svg
+*on.svg
+*off.svg
index 6efe3ecf4f688bfdf3d76de4586c5936a0dd78c6..9ce9cba8fb02ba23c6b2e8b0ea48802bb8563422 100644 (file)
@@ -183,3 +183,6 @@ $(EXE_FILES): windows-stub.o make-rc
 
 windows-stub.o: windows-stub.c
        $(MINGCC32) -c $(MINGFLAGS) windows-stub.c
+
+altosdroid.png: altosdroid.svg
+       rsvg-convert -a -b white -h 480 altosdroid.svg | pngtopnm | pnmpad -white -width 512 -height 512 | pnmtopng > $@
diff --git a/icon/altosdroid.png b/icon/altosdroid.png
new file mode 100644 (file)
index 0000000..11a41e7
Binary files /dev/null and b/icon/altosdroid.png differ
diff --git a/icon/altosdroid.svg b/icon/altosdroid.svg
new file mode 100644 (file)
index 0000000..65135e4
--- /dev/null
@@ -0,0 +1,250 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg2"
+   width="194.5914"
+   height="245.27174"
+   version="1.0"
+   sodipodi:version="0.32"
+   inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
+   sodipodi:docname="altosdroid.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   inkscape:export-filename="/home/keithp/src/cc1111/altus-logo/bottom.png"
+   inkscape:export-xdpi="119.89881"
+   inkscape:export-ydpi="119.89881">
+  <metadata
+     id="metadata14">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs12">
+    <linearGradient
+       id="linearGradient3165">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop3167" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop3169" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3177">
+      <stop
+         style="stop-color:#da7000;stop-opacity:1;"
+         offset="0"
+         id="stop3179" />
+      <stop
+         id="stop3447"
+         offset="0.24528302"
+         style="stop-color:#a63852;stop-opacity:1;" />
+      <stop
+         style="stop-color:#7200a4;stop-opacity:1;"
+         offset="1"
+         id="stop3181" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3169">
+      <stop
+         style="stop-color:#ff8a00;stop-opacity:1;"
+         offset="0"
+         id="stop3171" />
+      <stop
+         id="stop3445"
+         offset="0.71698111"
+         style="stop-color:#c24573;stop-opacity:0.98039216;" />
+      <stop
+         style="stop-color:#8500e7;stop-opacity:0.96078432;"
+         offset="1"
+         id="stop3173" />
+    </linearGradient>
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 121 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="191 : 121 : 1"
+       inkscape:persp3d-origin="95.5 : 80.666667 : 1"
+       id="perspective16" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3169"
+       id="radialGradient3175"
+       cx="951.68713"
+       cy="2305.2668"
+       fx="951.68713"
+       fy="2305.2668"
+       r="951.68701"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3165"
+       id="radialGradient3171"
+       cx="951.68713"
+       cy="1205.2668"
+       fx="951.68713"
+       fy="1205.2668"
+       r="951.68701"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3169"
+       id="radialGradient3020"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="2305.2668"
+       fx="951.68713"
+       fy="2305.2668"
+       r="951.68701" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3165"
+       id="radialGradient3022"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="1205.2668"
+       fx="951.68713"
+       fy="1205.2668"
+       r="951.68701" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3169"
+       id="radialGradient3024"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="2305.2668"
+       fx="951.68713"
+       fy="2305.2668"
+       r="951.68701" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3165"
+       id="radialGradient3026"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="1205.2668"
+       fx="951.68713"
+       fy="1205.2668"
+       r="951.68701" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3169"
+       id="radialGradient3028"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="2305.2668"
+       fx="951.68713"
+       fy="2305.2668"
+       r="951.68701" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3165"
+       id="radialGradient3030"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+       cx="951.68713"
+       cy="1205.2668"
+       fx="951.68713"
+       fy="1205.2668"
+       r="951.68701" />
+    <filter
+       id="filter3005"
+       inkscape:label="Drop Shadow"
+       style="color-interpolation-filters:sRGB">
+      <feFlood
+         id="feFlood3007"
+         flood-opacity="0.604"
+         flood-color="rgb(0,0,0)"
+         result="flood" />
+      <feComposite
+         id="feComposite3009"
+         in2="SourceGraphic"
+         in="flood"
+         operator="in"
+         result="composite1" />
+      <feGaussianBlur
+         id="feGaussianBlur3011"
+         stdDeviation="80"
+         result="blur" />
+      <feOffset
+         id="feOffset3013"
+         dx="100"
+         dy="100"
+         result="offset" />
+      <feComposite
+         id="feComposite3015"
+         in2="offset"
+         in="SourceGraphic"
+         operator="over"
+         result="composite2" />
+    </filter>
+  </defs>
+  <sodipodi:namedview
+     inkscape:cy="21.690273"
+     inkscape:cx="35.762591"
+     inkscape:zoom="1.629332"
+     inkscape:window-height="1177"
+     inkscape:window-width="1462"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     guidetolerance="10.0"
+     gridtolerance="10.0"
+     objecttolerance="10.0"
+     borderopacity="1.0"
+     bordercolor="#666666"
+     pagecolor="#ffffff"
+     id="base"
+     showgrid="false"
+     inkscape:window-x="266"
+     inkscape:window-y="43"
+     inkscape:current-layer="svg2"
+     inkscape:window-maximized="0"
+     fit-margin-top="2"
+     fit-margin-left="2"
+     fit-margin-right="2"
+     fit-margin-bottom="2" />
+  <g
+     transform="matrix(0.1,0,0,0.1,2.1269908,2.1683864)"
+     id="g3"
+     style="fill:url(#radialGradient3175);fill-opacity:1;stroke:url(#radialGradient3171);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none">
+    <g
+       transform="translate(20.61545,-27.69425)"
+       style="fill:url(#radialGradient3028);fill-opacity:1;fill-rule:evenodd;stroke:url(#radialGradient3030);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
+       id="g5">
+      <path
+         d="m 931.07168,1164.597 248.86992,-331.80265 416.1687,1338.32935 286.6484,267.1042 H 1362.3363 L 1092.0566,2176.0098 V 1142.9471 L 931.07168,1249.6289 770.08676,1142.9471 v 1033.0627 l -270.2797,262.2181 h -520.4224 l 286.6484,-267.1042 416.1687,-1338.32935 z"
+         id="path7"
+         style="fill:url(#radialGradient3020);fill-opacity:1;stroke:url(#radialGradient3022);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
+         inkscape:connector-curvature="0" />
+      <path
+         d="m 931.07168,27.69425 224.03682,720.46517 -63.341,76.00913 -160.69582,-337.84165 -160.69582,337.84165 -63.341,-76.00913 z"
+         id="path9"
+         style="fill:url(#radialGradient3024);fill-opacity:1;stroke:url(#radialGradient3026);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
+         inkscape:connector-curvature="0" />
+    </g>
+  </g>
+</svg>
index 20c3d47a316c92d4b3236f1d04c28612b53e68ca..6caf63cfd492c30a5e526e5904667d0929b5a8df 100644 (file)
@@ -11,5 +11,6 @@ libaltosJNI
 cjnitest
 cjnitest32
 cjnitest64
+btletest
 libaltos.swig
 swig_bindings/
index 69fe7a5716a96d002eb94cb4854dc7f0aeb6d4b2..eb5eb6774fc5e42fa8b14dc1b428e1dd7fd919c4 100644 (file)
@@ -1,6 +1,5 @@
-JAVAC=javac
 AM_CFLAGS=-DLINUX -DPOSIX_TTY -I$(JVM_INCLUDE) -I$(JVM_INCLUDE)/linux
-AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -source 6
+AM_JAVACFLAGS=$(JAVAC_VERSION_FLAGS) -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked
 
 altoslibdir=$(libdir)/altos
 
index 39f67536c2fb43bb0baa2eb30a192704f4642c24..bb20dd845886ec795c4234006890f2351748b41a 100644 (file)
@@ -1,5 +1,5 @@
 JAVAROOT=classes
-AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked -source 6
+AM_JAVACFLAGS=$(JAVAC_VERSION_FLAGS) -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked
 
 altoslibdir=$(libdir)/altos
 
@@ -42,12 +42,18 @@ classes/altosmapd:
 $(JAR): classaltosmapd.stamp Manifest.txt $(ALTOSLIB_CLASS)
        jar cfm $@ Manifest.txt \
                -C classes altosmapd
+if STRIP_NONDETERMINISM
+       $(STRIP_NONDETERMINISM) $@
+endif
 
 altosmapddir=$(datadir)/java
 
 $(FATJAR): classaltosmapd.stamp Manifest-fat.txt $(ALTOSLIB_CLASS)
        jar cfm $@ Manifest-fat.txt \
                -C classes altosmapd
+if STRIP_NONDETERMINISM
+       $(STRIP_NONDETERMINISM) $@
+endif
 
 altos-mapd: Makefile
        echo "#!/bin/sh" > $@
index f447adb629d52d24836ff4704942e464702a2ebb..a8dfffecc55a37a924ec469fe2ebe21e7a1893ae 100644 (file)
@@ -1,5 +1,5 @@
 JAVAROOT=classes
-AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked -source 6
+AM_JAVACFLAGS=$(JAVAC_VERSION_FLAGS) -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked
 
 altoslibdir=$(libdir)/altos
 
@@ -31,12 +31,18 @@ classes/altosmap:
 $(JAR): classaltosmap.stamp Manifest.txt $(ALTOSLIB_CLASS)
        jar cfm $@ Manifest.txt \
                -C classes altosmap
+if STRIP_NONDETERMINISM
+       $(STRIP_NONDETERMINISM) $@
+endif
 
 altosmapdir=$(datadir)/java
 
 $(FATJAR): classaltosmap.stamp Manifest-fat.txt $(ALTOSLIB_CLASS)
        jar cfm $@ Manifest-fat.txt \
                -C classes altosmap
+if STRIP_NONDETERMINISM
+       $(STRIP_NONDETERMINISM) $@
+endif
 
 altos-mapj: Makefile
        echo "#!/bin/sh" > $@
index f01c5c9f6d276f16d5a174945c95b1d39d065799..23ec077ec4cda796c35f9b4d4970c2ec93621465 100644 (file)
@@ -1,5 +1,5 @@
 JAVAROOT=classes
-AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked -source 6
+AM_JAVACFLAGS=$(JAVAC_VERSION_FLAGS) -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked
 
 man_MANS=micropeak.1
 
@@ -222,12 +222,18 @@ $(JAR): classmicropeak.stamp Manifest.txt $(JAVA_ICONS) $(ALTOSLIB_CLASS) $(ALTO
                $(ICONJAR) \
                -C classes org \
                -C ../libaltos libaltosJNI
+if STRIP_NONDETERMINISM
+       $(STRIP_NONDETERMINISM) $@
+endif
 
 $(FATJAR): classmicropeak.stamp Manifest-fat.txt $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(JAVA_ICONS)
        jar cfm $@ Manifest-fat.txt \
                $(ICONJAR) \
                -C classes org \
                -C ../libaltos libaltosJNI
+if STRIP_NONDETERMINISM
+       $(STRIP_NONDETERMINISM) $@
+endif
 
 classaltosui.stamp: $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS)
 
index b87e88465a3b5f137fcad54f76daa49219e20daf..b5639f7329aef479774b4f7dea4e2051e6c66c55 100644 (file)
@@ -7,3 +7,5 @@ HAVE_NEWLIB_NANO=@HAVE_NEWLIB_NANO@
 AVR_CC=@AVR_CC@
 AVR_OBJCOPY=@AVR_OBJCOPY@
 HAVE_AVR_CC=@HAVE_AVR_CC@
+
+VERSION=@VERSION@
index 757641f7ec32c609321930e3ba520d4e32f4c713..f0c9cbb5631ffe0f1a32d46276b5a4548e4afed4 100644 (file)
@@ -12,8 +12,8 @@ vpath kalman_micro.5c kalman
 vpath load_csv.5c kalman
 vpath matrix.5c kalman
 
-include Version
 TOPDIR=.
+
 include Makedefs
 
 ARMM3DIRS=\
@@ -37,8 +37,10 @@ ARMM3DIRS=\
        telebt-v3.0 telebt-v3.0/flash-loader \
        telebt-v4.0 telebt-v4.0/flash-loader \
        telelcotwo-v0.1 telelcotwo-v0.1/flash-loader \
+       telefireone-v1.0 telefireone-v1.0/flash-loader \
        telefiretwo-v0.1 telefiretwo-v0.1/flash-loader \
-       telefireeight-v1.0 telefireeight-v1.0/flash-loader 
+       telefireeight-v1.0 telefireeight-v1.0/flash-loader \
+       telefireeight-v2.0 telefireeight-v2.0/flash-loader 
 
 ARMM0DIRS=\
        easymini-v1.0 easymini-v1.0/flash-loader \
@@ -48,7 +50,7 @@ ARMM0DIRS=\
        micropeak-v2.0 micropeak-v2.0/flash-loader
 
 AVRDIRS=\
-       micropeak microkite
+       micropeak microkite microsplash
 
 SUBDIRS=
 
diff --git a/src/Makefile.defs b/src/Makefile.defs
new file mode 100644 (file)
index 0000000..d52cc70
--- /dev/null
@@ -0,0 +1,58 @@
+include $(TOPDIR)/Makedefs
+
+AO_VPATH=$(TOPDIR)/product:$(TOPDIR)/drivers:$(TOPDIR)/kernel:$(TOPDIR)/util:$(TOPDIR)/kalman:$(TOPDIR)/aes:$(TOPDIR)/math:$(TOPDIR)/draw:$(TOPDIR)
+vpath make-altitude $(TOPDIR)/util
+vpath make-kalman $(TOPDIR)/util
+vpath kalman.5c $(TOPDIR)/kalman
+vpath kalman_filter.5c $(TOPDIR)/kalman
+vpath load_csv.5c $(TOPDIR)/kalman
+vpath matrix.5c $(TOPDIR)/kalman
+vpath ao-make-product.5c $(TOPDIR)/util
+
+WARN_FLAGS=-Wall -Wextra -Werror -Wcast-align \
+       -Wpointer-arith \
+       -Wstrict-prototypes \
+       -Wmissing-prototypes \
+       -Wmissing-declarations \
+       -Wnested-externs \
+       -Wshadow \
+       -Warray-bounds=2
+
+OPT=-Os
+
+NEWLIB_PRINTF_CFLAGS =         -DNEWLIB_INTEGER_PRINTF_SCANF
+
+NEWLIB_CFLAGS= \
+       -ffreestanding -nostdlib \
+       -isystem $(NEWLIB_NANO)/arm-none-eabi/include \
+       $(NEWLIB_PRINTF_CFLAGS)
+
+AO_CFLAGS=\
+       -std=gnu99 \
+       -I. -I$(TOPDIR) -I$(TOPDIR)/kernel -I$(TOPDIR)/drivers \
+       -I$(TOPDIR)/math -I$(TOPDIR)/draw -I$(TOPDIR)/product $(WARN_FLAGS) $(OPT) -g
+
+NICKLE=nickle
+ELFTOHEX=$(TOPDIR)/../ao-tools/ao-elftohex/ao-elftohex
+
+.SUFFIXES: .elf .ihx
+
+.elf.ihx:
+       $(ELFTOHEX) --output=$@ $*.elf
+
+V=0
+# The user has explicitly enabled quiet compilation.
+ifeq ($(V),0)
+quiet = @printf "  $1 $2 $@\n"; $($1)
+endif
+# Otherwise, print the full command line.
+quiet ?= $($1)
+
+.c.o:
+       $(call quiet,CC) -c $(CFLAGS) -o $@ $<
+
+.DEFAULT_GOAL=all
+
+ao_product.h: ao-make-product.5c $(TOPDIR)/Makedefs
+       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
diff --git a/src/Version.in b/src/Version.in
deleted file mode 100644 (file)
index aff9490..0000000
+++ /dev/null
@@ -1 +0,0 @@
-VERSION=@VERSION@
diff --git a/src/attiny/Makefile-attiny.defs b/src/attiny/Makefile-attiny.defs
new file mode 100644 (file)
index 0000000..8949ba4
--- /dev/null
@@ -0,0 +1,12 @@
+include $(TOPDIR)/avr/Makefile-avr.defs
+
+vpath % $(TOPDIR)/attiny:$(AO_VPATH)
+
+MCU=attiny85
+DUDECPUTYPE=t85
+#PROGRAMMER=stk500v2 -P usb
+LOADSLOW=-i 32 -B 32
+LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w:
+
+ATTINY_CFLAGS = -mmcu=$(MCU) -mcall-prologues -DATTINY \
+       -I$(TOPDIR)/attiny $(AO_CFLAGS)
\ No newline at end of file
diff --git a/src/attiny/Makefile.defs b/src/attiny/Makefile.defs
new file mode 100644 (file)
index 0000000..a3a6d8a
--- /dev/null
@@ -0,0 +1 @@
+include $(TOPDIR)/attiny/Makefile-attiny.defs
index dfd41afe2ec90dba9d5decdc51f7f340101fc714..5550eb447e101f3fa724120bf634053ca1b28540 100644 (file)
 
 #define AO_LED_TYPE    uint8_t
 
+#ifndef AO_TICK_TYPE
+#define AO_TICK_TYPE   uint16_t
+#define AO_TICK_SIGNED int16_t
+#endif
+
 /* Various definitions to make GCC look more like SDCC */
 
 #define ao_arch_naked_declare  __attribute__((naked))
index d722d568d75da0e23e759b26231d3c185822bde9..2ac0500b217f307466fd8be143eae566969eac89 100644 (file)
@@ -28,7 +28,7 @@ ISR(TIMER1_COMPA_vect)
                ao_wakeup((void *) &ao_tick_count);
 }
 
-uint16_t
+AO_TICK_TYPE
 ao_time(void)
 {
        uint16_t        r;
index 8ae1c4a09542baad4e5fd7a77938d62ca95445bd..c5b7eb2b078380b531b200058e7dc3a0470a781d 100644 (file)
@@ -31,6 +31,7 @@ ISR(PCINT0_vect)
 void
 ao_exti_setup_port(uint8_t pin, uint8_t mode, void (*callback)(void))
 {
+       (void) mode;
        pcint_callback = callback;
        pcint_mask = (1 << pin);
        ao_exti_disable(PORTB, pin);
index 0aca6f8af6252447d07224cd660646fbfd432650..2f3a0750a1e7ff178aff7de93dedf5c506fd8563 100644 (file)
@@ -47,7 +47,7 @@ MCU=atmega32u4
 PRODUCT_DEF=-DAVR_DEMO
 IDPRODUCT=0x000a
 CFLAGS = $(PRODUCT_DEF) -I. -I../avr -I../kernel -I..
-CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -Os -mcall-prologues
+CFLAGS += -mmcu=$(MCU) -Wall -Wstrict-prototypes -mcall-prologues
 
 NICKLE=nickle
 
diff --git a/src/avr/Makefile-avr.defs b/src/avr/Makefile-avr.defs
new file mode 100644 (file)
index 0000000..48aff48
--- /dev/null
@@ -0,0 +1,12 @@
+ifndef TOPDIR
+TOPDIR=..
+endif
+
+include $(TOPDIR)/Makefile.defs
+
+CC=$(AVR_CC)
+OBJCOPY=$(AVR_OBJCOPY)
+LDSCRIPTS=/usr/lib/avr/lib/ldscripts
+
+PROGRAMMER=usbtiny
+LOADCMD=avrdude
index eeb9a8810eddf1550a3b955bc5349db10cec82dd..48aff48e60b6b2934d6d686f9ff0885c59582846 100644 (file)
@@ -2,11 +2,7 @@ ifndef TOPDIR
 TOPDIR=..
 endif
 
-ifndef VERSION
-include $(TOPDIR)/Version
-endif
-
-include $(TOPDIR)/Makedefs
+include $(TOPDIR)/Makefile.defs
 
 CC=$(AVR_CC)
 OBJCOPY=$(AVR_OBJCOPY)
index 6166c50e67f489fddae53c10b1182349adad1e71..d3454f917fc6f75aa32d5879d2d3d9a4cf821198 100644 (file)
@@ -78,27 +78,25 @@ extern uint8_t      ao_cpu_sleep_disable;
 
 #define ao_arch_task_globals   uint8_t ao_cpu_sleep_disable;
 
-#define ao_arch_task_members\
-       uint8_t *sp;                    /* saved stack pointer */
-
-#define ao_arch_init_stack(task, start) do {                   \
-       uint8_t         *sp = task->stack + AO_STACK_SIZE - 1;  \
-       uint16_t        a = (uint16_t) start;                   \
-       int             i;                                      \
-                                                               \
-       /* Return address */                                    \
-       AVR_PUSH8(sp, a);                                       \
-       AVR_PUSH8(sp, (a >> 8));                                \
-                                                               \
-       /* Clear register values */                             \
-       i = 32;                                                 \
-       while (i--)                                             \
-               AVR_PUSH8(sp, 0);                               \
-                                                               \
-       /* SREG with interrupts enabled */                      \
-       AVR_PUSH8(sp, 0x80);                                    \
-       task->sp = sp;                                          \
-} while (0);
+#define ao_arch_init_stack(task, start) \
+       do {                                                            \
+               uint8_t         *sp = task->stack8 + AO_STACK_SIZE - 1; \
+               uint16_t        a = (uint16_t) start;                   \
+               int             i;                                      \
+                                                                       \
+               /* Return address */                                    \
+               AVR_PUSH8(sp, a);                                       \
+               AVR_PUSH8(sp, (a >> 8));                                \
+                                                                       \
+               /* Clear register values */                             \
+               i = 32;                                                 \
+               while (i--)                                             \
+                       AVR_PUSH8(sp, 0);                               \
+                                                                       \
+               /* SREG with interrupts enabled */                      \
+               AVR_PUSH8(sp, 0x80);                                    \
+               task->sp8 = sp;                                         \
+       } while (0);
        
 #define ao_arch_save_regs() do {                                       \
                asm("push r31" "\n\t" "push r30");                      \
@@ -115,7 +113,7 @@ extern uint8_t      ao_cpu_sleep_disable;
                uint8_t sp_l, sp_h;                                     \
                asm("in %0,__SP_L__" : "=&r" (sp_l) );                  \
                asm("in %0,__SP_H__" : "=&r" (sp_h) );                  \
-               ao_cur_task->sp = (uint8_t *) ((uint16_t) sp_l | ((uint16_t) sp_h << 8)); \
+               ao_cur_task->sp8 = (uint8_t *) ((uint16_t) sp_l | ((uint16_t) sp_h << 8)); \
        } while (0)
 
 #define ao_arch_isr_stack()    /* nothing */
@@ -140,8 +138,8 @@ extern uint8_t      ao_cpu_sleep_disable;
 
 #define ao_arch_restore_stack() do { \
                uint8_t sp_l, sp_h;                                     \
-               sp_l = (uint16_t) ao_cur_task->sp                     \
-               sp_h = ((uint16_t) ao_cur_task->sp) >> 8;               \
+               sp_l = (uint16_t) ao_cur_task->sp8;                     \
+               sp_h = ((uint16_t) ao_cur_task->sp8) >> 8;              \
                asm("out __SP_H__,%0" : : "r" (sp_h) );                 \
                asm("out __SP_L__,%0" : : "r" (sp_l) );                 \
                asm("pop r0"    "\n\t"                                  \
index faa4a291b0d7e6c81df64bfd89f173f6a9ddb49e..43f8bf9ab8096140005716114dccc1f5094c929d 100644 (file)
@@ -43,7 +43,7 @@ PRODUCT_DEF=-DCHAOSKEY_V_0_1
 IDVENDOR=0x1d50
 IDPRODUCT=0x60c6
 
-CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -g -Os
+CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS)
 
 PROGNAME=chaoskey-v0.1
 PROG=$(PROGNAME)-$(VERSION).elf
index 329f603d1107a58cc83b5d8d0767735a25a30c47..2d92d4f042631cce5f40471e7e1f0688fcf6f0eb 100644 (file)
@@ -48,7 +48,7 @@ PRODUCT_DEF=-DCHAOSKEY_V_1_0
 IDVENDOR=0x1d50
 IDPRODUCT=0x60c6
 
-CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -g -Os
+CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS)
 
 PROGNAME=chaoskey-v1.0
 PROG=$(PROGNAME)-$(VERSION).elf
@@ -62,10 +62,7 @@ OBJ=$(SRC:.c=.o)
 all: $(PROG) $(HEX) $(BIN)
 
 $(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 $@
+       $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS)
 
 $(OBJ): $(INC)
 
index 80f5a4ba613152fff72d8f3c36891dc5c76b5d75..4488208d57e5f706192d20c1f89f36f282cb4491 100644 (file)
@@ -22,7 +22,8 @@
 #include <ao_trng_send.h>
 #include <ao_flash_readout.h>
 
-void main(void)
+int
+main(void)
 {
        ao_led_init();
        ao_clock_init();
index 12c658dc22be0ba2980b79a99232ab770e68316a..63619b7a9e55532b5e22cdf19ff8ec11117da255 100644 (file)
@@ -95,7 +95,7 @@ LDFLAGS=-L../stm -L/local/newlib-mini/arm-none-eabi/lib/thumb/v7-m/ -Wl,-Tcortex
 AO_CFLAGS=-I. -I../stm -I../kernel -I../drivers -I../draw -I../scheme -I.. -I/local/newlib-mini/arm-none-eabi/include
 LIBS=-lc -lm -lgcc
 
-CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF)
 
 
 SRC=$(ALTOS_SRC) ao_cortexelf.c
index 7681a0495411a3ca868908de08c9c492177e859d..e527fa0936677e1439ef528966a3287e7b99998a 100644 (file)
@@ -52,7 +52,7 @@ PRODUCT=Detherm-v1.0
 PRODUCT_DEF=-DDETHERM_V_1_0
 IDPRODUCT=0x0013
 
-CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -g -Os
+CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS)
 
 PROGNAME=detherm-v1.0
 PROG=$(PROGNAME)-$(VERSION).elf
index c73f54df8edaa15c7febe6e1eab4a1df4b244d42..2139dadc0e1e22e950e578022c27b0e07feb0da0 100644 (file)
@@ -169,7 +169,7 @@ ao_storage_device_write(uint32_t pos, void *buf, uint16_t len)
                        ao_ee_flush_internal();
                        ao_ee_block = block;
                }
-               ao_xmemcpy(ao_ee_data + (uint16_t) (pos & 0xff), buf, len);
+               memcpy(ao_ee_data + (uint16_t) (pos & 0xff), buf, len);
                ao_ee_block_dirty = 1;
        } ao_mutex_put(&ao_ee_mutex);
        return 1;
@@ -183,7 +183,7 @@ ao_storage_device_read(uint32_t pos, void *buf, uint16_t len)
        /* Transfer the data */
        ao_mutex_get(&ao_ee_mutex); {
                ao_ee_fill(block);
-               ao_xmemcpy(buf, ao_ee_data + (uint16_t) (pos & 0xff), len);
+               memcpy(buf, ao_ee_data + (uint16_t) (pos & 0xff), len);
        } ao_mutex_put(&ao_ee_mutex);
        return 1;
 }
@@ -202,7 +202,7 @@ ao_storage_erase(uint32_t pos)
        ao_mutex_get(&ao_ee_mutex); {
                ao_ee_flush_internal();
                ao_ee_block = (uint16_t) (pos >> EE_BLOCK_SHIFT);
-               ao_xmemset(ao_ee_data, 0xff, EE_BLOCK_SIZE);
+               memset(ao_ee_data, 0xff, EE_BLOCK_SIZE);
                ao_ee_block_dirty = 1;
        } ao_mutex_put(&ao_ee_mutex);
        return 1;
diff --git a/src/drivers/ao_ads124s0x.c b/src/drivers/ao_ads124s0x.c
new file mode 100644 (file)
index 0000000..fa63ec0
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * Copyright © 2019 Bdale Garbee <bdale@gag.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <ao.h>
+#include <ao_exti.h>
+#include "ao_ads124s0x.h"
+
+#define DEBUG_LOW      1
+#define DEBUG_HIGH     2
+
+#define DEBUG          0
+
+#if DEBUG
+#define PRINTD(l, ...) do { if (DEBUG & (l)) { printf ("\r%5u %s: ", ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } } while(0)
+#else
+#define PRINTD(l,...)
+#endif
+
+struct ao_ads124s0x_sample     ao_ads124s0x_current;
+uint8_t                nextchan = 0;
+uint8_t                ao_ads124s0x_drdy;
+
+static void
+ao_ads124s0x_start(void) {
+       ao_spi_get_bit(AO_ADS124S0X_SPI_CS_PORT,
+                      AO_ADS124S0X_SPI_CS_PIN,
+                      AO_ADS124S0X_SPI_BUS,
+                      AO_ADS124S0X_SPI_SPEED);
+}
+
+static void
+ao_ads124s0x_stop(void) {
+       ao_spi_put_bit(AO_ADS124S0X_SPI_CS_PORT,
+                      AO_ADS124S0X_SPI_CS_PIN,
+                      AO_ADS124S0X_SPI_BUS);
+}
+
+static uint8_t
+ao_ads124s0x_reg_read(uint8_t addr)
+{
+       uint8_t d[3];
+
+       d[0] = addr | AO_ADS124S0X_RREG;
+       d[1] = 0;                       
+       d[2] = 0;                       
+       ao_ads124s0x_start();
+       ao_spi_duplex(d, d, 3, AO_ADS124S0X_SPI_BUS);
+       ao_ads124s0x_stop();
+
+       PRINTD(DEBUG_LOW, "read %x = %x\n", addr, d[0]);
+
+       return d[2];
+}
+
+/*
+static void
+ao_ads124s0x_reg_write(uint8_t addr, uint8_t value)
+{
+       uint8_t d[3];
+
+       PRINTD(DEBUG_LOW, "write %x %x\n", addr, value);
+       d[0] = addr | AO_ADS124S0X_WREG;
+       d[1] = 0;                       
+       d[2] = value;
+       ao_ads124s0x_start();
+       ao_spi_send(d, 3, AO_ADS124S0X_SPI_BUS);
+       ao_ads124s0x_stop();
+
+}
+*/
+
+static void 
+ao_ads124s0x_isr(void)
+{
+       ao_ads124s0x_drdy = 1;
+       ao_wakeup(&ao_ads124s0x_drdy);
+}
+
+static void
+ao_ads124s0x_setup(void)
+{
+       uint8_t d[20];
+
+       ao_delay(1);
+
+       ao_gpio_set(AO_ADS124S0X_RESET_PORT, AO_ADS124S0X_RESET_PIN, 1);
+
+       ao_delay(1);
+
+       uint8_t devid = ao_ads124s0x_reg_read(AO_ADS124S0X_ID);
+       if ((devid & 7) != AO_ADS124S0X_ID_ADS124S06)
+               ao_panic(AO_PANIC_SELF_TEST_ADS124S0X);
+
+       ao_exti_setup(AO_ADS124S0X_DRDY_PORT, AO_ADS124S0X_DRDY_PIN,
+               AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
+               ao_ads124s0x_isr);
+
+       /* run converter at 4ksps so we can scan 4 channels at 1ksps using
+          full duplex ala datasheet section 9.5.4.3 */
+
+       d[0] = AO_ADS124S0X_INPMUX | AO_ADS124S0X_WREG;
+       d[1] = 8;       /* write 8 registers starting with INPMUX */
+       d[2] = 0x0c;    /* input mux AIN0 relative to AINCOM */
+       d[3] = 0x00;    /* default first conversion delay, pga disabled */
+       d[4] = 0x1e;    /* gchop disabled, internal clock, continuous 
+                          conversion, low-latency filter, 4000 SPS */
+       d[5] = 0x00;    /* ref monitor disabled, ref buffers bypassed, ref 
+                          set to REFP0/REFN0, internal reference off */
+       d[6] = 0x00;    /* pga otuput rail, low side power switch, excitation
+                          current source all off */
+       d[7] = 0xff;    /* idac1 and idac2 disconnected */
+       d[8] = 0x00;    /* all vbias disconnected */
+       d[9] = 0x10;    /* sys monitor off, spi timeout disabled, crc disabled,
+                          prepending status byte disabled */
+       ao_ads124s0x_start();
+       ao_spi_send(d, 10, AO_ADS124S0X_SPI_BUS);
+       ao_ads124s0x_stop();
+
+       /* start conversions */
+       
+       d[0] = AO_ADS124S0X_START;
+       ao_ads124s0x_start();
+       ao_spi_send(d, 1, AO_ADS124S0X_SPI_BUS);
+       ao_ads124s0x_stop();
+}
+
+static void
+ao_ads124s0x(void)
+{
+       uint8_t d[3], curchan;
+
+       ao_ads124s0x_setup();
+
+       ao_exti_enable(AO_ADS124S0X_DRDY_PORT, AO_ADS124S0X_DRDY_PIN);
+
+       for (;;) {
+               ao_arch_block_interrupts();
+               ao_ads124s0x_drdy = 0;
+               while (ao_ads124s0x_drdy == 0)
+                       ao_sleep(&ao_ads124s0x_drdy);
+               ao_arch_release_interrupts();
+
+               curchan = nextchan;
+               nextchan = (nextchan + 1) % AO_ADS124S0X_CHANNELS;
+
+               d[0] = AO_ADS124S0X_INPMUX | AO_ADS124S0X_WREG;
+               d[1] = 1;                       
+               d[2] = nextchan << 4 | 0x0c; ;  /* relative to AINCOM */
+               ao_ads124s0x_start();
+               ao_spi_duplex(d, d, 3, AO_ADS124S0X_SPI_BUS);
+               ao_ads124s0x_stop();
+
+               ao_ads124s0x_current.ain[curchan] = 
+                       d[0] << 16 | d[1] << 8 | d[2];
+
+               // FIXME
+               //      If nextchan == 0, we have a complete set of inputs
+               //      and we need to log them somewhere
+
+               ao_ads124s0x_drdy = 0;
+       }
+}
+
+static struct ao_task ao_ads124s0x_task;
+
+static void
+ao_ads124s0x_dump(void)        
+{
+       static int done;
+
+       if (!done) {
+               done = 1;
+               ao_add_task(&ao_ads124s0x_task, ao_ads124s0x, "ads124s0x");
+       }
+               
+       printf ("ADS124S0X value %d %d %d %d\n",
+               ao_ads124s0x_current.ain[0],
+               ao_ads124s0x_current.ain[1],
+               ao_ads124s0x_current.ain[2],
+               ao_ads124s0x_current.ain[3]);
+}
+
+const struct ao_cmds ao_ads124s0x_cmds[] = {
+       { ao_ads124s0x_dump,    "I\0Display ADS124S0X data" },
+       { 0, NULL },
+};
+
+void
+ao_ads124s0x_init(void)
+{
+       ao_cmd_register(ao_ads124s0x_cmds);
+
+       ao_enable_output(AO_ADS124S0X_RESET_PORT, AO_ADS124S0X_RESET_PIN, 0);
+
+       ao_spi_init_cs(AO_ADS124S0X_SPI_CS_PORT, 
+               (1 << AO_ADS124S0X_SPI_CS_PIN));
+
+//     ao_add_task(&ao_ads124s0x_task, ao_ads124s0x, "ads124s0x");
+}
diff --git a/src/drivers/ao_ads124s0x.h b/src/drivers/ao_ads124s0x.h
new file mode 100644 (file)
index 0000000..c881ca5
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright © 2019 Bdale Garbee <bdale@gag.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef _AO_ADS124S0X_H_
+#define _AO_ADS124S0X_H_
+
+/* control commands */
+#define AO_ADS124S0X_NOP               0x00
+#define AO_ADS124S0X_WAKEUP            0x02
+#define AO_ADS124S0X_POWERDOWN         0x04
+#define AO_ADS124S0X_RESET             0x06
+#define AO_ADS124S0X_START             0x08
+#define AO_ADS124S0X_STOP              0x0a
+
+/* calibration commands */
+#define AO_ADS124S0X_SYOCAL            0x16
+#define AO_ADS124S0X_SYGCAL            0x17
+#define AO_ADS124S0X_SFOCAL            0x19
+
+/* data read command */
+#define AO_ADS124S0X_RDATA             0x12
+
+/* register read and write commands */
+#define AO_ADS124S0X_RREG              0x20
+#define AO_ADS124S0X_WREG              0x40
+
+/* configuration register map */
+#define AO_ADS124S0X_ID                        0x00
+#define AO_ADS124S0X_ID_ADS124S08              0x00
+#define AO_ADS124S0X_ID_ADS124S06              0x01
+#define AO_ADS124S0X_STATUS            0x01
+#define AO_ADS124S0X_INPMUX            0x02
+#define AO_ADS124S0X_PGA               0x03
+#define AO_ADS124S0X_DATARATE          0x04
+#define AO_ADS124S0X_REF               0x05
+#define AO_ADS124S0X_IDACMAG           0x06
+#define AO_ADS124S0X_IDACMUX           0x07
+#define AO_ADS124S0X_VBIAS             0x08
+#define AO_ADS124S0X_SYS               0x09
+#define AO_ADS124S0X_OFCAL0            0x0a
+#define AO_ADS124S0X_OFCAL1            0x0b
+#define AO_ADS124S0X_OFCAL2            0x0c
+#define AO_ADS124S0X_FSCAL0            0x0d
+#define AO_ADS124S0X_FSCAL1            0x0e
+#define AO_ADS124S0X_FSCAL2            0x0f
+#define AO_ADS124S0X_GPIODAT           0x10
+#define AO_ADS124S0X_GPIOCON           0x11
+
+struct ao_ads124s0x_sample {
+       int32_t ain[AO_ADS124S0X_CHANNELS];
+};
+
+extern struct ao_ads124s0x_sample      ao_ads124s0x_current;
+
+void
+ao_ads124s0x_init(void);
+
+#endif /* _AO_ADS124S0X_H_ */
diff --git a/src/drivers/ao_ads131a0x.h b/src/drivers/ao_ads131a0x.h
new file mode 100644 (file)
index 0000000..7ceb935
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright © 2019 Bdale Garbee <bdale@gag.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef _AO_ADS131A0X_H_
+#define _AO_ADS131A0X_H_
+
+/* control commands */
+#define AO_ADS131A0X_NOP               0x00
+#define AO_ADS131A0X_WAKEUP            0x02
+#define AO_ADS131A0X_POWERDOWN         0x04
+#define AO_ADS131A0X_RESET             0x06
+#define AO_ADS131A0X_START             0x08
+#define AO_ADS131A0X_STOP              0x0a
+
+/* calibration commands */
+#define AO_ADS131A0X_SYOCAL            0x16
+#define AO_ADS131A0X_SYGCAL            0x17
+#define AO_ADS131A0X_SFOCAL            0x19
+
+/* data read command */
+#define AO_ADS131A0X_RDATA             0x12
+
+/* register read and write commands */
+#define AO_ADS131A0X_RREG              0x20
+#define AO_ADS131A0X_WREG              0x40
+
+/* configuration register map */
+#define AO_ADS131A0X_ID                        0x00
+#define AO_ADS131A0X_ID_ADS131A08              0x00
+#define AO_ADS131A0X_ID_ADS131A06              0x01
+#define AO_ADS131A0X_STATUS            0x01
+#define AO_ADS131A0X_INPMUX            0x02
+#define AO_ADS131A0X_PGA               0x03
+#define AO_ADS131A0X_DATARATE          0x04
+#define AO_ADS131A0X_REF               0x05
+#define AO_ADS131A0X_IDACMAG           0x06
+#define AO_ADS131A0X_IDACMUX           0x07
+#define AO_ADS131A0X_VBIAS             0x08
+#define AO_ADS131A0X_SYS               0x09
+#define AO_ADS131A0X_OFCAL0            0x0a
+#define AO_ADS131A0X_OFCAL1            0x0b
+#define AO_ADS131A0X_OFCAL2            0x0c
+#define AO_ADS131A0X_FSCAL0            0x0d
+#define AO_ADS131A0X_FSCAL1            0x0e
+#define AO_ADS131A0X_FSCAL2            0x0f
+#define AO_ADS131A0X_GPIODAT           0x10
+#define AO_ADS131A0X_GPIOCON           0x11
+
+struct ao_ads131a0x_sample {
+       int32_t ain[AO_ADS131A0X_CHANNELS];
+};
+
+extern struct ao_ads131a0x_sample      ao_ads131a0x_current;
+
+void
+ao_ads131a0x_init(void);
+
+#endif /* _AO_ADS131A0X_H_ */
index 66d39ff915b625c6f87acac828594ff1f8a6ad4b..4f6b816948709632e5462e1d8d0460a0f3911b49 100644 (file)
@@ -143,7 +143,7 @@ ao_adxl375_setup(void)
 
        uint8_t devid = ao_adxl375_reg_read(AO_ADXL375_DEVID);
        if (devid != AO_ADXL375_DEVID_ID)
-               ao_sensor_errors = 1;
+               AO_SENSOR_ERROR(AO_DATA_ADXL375);
 
        /* Set the data rate */
        ao_adxl375_reg_write(AO_ADXL375_BW_RATE,
@@ -204,12 +204,12 @@ ao_adxl375_setup(void)
        self_test_value = z_change;
 
        if (z_change < MIN_SELF_TEST)
-               ao_sensor_errors = 1;
+               AO_SENSOR_ERROR(AO_DATA_ADXL375);
 
        /* This check is commented out as maximum self test is unreliable
 
           if (z_change > MAX_SELF_TEST)
-               ao_sensor_errors = 1;
+               AO_SENSOR_ERROR(AO_DATA_ADXL375);
 
        */
 
index 2f17d04401eade3379e538874870991c3ba1bd04..bc5c29dfc85634d9f5a4905ead05b55308583293 100644 (file)
@@ -527,7 +527,7 @@ static int tncComment(uint8_t *buf)
        int16_t apogee = ao_ignite_decivolt(AO_SENSE_DROGUE(&packet));
 #endif
 #ifdef AO_SENSE_MAIN
-       int16_t main = ao_ignite_decivolt(AO_SENSE_MAIN(&packet));
+       int16_t main_value = ao_ignite_decivolt(AO_SENSE_MAIN(&packet));
 #endif
 
        return sprintf((char *) buf,
@@ -548,8 +548,8 @@ static int tncComment(uint8_t *buf)
                       apogee%10
 #endif
 #ifdef AO_SENSE_MAIN
-                      , main/10,
-                      main%10
+                      , main_value/10,
+                      main_value%10
 #endif
                       , ao_serial_number
                );
index 516811b86b1eb7925c896c71890b8216a64e3776..e04baaf63a9fc3c919c7042ac44ca0c8f7fefa63 100644 (file)
@@ -246,7 +246,7 @@ ao_storage_device_write(uint32_t pos, void *buf, uint16_t len)
                        ao_flash_flush_internal();
                        ao_flash_block = block;
                }
-               ao_xmemcpy(ao_flash_data + (uint16_t) (pos & ao_flash_block_mask),
+               memcpy(ao_flash_data + (uint16_t) (pos & ao_flash_block_mask),
                       buf,
                       len);
                ao_flash_block_dirty = 1;
@@ -262,7 +262,7 @@ ao_storage_device_read(uint32_t pos, void *buf, uint16_t len)
        /* Transfer the data */
        ao_mutex_get(&ao_flash_mutex); {
                ao_flash_fill(block);
-               ao_xmemcpy(buf,
+               memcpy(buf,
                       ao_flash_data + (uint16_t) (pos & ao_flash_block_mask),
                       len);
        } ao_mutex_put(&ao_flash_mutex);
@@ -283,7 +283,7 @@ ao_storage_erase(uint32_t pos)
        ao_mutex_get(&ao_flash_mutex); {
                ao_flash_flush_internal();
                ao_flash_block = (uint16_t) (pos >> ao_flash_block_shift);
-               ao_xmemset(ao_flash_data, 0xff, ao_flash_block_size);
+               memset(ao_flash_data, 0xff, ao_flash_block_size);
                ao_flash_block_dirty = 1;
        } ao_mutex_put(&ao_flash_mutex);
        return 1;
diff --git a/src/drivers/ao_bmx160.c b/src/drivers/ao_bmx160.c
new file mode 100644 (file)
index 0000000..e1af23a
--- /dev/null
@@ -0,0 +1,424 @@
+/*
+ * Copyright © 2019 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_bmx160.h>
+#include <ao_exti.h>
+
+static uint8_t ao_bmx160_configured;
+
+#define ao_bmx160_spi_get()    ao_spi_get(AO_BMX160_SPI_BUS, AO_SPI_SPEED_8MHz)
+#define ao_bmx160_spi_put()    ao_spi_put(AO_BMX160_SPI_BUS)
+
+#define ao_bmx160_spi_start()  ao_spi_set_cs(AO_BMX160_SPI_CS_PORT,    \
+                                             (1 << AO_BMX160_SPI_CS_PIN))
+
+#define ao_bmx160_spi_end()    ao_spi_clr_cs(AO_BMX160_SPI_CS_PORT,    \
+                                             (1 << AO_BMX160_SPI_CS_PIN))
+
+static void
+_ao_bmx160_reg_write(uint8_t addr, uint8_t value)
+{
+       uint8_t d[2] = { addr, value };
+       ao_bmx160_spi_start();
+       ao_spi_send(d, 2, AO_BMX160_SPI_BUS);
+       ao_bmx160_spi_end();
+}
+
+static void
+_ao_bmx160_read(uint8_t addr, void *data, uint8_t len)
+{
+       addr |= 0x80;
+       ao_bmx160_spi_start();
+       ao_spi_send(&addr, 1, AO_BMX160_SPI_BUS);
+       ao_spi_recv(data, len, AO_BMX160_SPI_BUS);
+       ao_bmx160_spi_end();
+}
+
+static uint8_t
+_ao_bmx160_reg_read(uint8_t addr)
+{
+       uint8_t value;
+       addr |= 0x80;
+       ao_bmx160_spi_start();
+       ao_spi_send(&addr, 1, AO_BMX160_SPI_BUS);
+       ao_spi_recv(&value, 1, AO_BMX160_SPI_BUS);
+       ao_bmx160_spi_end();
+       return value;
+}
+
+static void
+_ao_bmx160_cmd(uint8_t cmd)
+{
+       _ao_bmx160_reg_write(BMX160_CMD, cmd);
+       ao_delay(AO_MS_TO_TICKS(100));
+}
+
+static void
+_ao_bmx160_mag_setup(void)
+{
+       _ao_bmx160_reg_write(BMX160_MAG_IF_0, 0x80);
+}
+
+static void
+_ao_bmm150_wait_manual(void)
+{
+       while (_ao_bmx160_reg_read(BMX160_STATUS) & (1 << BMX160_STATUS_MAG_MAN_OP))
+               ;
+}
+
+static void
+_ao_bmm150_reg_write(uint8_t addr, uint8_t data)
+{
+       _ao_bmx160_reg_write(BMX160_MAG_IF_3, data);
+       _ao_bmx160_reg_write(BMX160_MAG_IF_2, addr);
+       _ao_bmm150_wait_manual();
+}
+
+#if BMX160_TEST
+static uint8_t
+_ao_bmm150_reg_read(uint8_t addr)
+{
+       _ao_bmx160_reg_write(BMX160_MAG_IF_1, addr);
+       _ao_bmm150_wait_manual();
+       return _ao_bmx160_reg_read(BMX160_DATA_0);
+}
+#endif
+
+static void
+_ao_bmx160_sample(struct ao_bmx160_sample *sample)
+{
+       _ao_bmx160_read(BMX160_MAG_X_0_7, sample, sizeof (*sample));
+#if __BYTE_ORDER != __LITTLE_ENDIAN
+       int             i = sizeof (*sample) / 2;
+       uint16_t        *d = (uint16_t *) sample;
+
+       /* byte swap */
+       while (i--) {
+               uint16_t        t = *d;
+               *d++ = (t >> 8) | (t << 8);
+       }
+#endif
+}
+
+#define G      981     /* in cm/s² */
+
+#if 0
+static int16_t /* cm/s² */
+ao_bmx160_accel(int16_t v)
+{
+       return (int16_t) ((v * (int32_t) (16.0 * 980.665 + 0.5)) / 32767);
+}
+
+static int16_t /* deg*10/s */
+ao_bmx160_gyro(int16_t v)
+{
+       return (int16_t) ((v * (int32_t) 20000) / 32767);
+}
+
+static uint8_t
+ao_bmx160_accel_check(int16_t normal, int16_t test)
+{
+       int16_t diff = test - normal;
+
+       if (diff < BMX160_ST_ACCEL(16) / 4) {
+               return 1;
+       }
+       if (diff > BMX160_ST_ACCEL(16) * 4) {
+               return 1;
+       }
+       return 0;
+}
+
+static uint8_t
+ao_bmx160_gyro_check(int16_t normal, int16_t test)
+{
+       int16_t diff = test - normal;
+
+       if (diff < 0)
+               diff = -diff;
+       if (diff < BMX160_ST_GYRO(2000) / 4) {
+               return 1;
+       }
+       if (diff > BMX160_ST_GYRO(2000) * 4) {
+               return 1;
+       }
+       return 0;
+}
+#endif
+
+static void
+_ao_bmx160_wait_alive(void)
+{
+       uint8_t i;
+
+       /* Wait for the chip to wake up */
+       for (i = 0; i < 30; i++) {
+               ao_delay(AO_MS_TO_TICKS(100));
+               if (_ao_bmx160_reg_read(BMX160_CHIPID) == BMX160_CHIPID_BMX160)
+                       break;
+       }
+       if (i == 30)
+               ao_panic(AO_PANIC_SELF_TEST_BMX160);
+}
+
+#define ST_TRIES       10
+#define MAG_TRIES      10
+
+static void
+_ao_bmx160_setup(void)
+{
+       if (ao_bmx160_configured)
+               return;
+
+       /* Make sure the chip is responding */
+       _ao_bmx160_wait_alive();
+
+       /* Reboot */
+       _ao_bmx160_cmd(BMX160_CMD_SOFTRESET);
+
+       /* Force SPI mode */
+       _ao_bmx160_reg_write(BMX160_NV_CONF, 1 << BMX160_NV_CONF_SPI_EN);
+
+       /* Configure accelerometer:
+        *
+        *      undersampling disabled
+        *      normal filter
+        *      200Hz sampling rate
+        *      16g range
+        *
+        * This yields a 3dB cutoff frequency of 80Hz
+        */
+       _ao_bmx160_reg_write(BMX160_ACC_CONF,
+                            (0 << BMX160_ACC_CONF_ACC_US) |
+                            (BMX160_ACC_CONF_ACC_BWP_NORMAL << BMX160_ACC_CONF_ACC_BWP) |
+                            (BMX160_ACC_CONF_ACC_ODR_200 << BMX160_ACC_CONF_ACC_ODR));
+       _ao_bmx160_reg_write(BMX160_ACC_RANGE,
+                            BMX160_ACC_RANGE_16G);
+
+       /* Configure gyro:
+        *
+        *      200Hz sampling rate
+        *      Normal filter mode
+        *      ±2000°/s
+        */
+       _ao_bmx160_reg_write(BMX160_GYR_CONF,
+                            (BMX160_GYR_CONF_GYR_BWP_NORMAL << BMX160_GYR_CONF_GYR_BWP) |
+                            (BMX160_GYR_CONF_GYR_ODR_200 << BMX160_GYR_CONF_GYR_ODR));
+       _ao_bmx160_reg_write(BMX160_GYR_RANGE,
+                            BMX160_GYR_RANGE_2000);
+
+
+       /* Configure magnetometer:
+        *
+        *      30Hz sampling rate
+        *      power on
+        *      axes enabled
+        */
+       _ao_bmx160_cmd(BMX160_CMD_MAG_IF_SET_PMU_MODE(BMX160_PMU_STATUS_MAG_IF_PMU_STATUS_NORMAL));
+
+       /* Enter setup mode */
+       _ao_bmx160_mag_setup();
+
+       /* Place in suspend mode to reboot the chip */
+       _ao_bmm150_reg_write(BMM150_POWER_MODE,
+                            (0 << BMM150_POWER_MODE_POWER_CONTROL));
+
+       /* Power on */
+       _ao_bmm150_reg_write(BMM150_POWER_MODE,
+                            (1 << BMM150_POWER_MODE_POWER_CONTROL));
+
+       /* Set data rate and place in sleep mode */
+       _ao_bmm150_reg_write(BMM150_CONTROL,
+                            (BMM150_CONTROL_DATA_RATE_30 << BMM150_CONTROL_DATA_RATE) |
+                            (BMM150_CONTROL_OP_MODE_SLEEP << BMM150_CONTROL_OP_MODE));
+
+       /* enable all axes (should already be enabled) */
+       _ao_bmm150_reg_write(BMM150_INT_CONF,
+                            (0 << BMM150_INT_CONF_X_DISABLE) |
+                            (0 << BMM150_INT_CONF_Y_DISABLE) |
+                            (0 << BMM150_INT_CONF_Z_DISABLE));
+
+       /* Set repetition values (?) */
+       _ao_bmm150_reg_write(BMM150_REPXY, BMM150_REPXY_VALUE(9));
+       _ao_bmm150_reg_write(BMM150_REPZ, BMM150_REPZ_VALUE(15));
+
+       /* To get data out of the magnetometer, set the control op mode to 'forced', then read
+        * from the data registers
+        */
+       _ao_bmx160_reg_write(BMX160_MAG_IF_3, (BMM150_CONTROL_OP_MODE_FORCED << BMM150_CONTROL_OP_MODE));
+       _ao_bmx160_reg_write(BMX160_MAG_IF_2, BMM150_CONTROL);
+       _ao_bmx160_reg_write(BMX160_MAG_IF_1, BMM150_DATA_X_0_4);
+
+       /* Set data rate to 200Hz */
+       _ao_bmx160_reg_write(BMX160_MAG_CONF,
+                            (BMX160_MAG_CONF_MAG_ODR_200 << BMX160_MAG_CONF_MAG_ODR));
+
+       /* Put magnetometer interface back into 'normal mode'
+        */
+       _ao_bmx160_reg_write(BMX160_MAG_IF_0,
+                            (0 << BMX160_MAG_IF_0_MAG_MANUAL_EN) |
+                            (0 << BMX160_MAG_IF_0_MAG_OFFSET) |
+                            (0 << BMX160_MAG_IF_0_MAG_RD_BURST));
+
+       /* Enable acc and gyr
+        */
+
+       _ao_bmx160_cmd(BMX160_CMD_ACC_SET_PMU_MODE(BMX160_PMU_STATUS_ACC_PMU_STATUS_NORMAL));
+       _ao_bmx160_cmd(BMX160_CMD_GYR_SET_PMU_MODE(BMX160_PMU_STATUS_GYR_PMU_STATUS_NORMAL));
+       ao_bmx160_configured = 1;
+}
+
+struct ao_bmx160_sample        ao_bmx160_current;
+
+static void
+ao_bmx160(void)
+{
+       struct ao_bmx160_sample sample;
+
+       /* ao_bmx160_init already grabbed the SPI bus and mutex */
+       _ao_bmx160_setup();
+       ao_bmx160_spi_put();
+       for (;;)
+       {
+               ao_bmx160_spi_get();
+               _ao_bmx160_sample(&sample);
+               ao_bmx160_spi_put();
+               ao_arch_block_interrupts();
+               ao_bmx160_current = sample;
+               AO_DATA_PRESENT(AO_DATA_BMX160);
+               AO_DATA_WAIT();
+               ao_arch_release_interrupts();
+       }
+}
+
+static struct ao_task ao_bmx160_task;
+
+static void
+ao_bmx160_show(void)
+{
+       printf ("Accel: %7d %7d %7d Gyro: %7d %7d %7d Mag: %7d %7d %7d\n",
+               ao_bmx160_current.acc_x,
+               ao_bmx160_current.acc_y,
+               ao_bmx160_current.acc_z,
+               ao_bmx160_current.gyr_x,
+               ao_bmx160_current.gyr_y,
+               ao_bmx160_current.gyr_z,
+               ao_bmx160_current.mag_x,
+               ao_bmx160_current.mag_y,
+               ao_bmx160_current.mag_z);
+}
+
+#if BMX160_TEST
+
+static void
+ao_bmx160_read(void)
+{
+       uint8_t addr;
+       uint8_t val;
+
+       addr = ao_cmd_hex();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       ao_bmx160_spi_get();
+       val = _ao_bmx160_reg_read(addr);
+       ao_bmx160_spi_put();
+       printf("Addr %02x val %02x\n", addr, val);
+}
+
+static void
+ao_bmx160_write(void)
+{
+       uint8_t addr;
+       uint8_t val;
+
+       addr = ao_cmd_hex();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       val = ao_cmd_hex();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       printf("Addr %02x val %02x\n", addr, val);
+       ao_bmx160_spi_get();
+       _ao_bmx160_reg_write(addr, val);
+       ao_bmx160_spi_put();
+}
+
+static void
+ao_bmm150_read(void)
+{
+       uint8_t addr;
+       uint8_t val;
+
+       addr = ao_cmd_hex();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       ao_bmx160_spi_get();
+       val = _ao_bmm150_reg_read(addr);
+       ao_bmx160_spi_put();
+       printf("Addr %02x val %02x\n", addr, val);
+}
+
+static void
+ao_bmm150_write(void)
+{
+       uint8_t addr;
+       uint8_t val;
+
+       addr = ao_cmd_hex();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       val = ao_cmd_hex();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       printf("Addr %02x val %02x\n", addr, val);
+       ao_bmx160_spi_get();
+       _ao_bmm150_reg_write(addr, val);
+       ao_bmx160_spi_put();
+}
+
+#endif /* BMX160_TEST */
+
+static const struct ao_cmds ao_bmx160_cmds[] = {
+       { ao_bmx160_show,       "I\0Show BMX160 status" },
+#if BMX160_TEST
+       { ao_bmx160_read,       "R <addr>\0Read BMX160 register" },
+       { ao_bmx160_write,      "W <addr> <val>\0Write BMX160 register" },
+       { ao_bmm150_read,       "M <addr>\0Read BMM150 register" },
+       { ao_bmm150_write,      "N <addr> <val>\0Write BMM150 register" },
+#endif
+       { 0, NULL }
+};
+
+void
+ao_bmx160_init(void)
+{
+       ao_add_task(&ao_bmx160_task, ao_bmx160, "bmx160");
+
+       ao_spi_init_cs(AO_BMX160_SPI_CS_PORT, (1 << AO_BMX160_SPI_CS_PIN));
+
+       /* Pretend to be the bmx160 task. Grab the SPI bus right away and
+        * hold it for the task so that nothing else uses the SPI bus before
+        * we get the I2C mode disabled in the chip
+        */
+
+       ao_cur_task = &ao_bmx160_task;
+       ao_bmx160_spi_get();
+       ao_cur_task = NULL;
+       ao_cmd_register(&ao_bmx160_cmds[0]);
+}
diff --git a/src/drivers/ao_bmx160.h b/src/drivers/ao_bmx160.h
new file mode 100644 (file)
index 0000000..2b7e7bd
--- /dev/null
@@ -0,0 +1,269 @@
+/*
+ * Copyright © 2019 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_BMX160_H_
+#define _AO_BMX160_H_
+
+#include <math.h>
+
+struct ao_bmx160_sample {
+       int16_t         mag_x;
+       int16_t         mag_y;
+       int16_t         mag_z;
+       int16_t         rhall;
+       int16_t         gyr_x;
+       int16_t         gyr_y;
+       int16_t         gyr_z;
+       int16_t         acc_x;
+       int16_t         acc_y;
+       int16_t         acc_z;
+};
+
+extern struct ao_bmx160_sample ao_bmx160_current;
+
+struct ao_bmx160_offset {
+       int8_t          off_acc_x;
+       int8_t          off_acc_y;
+       int8_t          off_acc_z;
+       int8_t          off_gyr_x;
+       int8_t          off_gyr_y;
+       int8_t          off_gyr_z;
+       uint8_t         offset_6;
+};
+
+void
+ao_bmx160_init(void);
+
+#define BMX160_CHIPID                  0x00
+#define  BMX160_CHIPID_BMX160                  0xd8
+#define BMX160_ERR_REG                 0x02
+#define BMX160_PMU_STATUS              0x03
+#define  BMX160_PMU_STATUS_MAG_IF_PMU_STATUS   0
+#define   BMX160_PMU_STATUS_MAG_IF_PMU_STATUS_SUSPEND          0
+#define   BMX160_PMU_STATUS_MAG_IF_PMU_STATUS_NORMAL           1
+#define   BMX160_PMU_STATUS_MAG_IF_PMU_STATUS_LOW_POWER                2
+#define  BMX160_PMU_STATUS_GYR_PMU_STATUS      2
+#define   BMX160_PMU_STATUS_GYR_PMU_STATUS_SUSPEND             0
+#define   BMX160_PMU_STATUS_GYR_PMU_STATUS_NORMAL              1
+#define   BMX160_PMU_STATUS_GYR_PMU_STATUS_FAST_START_UP       3
+#define  BMX160_PMU_STATUS_ACC_PMU_STATUS      4
+#define   BMX160_PMU_STATUS_ACC_PMU_STATUS_SUSPEND             0
+#define   BMX160_PMU_STATUS_ACC_PMU_STATUS_NORMAL              1
+#define   BMX160_PMU_STATUS_ACC_PMU_STATUS_LOW_POWER           2
+#define BMX160_DATA_0                  0x04
+#define BMX160_MAG_X_0_7               0x04
+#define BMX160_MAG_X_8_15              0x05
+#define BMX160_MAG_Y_0_7               0x06
+#define BMX160_MAG_Y_8_15              0x07
+#define BMX160_MAG_Z_0_7               0x08
+#define BMX160_MAG_Z_8_15              0x09
+#define BMX160_RHALL_0_7               0x0A
+#define BMX160_RHALL_8_15              0x0B
+#define BMX160_GYRO_X_0_7              0x0C
+#define BMX160_GYRO_X_8_15             0x0D
+#define BMX160_GYRO_Y_0_7              0x0E
+#define BMX160_GYRO_Y_8_15             0x0F
+#define BMX160_GYRO_Z_0_7              0x10
+#define BMX160_GYRO_Z_8_15             0x11
+#define BMX160_ACCEL_X_0_7             0x12
+#define BMX160_ACCEL_X_8_15            0x13
+#define BMX160_ACCEL_Y_0_7             0x14
+#define BMX160_ACCEL_Y_8_15            0x15
+#define BMX160_ACCEL_Z_0_7             0x16
+#define BMX160_ACCEL_Z_8_15            0x17
+#define BMX160_SENSORTIME_0_7          0x18
+#define BMX160_SENSORTIME_8_15         0x19
+#define BMX160_SENSORTIME_16_23                0x1A
+#define BMX160_STATUS                  0x1B
+#define  BMX160_STATUS_GYR_SELF_TEST_OK                1
+#define  BMX160_STATUS_MAG_MAN_OP              2
+#define  BMX160_STATUS_FOC_RDY                 3
+#define  BMX160_STATUS_NVM_RDY                 4
+#define  BMX160_STATUS_DRDY_MAG                        5
+#define  BMX160_STATUS_DRDY_GYR                        6
+#define  BMX160_STATUS_DRDY_ACC                        7
+#define BMX160_INT_STATUS_0            0x1C-0x1F
+#define BMX160_INT_STATUS_1            0x1D
+#define BMX160_INT_STATUS_2            0x1E
+#define BMX160_INT_STATUS_3            0x1F
+#define BMX160_TEMPERATURE_0_7         0x20
+#define BMX160_TEMPERATURE_8_15                0x21
+#define BMX160_FIFO_LENGTH_0_7         0x22
+#define BMX160_FIFO_LENGTH_8_15                0x23
+#define BMX160_FIFO_DATA               0x24
+#define BMX160_ACC_CONF                        0x40
+#define  BMX160_ACC_CONF_ACC_ODR               0
+#define   BMX160_ACC_CONF_ACC_ODR_25_32                        0x1
+#define   BMX160_ACC_CONF_ACC_ODR_25_16                        0x2
+#define   BMX160_ACC_CONF_ACC_ODR_25_8                 0x3
+#define   BMX160_ACC_CONF_ACC_ODR_25_4                 0x4
+#define   BMX160_ACC_CONF_ACC_ODR_25_2                 0x5
+#define   BMX160_ACC_CONF_ACC_ODR_25                   0x6
+#define   BMX160_ACC_CONF_ACC_ODR_50                   0x7
+#define   BMX160_ACC_CONF_ACC_ODR_100                  0x8
+#define   BMX160_ACC_CONF_ACC_ODR_200                  0x9
+#define   BMX160_ACC_CONF_ACC_ODR_400                  0xa
+#define   BMX160_ACC_CONF_ACC_ODR_800                  0xb
+#define   BMX160_ACC_CONF_ACC_ODR_1600                 0xc
+#define  BMX160_ACC_CONF_ACC_BWP               4
+#define   BMX160_ACC_CONF_ACC_BWP_NORMAL                       0x2
+#define   BMX160_ACC_CONF_ACC_BWP_OSR2                         0x1
+#define   BMX160_ACC_CONF_ACC_BWP_OSR4                         0x0
+#define  BMX160_ACC_CONF_ACC_US                        7
+#define BMX160_ACC_RANGE               0x41
+#define  BMX160_ACC_RANGE_2G                   0x3
+#define  BMX160_ACC_RANGE_4G                   0x5
+#define  BMX160_ACC_RANGE_8G                   0x8
+#define  BMX160_ACC_RANGE_16G                  0xc
+#define  BMX160_ACC_RANGE_
+#define  BMX160_ACC_RANGE_
+#define BMX160_GYR_CONF                        0x42
+#define  BMX160_GYR_CONF_GYR_ODR               0
+#define   BMX160_GYR_CONF_GYR_ODR_25                   0x6
+#define   BMX160_GYR_CONF_GYR_ODR_50                   0x7
+#define   BMX160_GYR_CONF_GYR_ODR_100                  0x8
+#define   BMX160_GYR_CONF_GYR_ODR_200                  0x9
+#define   BMX160_GYR_CONF_GYR_ODR_400                  0xa
+#define   BMX160_GYR_CONF_GYR_ODR_800                  0xb
+#define   BMX160_GYR_CONF_GYR_ODR_1600                 0xc
+#define   BMX160_GYR_CONF_GYR_ODR_3200                 0xd
+#define  BMX160_GYR_CONF_GYR_BWP               4
+#define   BMX160_GYR_CONF_GYR_BWP_NORMAL                       0x2
+#define   BMX160_GYR_CONF_GYR_BWP_OSR2                         0x1
+#define   BMX160_GYR_CONF_GYR_BWP_OSR4                         0x0
+#define BMX160_GYR_RANGE               0x43
+#define  BMX160_GYR_RANGE_2000                                 0x0
+#define  BMX160_GYR_RANGE_1000                                 0x1
+#define  BMX160_GYR_RANGE_500                                  0x2
+#define  BMX160_GYR_RANGE_250                                  0x3
+#define  BMX160_GYR_RANGE_125                                  0x4
+#define BMX160_MAG_CONF                        0x44
+#define  BMX160_MAG_CONF_MAG_ODR                       0
+#define   BMX160_MAG_CONF_MAG_ODR_25_32                                0x1
+#define   BMX160_MAG_CONF_MAG_ODR_25_16                                0x2
+#define   BMX160_MAG_CONF_MAG_ODR_25_8                         0x3
+#define   BMX160_MAG_CONF_MAG_ODR_25_4                         0x4
+#define   BMX160_MAG_CONF_MAG_ODR_25_2                         0x5
+#define   BMX160_MAG_CONF_MAG_ODR_25                           0x6
+#define   BMX160_MAG_CONF_MAG_ODR_50                           0x7
+#define   BMX160_MAG_CONF_MAG_ODR_100                          0x8
+#define   BMX160_MAG_CONF_MAG_ODR_200                          0x9
+#define   BMX160_MAG_CONF_MAG_ODR_400                          0xa
+#define   BMX160_MAG_CONF_MAG_ODR_800                          0xb
+#define BMX160_FIFO_DOWNS              0x45
+#define BMX160_FIFO_CONFIG_0           0x46
+#define BMX160_FIFO_CONFIG_1           0x47
+#define BMX160_MAG_IF_0                        0x4C
+#define  BMX160_MAG_IF_0_MAG_RD_BURST          0
+#define  BMX160_MAG_IF_0_MAG_OFFSET            2
+#define  BMX160_MAG_IF_0_MAG_MANUAL_EN         7
+#define BMX160_MAG_IF_1                        0x4D
+#define BMX160_MAG_IF_2                        0x4E
+#define BMX160_MAG_IF_3                        0x4F
+#define BMX160_INT_EN                  0x50-0x52
+#define BMX160_INT_OUT_CTRL            0x53
+#define BMX160_INT_LATCH               0x54
+#define BMX160_INT_MAP                 0x55-0x57
+#define BMX160_INT_DATA                        0x58-0x59
+#define BMX160_INT_LOWHIGH             0x5A-0x5E
+#define BMX160_INT_MOTION              0x5F-0x62
+#define BMX160_INT_TAP                 0x63-0x64
+#define BMX160_INT_ORIENT              0x65-0x66
+#define BMX160_INT_FLAT                        0x67-0x68
+#define BMX160_FOC_CONF                        0x69
+#define BMX160_CONF                    0x6A
+#define BMX160_IF_CONF                 0x6B
+#define BMX160_PMU_TRIGGER             0x6C
+#define BMX160_SELF_TEST               0x6D
+#define BMX160_NV_CONF                 0x70
+#define  BMX160_NV_CONF_SPI_EN                 0
+#define  BMX160_NV_CONF_I2C_WDT_SEL            1
+#define  BMX160_NV_CONF_I2C_WDT_EN             2
+#define BMX160_OFFSET                  0x71-0x77
+#define BMX160_STEP_CNT                        0x78-0x79
+#define BMX160_STEP_CONF               0x7A-0x7B
+#define BMX160_CMD                     0x7E
+#define  BMX160_CMD_START_FOC                  0x03
+#define  BMX160_CMD_ACC_SET_PMU_MODE(n)                (0x10 | (n))
+#define  BMX160_CMD_GYR_SET_PMU_MODE(n)                (0x14 | (n))
+#define  BMX160_CMD_MAG_IF_SET_PMU_MODE(n)     (0x18 | (n))
+#define  BMX160_CMD_PROG_NVM                   0xa0
+#define  BMX160_CMD_FIFO_FLUSH                 0xb0
+#define  BMX160_CMD_INT_RESET                  0xb1
+#define  BMX160_CMD_SOFTRESET                  0xb6
+#define  BMX160_CMD_STEP_CNT_CLR               0xb2
+
+#define BMM150_CHIP_ID                         0x40
+#define BMM150_DATA_X_0_4                      0x42
+#define BMM150_DATA_X_5_12                     0x43
+#define BMM150_DATA_Y_0_4                      0x44
+#define BMM150_DATA_Y_5_12                     0x45
+#define BMM150_DATA_Z_0_6                      0x46
+#define BMM150_DATA_Z_7_14                     0x47
+#define BMM150_RHALL_0_5                       0x48
+#define BMM150_RHALL_6_13                      0x49
+#define BMM150_INT_STATUS                      0x4a
+#define BMM150_POWER_MODE                      0x4b
+#define  BMM150_POWER_MODE_SOFT_RESET_HI               7
+#define  BMM150_POWER_MODE_SPI3EN                      2
+#define  BMM150_POWER_MODE_SOFT_RESET_LO               1
+#define  BMM150_POWER_MODE_POWER_CONTROL               0
+#define BMM150_CONTROL                         0x4c
+#define  BMM150_CONTROL_ADV_ST_1                       7
+#define  BMM150_CONTROL_ADV_ST_0                       6
+#define  BMM150_CONTROL_DATA_RATE                      3
+#define   BMM150_CONTROL_DATA_RATE_10                          0
+#define   BMM150_CONTROL_DATA_RATE_2                           1
+#define   BMM150_CONTROL_DATA_RATE_6                           2
+#define   BMM150_CONTROL_DATA_RATE_8                           3
+#define   BMM150_CONTROL_DATA_RATE_15                          4
+#define   BMM150_CONTROL_DATA_RATE_20                          5
+#define   BMM150_CONTROL_DATA_RATE_25                          6
+#define   BMM150_CONTROL_DATA_RATE_30                          7
+#define  BMM150_CONTROL_OP_MODE                                1
+#define   BMM150_CONTROL_OP_MODE_NORMAL                                0
+#define   BMM150_CONTROL_OP_MODE_FORCED                                1
+#define   BMM150_CONTROL_OP_MODE_SLEEP                         3
+#define  BMM150_CONTROL_SELF_TEST                      0
+#define BMM150_INT_EN                          0x4d
+#define BMM150_INT_CONF                                0x4e
+#define  BMM150_INT_CONF_X_DISABLE                     3
+#define  BMM150_INT_CONF_Y_DISABLE                     4
+#define  BMM150_INT_CONF_Z_DISABLE                     5
+#define BMM150_LOW_THRESHOLD                   0x4f
+#define BMM150_HIGH_THRESHOLD                  0x50
+#define BMM150_REPXY                           0x51
+#define  BMM150_REPXY_VALUE(n)                         (((n)-1) >> 1)
+#define BMM150_REPZ                            0x52
+#define  BMM150_REPZ_VALUE(n)                          ((n) -1)
+
+#define BMX160_GYRO_FULLSCALE  ((float) 2000 * M_PI/180.0)
+
+static inline float
+ao_bmx160_gyro(float sensor) {
+       return sensor * ((float) (BMX160_GYRO_FULLSCALE / 32767.0));
+}
+
+#define BMX160_ACCEL_FULLSCALE 16
+
+static inline float
+ao_bmx160_accel(int16_t sensor) {
+       return (float) sensor * ((float) (BMX160_ACCEL_FULLSCALE * GRAVITY / 32767.0));
+}
+
+#endif /* _BMX160_H_ */
index 04bf413890e349014f0448b12bbedfef892d1841..71599fbd6665b11d7e1ec184b2f2477622a68a32 100644 (file)
@@ -187,7 +187,7 @@ ao_btm_getchar(void)
  * it after a few characters.
  */
 
-uint8_t
+static uint8_t
 ao_btm_get_line(void)
 {
        uint8_t ao_btm_reply_len = 0;
@@ -209,8 +209,8 @@ ao_btm_get_line(void)
 /*
  * Drain the serial port completely
  */
-void
-ao_btm_drain()
+static void
+ao_btm_drain(void)
 {
        while (ao_btm_get_line())
                ;
@@ -219,7 +219,7 @@ ao_btm_drain()
 /*
  * Set the stdio echo for the bluetooth link
  */
-void
+static void
 ao_btm_echo(uint8_t echo)
 {
        ao_stdios[ao_btm_stdio].echo = echo;
@@ -230,7 +230,7 @@ ao_btm_echo(uint8_t echo)
  * can't keep up with 57600 baud
  */
 
-void
+static void
 ao_btm_putchar(char c)
 {
        ao_btm_log_out_char(c);
@@ -242,7 +242,7 @@ ao_btm_putchar(char c)
  * Wait for the bluetooth device to return
  * status from the previously executed command
  */
-uint8_t
+static uint8_t
 ao_btm_wait_reply(void)
 {
        for (;;) {
@@ -256,7 +256,7 @@ ao_btm_wait_reply(void)
        }
 }
 
-void
+static void
 ao_btm_string(const char *cmd)
 {
        char    c;
@@ -265,7 +265,7 @@ ao_btm_string(const char *cmd)
                ao_btm_putchar(c);
 }
 
-uint8_t
+static uint8_t
 ao_btm_cmd(const char *cmd)
 {
        ao_btm_drain();
@@ -282,7 +282,7 @@ ao_btm_cmd(const char *cmd)
        return ao_btm_wait_reply();
 }
 
-uint8_t
+static uint8_t
 ao_btm_set_name(void)
 {
        char    sn[8];
@@ -301,7 +301,7 @@ ao_btm_set_name(void)
        return ao_btm_wait_reply();
 }
 
-uint8_t
+static uint8_t
 ao_btm_try_speed(uint8_t speed)
 {
        ao_serial_btm_set_speed(speed);
@@ -329,8 +329,8 @@ ao_btm_try_speed(uint8_t speed)
 #define BT_CC1111      1
 #endif
 
-void
-ao_btm_check_link()
+static void
+ao_btm_check_link(void)
 {
 #if BT_CC1111
        ao_arch_critical(
@@ -362,7 +362,7 @@ struct ao_task ao_btm_task;
  * A thread to initialize the bluetooth device and
  * hang around to blink the LED when connected
  */
-void
+static void
 ao_btm(void)
 {
 #ifdef AO_BTM_INT_PORT
index c8103e884d3cd47bfacb5909a0034acafa41a325..53728bceef47d99c26b54fe6ad58a637dc985c8c 100644 (file)
@@ -19,6 +19,7 @@
 #include <ao.h>
 #include <ao_button.h>
 #include <ao_exti.h>
+#include <ao_fast_timer.h>
 #if AO_EVENT
 #include <ao_event.h>
 #define ao_button_queue(b,v)   ao_event_put_isr(AO_EVENT_BUTTON, b, v)
@@ -149,12 +150,7 @@ ao_button_isr(void)
 }
 
 #define init(b) do {                                                   \
-               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_exti_enable(port(b), bit(b));                        \
+               ao_enable_input(port(b), bit(b), AO_BUTTON_MODE);       \
                _ao_button_init(b);                                     \
        } while (0)
 
@@ -212,4 +208,6 @@ ao_button_init(void)
 #if AO_BUTTON_COUNT > 16
        #error too many buttons
 #endif
+       ao_fast_timer_init();
+       ao_fast_timer_on(ao_button_isr);
 }
index a8f2c4f5102e2acf0bc7ca8d269d5de243508613..2b5fd3fd9313ffaf636b78649752ed74a42a05f3 100644 (file)
@@ -596,7 +596,7 @@ uint8_t ao_radio_tone_count;
 uint8_t ao_radio_tone_current;
 uint8_t ao_radio_tone_offset;
 
-int16_t
+static int16_t
 ao_radio_tone_fill(uint8_t *buf, int16_t len)
 {
        int16_t ret = 0;
index 44868fb646e48faa232ff9192c162c6d3deb06ce..d6fbb6b7480de528c322eac0f778a671b9d44d85 100644 (file)
@@ -93,7 +93,7 @@ ao_companion_notify(void)
        COMPANION_DESELECT();
 }
 
-void
+static void
 ao_companion(void)
 {
        uint8_t i;
@@ -113,7 +113,7 @@ ao_companion(void)
        ao_exit();
 }
 
-void
+static void
 ao_companion_status(void) 
 {
        uint8_t i;
index 193f20dc4eb4a6af61651534d1816857a7e8355c..3b4a62ec1a521507da3f2b95e72fd4c8033599ae 100644 (file)
@@ -88,7 +88,7 @@ ao_gps_lexchar(void)
        ao_gps_char = c;
 }
 
-void
+static void
 ao_gps_skip_field(void)
 {
        for (;;) {
@@ -99,7 +99,7 @@ ao_gps_skip_field(void)
        }
 }
 
-void
+static void
 ao_gps_skip_sep(void)
 {
        char c = ao_gps_char;
@@ -298,7 +298,7 @@ ao_nmea_gga(void)
                ao_mutex_get(&ao_gps_mutex);
                ao_gps_new |= AO_GPS_NEW_DATA;
                ao_gps_tick = ao_gps_next_tick;
-               ao_xmemcpy(&ao_gps_data, &ao_gps_next, sizeof (ao_gps_data));
+               memcpy(&ao_gps_data, &ao_gps_next, sizeof (ao_gps_data));
                ao_mutex_put(&ao_gps_mutex);
                ao_wakeup(&ao_gps_new);
        }
@@ -357,7 +357,7 @@ ao_nmea_gsv(void)
        else if (done) {
                ao_mutex_get(&ao_gps_mutex);
                ao_gps_new |= AO_GPS_NEW_TRACKING;
-               ao_xmemcpy(&ao_gps_tracking_data, &ao_gps_tracking_next, sizeof(ao_gps_tracking_data));
+               memcpy(&ao_gps_tracking_data, &ao_gps_tracking_next, sizeof(ao_gps_tracking_data));
                ao_mutex_put(&ao_gps_mutex);
                ao_wakeup(&ao_gps_new);
        }
index f470570829e82eebd6ae34a978acf9eee3a8a683..55a193ac5adb58236acb51be0e3a3f9eb78fe5e5 100644 (file)
@@ -66,7 +66,7 @@ ao_hmc5883_isr(void)
 
 static uint32_t        ao_hmc5883_missed_irq;
 
-void
+static void
 ao_hmc5883_sample(struct ao_hmc5883_sample *sample)
 {
        uint16_t        *d = (uint16_t *) sample;
index 5f5db572c31eb29aa1596d00f34f502e5c8039fd..b314ef7c0273acf55f8ab277ed927bc05917c363 100644 (file)
@@ -269,7 +269,7 @@ ao_lco_input(void)
  * visually inspect the system for correct operation
  */
 static void
-ao_lco_display_test()
+ao_lco_display_test(void)
 {
        ao_mutex_get(&ao_lco_display_mutex);
        ao_seven_segment_set(AO_LCO_PAD_DIGIT, 8 | 0x10);
@@ -316,7 +316,7 @@ ao_lco_main(void)
 }
 
 #if DEBUG
-void
+static void
 ao_lco_set_debug(void)
 {
        uint16_t r  = ao_cmd_decimal();
index 49ea123678714f65d46841cc581bcdfb96817867..cfef2a631c488a12e86d130d2680dd3444593447 100644 (file)
@@ -121,7 +121,7 @@ ao_lco_main(void)
 }
 
 #if DEBUG
-void
+static void
 ao_lco_set_debug(void)
 {
        uint16_t r = ao_cmd_decimal();
index 0f7b7c27c7776332ea90f8a6455d4f90d9f058d0..899bee74915e0be87330b4892bb62cd15a5dfc31 100644 (file)
@@ -19,7 +19,7 @@
 #include "ao.h"
 
 static const struct {
-       struct stm_gpio *port;
+       void            *port;
        uint16_t        pin;
 } ao_leds[] = {
 #ifdef LED_0_PORT
diff --git a/src/drivers/ao_max6691.c b/src/drivers/ao_max6691.c
new file mode 100644 (file)
index 0000000..5aeca50
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+ * Copyright © 2019 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.
+ */
+
+#include "ao.h"
+#include "ao_max6691.h"
+#include "ao_exti.h"
+
+#define cat2(a,b)      a ## b
+#define cat(a,b)       cat2(a,b)
+
+#if AO_MAX6691_CH != 2
+#error ao_max6691 driver currently only works for timer channel 2
+#endif
+
+#define AO_MAX6691_CCR         (AO_MAX6691_TIMER->cat(ccr, AO_MAX6691_CH))
+
+/* Two samples per channel, plus time start value and two for Tready pulse */
+
+#define AO_MAX6691_SAMPLES     (AO_MAX6691_CHANNELS * 2 + 3)
+
+static uint16_t        ao_max6691_raw[AO_MAX6691_SAMPLES];
+
+static inline uint16_t
+ao_max6691_t_high(int channel)
+{
+       return ao_max6691_raw[channel * 2 + 3] - ao_max6691_raw[channel * 2 + 2];
+}
+
+static inline uint16_t
+ao_max6691_t_low(int channel)
+{
+       return ao_max6691_raw[channel * 2 + 4] - ao_max6691_raw[channel * 2 + 3];
+}
+
+struct ao_max6691_sample ao_max6691_current;
+
+static void
+ao_max6691_sample(void)
+{
+       struct stm_tim234       *tim = AO_MAX6691_TIMER;
+
+       tim->sr = 0;
+
+       memset(&ao_max6691_raw, '\0', sizeof (ao_max6691_raw));
+       /* Get the DMA engine ready */
+       ao_dma_set_transfer(AO_MAX6691_DMA,
+                           &AO_MAX6691_CCR,
+                           &ao_max6691_raw,
+                           AO_MAX6691_SAMPLES,
+                           (0 << STM_DMA_CCR_MEM2MEM) |
+                           (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+                           (STM_DMA_CCR_MSIZE_16 << STM_DMA_CCR_MSIZE) |
+                           (STM_DMA_CCR_PSIZE_16 << 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));
+       ao_dma_start(AO_MAX6691_DMA);
+
+       /* Prod the max6691 */
+       ao_set_output(AO_MAX6691_GPIO, AO_MAX6691_PIN, 0);
+       int i;
+       for (i = 0; i < 100; i++)
+               ao_arch_nop();
+       ao_set_input(AO_MAX6691_GPIO, AO_MAX6691_PIN);
+       for (i = 0; i < 100; i++)
+               ao_arch_nop();
+
+       /* Reset the timer count */
+       tim->cnt = 0;
+
+       /* Switch the pin to timer input mode */
+       stm_afr_set(AO_MAX6691_GPIO, AO_MAX6691_PIN, STM_AFR_AF1);
+
+       tim->ccer = ((0 << STM_TIM234_CCER_CC1E) |
+                    (0 << STM_TIM234_CCER_CC1P) |
+                    (0 << STM_TIM234_CCER_CC1NP) |
+                    (1 << STM_TIM234_CCER_CC2E) |
+                    (1 << STM_TIM234_CCER_CC2P) |
+                    (1 << STM_TIM234_CCER_CC2NP) |
+                    (0 << STM_TIM234_CCER_CC3E) |
+                    (0 << STM_TIM234_CCER_CC3P) |
+                    (0 << STM_TIM234_CCER_CC3NP) |
+                    (0 << STM_TIM234_CCER_CC4E) |
+                    (0 << STM_TIM234_CCER_CC4P) |
+                    (0 << STM_TIM234_CCER_CC4NP));
+
+       /* Enable event generation on channel 2 */
+
+       tim->egr = ((0 << STM_TIM234_EGR_TG) |
+                   (0 << STM_TIM234_EGR_CC4G) |
+                   (0 << STM_TIM234_EGR_CC3G) |
+                   (1 << STM_TIM234_EGR_CC2G) |
+                   (0 << STM_TIM234_EGR_CC1G) |
+                   (0 << STM_TIM234_EGR_UG));
+       /* Start the timer */
+       tim->cr1 |= (1 << STM_TIM234_CR1_CEN);
+
+       ao_arch_block_interrupts();
+       while (!ao_dma_done[AO_MAX6691_DMA])
+               ao_sleep(&ao_dma_done[AO_MAX6691_DMA]);
+       ao_arch_release_interrupts();
+
+       /* Disable event generation */
+       tim->egr = 0;
+
+       /* Disable capture */
+       tim->ccer = 0;
+
+       /* Stop the timer */
+       tim->cr1 &= ~(1 << STM_TIM234_CR1_CEN);
+
+       /* Switch back to GPIO mode */
+       stm_moder_set(AO_MAX6691_GPIO, AO_MAX6691_PIN, STM_MODER_INPUT);
+
+       /* Mark DMA done */
+       ao_dma_done_transfer(AO_MAX6691_DMA);
+
+       for (i = 0; i < AO_MAX6691_CHANNELS; i++) {
+               ao_max6691_current.sensor[i].t_high = ao_max6691_t_high(i);
+               ao_max6691_current.sensor[i].t_low = ao_max6691_t_low(i);
+       }
+}
+
+static void
+ao_max6691(void)
+{
+       for (;;) {
+               ao_max6691_sample();
+               ao_arch_critical(AO_DATA_PRESENT(AO_DATA_MAX6691););
+       }
+}
+
+static struct ao_task ao_max6691_task;
+
+#define R_EXT  1000.0f
+
+static void
+ao_max6691_dump(void)
+{
+       struct ao_max6691_sample ao_max6691;
+
+       ao_max6691 = ao_max6691_current;
+
+       int i;
+       for (i = 0; i < AO_MAX6691_CHANNELS; i++) {
+               uint16_t        t_high = ao_max6691.sensor[i].t_high;
+               uint16_t        t_low = ao_max6691.sensor[i].t_low;
+
+               /*
+                * From the MAX6691 data sheet
+                *
+                *      Thigh   Vext               Rext
+                *      ----- = ---- - 0.0002 = ---------- - 0.0002
+                *      Tlow    Vref            Rext - Rth
+                *
+                *      We want to find Rth given Rext and the timing values
+                *
+                *      Thigh              Rext
+                *      ----- + 0.0002 = ----------
+                *      Tlow             Rext + Rth
+                *
+                *      V = (Thigh / Tlow + 0.0002)
+                *
+                *      (Rext + Rth) * V = Rext
+                *
+                *      Rext * V + Rth * V = Rext
+                *
+                *      Rth * V = Rext - Rext * V
+                *
+                *      Rth * V = Rext * (1 - V)
+                *
+                *      Rth = Rext * (1 - V) / V
+                */
+
+               float V = (float) t_high / (float) t_low + 0.0002f;
+
+               float Rth = R_EXT * (1 - V) / V;
+
+               printf("max6691 channel %d: high %5u low %5u ohms: %7g\n", i, t_high, t_low, Rth);
+       }
+}
+
+static const struct ao_cmds ao_max6691_cmds[] = {
+       { ao_max6691_dump,      "q\0Thermistor test" },
+       { 0, NULL },
+};
+
+
+void
+ao_max6691_init(void)
+{
+       ao_cmd_register(&ao_max6691_cmds[0]);
+
+       struct stm_tim234       *tim = AO_MAX6691_TIMER;
+
+       stm_rcc.apb1enr |= (1 << AO_MAX6691_TIMER_ENABLE);
+
+       tim->cr1 = 0;
+       tim->psc = (AO_TIM23467_CLK / 4000000) - 1;     /* run the timer at 4MHz */
+       tim->cnt = 0;
+
+       /*
+        * XXX This assumes we're using CH2, which is true on TeleFireOne v2.0
+        */
+       tim->ccmr1 = ((STM_TIM234_CCMR1_IC2F_NONE << STM_TIM234_CCMR1_IC2F) |
+                     (STM_TIM234_CCMR1_IC2PSC_NONE << STM_TIM234_CCMR1_IC2PSC) |
+                     (STM_TIM234_CCMR1_CC2S_INPUT_TI2 << STM_TIM234_CCMR1_CC2S));
+
+       tim->ccer = 0;
+
+       tim->sr = 0;
+       tim->dier = 0;
+       tim->smcr = 0;
+       tim->cr2 = ((0 << STM_TIM234_CR2_TI1S) |
+                   (STM_TIM234_CR2_MMS_RESET<< STM_TIM234_CR2_MMS) |
+                   (0 << STM_TIM234_CR2_CCDS));
+
+       tim->dier = ((0 << STM_TIM234_DIER_TDE) |
+                    (0 << STM_TIM234_DIER_CC4DE) |
+                    (0 << STM_TIM234_DIER_CC3DE) |
+                    (1 << STM_TIM234_DIER_CC2DE) |
+                    (0 << STM_TIM234_DIER_CC1DE) |
+                    (0 << STM_TIM234_DIER_TIE) |
+                    (0 << STM_TIM234_DIER_CC4IE) |
+                    (0 << STM_TIM234_DIER_CC3IE) |
+                    (0 << STM_TIM234_DIER_CC2IE) |
+                    (0 << STM_TIM234_DIER_CC1IE) |
+                    (0 << STM_TIM234_DIER_UIE));
+
+       tim->egr = 0;
+
+       tim->cr1 = ((STM_TIM234_CR1_CKD_1 << STM_TIM234_CR1_CKD) |
+                   (0 << STM_TIM234_CR1_ARPE) |
+                   (STM_TIM234_CR1_CMS_EDGE << STM_TIM234_CR1_CMS) |
+                   (STM_TIM234_CR1_DIR_UP << STM_TIM234_CR1_DIR) |
+                   (0 << STM_TIM234_CR1_OPM) |
+                   (0 << STM_TIM234_CR1_URS) |
+                   (0 << STM_TIM234_CR1_UDIS) |
+                   (0 << STM_TIM234_CR1_CEN));
+
+       stm_ospeedr_set(AO_MAX6691_GPIO, AO_MAX6691_PIN, STM_OSPEEDR_40MHz);
+       ao_enable_input(AO_MAX6691_GPIO, AO_MAX6691_PIN, AO_EXTI_MODE_PULL_UP);
+
+       ao_add_task(&ao_max6691_task, ao_max6691, "max6691");
+}
diff --git a/src/drivers/ao_max6691.h b/src/drivers/ao_max6691.h
new file mode 100644 (file)
index 0000000..b6186da
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright © 2019 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.
+ */
+
+#ifndef _AO_MAX6691_H_
+#define _AO_MAX6691_H_
+
+#define AO_MAX6691_CHANNELS    4
+
+struct ao_max6691_sample {
+       struct {
+               uint16_t        t_high;
+               uint16_t        t_low;
+       } sensor[AO_MAX6691_CHANNELS];
+};
+
+extern struct ao_max6691_sample ao_max6691_current;
+
+void
+ao_max6691_init(void);
+
+#endif /* _AO_MAX6691_H_ */
index e8eeea6e4b6dc8d424a9bf242ab60b706fbe399e..b0217368692fb7939ce391663aa815f4aa46132b 100644 (file)
@@ -232,7 +232,7 @@ ao_mma655x_setup(void)
                ao_delay(AO_ST_DELAY);
        }
        if (tries == AO_ST_TRIES)
-               ao_sensor_errors = 1;
+               AO_SENSOR_ERROR(AO_DATA_MMA655X);
 
        ao_mma655x_reg_write(AO_MMA655X_DEVCFG,
                             DEVCFG_VALUE | (1 << AO_MMA655X_DEVCFG_ENDINIT));
index 8c85ab01fd82c00041128a9147e3f6a26f2caa39..c894239ec0e54ae0934781886c44a759e8bcc38b 100644 (file)
@@ -305,7 +305,7 @@ _ao_mpu6000_setup(void)
        }
 
        if (st_tries == ST_TRIES)
-               ao_sensor_errors = 1;
+               AO_SENSOR_ERROR(AO_DATA_MPU6000);
 
        /* Filter to about 100Hz, which also sets the gyro rate to 1000Hz */
        _ao_mpu6000_reg_write(MPU6000_CONFIG,
index 74e444a9d0950ba21a4439d19a5adcc5999a0f3c..1b31edf4611754fe1b8c8d8fe52562b161e8579e 100644 (file)
@@ -26,8 +26,6 @@
 
 static uint8_t ao_mpu9250_configured;
 
-extern uint8_t ao_sensor_errors;
-
 #ifndef AO_MPU9250_I2C_INDEX
 #define AO_MPU9250_SPI 1
 #else
@@ -361,7 +359,7 @@ _ao_mpu9250_setup(void)
        }
 
        if (st_tries == ST_TRIES)
-               ao_sensor_errors = 1;
+               AO_SENSOR_ERROR(AO_DATA_MPU9250);
 
        /* Set up the mag sensor */
 
@@ -372,7 +370,7 @@ _ao_mpu9250_setup(void)
        }
 
        if (mag_tries == MAG_TRIES)
-               ao_sensor_errors = 1;
+               AO_SENSOR_ERROR(AO_DATA_MPU9250);
 
        /* Select continuous mode 2 (100Hz), 16 bit samples */
 
index e2327bf4113bbe985ba2e49180171088e16ead3c..1ebba3e9c6f99ccfb0fd7a7bbebd42b1e7da2c58 100644 (file)
@@ -112,8 +112,14 @@ ao_ms5607_prom_read(struct ao_ms5607_prom *prom)
                r++;
        }
 
-       if (!ao_ms5607_prom_valid((uint8_t *) prom))
+
+       if (!ao_ms5607_prom_valid((uint8_t *) prom)) {
+#if HAS_SENSOR_ERRORS
+               AO_SENSOR_ERROR(AO_DATA_MS5607);
+#else
                ao_panic(AO_PANIC_SELF_TEST_MS5607);
+#endif
+       }
 
 #if __BYTE_ORDER == __LITTLE_ENDIAN
        /* Byte swap */
@@ -240,6 +246,9 @@ struct ao_task ao_ms5607_task;
 void
 ao_ms5607_info(void)
 {
+#if !HAS_MS5607_TASK
+       ao_ms5607_setup();
+#endif
        printf ("ms5607 reserved: %u\n", ao_ms5607_prom.reserved);
        printf ("ms5607 sens: %u\n", ao_ms5607_prom.sens);
        printf ("ms5607 off: %u\n", ao_ms5607_prom.off);
@@ -255,6 +264,9 @@ ao_ms5607_dump(void)
 {
        struct ao_ms5607_value value;
 
+#if !HAS_MS5607_TASK
+       ao_ms5607_sample(&ao_ms5607_current);
+#endif
        ao_ms5607_convert(&ao_ms5607_current, &value);
        printf ("Pressure:    %8lu %8ld\n", ao_ms5607_current.pres, value.pres);
        printf ("Temperature: %8lu %8ld\n", ao_ms5607_current.temp, value.temp);
index b5a0a4b7e15bbdfd2925d8b3974d26d686cdc0ad..b9331c4d889e38fe0449fa3f3ab7853ee6a61a31 100644 (file)
@@ -42,7 +42,7 @@ ao_packet_send(void)
 #endif
        /* If any tx data is pending then copy it into the tx packet */
        if (ao_packet_tx_used && ao_tx_packet.len == 0) {
-               ao_xmemcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used);
+               memcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used);
                ao_tx_packet.len = ao_packet_tx_used;
                ao_tx_packet.seq++;
                ao_packet_tx_used = 0;
@@ -88,10 +88,10 @@ ao_packet_recv(uint16_t timeout)
        /* Accept packets with matching call signs, or any packet if
         * our callsign hasn't been configured
         */
-       if (ao_xmemcmp(ao_rx_packet.packet.callsign,
+       if (memcmp(ao_rx_packet.packet.callsign,
                       ao_config.callsign,
                       AO_MAX_CALLSIGN) != 0 &&
-           ao_xmemcmp(ao_config.callsign, "N0CALL", 7) != 0)
+           memcmp(ao_config.callsign, "N0CALL", 7) != 0)
                return 0;
 
        /* SYN packets carry no data */
@@ -111,7 +111,7 @@ ao_packet_recv(uint16_t timeout)
                        /* Copy data to the receive data buffer and set up the
                         * offsets
                         */
-                       ao_xmemcpy(rx_data, ao_rx_packet.packet.d, ao_rx_packet.packet.len);
+                       memcpy(rx_data, ao_rx_packet.packet.d, ao_rx_packet.packet.len);
                        ao_packet_rx_used = 0;
                        ao_packet_rx_len = ao_rx_packet.packet.len;
 
index 68a5efef366c4747b2e6a54529035c1ec4b359c4..a44b34cf0acdd84cd0905f745066dec630f6a08b 100644 (file)
@@ -83,7 +83,7 @@ ao_packet_master_check_busy(void)
                ao_packet_master_delay = AO_PACKET_MASTER_DELAY_LONG;
 }
 
-void
+static void
 ao_packet_master(void)
 {
        ao_config_get();
@@ -93,7 +93,7 @@ ao_packet_master(void)
        ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT;
        while (ao_packet_enable) {
                uint8_t r;
-               ao_xmemcpy(ao_tx_packet.callsign, ao_config.callsign, AO_MAX_CALLSIGN);
+               memcpy(ao_tx_packet.callsign, ao_config.callsign, AO_MAX_CALLSIGN);
                ao_packet_send();
                if (ao_tx_packet.len)
                        ao_packet_master_busy();
index 3ae1138ce0df5cffeb2dffc6c6b65891100bdcee..314ce14a2bc3866406e54c9306eefc842ec307b0 100644 (file)
@@ -18,7 +18,7 @@
 
 #include "ao.h"
 
-void
+static void
 ao_packet_slave(void)
 {
        ao_tx_packet.addr = ao_serial_number;
@@ -26,7 +26,7 @@ ao_packet_slave(void)
        ao_packet_restart = 1;
        while (ao_packet_enable) {
                if (ao_packet_recv(0)) {
-                       ao_xmemcpy(&ao_tx_packet.callsign, &ao_rx_packet.packet.callsign, AO_MAX_CALLSIGN);
+                       memcpy(&ao_tx_packet.callsign, &ao_rx_packet.packet.callsign, AO_MAX_CALLSIGN);
 #if HAS_FLIGHT
                        ao_flight_force_idle = true;
 #endif
index 85691f5c933474efa5fd73958b242a875d685f70..2592a084261bec25640f0820dfc018c579f44486 100644 (file)
@@ -176,7 +176,7 @@ ao_pad_run(void)
  *     AO_PAD_R_IGNITER_SENSE_GND      Resistors from igniter sense ADC inputs to ground
  */
 
-int16_t
+static int16_t
 ao_pad_decivolt(int16_t adc, int16_t r_plus, int16_t r_minus)
 {
        int32_t mul = (int32_t) AO_ADC_REFERENCE_DV * (r_plus + r_minus);
@@ -378,7 +378,7 @@ ao_pad(void)
                while (ao_pad_disabled)
                        ao_sleep(&ao_pad_disabled);
                ret = ao_radio_cmac_recv(&command, sizeof (command), 0);
-               PRINTD ("cmac_recv %d %d\n", ret, ao_radio_cmac_rssi);
+               PRINTD ("receive packet status %d rssi %d\n", ret, ao_radio_cmac_rssi);
                if (ret != AO_RADIO_CMAC_OK)
                        continue;
                ao_pad_packet_time = ao_time();
@@ -406,6 +406,10 @@ ao_pad(void)
                                PRINTD ("time difference too large %d\n", time_difference);
                                break;
                        }
+                       if (query.arm_status != AO_PAD_ARM_STATUS_ARMED) {
+                               PRINTD ("box not armed locally\n");
+                               break;
+                       }
                        PRINTD ("armed\n");
                        ao_pad_armed = command.channels;
                        ao_pad_arm_time = ao_time();
@@ -472,7 +476,7 @@ ao_pad(void)
        }
 }
 
-void
+static void
 ao_pad_test(void)
 {
        uint8_t c;
@@ -501,7 +505,7 @@ ao_pad_test(void)
        }
 }
 
-void
+static void
 ao_pad_manual(void)
 {
        uint8_t ignite;
@@ -529,7 +533,7 @@ static struct ao_task ao_pad_ignite_task;
 static struct ao_task ao_pad_monitor_task;
 
 #if DEBUG
-void
+static void
 ao_pad_set_debug(void)
 {
        uint16_t r = ao_cmd_decimal();
index 8b62a4de0e5df9884e62d7b7202d6f2b63634cb4..b229bd6fe1354f6209aa8b0055a390ddff6b3c78 100644 (file)
@@ -134,7 +134,7 @@ ao_radio_get_data(void *d, uint8_t size)
                    AO_RADIO_SPI_REPLY_HEADER_LEN + size,
                    AO_RADIO_SPI_BUS);
        ao_radio_master_stop();
-       ao_xmemcpy(d, ao_radio_spi_reply.payload, size);
+       memcpy(d, ao_radio_spi_reply.payload, size);
        PRINTD ("fetched %d\n", size);
 }
 
@@ -150,7 +150,7 @@ void
 ao_radio_send(const void *d, uint8_t size)
 {
        ao_radio_get(AO_RADIO_SPI_SEND, size);
-       ao_xmemcpy(&ao_radio_spi_request.payload, d, size);
+       memcpy(&ao_radio_spi_request.payload, d, size);
        ao_radio_master_send();
        ao_radio_put();
 }
@@ -190,7 +190,7 @@ ao_radio_cmac_set_key(void)
         */
        PRINTD ("set key\n");
        ao_radio_get(AO_RADIO_SPI_CMAC_KEY, AO_AES_LEN);
-       ao_xmemcpy(&ao_radio_spi_request.payload, &ao_config.aes_key, AO_AES_LEN);
+       memcpy(&ao_radio_spi_request.payload, &ao_config.aes_key, AO_AES_LEN);
        ao_radio_master_send();
        ao_radio_put();
        PRINTD ("key set\n");
@@ -212,7 +212,7 @@ ao_radio_cmac_send(void *packet, uint8_t len)
        
        PRINTD ("sending packet\n");
        ao_radio_get(AO_RADIO_SPI_CMAC_SEND, len);
-       ao_xmemcpy(&ao_radio_spi_request.payload, packet, len);
+       memcpy(&ao_radio_spi_request.payload, packet, len);
        ao_radio_master_send();
        ao_radio_put();
        PRINTD ("packet sent\n");
index 7859d6b65a102bf53c2daaf5e87fc5f16fe299af..e047093466ab138033b4f194605bed74543ec9a5 100644 (file)
@@ -107,7 +107,7 @@ ao_radio_slave_spi(void)
                        break;
                        
                case AO_RADIO_SPI_CMAC_KEY:
-                       ao_xmemcpy(&ao_config.aes_key, ao_radio_spi_request.payload, AO_AES_LEN);
+                       memcpy(&ao_config.aes_key, ao_radio_spi_request.payload, AO_AES_LEN);
                        break;
 
                case AO_RADIO_SPI_TEST_ON:
index 4ace4b78595c1a4a00743675fbe459cf670b6aa9..4d13decc46ec271bb9fff384ad937c6db8b79bd6 100644 (file)
@@ -116,7 +116,7 @@ static AO_TICK_TYPE ao_rn_buf_time;
  * disabled due to a firmware bug. So, this code finds those in the
  * input and strips them out.
  */
-int
+static int
 _ao_wrap_rn_pollchar(void)
 {
        int             c = AO_READ_AGAIN;
@@ -368,7 +368,7 @@ static uint8_t      ao_rn_stdio;
 /*
  * Set the stdio echo for the bluetooth link
  */
-void
+static void
 ao_rn_echo(uint8_t echo)
 {
        ao_stdios[ao_rn_stdio].echo = echo;
index 76e7319e43b85c419d65527cb9824d592f73ae43..b8f6df4a264eb863e38914c764b32ccff654fa09 100644 (file)
@@ -93,7 +93,7 @@ PRODUCT=EasyMega-v1.0
 PRODUCT_DEF=-DEASYMEGA
 IDPRODUCT=0x0028
 
-CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF)
 
 PROGNAME=easymega-v1.0
 PROG=$(PROGNAME)-$(VERSION).elf
@@ -105,16 +105,10 @@ OBJ=$(SRC:.c=.o)
 all: $(PROG) $(HEX)
 
 $(PROG): Makefile $(OBJ) altos.ld
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
-
-../altitude-pa.h: make-altitude-pa
-       nickle $< > $@
+       $(call quiet,CC) $(LDFLAGS) -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:
diff --git a/src/easymega-v2.0/.gitignore b/src/easymega-v2.0/.gitignore
new file mode 100644 (file)
index 0000000..410943d
--- /dev/null
@@ -0,0 +1,2 @@
+ao_product.h
+easymega-*.elf
index bfe8a849a9aa98192d47dde6c2215f5d66f9902f..ab478a4238c61fbd9bd5c496a07311da22a86b97 100644 (file)
@@ -90,7 +90,7 @@ PRODUCT=EasyMega-v2.0
 PRODUCT_DEF=-DEASYMEGA
 IDPRODUCT=0x0028
 
-CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF)
 
 PROGNAME=easymega-v2.0
 PROG=$(PROGNAME)-$(VERSION).elf
@@ -102,16 +102,10 @@ OBJ=$(SRC:.c=.o)
 all: $(PROG) $(HEX)
 
 $(PROG): Makefile $(OBJ) altos.ld
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
-
-../altitude-pa.h: make-altitude-pa
-       nickle $< > $@
+       $(call quiet,CC) $(LDFLAGS) -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:
diff --git a/src/easymega-v3.0/.gitignore b/src/easymega-v3.0/.gitignore
new file mode 100644 (file)
index 0000000..410943d
--- /dev/null
@@ -0,0 +1,2 @@
+ao_product.h
+easymega-*.elf
diff --git a/src/easymega-v3.0/Makefile b/src/easymega-v3.0/Makefile
new file mode 100644 (file)
index 0000000..51c5175
--- /dev/null
@@ -0,0 +1,117 @@
+#
+# AltOS build
+#
+#
+
+include ../stm/Makefile.defs
+
+INC = \
+       ao.h \
+       ao_arch.h \
+       ao_arch_funcs.h \
+       ao_boot.h \
+       ao_companion.h \
+       ao_data.h \
+       ao_sample.h \
+       ao_pins.h \
+       altitude-pa.h \
+       ao_kalman.h \
+       ao_product.h \
+       ao_ms5607.h \
+       ao_bmx160.h \
+       ao_adxl375.h \
+       ao_profile.h \
+       ao_task.h \
+       ao_whiten.h \
+       ao_sample_profile.h \
+       ao_quaternion.h \
+       ao_mpu.h \
+       stm32l.h \
+       Makefile
+
+#
+# Common AltOS sources
+#
+
+#PROFILE=ao_profile.c
+#PROFILE_DEF=-DAO_PROFILE=1
+
+#SAMPLE_PROFILE=ao_sample_profile.c \
+#      ao_sample_profile_timer.c
+#SAMPLE_PROFILE_DEF=-DHAS_SAMPLE_PROFILE=1
+
+#STACK_GUARD=ao_mpu_stm.c
+#STACK_GUARD_DEF=-DHAS_STACK_GUARD=1
+
+ALTOS_SRC = \
+       ao_boot_chain.c \
+       ao_interrupt.c \
+       ao_product.c \
+       ao_romconfig.c \
+       ao_cmd.c \
+       ao_config.c \
+       ao_task.c \
+       ao_led_stm.c \
+       ao_stdio.c \
+       ao_panic.c \
+       ao_timer.c \
+       ao_mutex.c \
+       ao_ignite.c \
+       ao_freq.c \
+       ao_dma_stm.c \
+       ao_spi_stm.c \
+       ao_data.c \
+       ao_ms5607.c \
+       ao_bmx160.c \
+       ao_adxl375.c \
+       ao_adc_stm.c \
+       ao_beep_stm.c \
+       ao_eeprom_stm.c \
+       ao_storage.c \
+       ao_m25.c \
+       ao_usb_stm.c \
+       ao_exti_stm.c \
+       ao_report.c \
+       ao_i2c_stm.c \
+       ao_convert_pa.c \
+       ao_convert_volt.c \
+       ao_log.c \
+       ao_log_mega.c \
+       ao_sample.c \
+       ao_kalman.c \
+       ao_flight.c \
+       ao_companion.c \
+       ao_pyro.c \
+       $(PROFILE) \
+       $(SAMPLE_PROFILE) \
+       $(STACK_GUARD)
+
+PRODUCT=EasyMega-v3.0
+PRODUCT_DEF=-DEASYMEGA
+IDPRODUCT=0x0028
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF)
+
+PROGNAME=easymega-v3.0
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_easymega.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+       $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+$(OBJ): $(INC)
+
+distclean:     clean
+
+clean:
+       rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+       rm -f ao_product.h
+
+install:
+
+uninstall:
diff --git a/src/easymega-v3.0/ao_easymega.c b/src/easymega-v3.0/ao_easymega.c
new file mode 100644 (file)
index 0000000..70a6e40
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright © 2014 Bdale Garbee <bdale@gag.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_ms5607.h>
+#include <ao_bmx160.h>
+#include <ao_adxl375.h>
+#include <ao_log.h>
+#include <ao_exti.h>
+#include <ao_companion.h>
+#include <ao_profile.h>
+#include <ao_eeprom.h>
+#if HAS_SAMPLE_PROFILE
+#include <ao_sample_profile.h>
+#endif
+#include <ao_pyro.h>
+#if HAS_STACK_GUARD
+#include <ao_mpu.h>
+#endif
+
+int
+main(void)
+{
+       ao_clock_init();
+
+#if HAS_STACK_GUARD
+       ao_mpu_init();
+#endif
+
+       ao_task_init();
+       ao_led_init();
+       ao_led_on(LEDS_AVAILABLE);
+       ao_timer_init();
+
+       ao_i2c_init();
+       ao_spi_init();
+       ao_dma_init();
+       ao_exti_init();
+
+       ao_adc_init();
+       ao_beep_init();
+       ao_cmd_init();
+
+       ao_ms5607_init();
+       ao_bmx160_init();
+       ao_adxl375_init();
+
+       ao_eeprom_init();
+       ao_storage_init();
+
+       ao_flight_init();
+       ao_log_init();
+       ao_report_init();
+
+       ao_usb_init();
+       ao_igniter_init();
+       ao_companion_init();
+       ao_pyro_init();
+
+       ao_config_init();
+#if AO_PROFILE
+       ao_profile_init();
+#endif
+#if HAS_SAMPLE_PROFILE
+       ao_sample_profile_init();
+#endif
+
+       ao_led_off(LEDS_AVAILABLE);
+       ao_start_scheduler();
+       return 0;
+}
diff --git a/src/easymega-v3.0/ao_pins.h b/src/easymega-v3.0/ao_pins.h
new file mode 100644 (file)
index 0000000..fa810fd
--- /dev/null
@@ -0,0 +1,366 @@
+/*
+ * Copyright © 2014 Bdale Garbee <bdale@gag.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define HAS_TASK_QUEUE         1
+
+/* 16MHz High speed external crystal */
+#define AO_HSE                 16000000
+
+/* PLLVCO = 96MHz (so that USB will work) */
+#define AO_PLLMUL              6
+#define AO_RCC_CFGR_PLLMUL     (STM_RCC_CFGR_PLLMUL_6)
+
+/* SYSCLK = 32MHz (no need to go faster than CPU) */
+#define AO_PLLDIV              3
+#define AO_RCC_CFGR_PLLDIV     (STM_RCC_CFGR_PLLDIV_3)
+
+/* HCLK = 32MHz (CPU clock) */
+#define AO_AHB_PRESCALER       1
+#define AO_RCC_CFGR_HPRE_DIV   STM_RCC_CFGR_HPRE_DIV_1
+
+/* Run APB1 at 16MHz (HCLK/2) */
+#define AO_APB1_PRESCALER      2
+#define AO_RCC_CFGR_PPRE1_DIV  STM_RCC_CFGR_PPRE2_DIV_2
+
+/* Run APB2 at 16MHz (HCLK/2) */
+#define AO_APB2_PRESCALER      2
+#define AO_RCC_CFGR_PPRE2_DIV  STM_RCC_CFGR_PPRE2_DIV_2
+
+#define HAS_SERIAL_1           0
+#define USE_SERIAL_1_STDIN     0
+#define SERIAL_1_PB6_PB7       0
+#define SERIAL_1_PA9_PA10      0
+
+#define HAS_SERIAL_2           0
+#define USE_SERIAL_2_STDIN     0
+#define SERIAL_2_PA2_PA3       0
+#define SERIAL_2_PD5_PD6       0
+
+#define HAS_SERIAL_3           0
+#define USE_SERIAL_3_STDIN     0
+#define SERIAL_3_PB10_PB11     0
+#define SERIAL_3_PC10_PC11     0
+#define SERIAL_3_PD8_PD9       0
+
+#define ao_gps_getchar         ao_serial1_getchar
+#define ao_gps_putchar         ao_serial1_putchar
+#define ao_gps_set_speed       ao_serial1_set_speed
+#define ao_gps_fifo            (ao_stm_usart1.rx_fifo)
+
+#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX       (1024 * 1024)
+#define AO_CONFIG_MAX_SIZE                     1024
+#define LOG_ERASE_MARK                         0x55
+#define LOG_MAX_ERASE                          128
+#define AO_LOG_FORMAT                          AO_LOG_FORMAT_EASYMEGA_2
+
+#define HAS_EEPROM             1
+#define USE_INTERNAL_FLASH     0
+#define USE_EEPROM_CONFIG      1
+#define USE_STORAGE_CONFIG     0
+#define HAS_USB                        1
+#define HAS_BEEP               1
+#define BEEPER_TIMER           2
+#define BEEPER_CHANNEL         3
+#define BEEPER_PORT            (&stm_gpioa)
+#define BEEPER_PIN             2
+#define HAS_BATTERY_REPORT     1
+#define HAS_RADIO              0
+#define HAS_TELEMETRY          0
+#define HAS_APRS               0
+#define HAS_COMPANION          1
+
+#define HAS_SPI_1              1
+#define SPI_1_PA5_PA6_PA7      1       /* Barometer */
+#define SPI_1_PB3_PB4_PB5      1       /* Accelerometer */
+#define SPI_1_PE13_PE14_PE15   0
+#define SPI_1_OSPEEDR          STM_OSPEEDR_10MHz
+
+#define HAS_SPI_2              1
+#define SPI_2_PB13_PB14_PB15   1       /* Flash, IMU, Companion */
+#define SPI_2_PD1_PD3_PD4      0
+#define SPI_2_OSPEEDR          STM_OSPEEDR_10MHz
+
+#define HAS_I2C_1              1
+#define I2C_1_PB8_PB9          1
+
+#define HAS_I2C_2              0
+#define I2C_2_PB10_PB11                0
+
+#define PACKET_HAS_SLAVE       0
+#define PACKET_HAS_MASTER      0
+
+#define LOW_LEVEL_DEBUG                0
+
+#define LED_PORT_ENABLE                STM_RCC_AHBENR_GPIOAEN
+#define LED_PORT               (&stm_gpioa)
+#define LED_PIN_RED            9
+#define LED_PIN_GREEN          10
+#define AO_LED_RED             (1 << LED_PIN_RED)
+#define AO_LED_GREEN           (1 << LED_PIN_GREEN)
+
+#define LEDS_AVAILABLE         (AO_LED_RED | AO_LED_GREEN)
+
+#define HAS_GPS                        0
+#define HAS_FLIGHT             1
+#define HAS_ADC                        1
+#define HAS_ADC_TEMP           1
+#define HAS_LOG                        1
+
+/*
+ * Igniter
+ */
+
+#define HAS_IGNITE             1
+#define HAS_IGNITE_REPORT      1
+
+#define AO_SENSE_PYRO(p,n)     ((p)->adc.sense[n])
+#define AO_SENSE_DROGUE(p)     ((p)->adc.sense[4])
+#define AO_SENSE_MAIN(p)       ((p)->adc.sense[5])
+#define AO_IGNITER_CLOSED      400
+#define AO_IGNITER_OPEN                60
+
+/* Pyro A */
+#define AO_PYRO_PORT_0 (&stm_gpioa)
+#define AO_PYRO_PIN_0  15
+
+/* Pyro B */
+#define AO_PYRO_PORT_1 (&stm_gpioc)
+#define AO_PYRO_PIN_1  10
+
+/* Pyro C */
+#define AO_PYRO_PORT_2 (&stm_gpiob)
+#define AO_PYRO_PIN_2  11
+
+/* Pyro D */
+#define AO_PYRO_PORT_3 (&stm_gpiob)
+#define AO_PYRO_PIN_3  10
+
+/* Drogue */
+#define AO_IGNITER_DROGUE_PORT (&stm_gpioa)
+#define AO_IGNITER_DROGUE_PIN  0
+
+/* Main */
+#define AO_IGNITER_MAIN_PORT   (&stm_gpioa)
+#define AO_IGNITER_MAIN_PIN    1
+
+/* Number of general purpose pyro channels available */
+#define AO_PYRO_NUM    4
+
+/*
+ * ADC
+ */
+#define AO_DATA_RING           32
+#define AO_ADC_NUM_SENSE       6
+
+struct ao_adc {
+       int16_t                 sense[AO_ADC_NUM_SENSE];
+       int16_t                 v_batt;
+       int16_t                 v_pbatt;
+       int16_t                 temp;
+};
+
+#define AO_ADC_DUMP(p) \
+       printf("tick: %5u A: %5d B: %5d C: %5d D: %5d drogue: %5d main: %5d batt: %5d pbatt: %5d temp: %5d\n", \
+              (p)->tick, \
+              (p)->adc.sense[0], (p)->adc.sense[1], (p)->adc.sense[2], \
+              (p)->adc.sense[3], (p)->adc.sense[4], (p)->adc.sense[5], \
+              (p)->adc.v_batt, (p)->adc.v_pbatt, (p)->adc.temp)
+
+#define AO_ADC_SENSE_A         14
+#define AO_ADC_SENSE_A_PORT    (&stm_gpioc)
+#define AO_ADC_SENSE_A_PIN     4
+
+#define AO_ADC_SENSE_B         15
+#define AO_ADC_SENSE_B_PORT    (&stm_gpioc)
+#define AO_ADC_SENSE_B_PIN     5
+
+#define AO_ADC_SENSE_C         13
+#define AO_ADC_SENSE_C_PORT    (&stm_gpioc)
+#define AO_ADC_SENSE_C_PIN     3
+
+#define AO_ADC_SENSE_D         12
+#define AO_ADC_SENSE_D_PORT    (&stm_gpioc)
+#define AO_ADC_SENSE_D_PIN     2
+
+#define AO_ADC_SENSE_DROGUE    11
+#define AO_ADC_SENSE_DROGUE_PORT       (&stm_gpioc)
+#define AO_ADC_SENSE_DROGUE_PIN        1
+
+#define AO_ADC_SENSE_MAIN      10
+#define AO_ADC_SENSE_MAIN_PORT (&stm_gpioc)
+#define AO_ADC_SENSE_MAIN_PIN  0
+
+#define AO_ADC_V_BATT          8
+#define AO_ADC_V_BATT_PORT     (&stm_gpiob)
+#define AO_ADC_V_BATT_PIN      0
+
+#define AO_ADC_V_PBATT         9
+#define AO_ADC_V_PBATT_PORT    (&stm_gpiob)
+#define AO_ADC_V_PBATT_PIN     1
+
+#define AO_ADC_TEMP            16
+
+#define AO_ADC_RCC_AHBENR      ((1 << STM_RCC_AHBENR_GPIOAEN) | \
+                                (1 << STM_RCC_AHBENR_GPIOEEN) | \
+                                (1 << STM_RCC_AHBENR_GPIOBEN))
+
+#define AO_NUM_ADC_PIN         (AO_ADC_NUM_SENSE + 2)
+
+#define AO_ADC_PIN0_PORT       AO_ADC_SENSE_A_PORT
+#define AO_ADC_PIN0_PIN                AO_ADC_SENSE_A_PIN
+#define AO_ADC_PIN1_PORT       AO_ADC_SENSE_B_PORT
+#define AO_ADC_PIN1_PIN                AO_ADC_SENSE_B_PIN
+#define AO_ADC_PIN2_PORT       AO_ADC_SENSE_C_PORT
+#define AO_ADC_PIN2_PIN                AO_ADC_SENSE_C_PIN
+#define AO_ADC_PIN3_PORT       AO_ADC_SENSE_D_PORT
+#define AO_ADC_PIN3_PIN                AO_ADC_SENSE_D_PIN
+#define AO_ADC_PIN4_PORT       AO_ADC_SENSE_DROGUE_PORT
+#define AO_ADC_PIN4_PIN                AO_ADC_SENSE_DROGUE_PIN
+#define AO_ADC_PIN5_PORT       AO_ADC_SENSE_MAIN_PORT
+#define AO_ADC_PIN5_PIN                AO_ADC_SENSE_MAIN_PIN
+#define AO_ADC_PIN6_PORT       AO_ADC_V_BATT_PORT
+#define AO_ADC_PIN6_PIN                AO_ADC_V_BATT_PIN
+#define AO_ADC_PIN7_PORT       AO_ADC_V_PBATT_PORT
+#define AO_ADC_PIN7_PIN                AO_ADC_V_PBATT_PIN
+
+#define AO_NUM_ADC             (AO_ADC_NUM_SENSE + 3)
+
+#define AO_ADC_SQ1             AO_ADC_SENSE_A
+#define AO_ADC_SQ2             AO_ADC_SENSE_B
+#define AO_ADC_SQ3             AO_ADC_SENSE_C
+#define AO_ADC_SQ4             AO_ADC_SENSE_D
+#define AO_ADC_SQ5             AO_ADC_SENSE_DROGUE
+#define AO_ADC_SQ6             AO_ADC_SENSE_MAIN
+#define AO_ADC_SQ7             AO_ADC_V_BATT
+#define AO_ADC_SQ8             AO_ADC_V_PBATT
+#define AO_ADC_SQ9             AO_ADC_TEMP
+
+/*
+ * Voltage divider on ADC battery sampler
+ */
+#define AO_BATTERY_DIV_PLUS    56      /* 5.6k */
+#define AO_BATTERY_DIV_MINUS   100     /* 10k */
+
+/*
+ * Voltage divider on ADC igniter samplers
+ */
+#define AO_IGNITE_DIV_PLUS     100     /* 100k */
+#define AO_IGNITE_DIV_MINUS    27      /* 27k */
+
+/*
+ * ADC reference in decivolts
+ */
+#define AO_ADC_REFERENCE_DV    33
+
+/*
+ * Pressure sensor settings
+ */
+#define HAS_MS5607             1
+#define HAS_MS5611             0
+#define AO_MS5607_PRIVATE_PINS 1
+#define AO_MS5607_CS_PORT      (&stm_gpioa)
+#define AO_MS5607_CS_PIN       3
+#define AO_MS5607_CS_MASK      (1 << AO_MS5607_CS_PIN)
+#define AO_MS5607_MISO_PORT    (&stm_gpioa)
+#define AO_MS5607_MISO_PIN     6
+#define AO_MS5607_MISO_MASK    (1 << AO_MS5607_MISO_PIN)
+#define AO_MS5607_SPI_INDEX    AO_SPI_1_PA5_PA6_PA7
+
+/*
+ * SPI Flash memory
+ */
+
+#define M25_MAX_CHIPS          1
+#define AO_M25_SPI_CS_PORT     (&stm_gpiob)
+#define AO_M25_SPI_CS_PIN      12
+#define AO_M25_SPI_CS_MASK     (1 << AO_M25_SPI_CS_PIN)
+#define AO_M25_SPI_BUS         AO_SPI_2_PB13_PB14_PB15
+
+/*
+ * bmx160
+ */
+
+#define HAS_BMX160             1
+#define AO_BMX160_INT_PORT     (&stm_gpioc)
+#define AO_BMX160_INT_PIN      15
+#define AO_BMX160_SPI_BUS      (AO_SPI_2_PB13_PB14_PB15 | AO_SPI_MODE_0)
+#define AO_BMX160_SPI_CS_PORT  (&stm_gpioc)
+#define AO_BMX160_SPI_CS_PIN   13
+#define HAS_IMU                        1
+
+#define ao_data_along(packet)  ((packet)->bmx160.acc_x)
+#define ao_data_across(packet) (-(packet)->bmx160.acc_y)
+#define ao_data_through(packet)        ((packet)->bmx160.acc_z)
+
+#define ao_data_roll(packet)   ((packet)->bmx160.gyr_x)
+#define ao_data_pitch(packet)  (-(packet)->bmx160.gyr_y)
+#define ao_data_yaw(packet)    ((packet)->bmx160.gyr_z)
+
+#define ao_data_mag_along(packet)      ((packet)->bmx160.mag_x)
+#define ao_data_mag_across(packet)     (-(packet)->bmx160.mag_y)
+#define ao_data_mag_through(packet)    ((packet)->bmx160.mag_z)
+
+/* ADXL375 */
+
+#define HAS_ADXL375            1
+#define AO_ADXL375_SPI_INDEX   (AO_SPI_1_PB3_PB4_PB5 | AO_SPI_MODE_3)
+#define AO_ADXL375_CS_PORT     (&stm_gpioc)
+#define AO_ADXL375_CS_PIN      12
+#define AO_ADXL375_SPI_SPEED   AO_SPI_SPEED_4MHz
+
+#define AO_ADXL375_INT1_PORT   (&stm_gpiob)
+#define AO_ADXL375_INT1_PIN    8
+
+#define AO_ADXL375_INT2_PORT   (&stm_gpiob)
+#define AO_ADXL375_INT2_PIN    9
+
+#define AO_ADXL375_AXIS                x
+#define AO_ADXL375_INVERT      1
+
+#define NUM_CMDS               16
+
+/*
+ * Companion
+ */
+
+#define AO_COMPANION_CS_PORT   (&stm_gpiob)
+#define AO_COMPANION_CS_PIN    (6)
+#define AO_COMPANION_SPI_BUS   AO_SPI_2_PB13_PB14_PB15
+
+/*
+ * Monitor
+ */
+
+#define HAS_MONITOR            0
+#define LEGACY_MONITOR         0
+#define HAS_MONITOR_PUT                0
+#define AO_MONITOR_LED         0
+#define HAS_RSSI               0
+
+/*
+ * Profiling Viterbi decoding
+ */
+
+#ifndef AO_PROFILE
+#define AO_PROFILE             0
+#endif
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/easymega-v3.0/flash-loader/Makefile b/src/easymega-v3.0/flash-loader/Makefile
new file mode 100644 (file)
index 0000000..2b715ca
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=easymega-v3.0
+include $(TOPDIR)/stm/Makefile-flash.defs
diff --git a/src/easymega-v3.0/flash-loader/ao_pins.h b/src/easymega-v3.0/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..324b0eb
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright © 2018 Bdale Garbee <bdale@gag.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+/* External crystal at 16MHz */
+#define AO_HSE         16000000
+
+#include <ao_flash_stm_pins.h>
+
+/* Companion port cs_companion0 PB6 */
+
+#define AO_BOOT_PIN            1
+#define AO_BOOT_APPLICATION_GPIO       stm_gpiob
+#define AO_BOOT_APPLICATION_PIN                6
+#define AO_BOOT_APPLICATION_VALUE      1
+#define AO_BOOT_APPLICATION_MODE       AO_EXTI_MODE_PULL_UP
+
+#endif /* _AO_PINS_H_ */
index 654be22bffa539378fcb0be747b3e544ec1133f1..301a0c1dde8ce0bc014f358a0f78ca3f8164f670 100644 (file)
@@ -51,7 +51,7 @@ PRODUCT=EasyMini-v1.0
 PRODUCT_DEF=-DEASYMINI_V_1_0
 IDPRODUCT=0x0026
 
-CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) -g -Os
+CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS)
 
 PROGNAME=easymini-v1.0
 PROG=$(PROGNAME)-$(VERSION).elf
@@ -63,10 +63,7 @@ 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) > $@
+       $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS)
 
 $(OBJ): $(INC)
 
index 6025219df44a26f4c0b1ec6cd8425744792dcb7e..05b2951f153fde37d900d320c54ca77dbc2a3833 100644 (file)
@@ -19,7 +19,7 @@
 #include <ao.h>
 #include <ao_exti.h>
 
-void
+int
 main(void)
 {
        ao_clock_init();
index 9b4cc6d7da4370364da02b8e474cf7dd9f3a4b5c..2f79024416cd52b3dcc79797b18e5e41d67f5cd1 100644 (file)
@@ -53,7 +53,7 @@ PRODUCT=EasyMini-v2.0
 PRODUCT_DEF=-DEASYMINI_V_2_0
 IDPRODUCT=0x0026
 
-CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -g -Os
+CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS)
 
 PROGNAME=easymini-v2.0
 PROG=$(PROGNAME)-$(VERSION).elf
@@ -65,10 +65,7 @@ OBJ=$(SRC:.c=.o)
 all: $(PROG) $(HEX)
 
 $(PROG): Makefile $(OBJ)
-       $(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) > $@
+       $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS)
 
 $(OBJ): $(INC)
 
index 7246cae27437338e29b06dd7e8bc2505de7d2aa7..ae80c436dc8f1b25acccba8738def8de8c83dc57 100644 (file)
@@ -19,7 +19,7 @@
 #include <ao.h>
 #include <ao_exti.h>
 
-void
+int
 main(void)
 {
        ao_clock_init();
index 61314db93cb7f2687e83469f4854f5b36544508a..0277dd7e2522ba1304d70bdb5dd26e04a793783c 100644 (file)
@@ -59,7 +59,7 @@ PRODUCT=Fox1IHU-v2
 PRODUCT_DEF=-DFOX
 IDPRODUCT=0x0024
 
-CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF)
 
 PROGNAME=fox1ihu-v0.1
 PROG=$(PROGNAME)-$(VERSION).elf
index 9baae8b437d310b071618b57795b11575c650637..fb7af24dac350c717c8620e425ce81bd1a6644f8 100644 (file)
@@ -75,7 +75,9 @@ typedef AO_PORT_TYPE ao_port_t;
 #define AO_PANIC_SELF_TEST_HMC5883     0x40 | 2        /* Self test failure */
 #define AO_PANIC_SELF_TEST_MPU6000     0x40 | 3        /* Self test failure */
 #define AO_PANIC_SELF_TEST_MPU9250     0x40 | 3        /* Self test failure */
+#define AO_PANIC_SELF_TEST_BMX160      0x40 | 3        /* Self test failure */
 #define AO_PANIC_SELF_TEST_MS5607      0x40 | 4        /* Self test failure */
+#define AO_PANIC_SELF_TEST_ADS124S0X   0x40 | 5        /* Self test failure */
 
 /* Stop the operating system, beeping and blinking the reason */
 void
@@ -99,8 +101,8 @@ extern AO_ROMCONFIG_SYMBOL uint32_t ao_radio_cal;
  */
 
 #ifndef AO_TICK_TYPE
-#define AO_TICK_TYPE   uint16_t
-#define AO_TICK_SIGNED int16_t
+#define AO_TICK_TYPE   uint32_t
+#define AO_TICK_SIGNED int32_t
 #endif
 
 extern volatile AO_TICK_TYPE ao_tick_count;
@@ -116,6 +118,10 @@ extern volatile AO_TICK_TYPE ao_tick_count;
 AO_TICK_TYPE
 ao_time(void);
 
+/* Returns the current time in ns */
+uint64_t
+ao_time_ns(void);
+
 /* Suspend the current task until ticks time has passed */
 void
 ao_delay(uint16_t ticks);
@@ -932,12 +938,6 @@ ao_log_single(void);
 
 #define AO_TELEPYRO_NUM_ADC    9
 
-#ifndef ao_xmemcpy
-#define ao_xmemcpy(d,s,c) memcpy(d,s,c)
-#define ao_xmemset(d,v,c) memset(d,v,c)
-#define ao_xmemcmp(d,s,c) memcmp(d,s,c)
-#endif
-
 /*
  * ao_terraui.c
  */
index 596a0410623774f68f68e1c3bf3a239c369141d8..9f329f17554b57e1271e94f788b51ccc3761c2f5 100644 (file)
@@ -39,6 +39,10 @@ uint8_t ao_config_mutex;
 uint8_t ao_force_freq;
 #endif
 
+#ifndef HAS_CONFIG_SAVE
+#define HAS_CONFIG_SAVE        HAS_EEPROM
+#endif
+
 #ifndef AO_CONFIG_DEFAULT_APRS_INTERVAL
 #define AO_CONFIG_DEFAULT_APRS_INTERVAL        0
 #endif
@@ -50,7 +54,7 @@ uint8_t ao_force_freq;
 #define AO_CONFIG_DEFAULT_IGNITE_MODE  AO_IGNITE_MODE_DUAL
 #define AO_CONFIG_DEFAULT_PAD_ORIENTATION      AO_PAD_ORIENTATION_ANTENNA_UP
 #define AO_CONFIG_DEFAULT_PYRO_TIME    AO_MS_TO_TICKS(50)
-#if HAS_EEPROM
+#if HAS_CONFIG_SAVE
 #ifndef USE_INTERNAL_FLASH
 #error Please define USE_INTERNAL_FLASH
 #endif
@@ -75,7 +79,7 @@ uint8_t ao_force_freq;
 #define AO_CONFIG_DEFAULT_APRS_SSID            (ao_serial_number % 10)
 #define AO_CONFIG_DEFAULT_RADIO_RATE           AO_RADIO_RATE_38400
 
-#if HAS_EEPROM
+#if HAS_CONFIG_SAVE
 static void
 _ao_config_put(void)
 {
@@ -120,7 +124,7 @@ _ao_config_get(void)
 
        if (ao_config_loaded)
                return;
-#if HAS_EEPROM
+#if HAS_CONFIG_SAVE
        /* Yes, I know ao_storage_read calls ao_storage_setup,
         * but ao_storage_setup *also* sets ao_storage_config, which we
         * need before calling ao_storage_read here
@@ -134,8 +138,8 @@ _ao_config_get(void)
 
                /* Version 0 stuff */
                ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY;
-               ao_xmemset(&ao_config.callsign, '\0', sizeof (ao_config.callsign));
-               ao_xmemcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN,
+               memset(&ao_config.callsign, '\0', sizeof (ao_config.callsign));
+               memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN,
                       sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1);
                ao_config._legacy_radio_channel = 0;
        }
@@ -167,7 +171,7 @@ _ao_config_get(void)
                if (minor < 8)
                        ao_config.radio_enable = AO_RADIO_ENABLE_CORE;
                if (minor < 9)
-                       ao_xmemset(&ao_config.aes_key, '\0', AO_AES_LEN);
+                       memset(&ao_config.aes_key, '\0', AO_AES_LEN);
                if (minor < 10)
                        ao_config.frequency = 434550 + ao_config._legacy_radio_channel * 100;
                if (minor < 11)
@@ -246,7 +250,7 @@ _ao_config_get(void)
 #if HAS_RADIO_RATE
                ao_config.radio_rate = AO_CONFIG_DEFAULT_RADIO_RATE;
 #endif
-               ao_xmemcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN,
+               memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN,
                       sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1);
        }
 #endif
@@ -276,19 +280,21 @@ ao_config_get(void)
        ao_mutex_put(&ao_config_mutex);
 }
 
-void
+#if HAS_RADIO
+
+static void
 ao_config_callsign_show(void)
 {
        printf ("Callsign: \"%s\"\n", ao_config.callsign);
 }
 
-void
+static void
 ao_config_callsign_set(void) 
 {
        uint8_t c;
        static char callsign[AO_MAX_CALLSIGN + 1];
 
-       ao_xmemset(callsign, '\0', sizeof callsign);
+       memset(callsign, '\0', sizeof callsign);
        ao_cmd_white();
        c = 0;
        while (ao_cmd_lex_c != '\n') {
@@ -301,21 +307,19 @@ ao_config_callsign_set(void)
        if (ao_cmd_status != ao_cmd_success)
                return;
        _ao_config_edit_start();
-       ao_xmemcpy(&ao_config.callsign, &callsign,
+       memcpy(&ao_config.callsign, &callsign,
               AO_MAX_CALLSIGN + 1);
        _ao_config_edit_finish();
 }
 
-#if HAS_RADIO
-
-void
+static void
 ao_config_frequency_show(void) 
 {
        printf("Frequency: %ld\n",
               ao_config.frequency);
 }
 
-void
+static void
 ao_config_frequency_set(void) 
 {
        uint32_t r = ao_cmd_decimal();
@@ -359,14 +363,14 @@ ao_config_send_frequency_set(void)
 
 #if HAS_FLIGHT
 
-void
+static void
 ao_config_main_deploy_show(void) 
 {
        printf("Main deploy: %d meters\n",
               ao_config.main_deploy);
 }
 
-void
+static void
 ao_config_main_deploy_set(void) 
 {
        uint32_t r = ao_cmd_decimal();
@@ -378,7 +382,7 @@ ao_config_main_deploy_set(void)
 }
 
 #if HAS_ACCEL
-void
+static void
 ao_config_accel_calibrate_show(void) 
 {
        printf("Accel cal +1g: %d -1g: %d\n",
@@ -441,7 +445,7 @@ ao_config_accel_calibrate_auto(char *orientation)
        return accel_total >> ACCEL_CALIBRATE_SHIFT;
 }
 
-void
+static void
 ao_config_accel_calibrate_set(void) 
 {
        int16_t up, down;
@@ -494,14 +498,14 @@ ao_config_accel_calibrate_set(void)
 }
 #endif /* HAS_ACCEL */
 
-void
+static void
 ao_config_apogee_delay_show(void) 
 {
        printf("Apogee delay: %d seconds\n",
               ao_config.apogee_delay);
 }
 
-void
+static void
 ao_config_apogee_delay_set(void) 
 {
        uint32_t r = ao_cmd_decimal();
@@ -512,14 +516,14 @@ ao_config_apogee_delay_set(void)
        _ao_config_edit_finish();
 }
 
-void
+static void
 ao_config_apogee_lockout_show(void) 
 {
        printf ("Apogee lockout: %d seconds\n",
                ao_config.apogee_lockout);
 }
 
-void
+static void
 ao_config_apogee_lockout_set(void) 
 {
        uint16_t r = ao_cmd_decimal();
@@ -533,13 +537,13 @@ ao_config_apogee_lockout_set(void)
 #endif /* HAS_FLIGHT */
 
 #if HAS_RADIO
-void
+static void
 ao_config_radio_cal_show(void) 
 {
        printf("Radio cal: %ld\n", ao_config.radio_cal);
 }
 
-void
+static void
 ao_config_radio_cal_set(void) 
 {
        uint32_t r = ao_cmd_decimal();
@@ -558,13 +562,13 @@ ao_config_radio_cal_set(void)
 #error Please define HAS_TELEMETRY
 #endif
 
-void
+static void
 ao_config_radio_rate_show(void) 
 {
        printf("Telemetry rate: %d\n", ao_config.radio_rate);
 }
 
-void
+static void
 ao_config_radio_rate_set(void) 
 {
        uint16_t r = ao_cmd_decimal();
@@ -588,7 +592,7 @@ ao_config_radio_rate_set(void)
 
 #if HAS_LOG
 
-void
+static void
 ao_config_log_show(void) 
 {
        printf("Max flight log: %d kB\n", (int16_t) (ao_config.flight_log_max >> 10));
@@ -597,7 +601,7 @@ ao_config_log_show(void)
 #endif
 }
 
-#if FLIGHT_LOG_APPEND
+#if FLIGHT_LOG_APPEND && HAS_CONFIG_SAVE
 void
 ao_config_log_fix_append(void)
 {
@@ -611,7 +615,7 @@ ao_config_log_fix_append(void)
 }
 #endif
 
-void
+static void
 ao_config_log_set(void) 
 {
 #if FLIGHT_LOG_APPEND
@@ -640,13 +644,13 @@ ao_config_log_set(void)
 #endif /* HAS_LOG */
 
 #if HAS_IGNITE
-void
+static void
 ao_config_ignite_mode_show(void) 
 {
        printf("Ignite mode: %d\n", ao_config.ignite_mode);
 }
 
-void
+static void
 ao_config_ignite_mode_set(void) 
 {
        uint16_t r = ao_cmd_decimal();
@@ -659,17 +663,13 @@ ao_config_ignite_mode_set(void)
 #endif
 
 #if HAS_ACCEL
-void
+static void
 ao_config_pad_orientation_show(void) 
 {
        printf("Pad orientation: %d\n", ao_config.pad_orientation);
 }
 
-#ifndef AO_ACCEL_INVERT
-#define AO_ACCEL_INVERT        0x7fff
-#endif
-
-void
+static void
 ao_config_pad_orientation_set(void) 
 {
        uint16_t r = ao_cmd_decimal() & 1;
@@ -677,10 +677,10 @@ ao_config_pad_orientation_set(void)
                return;
        _ao_config_edit_start();
        if (ao_config.pad_orientation != r) {
-               int16_t t;
+               accel_t t;
                t = ao_config.accel_plus_g;
-               ao_config.accel_plus_g = AO_ACCEL_INVERT - ao_config.accel_minus_g;
-               ao_config.accel_minus_g = AO_ACCEL_INVERT - t;
+               ao_config.accel_plus_g = ao_data_accel_invert(ao_config.accel_minus_g);
+               ao_config.accel_minus_g = ao_data_accel_invert(t);
        }
        ao_config.pad_orientation = r;
        _ao_config_edit_finish();
@@ -688,13 +688,13 @@ ao_config_pad_orientation_set(void)
 #endif
 
 #if HAS_RADIO
-void
+static void
 ao_config_radio_enable_show(void) 
 {
        printf("Radio enable: %d\n", ao_config.radio_enable);
 }
 
-void
+static void
 ao_config_radio_enable_set(void) 
 {
        uint16_t r = ao_cmd_decimal();
@@ -713,7 +713,7 @@ ao_config_radio_enable_set(void)
 
 uint8_t        ao_config_aes_seq = 1;
 
-void
+static void
 ao_config_key_show(void) 
 {
        uint8_t i;
@@ -723,7 +723,7 @@ ao_config_key_show(void)
        printf("\n");
 }
 
-void
+static void
 ao_config_key_set(void) 
 {
        uint8_t i;
@@ -742,13 +742,13 @@ ao_config_key_set(void)
 
 #if HAS_APRS
 
-void
+static void
 ao_config_aprs_show(void)
 {
        printf ("APRS interval: %d\n", ao_config.aprs_interval);
 }
 
-void
+static void
 ao_config_aprs_set(void)
 {
        uint16_t r = ao_cmd_decimal();
@@ -805,13 +805,13 @@ ao_config_radio_power_set(void)
 #endif
 
 #if HAS_BEEP_CONFIG
-void
+static void
 ao_config_beep_show(void)
 {
        printf ("Beeper setting: %d\n", ao_config.mid_beep);
 }
 
-void
+static void
 ao_config_beep_set(void)
 {
        uint16_t r = ao_cmd_decimal();
@@ -824,7 +824,7 @@ ao_config_beep_set(void)
 #endif
 
 #if HAS_TRACKER
-void
+static void
 ao_config_tracker_show(void)
 {
        printf ("Tracker setting: %d %d\n",
@@ -832,7 +832,7 @@ ao_config_tracker_show(void)
                ao_config.tracker_interval);
 }
 
-void
+static void
 ao_config_tracker_set(void)
 {
        uint16_t        m, i;
@@ -853,13 +853,13 @@ ao_config_tracker_set(void)
 #endif /* HAS_TRACKER */
 
 #if AO_PYRO_NUM
-void
+static void
 ao_config_pyro_time_show(void)
 {
        printf ("Pyro time: %d\n", ao_config.pyro_time);
 }
 
-void
+static void
 ao_config_pyro_time_set(void)
 {
        uint16_t r = ao_cmd_decimal();
@@ -872,14 +872,14 @@ ao_config_pyro_time_set(void)
 #endif
 
 #if HAS_APRS
-void
+static void
 ao_config_aprs_ssid_show(void)
 {
        printf ("APRS SSID: %d\n",
                ao_config.aprs_ssid);
 }
 
-void
+static void
 ao_config_aprs_ssid_set(void)
 {
        uint16_t r = ao_cmd_decimal();
@@ -894,7 +894,7 @@ ao_config_aprs_ssid_set(void)
        _ao_config_edit_finish();
 }
 
-void
+static void
 ao_config_aprs_format_set(void)
 {
        uint16_t r = ao_cmd_decimal();
@@ -905,7 +905,7 @@ ao_config_aprs_format_set(void)
        _ao_config_edit_finish();
 }
 
-void
+static void
 ao_config_aprs_format_show(void)
 {
        printf ("APRS format: %d\n", ao_config.aprs_format);
@@ -913,13 +913,13 @@ ao_config_aprs_format_show(void)
 #endif /* HAS_APRS */
 
 #if HAS_FIXED_PAD_BOX
-void
+static void
 ao_config_pad_box_show(void)
 {
        printf ("Pad box: %d\n", ao_config.pad_box);
 }
 
-void
+static void
 ao_config_pad_box_set(void)
 {
        uint16_t r = ao_cmd_decimal();
@@ -930,13 +930,13 @@ ao_config_pad_box_set(void)
        _ao_config_edit_finish();
 }
 
-void
+static void
 ao_config_pad_idle_show(void)
 {
        printf ("Idle timeout: %d\n", ao_config.pad_idle);
 }
 
-void
+static void
 ao_config_pad_idle_set(void)
 {
        uint16_t r = ao_cmd_decimal();
@@ -960,7 +960,7 @@ ao_config_help(void);
 static void
 ao_config_show(void);
 
-#if HAS_EEPROM
+#if HAS_CONFIG_SAVE
 static void
 ao_config_save(void);
 #endif
@@ -1050,7 +1050,7 @@ const struct ao_config_var ao_config_vars[] = {
 #endif
        { "s\0Show",
          ao_config_show,               0 },
-#if HAS_EEPROM
+#if HAS_CONFIG_SAVE
        { "w\0Write to eeprom",
          ao_config_save,               0 },
 #endif
@@ -1059,7 +1059,7 @@ const struct ao_config_var ao_config_vars[] = {
        { 0, 0, 0 }
 };
 
-void
+static void
 ao_config_set(void)
 {
        char    c;
@@ -1102,7 +1102,7 @@ ao_config_show(void)
 #endif
 }
 
-#if HAS_EEPROM
+#if HAS_CONFIG_SAVE
 static void
 ao_config_save(void) 
 {
index dda5de4c6638bc62161619c677f4a877c345c5b9..a7e58762c0a58dafd11409cb6ed687816e236404 100644 (file)
 #define AO_DATA_ADXL375 0
 #endif
 
+#if HAS_MAX6691
+#include <ao_max6691.h>
+#define AO_DATA_MAX6691 (1 << 4)
+#else
+#define AO_DATA_MAX6691 0
+#endif
+
+#if HAS_BMX160
+#include <ao_bmx160.h>
+#define AO_DATA_BMX160 (1 << 2)
+#else
+#define AO_DATA_BMX160 0
+#endif
+
+#ifndef HAS_SENSOR_ERRORS
+#if HAS_IMU || HAS_MMA655X || HAS_MS5607 || HAS_MS5611
+#define HAS_SENSOR_ERRORS      1
+#endif
+#endif
+
+#if HAS_SENSOR_ERRORS
+extern uint8_t                 ao_sensor_errors;
+#endif
+
 #ifdef AO_DATA_RING
 
-#define AO_DATA_ALL    (AO_DATA_ADC|AO_DATA_MS5607|AO_DATA_MPU6000|AO_DATA_HMC5883|AO_DATA_MMA655X|AO_DATA_MPU9250|AO_DATA_ADXL375)
+#define AO_DATA_ALL    (AO_DATA_ADC|AO_DATA_MS5607|AO_DATA_MPU6000|AO_DATA_HMC5883|AO_DATA_MMA655X|AO_DATA_MPU9250|AO_DATA_ADXL375|AO_DATA_BMX160)
 
 struct ao_data {
        uint16_t                        tick;
@@ -100,6 +124,15 @@ struct ao_data {
 #if HAS_ADXL375
        struct ao_adxl375_sample        adxl375;
 #endif
+#if HAS_MAX6691
+       struct ao_max6691_sample        max6691;
+#endif
+#if HAS_ADS131A0X
+       struct ao_ads131a0x_sample      ads131a0x;
+#endif
+#if HAS_BMX160
+       struct ao_bmx160_sample         bmx160;
+#endif
 };
 
 #define ao_data_ring_next(n)   (((n) + 1) & (AO_DATA_RING - 1))
@@ -119,6 +152,12 @@ extern volatile uint8_t            ao_data_count;
  */
 #define AO_DATA_PRESENT(bit)   (ao_data_present |= (bit))
 
+/*
+ * Mark sensor failed, and unblock the sample collection code by
+ * marking the data as present
+ */
+#define AO_SENSOR_ERROR(bit)   (ao_data_present |= (ao_sensor_errors |= (bit)))
+
 /*
  * Wait until it is time to write a sensor sample; this is
  * signaled by the timer tick
@@ -328,8 +367,6 @@ typedef int16_t     accel_t;
 
 #define HAS_ACCEL      1
 
-#define AO_ACCEL_INVERT                0
-
 typedef int16_t accel_t;
 
 /* MPU6000 is hooked up so that positive y is positive acceleration */
@@ -404,6 +441,29 @@ static inline float ao_convert_accel(int16_t sensor)
 
 #endif
 
+#if !HAS_GYRO && HAS_BMX160
+
+#define HAS_GYRO       1
+
+typedef int16_t        gyro_t;         /* in raw sample units */
+typedef int16_t angle_t;       /* in degrees */
+
+/* Y axis is aligned with the direction of motion (along) */
+/* X axis is aligned in the other board axis (across) */
+/* Z axis is aligned perpendicular to the board (through) */
+
+static inline float ao_convert_gyro(float sensor)
+{
+       return ao_bmx160_gyro(sensor);
+}
+
+static inline float ao_convert_accel(int16_t sensor)
+{
+       return ao_bmx160_accel(sensor);
+}
+
+#endif
+
 #if !HAS_MAG && HAS_HMC5883
 
 #define HAS_MAG                1
@@ -457,6 +517,12 @@ ao_data_fill(int head) {
 #endif
 #if HAS_ADXL375
                ao_data_ring[head].adxl375 = ao_adxl375_current;
+#endif
+#if HAS_MAX6691
+               ao_data_ring[head].max6691 = ao_max6691_current;
+#endif
+#if HAS_ADS131A0X
+               ao_data_ring[head].ads131a0x = ao_ads131a0x_current;
 #endif
                ao_data_ring[head].tick = ao_tick_count;
                ao_data_head = ao_data_ring_next(head);
index cef0a4381e7e685f0df98a8f9726781c44c44683..f5e195adc18b1a5cca6219d0370c39e277cc038a 100644 (file)
@@ -33,6 +33,6 @@ ao_ee_write_config(uint8_t *buf, uint16_t len)
 uint8_t
 ao_ee_read_config(uint8_t *buf, uint16_t len) 
 {
-       ao_xmemset(buf, '\0', len);
+       memset(buf, '\0', len);
        return 1;
 }
index af6b0c55bedd465ed209b8284d503808c35911f5..c66860d0f4790266eb85d1b3ce8bf4832bb1de82 100644 (file)
@@ -43,14 +43,6 @@ extern uint16_t                      ao_boost_tick;
 extern uint16_t                        ao_launch_tick;
 extern uint16_t                        ao_motor_number;
 
-#if HAS_IMU || HAS_MMA655X
-#define HAS_SENSOR_ERRORS      1
-#endif
-
-#if HAS_SENSOR_ERRORS
-extern uint8_t                 ao_sensor_errors;
-#endif
-
 extern uint16_t                        ao_launch_time;
 extern uint8_t                 ao_flight_force_idle;
 
index 81640ce8af72a8678c51158678c063e94f9562c8..5a701b91a69dad94fc4e39e88a1952c7297b58cc 100644 (file)
 /*
  * The provided 'calibration' value is
  * that needed to tune the radio to precisely 434550kHz.
- * Use that to 'walk' to the target frequency by following
- * a 'bresenham' line from 434550kHz to the target
- * frequency, and updating the radio setting along the way
+ * The relation between value and freq is linear, so
+ * to get the value for an arbitrary frequency:
+ *
+ *     target_value   target_freq
+ *     ------------ = ------------
+ *      cal_value       cal_freq
+ *
+ *                     cal_value * target_freq
+ *     target_value = -----------------------
+ *                             cal_freq
  */
 
-int32_t ao_freq_to_set(int32_t freq, int32_t cal) 
+int32_t ao_freq_to_set(int32_t target_freq, int32_t cal_value)
 {
-       static int32_t  set;
-       static uint8_t  neg;
-       static int32_t  error;
+       int64_t prod = (int64_t) target_freq * (int64_t) cal_value;
 
-       set = 0;
-       neg = 0;
-       error = -434550 / 2;
+       /* Round to nearest */
+       int32_t target_value = (prod + (434550 / 2)) / 434550;
 
-       if ((freq -= 434550) < 0) {
-               neg = 1;
-               freq = -freq;
-       }
-       for (;;) {
-               if (error > 0) {
-                       error -= 434550;
-                       set++;
-               } else {
-                       error += cal;
-                       if (--freq < 0)
-                               break;
-               }
-       }
-       if (neg)
-               set = -set;
-       return cal + set;
+       return target_value;
 }
index 0ef9a725fc8481e1103c59fcdc0453e7bba56d71..01226ba5c8b224343e62145072e49a6589a5f8c2 100644 (file)
@@ -32,9 +32,9 @@ ao_gps_report(void)
                        ao_sleep(&ao_gps_new);
                ao_mutex_get(&ao_gps_mutex);
                if (new & AO_GPS_NEW_DATA)
-                       ao_xmemcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data));
+                       memcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data));
                if (new & AO_GPS_NEW_TRACKING)
-                       ao_xmemcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data));
+                       memcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data));
                ao_gps_new = 0;
                ao_mutex_put(&ao_gps_mutex);
 
index 37f1beaa9b1d5d1314c87a7fe2f8b8926bd60d56..0cba972be07ce35bb353e97eba0a3e7b9a8c174b 100644 (file)
@@ -70,9 +70,9 @@ ao_gps_report_mega(void)
                        ao_sleep(&ao_gps_new);
                ao_mutex_get(&ao_gps_mutex);
                if (new & AO_GPS_NEW_DATA)
-                       ao_xmemcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data));
+                       memcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data));
                if (new & AO_GPS_NEW_TRACKING)
-                       ao_xmemcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data));
+                       memcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data));
                ao_gps_new = 0;
                ao_mutex_put(&ao_gps_mutex);
 
index 06863fe4844a05d08ccc98618b7d1efa141a22bb..b5f58893b78184679adbd9d126c8d5ba3532d871 100644 (file)
@@ -19,7 +19,7 @@
 #include "ao.h"
 #include "ao_log.h"
 
-void
+static void
 ao_gps_report_metrum(void)
 {
        static struct ao_log_metrum             gps_log;
@@ -34,9 +34,9 @@ ao_gps_report_metrum(void)
                        ao_sleep(&ao_gps_new);
                ao_mutex_get(&ao_gps_mutex);
                if (new & AO_GPS_NEW_DATA)
-                       ao_xmemcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data));
+                       memcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data));
                if (new & AO_GPS_NEW_TRACKING)
-                       ao_xmemcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data));
+                       memcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data));
                ao_gps_new = 0;
                ao_mutex_put(&ao_gps_mutex);
 
index 592de54ce348b6dc96f1fdcb64e4eba8eb3fd9b3..e2f14e7963a38333c3a2f8686130d99e27006f3e 100644 (file)
@@ -41,12 +41,6 @@ struct ao_adc {
        int16_t         sense_m;        /* main continuity sense */
 };
 
-#define const
-
-#define a      (a)
-#define a      (a)
-#define a      (a)
-
 enum ao_flight_state {
        ao_flight_startup = 0,
        ao_flight_idle = 1,
@@ -127,6 +121,6 @@ struct ao_config {
 
 struct ao_config ao_config = { 250, 16000 };
 
-#define ao_xmemcpy(d,s,c) memcpy(d,s,c)
-#define ao_xmemset(d,v,c) memset(d,v,c)
-#define ao_xmemcmp(d,s,c) memcmp(d,s,c)
+#define memcpy(d,s,c) memcpy(d,s,c)
+#define memset(d,v,c) memset(d,v,c)
+#define memcmp(d,s,c) memcmp(d,s,c)
index a6ff997984e7e6cc20617ac753ef42c431eb7eba..e9d04dcce4ba848641e73d9fbfa06f5bac3d04e5 100644 (file)
@@ -83,7 +83,7 @@ ao_igniter_status(enum ao_igniter igniter)
 #define AO_IGNITER_CHARGE_TIME         AO_MS_TO_TICKS(2000)
 #endif
 
-void
+static void
 ao_igniter_fire(enum ao_igniter igniter)
 {
        ao_ignition[igniter].firing = 1;
@@ -136,7 +136,7 @@ ao_igniter_fire(enum ao_igniter igniter)
        ao_ignition[igniter].firing = 0;
 }
 
-void
+static void
 ao_igniter(void)
 {
        enum ao_igniter igniter;
@@ -159,7 +159,7 @@ ao_igniter(void)
 
 #endif
 
-void
+static void
 ao_ignite_manual(void)
 {
        ao_cmd_white();
@@ -190,7 +190,7 @@ const char * const ao_igniter_status_names[] = {
 };
 
 #if HAS_IGNITE
-void
+static void
 ao_ignite_print_status(enum ao_igniter igniter, const char *name) 
 {
        enum ao_igniter_status status = ao_igniter_status(igniter);
@@ -200,7 +200,7 @@ ao_ignite_print_status(enum ao_igniter igniter, const char *name)
 }
 #endif
 
-void
+static void
 ao_ignite_test(void)
 {
 #if HAS_IGNITE
index 5d982ca6d1f0e7101467d072ce215678e8ae8793..b770381f7efb8aea3dcb379a5cb0981800788328 100644 (file)
@@ -43,7 +43,7 @@ ao_led_set(AO_LED_TYPE colors);
 
 /* Set all LEDs in 'mask' to the specified state */
 void
-ao_led_set_mask(uint8_t colors, uint8_t mask);
+ao_led_set_mask(AO_LED_TYPE colors, AO_LED_TYPE mask);
 
 /* Toggle the specified LEDs */
 void
@@ -51,7 +51,7 @@ ao_led_toggle(AO_LED_TYPE colors);
 
 /* Turn on the specified LEDs for the indicated interval */
 void
-ao_led_for(AO_LED_TYPE colors, uint16_t ticks);
+ao_led_for(AO_LED_TYPE colors, AO_TICK_TYPE ticks);
 
 /* Initialize the LEDs */
 void
index fac211cf32549362b8380f55739c2b2e29a07565..c0a42b295938586cd9f968af2cdb2445ae28e373 100644 (file)
@@ -191,7 +191,7 @@ ao_log_flight(uint8_t slot)
 #endif
 
 static uint8_t
-ao_log_slots()
+ao_log_slots(void)
 {
        return (uint8_t) (ao_storage_log_max / ao_config.flight_log_max);
 }
@@ -405,7 +405,7 @@ ao_log_full(void)
 static struct ao_task ao_log_task;
 #endif
 
-void
+static void
 ao_log_list(void) 
 {
        uint8_t slot;
@@ -425,7 +425,7 @@ ao_log_list(void)
        printf ("done\n");
 }
 
-void
+static void
 ao_log_delete(void) 
 {
        uint8_t slot;
index 04f00d3ec3bd211545e948896994ebff3777736b..97bfdc3273076cf0ab80272fb6e4fee88e31c156 100644 (file)
@@ -56,6 +56,8 @@ extern enum ao_flight_state ao_log_state;
 #define AO_LOG_FORMAT_EASYMINI2                14      /* 16-byte MS5607 baro only, 3.3V supply, stm32f042 SoC */
 #define AO_LOG_FORMAT_TELEMEGA_3       15      /* 32 byte typed telemega records with 32 bit gyro cal and mpu9250 */
 #define AO_LOG_FORMAT_EASYMEGA_2       16      /* 32 byte typed telemega records with 32 bit gyro cal, mpu9250 rotated 90° and adxl375 */
+#define AO_LOG_FORMAT_TELESTATIC       17      /* 32 byte typed telestatic records */
+#define AO_LOG_FORMAT_MICROPEAK2       18      /* 2-byte baro values with header */
 #define AO_LOG_FORMAT_NONE             127     /* No log at all */
 
 /* Return the flight number from the given log slot, 0 if none, -slot on failure */
@@ -338,6 +340,33 @@ struct ao_log_firetwo {
        } u;    /* 32 */
 };
 
+struct ao_log_telestatic {
+       char                    type;                   /* 0 */
+       uint8_t                 csum;                   /* 1 */
+       uint16_t                tick;                   /* 2 */
+       union {                                         /* 4 */
+               /* AO_LOG_FLIGHT */
+               struct {
+                       uint16_t        flight;         /* 4 */
+               } flight;       /* 6 */
+               /* AO_LOG_STATE */
+               struct {
+                       uint16_t        state;          /* 4 */
+                       uint16_t        reason;         /* 6 */
+               } state;        /* 8 */
+               /* AO_LOG_SENSOR */
+               struct {
+                       uint32_t        pressure;       /* 4 */
+                       uint32_t        pressure2;      /* 8 */
+                       uint32_t        thrust;         /* 12 */
+                       uint32_t        mass;           /* 16 */
+                       uint16_t        t_low;          /* 20 */
+                       uint16_t        t_high[4];      /* 22 */
+               } sensor;       /* 30 */
+               uint8_t         align[28];              /* 4 */
+       } u;    /* 32 */
+};
+
 struct ao_log_metrum {
        char                    type;                   /* 0 */
        uint8_t                 csum;                   /* 1 */
@@ -483,6 +512,10 @@ typedef struct ao_log_mega ao_log_type;
 typedef struct ao_log_metrum ao_log_type;
 #endif
 
+#if AO_LOG_FORMAT == AO_LOG_FORMAT_TELEFIRETWO
+typedef struct ao_log_firetwo ao_log_type;
+#endif
+
 #if AO_LOG_FORMAT == AO_LOG_FORMAT_EASYMINI1 || AO_LOG_FORMAT == AO_LOG_FORMAT_EASYMINI2 || AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMINI2 || AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMINI3
 typedef struct ao_log_mini ao_log_type;
 #endif
@@ -507,6 +540,10 @@ typedef struct ao_log_record ao_log_type;
 #define AO_LOG_UNCOMMON        1
 #endif
 
+#if AO_LOG_FORMAT == AO_LOG_FORMAT_MICROPEAK2
+#define AO_LOG_UNCOMMON        1
+#endif
+
 #ifndef AO_LOG_UNCOMMON
 extern ao_log_type ao_log_data;
 
index 3dd52a1651d8580de39ded647f35d6501b8a7d6a..58119ec85b1ce0917d38fdb3b197bf8452821021 100644 (file)
@@ -21,7 +21,7 @@
 #include <ao_data.h>
 #include <ao_flight.h>
 
-static struct ao_log_firetwo log;
+static struct ao_log_firetwo ao_fireone_data;
 
 const uint8_t ao_log_format = AO_LOG_FORMAT_TELEFIRETWO;
 
@@ -36,20 +36,20 @@ ao_log_csum(uint8_t *b)
        return -sum;
 }
 
-uint8_t
-ao_log_firetwo(struct ao_log_firetwo *log) 
+static uint8_t
+ao_log_firetwo(void)
 {
        uint8_t wrote = 0;
        /* set checksum */
-       log->csum = 0;
-       log->csum = ao_log_csum((uint8_t *) log);
+       ao_fireone_data.csum = 0;
+       ao_fireone_data.csum = ao_log_csum((uint8_t *) &ao_fireone_data);
        ao_mutex_get(&ao_log_mutex); {
                if (ao_log_current_pos >= ao_log_end_pos && ao_log_running)
                        ao_log_stop();
                if (ao_log_running) {
                        wrote = 1;
                        ao_storage_write(ao_log_current_pos,
-                                        log,
+                                        &ao_fireone_data,
                                         sizeof (struct ao_log_firetwo));
                        ao_log_current_pos += sizeof (struct ao_log_firetwo);
                }
@@ -57,16 +57,8 @@ ao_log_firetwo(struct ao_log_firetwo *log)
        return wrote;
 }
 
-static uint8_t
-ao_log_dump_check_data(void)
-{
-       if (ao_log_csum((uint8_t *) &log) != 0)
-               return 0;
-       return 1;
-}
-
 #if HAS_ADC
-static uint8_t ao_log_data_pos;
+static uint8_t ao_fireone_data_pos;
 
 /* a hack to make sure that ao_log_metrums fill the eeprom block in even units */
 typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_firetwo))] ;
@@ -75,8 +67,6 @@ typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_firetwo))] ;
 void
 ao_log(void)
 {
-       uint16_t ao_flight_state = ao_flight_startup;
-
        ao_storage_setup();
 
        do {
@@ -85,42 +75,29 @@ ao_log(void)
                while (!ao_log_running)
                        ao_sleep(&ao_log_running);
        
-               log.type = AO_LOG_FLIGHT;
-               log.tick = ao_time();
-               log.u.flight.flight = ao_flight_number;
-               ao_log_firetwo(&log);
+               ao_fireone_data.type = AO_LOG_FLIGHT;
+               ao_fireone_data.tick = ao_time();
+               ao_fireone_data.u.flight.flight = ao_flight_number;
+               ao_log_firetwo();
 
                /* Write the whole contents of the ring to the log
                * when starting up.
                */
-               ao_log_data_pos = ao_data_ring_next(ao_data_head);
-               ao_log_state = ao_flight_startup;
+               ao_fireone_data_pos = ao_data_ring_next(ao_data_head);
                for (;;) {
                        /* Write samples to EEPROM */
-                       while (ao_log_data_pos != ao_data_head) {
-                               log.tick = ao_data_ring[ao_log_data_pos].tick;
-                               log.type = AO_LOG_SENSOR;
-                               log.u.sensor.pressure = ao_data_ring[ao_log_data_pos].adc.pressure;
-                               log.u.sensor.thrust = ao_data_ring[ao_log_data_pos].adc.thrust;
+                       while (ao_fireone_data_pos != ao_data_head) {
+                               ao_fireone_data.tick = ao_data_ring[ao_fireone_data_pos].tick;
+                               ao_fireone_data.type = AO_LOG_SENSOR;
+                               ao_fireone_data.u.sensor.pressure = ao_data_ring[ao_fireone_data_pos].adc.pressure;
+                               ao_fireone_data.u.sensor.thrust = ao_data_ring[ao_fireone_data_pos].adc.thrust;
        //                      for (i = 0; i < 4; i++) {
-       //                              log.u.sensor.thermistor[i] = ao_data_ring[ao_log_data_pos].sensor.thermistor[i];
+       //                              ao_fireone_data.u.sensor.thermistor[i] = ao_data_ring[ao_fireone_data_pos].sensor.thermistor[i];
        //                      }
-                               ao_log_firetwo(&log);
-                               ao_log_data_pos = ao_data_ring_next(ao_log_data_pos);
+                               ao_log_firetwo();
+                               ao_fireone_data_pos = ao_data_ring_next(ao_fireone_data_pos);
                        }
-                       /* Write state change to EEPROM */
-                       if (ao_flight_state != ao_log_state) {
-                               ao_log_state = ao_flight_state;
-                               log.type = AO_LOG_STATE;
-                               log.tick = ao_time();
-                               log.u.state.state = ao_log_state;
-                               log.u.state.reason = 0;
-                               ao_log_firetwo(&log);
-       
-                               if (ao_log_state == ao_flight_landed)
-                                       ao_log_stop();
-                       }
-       
+
                        ao_log_flush();
 
                        if (!ao_log_running) break;
@@ -131,15 +108,3 @@ ao_log(void)
        } while (ao_log_running);
 }
 
-uint16_t
-ao_log_flight(uint8_t slot)
-{
-       if (!ao_storage_read(ao_log_pos(slot),
-                            &log,
-                            sizeof (struct ao_log_firetwo)))
-               return 0;
-
-       if (ao_log_dump_check_data() && log.type == AO_LOG_FLIGHT)
-               return log.u.flight.flight;
-       return 0;
-}
index cc947d6e8c634f2b2a404ba33705e2449abe7e32..096c8383e7da70271147e7ce6c5e4a53ab5bdf0f 100644 (file)
@@ -28,4 +28,7 @@ ao_log_gps_flight(void);
 void
 ao_log_gps_data(uint16_t tick, struct ao_telemetry_location *gps_data);
 
+void
+ao_log_gps_tracking(uint16_t tick, struct ao_telemetry_satellite *gps_tracking_data);
+
 #endif /* _AO_LOG_GPS_H_ */
index 8c0b88e47441e0a30cd1264f429bf51be7a84d5f..f985417a310a27c2090c605cf358686770a1b859 100644 (file)
@@ -103,7 +103,7 @@ ao_log_single(void)
                while (ao_log_running) {
                        /* Write samples to EEPROM */
                        while (ao_log_monitor_pos != ao_monitor_head) {
-                               ao_xmemcpy(&ao_log_single_write_data.telemetry,
+                               memcpy(&ao_log_single_write_data.telemetry,
                                           &ao_monitor_ring[ao_log_monitor_pos],
                                           AO_LOG_SINGLE_SIZE);
                                ao_log_single_write();
diff --git a/src/kernel/ao_log_telestatic.c b/src/kernel/ao_log_telestatic.c
new file mode 100644 (file)
index 0000000..fdf8da4
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright © 2017 Bdale Garbee <bdale@gag.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+#include <ao_log.h>
+#include <ao_data.h>
+#include <ao_flight.h>
+
+static struct ao_log_telestatic log;
+
+const uint8_t ao_log_format = AO_LOG_FORMAT_TELESTATIC;
+
+static uint8_t
+ao_log_csum(uint8_t *b) 
+{
+       uint8_t sum = 0x5a;
+       uint8_t i;
+
+       for (i = 0; i < sizeof (struct ao_log_telestatic); i++)
+               sum += *b++;
+       return -sum;
+}
+
+static uint8_t
+ao_log_telestatic(void)
+{
+       uint8_t wrote = 0;
+       /* set checksum */
+       log.csum = 0;
+       log.csum = ao_log_csum((uint8_t *) &log);
+       ao_mutex_get(&ao_log_mutex); {
+               if (ao_log_current_pos >= ao_log_end_pos && ao_log_running)
+                       ao_log_stop();
+               if (ao_log_running) {
+                       wrote = 1;
+                       ao_storage_write(ao_log_current_pos,
+                                        &log,
+                                        sizeof (struct ao_log_telestatic));
+                       ao_log_current_pos += sizeof (struct ao_log_telestatic);
+               }
+       } ao_mutex_put(&ao_log_mutex);
+       return wrote;
+}
+
+#if HAS_ADC
+static uint8_t ao_log_data_pos;
+
+/* a hack to make sure that ao_log_metrums fill the eeprom block in even units */
+typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_telestatic))] ;
+#endif
+
+void
+ao_log(void)
+{
+       ao_storage_setup();
+
+       do {
+               ao_log_scan();
+       
+               while (!ao_log_running)
+                       ao_sleep(&ao_log_running);
+       
+               log.type = AO_LOG_FLIGHT;
+               log.tick = ao_time();
+               log.u.flight.flight = ao_flight_number;
+               ao_log_telestatic();
+
+               /* Write the whole contents of the ring to the log
+               * when starting up.
+               */
+               ao_log_data_pos = ao_data_ring_next(ao_data_head);
+               for (;;) {
+                       /* Write samples to EEPROM */
+                       while (ao_log_data_pos != ao_data_head) {
+                               log.tick = ao_data_ring[ao_log_data_pos].tick;
+                               log.type = AO_LOG_SENSOR;
+#if HAS_ADS131A0X
+                               log.u.sensor.pressure = ao_data_ring[ao_log_data_pos].ads131a0x.ain[0];
+                               log.u.sensor.pressure2 = ao_data_ring[ao_log_data_pos].ads131a0x.ain[1];
+                               log.u.sensor.thrust = ao_data_ring[ao_log_data_pos].ads131a0x.ain[2];
+                               log.u.sensor.mass = ao_data_ring[ao_log_data_pos].ads131a0x.ain[3];
+#endif
+                               log.u.sensor.t_low = ao_data_ring[ao_log_data_pos].max6691.sensor[0].t_low;
+                               int i;
+                               for (i = 0; i < 4; i++)
+                                       log.u.sensor.t_high[i] = ao_data_ring[ao_log_data_pos].max6691.sensor[i].t_high;
+                               ao_log_telestatic();
+                               ao_log_data_pos = ao_data_ring_next(ao_log_data_pos);
+                       }
+
+                       ao_log_flush();
+
+                       if (!ao_log_running) break;
+
+                       /* Wait for a while */
+                       ao_delay(AO_MS_TO_TICKS(100));
+               }
+       } while (ao_log_running);
+}
+
index 3f1ff217b18d2b4336eb2baba1befc1033d216f8..cd5116990b7046e83789dfbbe2431e620be74170 100644 (file)
@@ -62,7 +62,7 @@ _ao_monitor_adjust(void)
        ao_wakeup(&ao_monitoring);
 }
 
-void
+static void
 ao_monitor_get(void)
 {
        uint8_t size;
@@ -93,7 +93,7 @@ ao_monitor_get(void)
 #if AO_MONITOR_LED
 struct ao_task ao_monitor_blink_task;
 
-void
+static void
 ao_monitor_blink(void)
 {
 #ifdef AO_MONITOR_BAD
@@ -121,7 +121,7 @@ static const char xdigit[16] = {
 
 #define hex(c) do { putchar(xdigit[(c) >> 4]); putchar(xdigit[(c)&0xf]); } while (0)
 
-void
+static void
 ao_monitor_put(void)
 {
 #if LEGACY_MONITOR
@@ -157,7 +157,7 @@ ao_monitor_put(void)
                        state = recv_orig.telemetry_orig.flight_state;
 
                        rssi = (int16_t) AO_RSSI_FROM_RADIO(recv_orig.rssi);
-                       ao_xmemcpy(callsign, recv_orig.telemetry_orig.callsign, AO_MAX_CALLSIGN);
+                       memcpy(callsign, recv_orig.telemetry_orig.callsign, AO_MAX_CALLSIGN);
                        if (state > ao_flight_invalid)
                                state = ao_flight_invalid;
                        if (recv_orig.status & PKT_APPEND_STATUS_1_CRC_OK) {
index 155fce350b69f77c464d5fefe747ede3c6478b14..c7b48e06a338aa7b3c6d08aea9c3eb765f3cce96 100644 (file)
@@ -132,7 +132,7 @@ ao_radio_cmac_send(void *packet, uint8_t len)
        if (len > AO_CMAC_MAX_LEN)
                return AO_RADIO_CMAC_LEN_ERROR;
        ao_mutex_get(&ao_radio_cmac_mutex);
-       ao_xmemcpy(cmac_data, packet, len);
+       memcpy(cmac_data, packet, len);
 #if AO_LED_TX
        ao_led_on(AO_LED_TX);
 #endif
@@ -159,7 +159,7 @@ ao_radio_cmac_recv(void *packet, uint8_t len, uint16_t timeout)
        ao_led_off(AO_LED_RX);
 #endif
        if (i == AO_RADIO_CMAC_OK)
-               ao_xmemcpy(packet, cmac_data, len);
+               memcpy(packet, cmac_data, len);
        ao_mutex_put(&ao_radio_cmac_mutex);
        return i;
 }
index 08967af8450f3f2701b82e3c3df146e801dfa5e1..12c3a1e90acabb589114ed786edb08caf9a7c0fb 100644 (file)
@@ -251,7 +251,7 @@ ao_report_continuity(void)
 }
 #endif
 
-void
+static void
 ao_report(void)
 {
        for(;;) {
@@ -262,6 +262,11 @@ ao_report(void)
                else
 #endif
                        ao_report_beep();
+#if HAS_SENSOR_ERRORS
+               if (ao_report_state == ao_flight_invalid && ao_sensor_errors)
+                       ao_report_number(ao_sensor_errors);
+#endif
+
                if (ao_report_state == ao_flight_landed) {
                        ao_report_altitude();
 #if HAS_FLIGHT
index cae25151f4db99077a061123f2bb69792bba3c3a..ee4685998215a7899f123caf2780abc88ebdc00a 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 #include "ao.h"
+#include "ao_send_packet.h"
 
 #define AO_MAX_SEND    128
 
index 440b562b0b26e5c00ad3bf2ca8b22093b51e5d54..3500a0933d80b268898656fb123b212d5c6ff65c 100644 (file)
@@ -117,6 +117,9 @@ void
 ao_serial3_set_speed(uint8_t speed);
 #endif
 
+void
+ao_serial_shutdown(void);
+
 void
 ao_serial_init(void);
 
index c3b51d123ef1407702200798feaf17c6711c3e02..a42c97fbb2ecd085c87ce6b59ace4aaae788aa1c 100644 (file)
@@ -145,13 +145,13 @@ ao_echo(void)
 int8_t
 ao_add_stdio(int (*_pollchar)(void),
             void (*putchar)(char),
-            void (*flush)(void)) 
+            void (*_flush)(void)) 
 {
        if (ao_num_stdios == AO_NUM_STDIOS)
                ao_panic(AO_PANIC_STDIO);
        ao_stdios[ao_num_stdios]._pollchar = _pollchar;
        ao_stdios[ao_num_stdios].putchar = putchar;
-       ao_stdios[ao_num_stdios].flush = flush;
+       ao_stdios[ao_num_stdios].flush = _flush;
        ao_stdios[ao_num_stdios].echo = 1;
 #if AO_NUM_STDIOS > 1
        return ao_num_stdios++;
index 890bdcae9af991b457d018b69b179d5d72828de4..cfd116f9791bc536ae2e5709ddc066a3d84f3d8e 100644 (file)
 #include <ao_storage.h>
 
 uint8_t
-ao_storage_read(ao_pos_t pos, void *buf, uint16_t len) 
+ao_storage_read(ao_pos_t pos, void *v_buf, uint16_t len) 
 {
-#ifdef CC1111
-       return ao_storage_device_read(pos, buf, len);
-#else
+       uint8_t *buf = v_buf;
        uint16_t this_len;
        uint16_t this_off;
 
@@ -50,15 +48,12 @@ ao_storage_read(ao_pos_t pos, void *buf, uint16_t len)
                pos += this_len;
        }
        return 1;
-#endif
 }
 
 uint8_t
-ao_storage_write(ao_pos_t pos, void *buf, uint16_t len) 
+ao_storage_write(ao_pos_t pos, void *v_buf, uint16_t len) 
 {
-#ifdef CC1111
-       return ao_storage_device_write(pos, buf, len);
-#else
+       uint8_t *buf = v_buf;
        uint16_t this_len;
        uint16_t this_off;
 
@@ -84,7 +79,6 @@ ao_storage_write(ao_pos_t pos, void *buf, uint16_t len)
                pos += this_len;
        }
        return 1;
-#endif
 }
 
 static uint8_t storage_data[128];
@@ -143,7 +137,7 @@ ao_storage_store(void)
 }
 #endif
 
-void
+static void
 ao_storage_zap(void) 
 {
        uint32_t v = ao_cmd_hex();
@@ -152,7 +146,7 @@ ao_storage_zap(void)
        ao_storage_erase((uint32_t) v << 8);
 }
 
-void
+static void
 ao_storage_zapall(void) 
 {
        uint32_t        pos;
@@ -312,7 +306,7 @@ ao_storage_test(void)
 }
 #endif /* AO_STORAGE_TEST */
 
-void
+static void
 ao_storage_info(void) 
 {
        ao_storage_setup();
index dc5c19132caeb121a21b5bbe0698da713a68c9d8..0bc85d40aad2dc86c2df71ee884fb313733fbcb7 100644 (file)
@@ -67,7 +67,7 @@ static inline void ao_check_stack(void) {
 
 static struct ao_list  run_queue;
 static struct ao_list  alarm_queue;
-static struct ao_list  sleep_queue[SLEEP_HASH_SIZE];
+static struct ao_list  ao_sleep_queue[SLEEP_HASH_SIZE];
 
 static void
 ao_task_to_run_queue(struct ao_task *task)
@@ -80,7 +80,7 @@ ao_task_to_run_queue(struct ao_task *task)
 static struct ao_list *
 ao_task_sleep_queue(void *wchan)
 {
-       return &sleep_queue[(uintptr_t) wchan % SLEEP_HASH_SIZE];
+       return &ao_sleep_queue[(uintptr_t) wchan % SLEEP_HASH_SIZE];
 }
 
 static void
@@ -195,7 +195,7 @@ ao_task_init(void)
        ao_list_init(&alarm_queue);
        ao_task_alarm_tick = 0;
        for (i = 0; i < SLEEP_HASH_SIZE; i++)
-               ao_list_init(&sleep_queue[i]);
+               ao_list_init(&ao_sleep_queue[i]);
 }
 
 #if DEBUG
@@ -290,7 +290,7 @@ ao_task_validate(void)
 #endif /* HAS_TASK_QUEUE */
 
 void
-ao_add_task(struct ao_task * task, void (*start)(void), const char *name) 
+ao_add_task(struct ao_task * task, void (*task_func)(void), const char *name) 
 {
        uint8_t task_id;
        uint8_t t;
@@ -310,7 +310,7 @@ ao_add_task(struct ao_task * task, void (*start)(void), const char *name)
         * Construct a stack frame so that it will 'return'
         * to the start of the task
         */
-       ao_arch_init_stack(task, start);
+       ao_arch_init_stack(task, task_func);
        ao_arch_critical(
 #if HAS_TASK_QUEUE
                ao_task_init_queue(task);
index 709e10c60ce6f602a832a5b2396ee07390eeaaf1..03b629693c0e44baa9ba61a24caa39edc6d61ff4 100644 (file)
 #define HAS_TASK_INFO 1
 #endif
 
-/* arm stacks must be 32-bit aligned */
+/* arm stacks must be 64-bit aligned */
 #ifndef AO_STACK_ALIGNMENT
 #ifdef __arm__
-#define AO_STACK_ALIGNMENT __attribute__ ((aligned(4)))
+#define AO_STACK_ALIGNMENT __attribute__ ((aligned(8)))
 #else
 #define AO_STACK_ALIGNMENT
 #endif
 
 /* An AltOS task */
 struct ao_task {
-       void *wchan;            /* current wait channel (NULL if running) */
+       void *wchan;                    /* current wait channel (NULL if running) */
        uint16_t alarm;                 /* abort ao_sleep time */
-       ao_arch_task_members            /* any architecture-specific fields */
-       uint8_t task_id;                /* unique id */
+       uint16_t task_id;               /* unique id */
+       /* Saved stack pointer */
+       union {
+               uint32_t        *sp32;
+               uint8_t         *sp8;
+       };
        const char *name;               /* task name */
-#ifdef NEWLIB
-       int __errno;                    /* storage for errno in newlib libc */
-#endif
 #if HAS_TASK_QUEUE
        struct ao_list  queue;
        struct ao_list  alarm_queue;
 #endif
-       uint8_t stack[AO_STACK_SIZE] AO_STACK_ALIGNMENT;        /* saved stack */
+       /* Provide both 32-bit and 8-bit stacks */
+       union {
+               uint32_t stack32[AO_STACK_SIZE>>2];
+               uint8_t stack8[AO_STACK_SIZE];
+       } AO_STACK_ALIGNMENT;
 #if HAS_SAMPLE_PROFILE
        uint32_t ticks;
        uint32_t yields;
index 9e1304f73feec119c0f85ab814088c948a93179a..2aceaf283c893fa49b10a4c2228ada1eb229c626 100644 (file)
@@ -58,7 +58,7 @@ static uint16_t ao_aprs_time;
 #define AO_SEND_MEGA   1
 #endif
 
-#if defined (TELEMETRUM_V_2_0)
+#if defined (TELEMETRUM_V_2_0) || defined (TELEMETRUM_V_3_0)
 #define AO_SEND_METRUM 1
 #endif
 
@@ -333,12 +333,12 @@ ao_send_configuration(void)
 #endif
 
                telemetry.configuration.flight_log_max = ao_config.flight_log_max >> 10;
-               ao_xmemcpy (telemetry.configuration.callsign,
-                           ao_config.callsign,
-                           AO_MAX_CALLSIGN);
-               ao_xmemcpy (telemetry.configuration.version,
-                           ao_version,
-                           AO_MAX_VERSION);
+               memcpy (telemetry.configuration.callsign,
+                       ao_config.callsign,
+                       AO_MAX_CALLSIGN);
+               memcpy (telemetry.configuration.version,
+                       ao_version,
+                       AO_MAX_VERSION);
                ao_telemetry_config_cur = ao_telemetry_config_max;
                ao_telemetry_send();
        }
@@ -350,6 +350,18 @@ static int8_t ao_telemetry_gps_max;
 static int8_t ao_telemetry_loc_cur;
 static int8_t ao_telemetry_sat_cur;
 
+static inline void *
+telemetry_bits(struct ao_telemetry_location *l)
+{
+       return ((uint8_t *) l) + offsetof(struct ao_telemetry_location, flags);
+}
+
+static inline int
+telemetry_size(void)
+{
+       return sizeof(struct ao_telemetry_location) - offsetof(struct ao_telemetry_location, flags);
+}
+
 static void
 ao_send_location(void)
 {
@@ -357,9 +369,9 @@ ao_send_location(void)
        {
                telemetry.generic.type = AO_TELEMETRY_LOCATION;
                ao_mutex_get(&ao_gps_mutex);
-               ao_xmemcpy(&telemetry.location.flags,
-                      &ao_gps_data.flags,
-                      27);
+               memcpy(telemetry_bits(&telemetry.location),
+                      telemetry_bits(&ao_gps_data),
+                      telemetry_size());
                telemetry.location.tick = ao_gps_tick;
                ao_mutex_put(&ao_gps_mutex);
                ao_telemetry_loc_cur = ao_telemetry_gps_max;
@@ -375,7 +387,7 @@ ao_send_satellite(void)
                telemetry.generic.type = AO_TELEMETRY_SATELLITE;
                ao_mutex_get(&ao_gps_mutex);
                telemetry.satellite.channels = ao_gps_tracking_data.channels;
-               ao_xmemcpy(&telemetry.satellite.sats,
+               memcpy(&telemetry.satellite.sats,
                       &ao_gps_tracking_data.sats,
                       AO_MAX_GPS_TRACKING * sizeof (struct ao_telemetry_satellite_info));
                ao_mutex_put(&ao_gps_mutex);
@@ -399,7 +411,7 @@ ao_send_companion(void)
                telemetry.companion.update_period = ao_companion_setup.update_period;
                telemetry.companion.channels = ao_companion_setup.channels;
                ao_mutex_get(&ao_companion_mutex);
-               ao_xmemcpy(&telemetry.companion.companion_data,
+               memcpy(&telemetry.companion.companion_data,
                       ao_companion_data,
                       ao_companion_setup.channels * 2);
                ao_mutex_put(&ao_companion_mutex);
@@ -409,7 +421,7 @@ ao_send_companion(void)
 }
 #endif
 
-void
+static void
 ao_telemetry(void)
 {
        uint16_t        time;
index f8b5c7f5d43d9e4e41861da10df0d3a680c88c59..559b3655b75066a97db93575214499ffde6316f8 100644 (file)
@@ -40,7 +40,7 @@ PRODUCT=LambdaKey-v1.0
 PRODUCT_DEF=-DLAMBDAKEY
 IDPRODUCT=0x000a
 
-CFLAGS = $(PRODUCT_DEF) -I. -I$(aoschemelib) $(STMF0_CFLAGS) -Os -g
+CFLAGS = $(PRODUCT_DEF) -I. -I$(aoschemelib) $(STMF0_CFLAGS)
 
 PROGNAME=lambdakey-v1.0
 PROG=$(PROGNAME)-$(VERSION).elf
@@ -55,13 +55,10 @@ bletch:
 all: $(PROG) $(HEX)
 
 $(PROG): Makefile $(OBJ)
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) -Wl,-M=$(PROGNAME).map
 
 $(OBJ): $(INC)
 
-ao_product.h: ao-make-product.5c ../Version
-       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
-
 ao_scheme_const.h: ao-scheme-make-const ao_scheme_basic_syntax.scheme
        $^ -o $@ -d FLOAT,VECTOR,QUASI,BIGINT,POSIX,PORT,SAVE,UNDEF
 
index a608d8e49c3b90ec58ee0f10adadda3ba7a523b6..c50317c01a5fbea013257bcc1b292cdd729252e2 100644 (file)
@@ -15,7 +15,7 @@
 #include <ao.h>
 #include <ao_scheme.h>
 
-static void scheme_cmd() {
+static void scheme_cmd(void) {
        ao_scheme_read_eval_print(stdin, stdout, false);
 }
 
@@ -43,7 +43,7 @@ _ao_scheme_getc(void)
 void main(void)
 {
 #ifdef LEDS_AVAILABLE
-       ao_led_init(LEDS_AVAILABLE);
+       ao_led_init();
 #endif
        ao_clock_init();
        ao_timer_init();
index 4a245d103989a70b267f035eff07ec3447978337..44b43bfe94d5f627f6f5bfc3b9f26d7a702eab22 100644 (file)
@@ -33,7 +33,7 @@ PRODUCT=AltosFlash
 PRODUCT_DEF=-DALTOS_FLASH
 IDPRODUCT=0x000a
 
-CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) -g -Os
+CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS)
 
 LDFLAGS=$(CFLAGS) -L$(TOPDIR)/lpc -Wl,-Taltos-loader.ld
 
@@ -41,10 +41,7 @@ PROGNAME=altos-flash
 PROG=$(HARDWARE)-$(PROGNAME)-$(VERSION).elf
 
 $(PROG): Makefile $(OBJ) altos-loader.ld
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
-
-ao_product.h: ao-make-product.5c $(TOPDIR)/Version
-       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+       $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS)
 
 $(OBJ): $(INC)
 
index edeedaf0a15f03c53435f3eee05754e0f7a3d54d..8b2973512ba9d58b2e045631bfb22d90b91c9070 100644 (file)
@@ -2,51 +2,13 @@ ifndef TOPDIR
 TOPDIR=..
 endif
 
-include $(TOPDIR)/Makedefs
+include $(TOPDIR)/Makefile.defs
 
-vpath % $(TOPDIR)/lpc:$(TOPDIR)/product:$(TOPDIR)/drivers:$(TOPDIR)/kernel:$(TOPDIR)/util:$(TOPDIR)/kalman:$(TOPDIR)/aes:$(TOPDIR):$(TOPDIR)/math
-vpath make-altitude $(TOPDIR)/util
-vpath make-kalman $(TOPDIR)/util
-vpath kalman.5c $(TOPDIR)/kalman
-vpath kalman_filter.5c $(TOPDIR)/kalman
-vpath load_csv.5c $(TOPDIR)/kalman
-vpath matrix.5c $(TOPDIR)/kalman
-vpath ao-make-product.5c $(TOPDIR)/util
+vpath % $(TOPDIR)/lpc:$(AO_VPATH)
 
-.SUFFIXES: .elf .ihx
-
-.elf.ihx:
-       $(ELFTOHEX) --output=$@ $*.elf
-
-
-ifndef VERSION
-include $(TOPDIR)/Version
-endif
-
-ELFTOHEX=$(TOPDIR)/../ao-tools/ao-elftohex/ao-elftohex
 CC=$(ARM_CC)
 
-WARN_FLAGS=-Wall -Wextra -Werror -Wcast-align
-
-AO_CFLAGS=-I. -I$(TOPDIR)/lpc -I$(TOPDIR)/kernel -I$(TOPDIR)/drivers \
-       -DNEWLIB_INTEGER_PRINTF_SCANF \
-       -I$(TOPDIR)/product -I$(TOPDIR) -I$(TOPDIR)/math -I$(TOPDIR) \
-       -isystem $(NEWLIB_NANO)/arm-none-eabi/include
-
-LPC_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m0 -mthumb\
-       -ffreestanding -nostdlib $(AO_CFLAGS) $(WARN_FLAGS)
-
-NICKLE=nickle
-
 LIBS=-L$(NEWLIB_NANO)/arm-none-eabi/lib/thumb/v6-m -lc -lm -lgcc
 
-V=0
-# The user has explicitly enabled quiet compilation.
-ifeq ($(V),0)
-quiet = @printf "  $1 $2 $@\n"; $($1)
-endif
-# Otherwise, print the full command line.
-quiet ?= $($1)
-
-.c.o:
-       $(call quiet,CC) -c $(CFLAGS) -o $@ $<
+LPC_CFLAGS=-mlittle-endian -mcpu=cortex-m0 -mthumb\
+        -I$(TOPDIR)/lpc $(AO_CFLAGS) $(NEWLIB_CFLAGS)
index 5bb8133d5579cb82955356b0bb77557ba31c1e72..7fdcf0dc4770a0050e6fbd6c35eb65967a7d7f5a 100644 (file)
@@ -3,7 +3,6 @@ TOPDIR=..
 endif
 
 include $(TOPDIR)/lpc/Makefile-lpc.defs
-include $(TOPDIR)/Makedefs
 
 LDFLAGS=$(CFLAGS) -L$(TOPDIR)/lpc -Wl,-Taltos.ld -n
 
@@ -11,5 +10,3 @@ ao_serial_lpc.h: $(TOPDIR)/lpc/baud_rate ao_pins.h
        nickle $(TOPDIR)/lpc/baud_rate `awk '/AO_LPC_CLKOUT/{print $$3}' ao_pins.h` > $@
 
 ao_serial_lpc.o: ao_serial_lpc.h
-
-.DEFAULT_GOAL=all
index 35dcc9de57e2ad58286beab8d3f7cb5cfe67d45d..93676b860ff6c9edfb79804805307f288fd67c75 100644 (file)
 
 #define AO_LED_TYPE    AO_PORT_TYPE
 
-#ifndef AO_TICK_TYPE
-#define AO_TICK_TYPE   uint16_t
-#define AO_TICK_SIGNED int16_t
-#endif
-
 /* Various definitions to make GCC look more like SDCC */
 
 #define ao_arch_naked_declare  __attribute__((naked))
@@ -60,9 +55,6 @@
 
 #define AO_ROMCONFIG_SYMBOL __attribute__((section(".romconfig"))) const
 
-#define ao_arch_task_members\
-       uint32_t *sp;                   /* saved stack pointer */
-
 #define ao_arch_block_interrupts()     asm("cpsid i")
 #define ao_arch_release_interrupts()   asm("cpsie i")
 
index 0454b38b012e71f80d1dae78928dbe549579229e..1368f7e5e883ad4b8c94adf626d9d85db7657b67 100644 (file)
@@ -101,7 +101,7 @@ ao_arch_irqrestore(uint32_t primask) {
 }
 
 static inline void
-ao_arch_memory_barrier() {
+ao_arch_memory_barrier(void) {
        asm volatile("" ::: "memory");
 }
 
@@ -109,7 +109,7 @@ ao_arch_memory_barrier() {
 static inline void
 ao_arch_init_stack(struct ao_task *task, void *start)
 {
-       uint32_t        *sp = (uint32_t *) (void *) (task->stack + AO_STACK_SIZE);
+       uint32_t        *sp = &task->stack32[AO_STACK_SIZE >> 2];
        uint32_t        a = (uint32_t) start;
        int             i;
 
@@ -127,7 +127,7 @@ ao_arch_init_stack(struct ao_task *task, void *start)
        /* PRIMASK with interrupts enabled */
        ARM_PUSH32(sp, 0);
 
-       task->sp = sp;
+       task->sp32 = sp;
 }
 
 static inline void ao_arch_save_regs(void) {
@@ -146,17 +146,14 @@ static inline void ao_arch_save_regs(void) {
 static inline void ao_arch_save_stack(void) {
        uint32_t        *sp;
        asm("mov %0,sp" : "=&r" (sp) );
-       ao_cur_task->sp = (sp);
-       if ((uint8_t *) sp < &ao_cur_task->stack[0])
+       ao_cur_task->sp32 = (sp);
+       if (sp < &ao_cur_task->stack32[0])
                ao_panic (AO_PANIC_STACK);
 }
 
 static inline void ao_arch_restore_stack(void) {
-       uint32_t        sp;
-       sp = (uint32_t) ao_cur_task->sp;
-
        /* Switch stacks */
-       asm("mov sp, %0" : : "r" (sp) );
+       asm("mov sp, %0" : : "r" (ao_cur_task->sp32) );
 
        /* Restore PRIMASK */
        asm("pop {r0}");
@@ -258,6 +255,9 @@ static inline void ao_spi_send_byte(uint8_t byte, uint8_t spi_index)
                }                                                       \
        } while (0)
 
+void
+ao_debug_out(char c);
+
 #define HAS_ARCH_START_SCHEDULER       1
 
 static inline void ao_arch_start_scheduler(void) {
@@ -272,4 +272,6 @@ static inline void ao_arch_start_scheduler(void) {
        asm("isb");
 }
 
+void start(void);
+
 #endif /* _AO_ARCH_FUNCS_H_ */
index 75f2cf5fd7e7aeb11ca33d2bb34e7d0798908ddf..226979bc36c3c83755bb63920adf672bd1b9f065 100644 (file)
 #define AO_EXTI_PIN_NOCONFIGURE        64
 
 void
-ao_exti_setup(uint8_t gpio, uint8_t pin, uint8_t mode, void (*callback)());
+ao_exti_setup(uint8_t gpio, uint8_t pin, uint8_t mode, void (*callback)(void));
 
 void
 ao_exti_set_mode(uint8_t gpio, uint8_t pin, uint8_t mode);
 
 void
-ao_exti_set_callback(uint8_t gpio, uint8_t pin, void (*callback)());
+ao_exti_set_callback(uint8_t gpio, uint8_t pin, void (*callback)(void));
 
 void
 ao_exti_enable(uint8_t gpio, uint8_t pin);
index 193f45470b4ca6dee4774c2587f413af1d5c747d..12016072f7037e625c5006708fc4c39f507ee88f 100644 (file)
@@ -140,7 +140,7 @@ ao_exti_set_mode(uint8_t port, uint8_t pin, uint8_t mode)
 }
 
 void
-ao_exti_set_callback(uint8_t port, uint8_t pin, void (*callback)()) {
+ao_exti_set_callback(uint8_t port, uint8_t pin, void (*callback)(void)) {
        uint8_t         id = pin_id(port,pin);
        uint8_t         pint = ao_pint_map[id];
 
index 3a2d4c9886986b72889c50a07c0d13a0ba937cde..46bf0495988dfa82446ab7a49cb8b43cd4cdbc15 100644 (file)
@@ -49,7 +49,7 @@ ao_led_toggle(AO_PORT_TYPE colors)
 }
 
 void
-ao_led_for(AO_PORT_TYPE colors, uint16_t ticks) 
+ao_led_for(AO_PORT_TYPE colors, AO_TICK_TYPE ticks) 
 {
        ao_led_on(colors);
        ao_delay(ticks);
index 8999c7acf1af925e67d17125320644f503811eae..62b16318107f74fc354783ab8520390ac54d524b 100644 (file)
 
 #include <ao.h>
 
+#define AO_SYSTICK     (AO_LPC_SYSCLK / 2)
+
 volatile AO_TICK_TYPE ao_tick_count;
 
-uint16_t
+AO_TICK_TYPE
 ao_time(void)
 {
        return ao_tick_count;
 }
 
+uint64_t
+ao_time_ns(void)
+{
+       AO_TICK_TYPE    before, after;
+       uint32_t        cvr;
+
+       do {
+               before = ao_tick_count;
+               cvr = lpc_systick.cvr;
+               after = ao_tick_count;
+       } while (before != after);
+
+       return (uint64_t) after * (1000000000ULL / AO_HERTZ) +
+               (uint64_t) cvr * (1000000000ULL / AO_SYSTICK);
+}
+
 #if AO_DATA_ALL
 volatile uint8_t       ao_data_interval = 1;
 volatile uint8_t       ao_data_count;
index 594114b62ed856a8b4babc8f9ccf47f3597d9624..d6763c298bc08e458f4d1e9c17f5b4b954b21d42 100644 (file)
@@ -131,7 +131,7 @@ static inline uint32_t set_toggle(uint32_t  current_value,
  * Set current device address and mark the
  * interface as active
  */
-void
+static void
 ao_usb_set_address(uint8_t address)
 {
        debug("ao_usb_set_address %02x\n", address);
@@ -813,7 +813,7 @@ _ao_usb_out_recv(void)
        ao_usb_set_epn_out(AO_USB_OUT_EP, ao_usb_out_rx_buffer[1-ao_usb_out_rx_cur], AO_USB_OUT_SIZE);
 }
 
-int
+static int
 _ao_usb_pollchar(void)
 {
        uint8_t c;
diff --git a/src/lpc/clock_figure.5c b/src/lpc/clock_figure.5c
new file mode 100644 (file)
index 0000000..d2f632a
--- /dev/null
@@ -0,0 +1,113 @@
+#!/usr/bin/nickle
+
+real
+pll_out(real clock_in, int mul, int div)
+{
+       return clock_in * mul / div;
+}
+
+real
+pll_in(real pll_out, int mul, int div)
+{
+       return pll_out * div / mul;
+}
+
+real
+fcco_out(real clock_in, int mul, int div)
+{
+       real    out = pll_out(clock_in, mul, div);
+       return out * div;
+}
+
+bool
+valid_clock_in(real clock_in)
+{
+       return 10 <= clock_in && clock_in < 25;
+}
+
+bool
+valid_fcco(real clock_in, int mul, int div)
+{
+       real fcco = fcco_out (clock_in, mul, div);
+       return 156 <= fcco && fcco <= 320;
+}
+
+void
+all_clocks(real clock_in) {
+       for (int mul = 1; mul <= 32; mul++) {
+               for (int div = 2; div <= 16; div *= 2) {
+                       if (!valid_fcco(clock_in, mul, div))
+                               printf ("clock_in %f mul  %d div %d invalid fcco %f\n",
+                                       clock_in, mul, div, fcco_out(clock_in, mul, div));
+                       else
+                               printf ("clock_in %f mul %d div %d pll_out %f\n",
+                                       clock_in, mul, div, pll_out(clock_in, mul, div));
+               }
+       }
+}
+
+typedef struct {
+       real    clock_in;
+       int     mul;
+       int     div;
+       real    pll_out;
+} clock;
+
+clock[]
+all_ins(real pll_out)
+{
+       clock[...] clocks = {};
+       for (int mul = 1; mul <= 32; mul++) {
+               for (int div = 2; div <= 16; div *= 2) {
+                       real clock_in = pll_in(pll_out, mul, div);
+                       if (valid_clock_in(clock_in) && valid_fcco(clock_in, mul, div)) {
+                               clocks[dim(clocks)] = (clock) {
+                                       .clock_in = clock_in,
+                                       .mul = mul,
+                                       .div = div,
+                                       .pll_out = pll_out
+                               };
+                       }
+               }
+       }
+       return clocks;
+}
+
+#all_clocks(12.0);
+
+autoload Sort;
+
+void
+dump_clocks(clock[] clocks)
+{
+       printf ("Clocks for %f\n", clocks[0].pll_out);
+       Sort::qsort(&clocks, bool func(clock a, clock b) { return a.clock_in > b.clock_in; });
+       for (int i = 0; i < dim (clocks); i++) {
+               printf("\tclock_in %f mul %d div %d\n",
+                      clocks[i].clock_in,
+                      clocks[i].mul,
+                      clocks[i].div);
+       }
+}
+
+void
+find_clocks() {
+       clock[] c40 = all_ins(40.0);
+       clock[] c48 = all_ins(48.0);
+
+       dump_clocks(c40);
+       dump_clocks(c48);
+       for (int i40 = 0; i40 < dim(c40); i40++) {
+               for (int i48 = 0; i48 < dim(c48); i48++) {
+                       if (c40[i40].clock_in == c48[i48].clock_in)
+                               printf ("clock_in %f mul_40 %d div_40 %d mul_48 %d div_48 %d\n",
+                                       c40[i40].clock_in,
+                                       c40[i40].mul,
+                                       c40[i40].div,
+                                       c48[i48].mul,
+                                       c48[i48].div);
+               }
+       }
+}
+
+find_clocks();
index 38dd2aeedb2c222e4351c9d287ff393c736c0772..56b852300e4dc758a76d3d6626b3cab28431bf38 100644 (file)
@@ -1347,4 +1347,50 @@ extern struct lpc_ct32b lpc_ct32b0, lpc_ct32b1;
 #define LPC_CT32B_EMR_EMC_SET          2
 #define LPC_CT32B_EMR_EMC_TOGGLE       3
 
+#define isr_decl(name) \
+       void lpc_ ## name ## _isr(void)
+
+isr_decl(halt);
+isr_decl(ignore);
+
+isr_decl(nmi);
+isr_decl(hardfault);
+isr_decl(memmanage);
+isr_decl(busfault);
+isr_decl(usagefault);
+isr_decl(svc);
+isr_decl(debugmon);
+isr_decl(pendsv);
+isr_decl(systick);
+
+isr_decl(pin_int0);    /* IRQ0 */
+isr_decl(pin_int1);
+isr_decl(pin_int2);
+isr_decl(pin_int3);
+isr_decl(pin_int4);    /* IRQ4 */
+isr_decl(pin_int5);
+isr_decl(pin_int6);
+isr_decl(pin_int7);
+
+isr_decl(gint0);       /* IRQ8 */
+isr_decl(gint1);
+isr_decl(ssp1);
+isr_decl(i2c);
+
+isr_decl(ct16b0);      /* IRQ16 */
+isr_decl(ct16b1);
+isr_decl(ct32b0);
+isr_decl(ct32b1);
+isr_decl(ssp0);        /* IRQ20 */
+isr_decl(usart);
+isr_decl(usb_irq);
+isr_decl(usb_fiq);
+
+isr_decl(adc); /* IRQ24 */
+isr_decl(wwdt);
+isr_decl(bod);
+isr_decl(flash);
+
+isr_decl(usb_wakeup);
+
 #endif /* _LPC_H_ */
index 374c052ffa207bf950f813e4b1096ffd608c18ce..2eef24baee017cfb95779e3a01c39167232c0450 100644 (file)
@@ -33,7 +33,7 @@ PRODUCT=LpcDemo-v0.0
 PRODUCT_DEF=-DLPC_DEMO
 IDPRODUCT=0x000a
 
-CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) -g -Os
+CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS)
 
 PROG=lpc-demo.elf
 
index 5eb97206d0004b286cf3920117f8b25e749cdefc..5b38f572d2a8337ec8cffa6072c9493f17a9b10a 100644 (file)
@@ -2,11 +2,8 @@
 # Tiny AltOS build
 #
 #
-vpath % ../attiny:../drivers:../kernel:../product:..
-vpath ao-make-product.5c ../util
-vpath make-altitude-pa ../util
-
-include ../avr/Makefile.defs
+TOPDIR=..
+include $(TOPDIR)/attiny/Makefile.defs
 
 PROGNAME=microkite-v0.1
 PROG=$(PROGNAME)-$(VERSION).elf
@@ -18,14 +15,6 @@ PUBLISH_DIR=$(HOME)/altusmetrumllc/Binaries
 PUBLISH_HEX=$(PUBLISH_DIR)/$(HEX)
 PUBLISH_SCRIPT=$(PUBLISH_DIR)/$(SCRIPT)
 
-MCU=attiny85
-DUDECPUTYPE=t85
-#PROGRAMMER=stk500v2 -P usb
-LOADSLOW=-i 32 -B 32
-LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w:
-
-#LDFLAGS=-L$(LDSCRIPTS) -Tavr25.x
-
 ALTOS_SRC = \
        ao_micropeak.c \
        ao_spi_attiny.c \
@@ -52,28 +41,18 @@ INC=\
        ao_ms5607.h \
        ao_log_micro.h \
        ao_micropeak.h \
+       ao_product.h \
        altitude-pa.h
 
 IDPRODUCT=0
 PRODUCT=MicroKite-v0.1
 PRODUCT_DEF=-DMICROPEAK
-CFLAGS = $(PRODUCT_DEF) -I. -I../attiny -I../kernel -I.. -I../drivers -I../product
-CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O2 -mcall-prologues -DATTINY
-
-NICKLE=nickle
+CFLAGS = $(PRODUCT_DEF) $(ATTINY_CFLAGS)
 
 SRC=$(ALTOS_SRC)
 OBJ=$(SRC:.c=.o)
 
-V=0
-# The user has explicitly enabled quiet compilation.
-ifeq ($(V),0)
-quiet = @printf "  $1 $2 $@\n"; $($1)
-endif
-# Otherwise, print the full command line.
-quiet ?= $($1)
-
-all: $(PROG) $(HEX) microkite-load
+all: $(PROG) $(HEX) $(SCRIPT)
 
 CHECK=sh ../util/check-avr-mem
 
@@ -85,25 +64,16 @@ $(HEX): $(PROG)
        avr-size $(PROG)
        $(OBJCOPY) -R .eeprom -O ihex $(PROG) $@
 
-
 load: $(HEX)
        $(LOADCMD) $(LOADARG)$(HEX)
 
 load-slow: $(HEX)
        $(LOADCMD) $(LOADSLOW) $(LOADARG)$(HEX)
 
-ao_product.h: ao-make-product.5c ../Version
-       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
-
-ao_product.o: ao_product.c ao_product.h
-
-%.o : %.c $(INC)
-       $(call quiet,CC) -c $(CFLAGS) $<
-
 distclean:     clean
 
 clean:
-       rm -f *.o $(PROG) $(HEX) $(SCRIPT)
+       rm -f *.o *.elf *.ihx $(SCRIPT)
        rm -f ao_product.h
 
 publish: $(PUBLISH_HEX) $(PUBLISH_SCRIPT)
@@ -120,10 +90,7 @@ load-product:
 load-product-slow:
        ./$(SCRIPT) slow
 
-../altitude-pa.h: make-altitude-pa
-       nickle $< > $@
-
-$(SCRIPT): $(SCRIPT).tmpl Makefile ../Version
+$(SCRIPT): $(SCRIPT).tmpl Makefile $(TOPDIR)/Makedefs
        sed -e 's/%HEX%/$(HEX)/' -e 's/%LOADCMD%/$(LOADCMD)/' -e 's/%LOADARG%/$(LOADARG)/' -e 's/%LOADSLOW%/$(LOADSLOW)/' $(SCRIPT).tmpl > $@ || (rm $@ && exit 1)
        chmod +x $@
 
@@ -131,4 +98,4 @@ install:
 
 uninstall:
 
-$(OBJ): ao_product.h $(INC)
+$(OBJ): $(INC)
index 396b57e3e7e3143c95d3c256a1b2183720cd03f3..eb6d034fdeb30a715025eb85daca8595afb77c3f 100644 (file)
@@ -31,6 +31,7 @@
 #define HAS_SERIAL_1           0
 #define HAS_TASK               0
 #define HAS_MS5607             1
+#define HAS_SENSOR_ERRORS      0
 #define HAS_MS5611             0
 #define HAS_EEPROM             0
 #define HAS_BEEP               0
index c2062c3486699828780f94301c74a5da8457cce2..75d036b97c5c843899a8ddd5f9f0302c55372e24 100644 (file)
@@ -1,3 +1,3 @@
 ao_product.h
-microsplash-v*
-microsplash-load
+micropeak-v*
+
index c7d1b22d374a28caddfc698e19b81f8b39ba1af8..f1f57440a89c30f8ad42409c1fdaaac04fa1b096 100644 (file)
@@ -32,6 +32,7 @@ ALTOS_SRC = \
        ao_mutex.c \
        ao_interrupt.c \
        ao_cmd.c \
+       ao_config.c \
        ao_task.c \
        ao_data.c \
        ao_boot_chain.c \
@@ -52,13 +53,14 @@ INC=\
        ao_log_micro.h \
        ao_micropeak.h \
        altitude-pa.h \
+       ao_product.h \
        stm32f0.h
 
 IDPRODUCT=0x14
 PRODUCT=MicroPeak-v2.0
 PRODUCT_DEF=-DMICROPEAK
 
-CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -g -Os
+CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS)
 
 PROGNAME=micropeak-v2.0
 PROG=$(PROGNAME)-$(VERSION).elf
@@ -72,12 +74,7 @@ all: $(PROG) $(HEX)
 LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stmf0 -Wl,-Tmicropeak.ld -n
 
 $(PROG): Makefile $(OBJ) micropeak.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) > $@
-
-ao_product.o: ao_product.c ao_product.h
+       $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS)
 
 distclean:     clean
 
@@ -90,11 +87,8 @@ publish: $(PUBLISH_HEX)
 $(PUBLISH_HEX): $(HEX)
        cp -a $(HEX) $@
 
-../altitude-pa.h: make-altitude-pa
-       nickle $< > $@
-
 install:
 
 uninstall:
 
-$(OBJ): ao_product.h $(INC)
+$(OBJ): $(INC)
index df557e60f1b9168e42e9afe2cb247e25fbe25f23..f3fbc9f42ca016041026086b88b0e562e84574a0 100644 (file)
@@ -164,6 +164,13 @@ ao_battery_voltage(void)
        return 330 * stm_cal.vrefint_cal / vrefint;
 }
 
+static void
+ao_log_erase(void)
+{
+       uint32_t        pos;
+       for (pos = 0; pos < ao_storage_log_max; pos += ao_storage_block)
+               ao_storage_erase(pos);
+}
 
 uint8_t        ao_on_battery;
 
@@ -171,21 +178,22 @@ static void
 ao_micropeak(void)
 {
        ao_ms5607_setup();
-       ao_storage_setup();
 
        /* Give the person a second to get their finger out of the way */
        ao_delay(AO_MS_TO_TICKS(1000));
 
-       ao_pips();
-
        ao_log_micro_restore();
        ao_compute_height();
        ao_report_altitude();
+
+       ao_pips();
+
        ao_log_micro_dump();
 
 #if BOOST_DELAY
        ao_delay(BOOST_DELAY);
 #endif
+       ao_log_erase();
 
        ao_microflight();
 
@@ -193,6 +201,7 @@ ao_micropeak(void)
        ao_compute_height();
        ao_report_altitude();
 
+       ao_sleep_mode();
        ao_sleep(&ao_on_battery);
 }
 
@@ -202,7 +211,52 @@ ao_show_bat(void)
        printf("battery: %u\n", ao_battery_voltage());
 }
 
+uint8_t
+ao_log_present(void)
+{
+       uint16_t        n_samples;
+
+       ao_eeprom_read(N_SAMPLES_OFFSET, &n_samples, sizeof (n_samples));
+
+       return n_samples != 0xffff;
+}
+
+static void
+ao_log_list(void)
+{
+       if (ao_log_present())
+               printf ("flight %d start %x end %x\n",
+                       1,
+                       0, MAX_LOG_OFFSET >> 8);
+       printf ("done\n");
+}
+
+static void
+ao_log_delete(void)
+{
+       int16_t cmd_flight = 1;
+
+       ao_cmd_white();
+       if (ao_cmd_lex_c == '-') {
+               cmd_flight = -1;
+               ao_cmd_lex();
+       }
+       cmd_flight *= ao_cmd_decimal();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+
+       /* Look for the flight log matching the requested flight */
+       if (cmd_flight == 1 && ao_log_present()) {
+               ao_log_erase();
+               puts("Erased");
+               return;
+       }
+       printf("No such flight: %d\n", cmd_flight);
+}
+
 static struct ao_cmds mp_cmd[] = {
+       { ao_log_list,  "l\0List logs" },
+       { ao_log_delete,        "d <flight-number>\0Delete flight" },
        { ao_show_bat, "b\0Show battery voltage" },
        { 0 }
 };
@@ -218,9 +272,6 @@ ao_hsi_init(void)
        /* Enable prefetch */
        stm_flash.acr |= (1 << STM_FLASH_ACR_PRFTBE);
 
-       /* Enable power interface clock */
-       stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN);
-
        /* HCLK to 48MHz -> AHB prescaler = /1 */
        cfgr = stm_rcc.cfgr;
        cfgr &= ~(STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE);
@@ -240,9 +291,14 @@ ao_hsi_init(void)
        stm_rcc.csr |= (1 << STM_RCC_CSR_RMVF);
 }
 
-void
+int
 main(void)
 {
+       int i;
+
+       for (i = 0; i < 100000; i++)
+               ao_arch_nop();
+
        if (ao_battery_voltage() < 320)
                ao_on_battery = 1;
 
@@ -255,24 +311,31 @@ main(void)
        ao_led_init();
        ao_task_init();
        ao_timer_init();
-       ao_serial_init();
        stm_moder_set(&stm_gpioa, 2, STM_MODER_OUTPUT);
-
        ao_dma_init();
        ao_spi_init();
        ao_exti_init();
 
-       /* Leave USB disabled on battery */
-       if (!ao_on_battery) {
-               ao_usb_init();
-               ao_cmd_init();
-       }
+       ao_storage_setup();
 
        ao_ms5607_init();
-
        ao_storage_init();
 
-       ao_add_task(&mp_task, ao_micropeak, "micropeak");
-       ao_cmd_register(mp_cmd);
+       /* Let FLITF clock turn off in sleep mode */
+       stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_FLITFEN);
+
+       /* Le SRAM clock turn off in sleep mode */
+       stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_SRAMEN);
+
+       if (ao_on_battery) {
+               /* On battery power, run the flight code */
+               ao_add_task(&mp_task, ao_micropeak, "micropeak");
+       } else {
+               /* otherwise, turn on USB and run the command processor */
+               ao_usb_init();
+               ao_cmd_init();
+               ao_cmd_register(mp_cmd);
+               ao_config_init();
+       }
        ao_start_scheduler();
 }
index fa2ed804f6a6bccce59043c4f7433ae4d47f042f..d3bd22814a46f0264669237de7c06bf2beb87efb 100644 (file)
@@ -43,8 +43,8 @@ extern uint8_t ao_on_battery;
 #define AO_RCC_CFGR_HPRE_DIV   (ao_on_battery ? STM_RCC_CFGR_HPRE_DIV_16 : STM_RCC_CFGR_HPRE_DIV_1)
 
 /* APB = 12MHz usb / 2MHz battery */
-#define AO_APB_PRESCALER       1
-#define AO_RCC_CFGR_PPRE_DIV   STM_RCC_CFGR_PPRE_DIV_1
+#define AO_APB_PRESCALER       (ao_on_battery ? 2 : 1)
+#define AO_RCC_CFGR_PPRE_DIV   (ao_on_battery ? STM_RCC_CFGR_PPRE_DIV_2 : STM_RCC_CFGR_PPRE_DIV_1)
 
 #define HAS_USB                        1
 #define AO_PA11_PA12_RMP       1
@@ -63,16 +63,21 @@ extern uint8_t ao_on_battery;
 #define IS_FLASH_LOADER                0
 
 #define HAS_MS5607             1
+#define HAS_SENSOR_ERRORS      0
 #define HAS_MS5611             0
 #define HAS_MS5607_TASK                0
-#define HAS_EEPROM             0
+#define HAS_EEPROM             1
+#define HAS_CONFIG_SAVE                0
 #define HAS_BEEP               0
 
 /* Logging */
 #define LOG_INTERVAL           1
 #define SAMPLE_SLEEP           AO_MS_TO_TICKS(100)
 #define BOOST_DELAY            AO_SEC_TO_TICKS(60)
-#define AO_LOG_ID              AO_LOG_ID_MICRO_PEAK2
+#define AO_LOG_ID              AO_LOG_ID_MICROPEAK2
+#define HAS_LOG                        1
+#define AO_LOG_FORMAT          AO_LOG_FORMAT_MICROPEAK2
+#define FLIGHT_LOG_APPEND      1
 
 /* Kalman filter */
 
@@ -81,6 +86,7 @@ extern uint8_t ao_on_battery;
 
 /* SPI */
 #define HAS_SPI_1              1
+#define SPI_1_POWER_MANAGE     1
 #define SPI_1_PA5_PA6_PA7      1
 #define SPI_1_PB3_PB4_PB5      0
 #define SPI_1_OSPEEDR          STM_OSPEEDR_MEDIUM
@@ -123,9 +129,11 @@ void ao_delay_until(uint16_t target);
 #define ao_async_stop() do {                                   \
                ao_serial2_drain();                             \
                stm_moder_set(&stm_gpioa, 2, STM_MODER_OUTPUT); \
+               ao_serial_shutdown();                           \
        } while (0)
 
 #define ao_async_start() do {                                          \
+               ao_serial_init();                                       \
                stm_moder_set(&stm_gpioa, 2, STM_MODER_ALTERNATE);      \
                ao_delay(AO_MS_TO_TICKS(100));                          \
        } while (0)
@@ -135,6 +143,7 @@ void ao_delay_until(uint16_t target);
 #define ao_eeprom_read(pos, ptr, size) ao_storage_read(pos, ptr, size)
 #define ao_eeprom_write(pos, ptr, size) ao_storage_write(pos, ptr, size)
 #define MAX_LOG_OFFSET ao_storage_total
+#define ao_storage_log_max ao_storage_total
 
 extern uint32_t __flash__[];
 extern uint32_t __flash_end__[];
index f80d61b0743ef297e6eb41dd69503b6fef0414f7..74769802fc055942bde95199317adc657e143bd8 100644 (file)
@@ -2,11 +2,8 @@
 # Tiny AltOS build
 #
 #
-vpath % ../attiny:../drivers:../kernel:../product:..
-vpath ao-make-product.5c ../util
-vpath make-altitude-pa ../util
-
-include ../avr/Makefile.defs
+TOPDIR=..
+include $(TOPDIR)/attiny/Makefile.defs
 
 PROGNAME=micropeak-v0.1
 PROG=$(PROGNAME)-$(VERSION).elf
@@ -18,14 +15,6 @@ PUBLISH_DIR=$(HOME)/altusmetrumllc/Binaries
 PUBLISH_HEX=$(PUBLISH_DIR)/$(HEX)
 PUBLISH_SCRIPT=$(PUBLISH_DIR)/$(SCRIPT)
 
-MCU=attiny85
-DUDECPUTYPE=t85
-#PROGRAMMER=stk500v2 -P usb
-LOADSLOW=-i 32 -B 32
-LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w:
-
-#LDFLAGS=-L$(LDSCRIPTS) -Tavr25.x
-
 ALTOS_SRC = \
        ao_micropeak.c \
        ao_spi_attiny.c \
@@ -52,28 +41,18 @@ INC=\
        ao_ms5607.h \
        ao_log_micro.h \
        ao_micropeak.h \
+       ao_product.h \
        altitude-pa.h
 
 IDPRODUCT=0
 PRODUCT=MicroPeak-v0.1
 PRODUCT_DEF=-DMICROPEAK
-CFLAGS = $(PRODUCT_DEF) -I. -I../attiny -I../kernel -I.. -I../drivers -I../product
-CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O2 -mcall-prologues -DATTINY
-
-NICKLE=nickle
+CFLAGS = $(PRODUCT_DEF) $(ATTINY_CFLAGS)
 
 SRC=$(ALTOS_SRC)
 OBJ=$(SRC:.c=.o)
 
-V=0
-# The user has explicitly enabled quiet compilation.
-ifeq ($(V),0)
-quiet = @printf "  $1 $2 $@\n"; $($1)
-endif
-# Otherwise, print the full command line.
-quiet ?= $($1)
-
-all: $(PROG) $(HEX) micropeak-load
+all: $(PROG) $(HEX) $(SCRIPT)
 
 CHECK=sh ../util/check-avr-mem
 
@@ -85,21 +64,12 @@ $(HEX): $(PROG)
        avr-size $(PROG)
        $(OBJCOPY) -R .eeprom -O ihex $(PROG) $@
 
-
 load: $(HEX)
        $(LOADCMD) $(LOADARG)$(HEX)
 
 load-slow: $(HEX)
        $(LOADCMD) $(LOADSLOW) $(LOADARG)$(HEX)
 
-ao_product.h: ao-make-product.5c ../Version
-       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
-
-ao_product.o: ao_product.c ao_product.h
-
-%.o : %.c $(INC)
-       $(call quiet,CC) -c $(CFLAGS) $<
-
 distclean:     clean
 
 clean:
@@ -120,10 +90,7 @@ load-product:
 load-product-slow:
        ./$(SCRIPT) slow
 
-../altitude-pa.h: make-altitude-pa
-       nickle $< > $@
-
-$(SCRIPT): $(SCRIPT).tmpl Makefile ../Version
+$(SCRIPT): $(SCRIPT).tmpl Makefile $(TOPDIR)/Makedefs
        sed -e 's/%HEX%/$(HEX)/' -e 's/%LOADCMD%/$(LOADCMD)/' -e 's/%LOADARG%/$(LOADARG)/' -e 's/%LOADSLOW%/$(LOADSLOW)/' $(SCRIPT).tmpl > $@ || (rm $@ && exit 1)
        chmod +x $@
 
@@ -131,4 +98,4 @@ install:
 
 uninstall:
 
-$(OBJ): ao_product.h $(INC)
+$(OBJ): $(INC)
index 7cfbca490f17a2f4cb5094f5a8e514734210823e..2c02f3a3acb34b997d79b5b733741ef30fb91e28 100644 (file)
@@ -32,6 +32,7 @@
 #define HAS_TASK               0
 #define HAS_MS5607             1
 #define HAS_MS5611             0
+#define HAS_SENSOR_ERRORS      0
 #define HAS_EEPROM             0
 #define HAS_BEEP               0
 #define AVR_CLOCK              250000UL
index 0342838e3c3f2d632ee3765159c14204e1f8b02c..4850ef14f6e7eabc64f844eff25511b0d98dbaf6 100644 (file)
@@ -2,11 +2,8 @@
 # Tiny AltOS build
 #
 #
-vpath % ../attiny:../drivers:../kernel:../product:..
-vpath ao-make-product.5c ../util
-vpath make-altitude-pa ../util
-
-include ../avr/Makefile.defs
+TOPDIR=..
+include $(TOPDIR)/attiny/Makefile.defs
 
 PROGNAME=microsplash-v1.0
 PROG=$(PROGNAME)-$(VERSION).elf
@@ -18,14 +15,6 @@ PUBLISH_DIR=$(HOME)/altusmetrumllc/Binaries
 PUBLISH_HEX=$(PUBLISH_DIR)/$(HEX)
 PUBLISH_SCRIPT=$(PUBLISH_DIR)/$(SCRIPT)
 
-MCU=attiny85
-DUDECPUTYPE=t85
-#PROGRAMMER=stk500v2 -P usb
-LOADSLOW=-i 32 -B 32
-LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w:
-
-#LDFLAGS=-L$(LDSCRIPTS) -Tavr25.x
-
 ALTOS_SRC = \
        ao_micropeak.c \
        ao_spi_attiny.c \
@@ -52,27 +41,17 @@ INC=\
        ao_ms5607.h \
        ao_log_micro.h \
        ao_micropeak.h \
+       ao_product.h \
        altitude-pa.h
 
 IDPRODUCT=0
 PRODUCT=MicroSplash-v1.0
 PRODUCT_DEF=-DMICROPEAK
-CFLAGS = $(PRODUCT_DEF) -I. -I../attiny -I../kernel -I.. -I../drivers -I../product
-CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O2 -mcall-prologues -DATTINY
-
-NICKLE=nickle
+CFLAGS = $(PRODUCT_DEF) $(ATTINY_CFLAGS)
 
 SRC=$(ALTOS_SRC)
 OBJ=$(SRC:.c=.o)
 
-V=0
-# The user has explicitly enabled quiet compilation.
-ifeq ($(V),0)
-quiet = @printf "  $1 $2 $@\n"; $($1)
-endif
-# Otherwise, print the full command line.
-quiet ?= $($1)
-
 all: $(PROG) $(HEX) $(SCRIPT)
 
 CHECK=sh ../util/check-avr-mem
@@ -85,25 +64,16 @@ $(HEX): $(PROG)
        avr-size $(PROG)
        $(OBJCOPY) -R .eeprom -O ihex $(PROG) $@
 
-
 load: $(HEX)
        $(LOADCMD) $(LOADARG)$(HEX)
 
 load-slow: $(HEX)
        $(LOADCMD) $(LOADSLOW) $(LOADARG)$(HEX)
 
-ao_product.h: ao-make-product.5c ../Version
-       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
-
-ao_product.o: ao_product.c ao_product.h
-
-%.o : %.c $(INC)
-       $(call quiet,CC) -c $(CFLAGS) $<
-
 distclean:     clean
 
 clean:
-       rm -f *.o $(PROG) $(HEX) $(SCRIPT)
+       rm -f *.o *.elf *.ihx $(SCRIPT)
        rm -f ao_product.h
 
 publish: $(PUBLISH_HEX) $(PUBLISH_SCRIPT)
@@ -120,10 +90,7 @@ load-product:
 load-product-slow:
        ./$(SCRIPT) slow
 
-../altitude-pa.h: make-altitude-pa
-       nickle $< > $@
-
-$(SCRIPT): $(SCRIPT).tmpl Makefile ../Version
+$(SCRIPT): $(SCRIPT).tmpl Makefile $(TOPDIR)/Makedefs
        sed -e 's/%HEX%/$(HEX)/' -e 's/%LOADCMD%/$(LOADCMD)/' -e 's/%LOADARG%/$(LOADARG)/' -e 's/%LOADSLOW%/$(LOADSLOW)/' $(SCRIPT).tmpl > $@ || (rm $@ && exit 1)
        chmod +x $@
 
@@ -131,4 +98,4 @@ install:
 
 uninstall:
 
-$(OBJ): ao_product.h $(INC)
+$(OBJ): $(INC)
index 50a993464a76cf1554bf1ed1eb0597b4e6ed250c..0461b20e1480ea23ee217f542d2d1e95e33d877d 100644 (file)
@@ -31,6 +31,7 @@
 #define HAS_SERIAL_1           0
 #define HAS_TASK               0
 #define HAS_MS5607             1
+#define HAS_SENSOR_ERRORS      0
 #define HAS_MS5611             0
 #define HAS_EEPROM             0
 #define HAS_BEEP               0
index 961567413e62c227344e8d17bca571675064b278..c09eedcf4c0eddcb0c083572c01d4e3208669018 100644 (file)
@@ -38,7 +38,7 @@ PRODUCT=MicroPeakUSB-v3.0
 PRODUCT_DEF=-DMPUSB
 IDPRODUCT=0x002b
 
-CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -Os -g
+CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS)
 
 PROGNAME=mpusb-v3.0
 PROG=$(PROGNAME)-$(VERSION).elf
index 1ab2eea188a56453f43f3d8c1386fddef456ad8d..fba99c88b6931a4166eaa66c54d8ff5fbcec4f6c 100644 (file)
@@ -58,7 +58,7 @@ PRODUCT=Nucleo-32
 PRODUCT_DEF=-DNUCLEO
 IDPRODUCT=0x000a
 
-CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -Os -g
+CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS)
 
 LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stmf0 -Wl,-Tload.ld -n
 
index 443a6afbdb5dc1297f3297d11f6e05ee43475446..b3994a998392267d1945bd8f2a7942bb2c7b2e77 100644 (file)
@@ -37,7 +37,7 @@ PRODUCT=PNPservo-v1
 PRODUCT_DEF=-DPNPSERVO
 IDPRODUCT=0x000a
 
-CFLAGS = $(PRODUCT_DEF) -I. $(STMF0_CFLAGS) -Os -g
+CFLAGS = $(PRODUCT_DEF) -I. $(STMF0_CFLAGS)
 
 LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stmf0 -Wl,-Tlambda.ld
 
index 3a989f5a667f0a544fa9f6745cd822256fce65d6..102abb910a3d8e1050e8823aa2b3450aa1f5a843 100644 (file)
@@ -598,7 +598,7 @@ ao_terramonitor(void)
                case AO_TELEMETRY_SENSOR_TELEMETRUM:
                case AO_TELEMETRY_SENSOR_TELEMINI:
                case AO_TELEMETRY_SENSOR_TELENANO:
-                       ao_xmemcpy(&ao_tel_sensor, &ao_monitor_ring[monitor], sizeof (ao_tel_sensor));
+                       memcpy(&ao_tel_sensor, &ao_monitor_ring[monitor], sizeof (ao_tel_sensor));
                        if (ao_tel_sensor.state < ao_flight_boost) {
                                ao_tel_max_speed = 0;
                                ao_tel_max_height = 0;
@@ -611,10 +611,10 @@ ao_terramonitor(void)
                        ao_telem_progress = (ao_telem_progress + 1) & 0x3;
                        break;
                case AO_TELEMETRY_LOCATION:
-                       ao_xmemcpy(&ao_tel_location, &ao_monitor_ring[monitor], sizeof (ao_tel_location));
+                       memcpy(&ao_tel_location, &ao_monitor_ring[monitor], sizeof (ao_tel_location));
                        break;
                case AO_TELEMETRY_CONFIGURATION:
-                       ao_xmemcpy(&ao_tel_config, &ao_monitor_ring[monitor], sizeof (ao_tel_config));
+                       memcpy(&ao_tel_config, &ao_monitor_ring[monitor], sizeof (ao_tel_config));
                }
        }
 }
index b0943e5665fb34f94ee1872755df8d0f040e83a9..5373877123ce25c54cd1a2c8e6e679867dc5baca 100644 (file)
@@ -7,12 +7,12 @@ endif
 TOPDIR=..
 include $(TOPDIR)/Makedefs
 
-CC=arm-none-eabi-gcc
+CC=arm-none-eabicc
 OBJCOPY=arm-none-eabi-objcopy
 
 C_LIB=$(PDCLIB_LIBS_M3)
 
-DEF_CFLAGS=-g -std=gnu99 -Os -mlittle-endian -mthumb -ffreestanding -nostdlib -I. -I../stm $(PDCLIB_INCLUDES)
+DEF_CFLAGS= -std=gnu99 -mlittle-endian -mthumb -ffreestanding -nostdlib -I. -I../stm $(PDCLIB_INCLUDES)
 
 # to run from SRAM
 LD_FLAGS_RAM=-L../stm -Wl,-Taltos-ram.ld
index ccce37a5a9b2cdbd175fe25b1bc01c4db2bfb4c8..483d5784a493dc863994e296362b9ae397ab7678 100644 (file)
@@ -44,7 +44,7 @@ PRODUCT=StmDemo-v0.0
 PRODUCT_DEF=-DSTM_DEMO
 IDPRODUCT=0x000a
 
-CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -g -Os
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS)
 
 PROG=stm-demo-$(VERSION)
 ELF=$(PROG).elf
index 4b963e4281fa3e5ebb3e5478d3deae5e9395284f..93eb92f48c238e8d2ee698bf824cca5c80ec58b3 100644 (file)
@@ -27,35 +27,6 @@ struct ao_task demo_task;
 
 static inline int min(int a, int b) { return a < b ? a : b; }
 
-void
-ao_demo(void)
-{
-       char    message[] = "Hello, Mike & Bdale --- ";
-       char    part[7];
-       int     i = 0;
-       int     len = sizeof(message) - 1;
-       int     first, second;
-
-       part[6] = '\0';
-       for (;;) {
-               ao_delay(AO_MS_TO_TICKS(150));
-               first = min(6, len - i);
-               second = 6 - first;
-               memcpy(part, message + i, first);
-               memcpy(part + first, message, second);
-               ao_lcd_font_string(part);
-               if (++i >= len)
-                       i = 0;
-       }
-}
-
-void _close() { }
-void _sbrk() { }
-void _isatty() { }
-void _lseek() { }
-void _exit () { }
-void _read () { }
-void _fstat() { }
 
 #define AO_DMA_TEST_INDEX      STM_DMA_INDEX(4)
 
@@ -215,7 +186,7 @@ main(void)
        
        ao_task_init();
 
-       ao_led_init(LEDS_AVAILABLE);
+       ao_led_init();
        ao_led_on(AO_LED_GREEN);
        ao_led_off(AO_LED_BLUE);
        ao_timer_init();
index 568ab85af1b9df167cab3fc99f975495271a96be..4b0a987a6035404222217db59a2694ca94624619 100644 (file)
@@ -30,7 +30,7 @@ PRODUCT=AltosFlash-$(VERSION)
 PRODUCT_DEF=-DALTOS_FLASH
 IDPRODUCT=0x000a
 
-CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -g -Os
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS)
 
 PROG=altos-flash-$(VERSION).elf
 
index 1db58f10b131e2767ff5f6c5ca1b01c1cf1d60db..b02b762d28fc089cfccb517ac55f2b43a946c35e 100644 (file)
@@ -44,7 +44,7 @@ PRODUCT=StmScheme-v0.0
 PRODUCT_DEF=-DSTM_SCHEME
 IDPRODUCT=0x000a
 
-CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -g -Os
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS)
 
 PROG=stm-scheme-$(VERSION)
 ELF=$(PROG).elf
index fa0d008f36bff178aa6d6f4db2460a1ce9958566..fb73ba2c4045e14baf95fde4723b392ac07c1b91 100644 (file)
@@ -53,7 +53,7 @@ ALTOS_SRC = \
 PRODUCT=StmVga-v0.0
 IDPRODUCT=0x000a
 
-CFLAGS = $(STM_CFLAGS) -g -Os
+CFLAGS = $(STM_CFLAGS)
 
 PROG=stm-vga-$(VERSION)
 ELF=$(PROG).elf
index 66ad163716407d1cb1e21b1e904ba43caa4b0a5c..08a4b1773e00be742ac16856a883402d7e4f16b3 100644 (file)
@@ -1,40 +1,4 @@
-vpath % $(TOPDIR)/stm:$(TOPDIR)/product:$(TOPDIR)/drivers:$(TOPDIR)/kernel:$(TOPDIR)/util:$(TOPDIR)
-vpath ao-make-product.5c $(TOPDIR)/util
-
-.SUFFIXES: .elf .ihx
-
-.elf.ihx:
-       objcopy -O ihex $*.elf $@
-
-ifndef VERSION
-include $(TOPDIR)/Version
-endif
-include $(TOPDIR)/Makedefs
-
-CC=$(ARM_CC)
-LIBS=-L$(NEWLIB_NANO)/arm-none-eabi/lib/thumb/v7-m -lc -lm -lgcc
-
-AO_CFLAGS=-I. -I$(TOPDIR)/stm -I$(TOPDIR)/kernel -I$(TOPDIR)/drivers \
-       -DNEWLIB_INTEGER_PRINTF_SCANF \
-       -I$(TOPDIR)/product -I$(TOPDIR) -isystem $(NEWLIB_NANO)/arm-none-eabi/include
-
-STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb \
-       -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS)
-
-LDFLAGS=-L$(TOPDIR)/stm -Wl,-Taltos-loader.ld
-
-NICKLE=nickle
-
-V=0
-# The user has explicitly enabled quiet compilation.
-ifeq ($(V),0)
-quiet = @printf "  $1 $2 $@\n"; $($1)
-endif
-# Otherwise, print the full command line.
-quiet ?= $($1)
-
-.c.o:
-       $(call quiet,CC) -c $(CFLAGS) -o $@ $<
+include $(TOPDIR)/stm/Makefile-stm.defs
 
 INC = \
        ao.h \
@@ -69,7 +33,9 @@ PRODUCT=AltosFlash
 PRODUCT_DEF=-DALTOS_FLASH
 IDPRODUCT=0x000a
 
-CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -g -Os
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS)
+
+LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stm -Wl,-Taltos-loader.ld -n
 
 PROGNAME=altos-flash
 PROG=$(HARDWARE)-$(PROGNAME)-$(VERSION).elf
@@ -77,9 +43,6 @@ PROG=$(HARDWARE)-$(PROGNAME)-$(VERSION).elf
 $(PROG): Makefile $(OBJ) altos-loader.ld
        $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
 
-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)
diff --git a/src/stm/Makefile-stm.defs b/src/stm/Makefile-stm.defs
new file mode 100644 (file)
index 0000000..cce28f0
--- /dev/null
@@ -0,0 +1,13 @@
+ifndef TOPDIR
+TOPDIR=..
+endif
+
+include $(TOPDIR)/Makefile.defs
+
+vpath % $(TOPDIR)/stm:$(AO_VPATH)
+
+CC=$(ARM_CC)
+LIBS=-L$(NEWLIB_NANO)/arm-none-eabi/lib/thumb/v7-m -lm -lc -lgcc
+
+STM_CFLAGS=-mlittle-endian -mcpu=cortex-m3 -mthumb \
+       -I$(TOPDIR)/stm $(AO_CFLAGS) $(NEWLIB_CFLAGS)
index 8173b349c33446f6ba14e7bc644e400746c7c001..26ba582404fa4cd99b74701e71487970f99788ea 100644 (file)
@@ -1,50 +1,7 @@
-vpath % ../stm:../product:../drivers:../kernel:../util:../kalman:../aes:../math:../draw:../scheme:..
-vpath make-altitude ../util
-vpath make-kalman ../util
-vpath kalman.5c ../kalman
-vpath kalman_filter.5c ../kalman
-vpath load_csv.5c ../kalman
-vpath matrix.5c ../kalman
-vpath ao-make-product.5c ../util
-
-.SUFFIXES: .elf .ihx
-
-.elf.ihx:
-       $(ELFTOHEX) --output=$@ $*.elf
-
 ifndef TOPDIR
 TOPDIR=..
 endif
 
-ifndef VERSION
-include $(TOPDIR)/Version
-endif
-include $(TOPDIR)/Makedefs
-
-CC=$(ARM_CC)
-LIBS=-L$(NEWLIB_NANO)/arm-none-eabi/lib/thumb/v7-m -lm -lc -lgcc
-
-WARN_FLAGS=-Wall -Wextra -Werror
-
-AO_CFLAGS=-I. -I../stm -I../kernel -I../drivers -I../math -I../draw \
-       -DNEWLIB_INTEGER_PRINTF_SCANF \
-       -I../lisp -I.. -isystem $(NEWLIB_NANO)/arm-none-eabi/include
-
-STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb -Wcast-align \
-       -ffreestanding -nostdlib $(AO_CFLAGS) $(WARN_FLAGS)
-
-LDFLAGS=-L../stm -Wl,-Taltos.ld -nostartfiles -Wl,-Map=$(PROGNAME).map
-
-NICKLE=nickle
-ELFTOHEX=$(TOPDIR)/../ao-tools/ao-elftohex/ao-elftohex
-
-V=0
-# The user has explicitly enabled quiet compilation.
-ifeq ($(V),0)
-quiet = @printf "  $1 $2 $@\n"; $($1)
-endif
-# Otherwise, print the full command line.
-quiet ?= $($1)
+include $(TOPDIR)/stm/Makefile-stm.defs
 
-.c.o:
-       $(call quiet,CC) -c $(CFLAGS) -o $@ $<
+LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stm -Wl,-Taltos.ld -n
index fe78585447298064eb99c1b25b33df451dc0956f..152d4e8388c365d7041740b8b0d339fdf38b3ac8 100644 (file)
@@ -154,13 +154,13 @@ glyph[*] read_font(file f) {
 
 glyph[*] font;
 void init () {
-       twixt (file f = File::open("ao_lcd_font.h", "r"); File::close(f)) {
+       twixt (file f = File::open("ao_lcd_font_bits.h", "r"); File::close(f)) {
                font = read_font(f);
        }
 }
 
 void dump() {
-       twixt(file f = File::open("ao_lcd_font.h.new", "w"); File::close(f)) {
+       twixt(file f = File::open("ao_lcd_font_bits.h.new", "w"); File::close(f)) {
                for (int i = 0; i < dim(font); i++) {
                        File::fprintf (f, "\t[%d] = 0x%04x,\n", i, glyph_value(font[i]));
                        File::fprintf (f, "/*\n");
index 5737cd50cf02acdc972a05f012d331406d3f19dd..c3a332f4f19dd58bc97e6f3c3880f2bb3c5947e1 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <ao.h>
 #include <ao_data.h>
+#include <ao_adc_single.h>
 
 static uint8_t                 ao_adc_ready;
 
index ffdcccc05adaf48bc1b885935238eec6d7c35517..8c827aae78bb66f703038327cf6f3f09086c32c8 100644 (file)
@@ -77,20 +77,6 @@ ao_adc_poll(void)
        stm_adc.cr2 = AO_ADC_CR2_VAL | (1 << STM_ADC_CR2_SWSTART);
 }
 
-/*
- * Fetch a copy of the most recent ADC data
- */
-void
-ao_adc_get(struct ao_adc *packet)
-{
-#if HAS_FLIGHT
-       uint8_t i = ao_data_ring_prev(ao_sample_data);
-#else
-       uint8_t i = ao_data_ring_prev(ao_data_head);
-#endif
-       memcpy(packet, (void *) &ao_data_ring[i].adc, sizeof (struct ao_adc));
-}
-
 #ifdef AO_ADC_SQ1_NAME
 static const char *ao_adc_name[AO_NUM_ADC] = {
        AO_ADC_SQ1_NAME,
index e56375ca35a9524314e601cd84fb776ce58ebc07..e83b6bd2cfbf3e1dac4a7c2816703fcf1214ba08 100644 (file)
 #define AO_STACK_SIZE  512
 #endif
 
-#ifndef AO_TICK_TYPE
-#define AO_TICK_TYPE   uint16_t
-#define AO_TICK_SIGNED int16_t
-#endif
-
 #define AO_PORT_TYPE   uint16_t
 
 /* Various definitions to make GCC look more like SDCC */
@@ -58,9 +53,6 @@
 
 #define AO_ROMCONFIG_SYMBOL __attribute__((section(".romconfig"))) const
 
-#define ao_arch_task_members\
-       uint32_t *sp;                   /* saved stack pointer */
-
 /*
  * For now, we're running at a weird frequency
  */
@@ -119,7 +111,7 @@ void ao_lcd_font_string(char *s);
 extern const uint32_t  ao_radio_cal;
 
 void
-ao_adc_init();
+ao_adc_init(void);
 
 /* ADC maximum reported value */
 #define AO_ADC_MAX                     4095
index 7fe6a732478b442f1b9ce445f7cb253d01cadd88..ad46ef32babf9fd52b0f9d58f08fd09e6f534275 100644 (file)
@@ -393,6 +393,9 @@ struct ao_stm_usart {
 #endif
 };
 
+void
+ao_debug_out(char c);
+
 #if HAS_SERIAL_1
 extern struct ao_stm_usart     ao_stm_usart1;
 #endif
@@ -449,7 +452,7 @@ ao_arch_irqrestore(uint32_t basepri) {
 }
 
 static inline void
-ao_arch_memory_barrier() {
+ao_arch_memory_barrier(void) {
        asm volatile("" ::: "memory");
 }
 
@@ -472,7 +475,7 @@ ao_arch_irq_check(void) {
 static inline void
 ao_arch_init_stack(struct ao_task *task, void *start)
 {
-       uint32_t        *sp = (uint32_t *) ((void*) task->stack + AO_STACK_SIZE);
+       uint32_t        *sp = &task->stack32[AO_STACK_SIZE>>2];
        uint32_t        a = (uint32_t) start;
        int             i;
 
@@ -490,7 +493,7 @@ ao_arch_init_stack(struct ao_task *task, void *start)
        /* BASEPRI with interrupts enabled */
        ARM_PUSH32(sp, 0);
 
-       task->sp = sp;
+       task->sp32 = sp;
 }
 
 static inline void ao_arch_save_regs(void) {
@@ -514,12 +517,12 @@ static inline void ao_arch_save_regs(void) {
 static inline void ao_arch_save_stack(void) {
        uint32_t        *sp;
        asm("mov %0,sp" : "=&r" (sp) );
-       ao_cur_task->sp = (sp);
+       ao_cur_task->sp32 = (sp);
 }
 
 static inline void ao_arch_restore_stack(void) {
        /* Switch stacks */
-       asm("mov sp, %0" : : "r" (ao_cur_task->sp) );
+       asm("mov sp, %0" : : "r" (ao_cur_task->sp32) );
 
 #ifdef AO_NONMASK_INTERRUPTS
        /* Restore BASEPRI */
@@ -607,4 +610,6 @@ ao_arch_wait_interrupt(void) {
                ao_arch_irqrestore(__mask);             \
        } while (0)
 
+void start(void);
+
 #endif /* _AO_ARCH_FUNCS_H_ */
index 2746d7f8e60b558e48056f2b3653daf237a6be2b..2bcd684909af1fccfe843fd9655dee4e586d53e0 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 #include "ao.h"
+#include "ao_beep.h"
 
 #if BEEPER_TIMER == 2
 #define stm_beeper     stm_tim2
index 8aa2bdca9ad73cca16a2559ee1becd2f5c51075a..1d19a48f60dcd63b99a3b964d318710197b9f72a 100644 (file)
 #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);
 
 void
-ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)());
+ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)(void));
 
 void
 ao_exti_enable(struct stm_gpio *gpio, uint8_t pin);
index 2491b609893607b2a340a455be93f59c513f860b..3a2748a9a8c5ea908f80d592008fe82f7ca5ff27 100644 (file)
@@ -135,7 +135,7 @@ ao_exti_set_mode(struct stm_gpio *gpio, uint8_t pin, uint8_t mode) {
 }
 
 void
-ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)()) {
+ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)(void)) {
        (void) gpio;
        ao_exti_callback[pin] = callback;
 }
index 23805aa8929a1bbc957ba3c20dadff8643ad3ee0..8f54931808a7f95abab74a9e684b10c47299adf4 100644 (file)
@@ -278,7 +278,7 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop)
        return true;
 }
 
-void
+static void
 ao_i2c_recv_dma_isr(int index)
 {
        int             i;
@@ -341,6 +341,17 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop)
                                    (0 << STM_DMA_CCR_PINC) |
                                    (0 << STM_DMA_CCR_CIRC) |
                                    (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR));
+
+               /* XXX ao_i2c_recv_dma_isr hasn't ever been used, so it
+                * doesn't appear to be necessary. Testing with a device
+                * that uses i2c would really be useful here to discover
+                * whether this function is necessary or not.
+                */
+#if 0
+               ao_dma_set_isr(rx_dma_index, ao_i2c_recv_dma_isr);
+#else
+               (void) ao_i2c_recv_dma_isr;
+#endif
                stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_ACK);
                stm_i2c->cr2 = AO_STM_I2C_CR2 |
                        (1 << STM_I2C_CR2_DMAEN) | (1 << STM_I2C_CR2_LAST);
@@ -363,7 +374,7 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop)
        return ret;
 }
 
-void
+static void
 ao_i2c_channel_init(uint8_t index)
 {
        struct stm_i2c  *stm_i2c = ao_i2c_stm_info[index].stm_i2c;
index b1664b1381f0ad2b9853bb982b7ddec65117fb1f..6c5ea5c2abcf6f07cfeb51439d4438cd5da15359 100644 (file)
  */
 
 #include <ao.h>
+#include "ao_lcd_font.h"
 
 static const uint16_t ao_lcd_font[] = {
-#include "ao_lcd_font.h"
+#include "ao_lcd_font_bits.h"
 };
 
 /*
@@ -116,7 +117,7 @@ ao_lcd_font_text(void)
        ao_lcd_font_string(string);
 }
 
-const struct ao_cmds ao_lcd_font_cmds[] = {
+static const struct ao_cmds ao_lcd_font_cmds[] = {
        { ao_lcd_font_text,     "t <string>\0Write <string> to LCD" },
        { 0, NULL }
 };
@@ -126,4 +127,3 @@ ao_lcd_font_init(void)
 {
        ao_cmd_register(ao_lcd_font_cmds);
 }
-       
index 08adc9ab8c89f4fa07b86288216f052dbdd3db8c..89c563cdb3c1b357f5e3ccfd380cdef4a14f8326 100644 (file)
-       [0] = 0x0000,
 /*
-CHAR 32 ' '
-              
-              
-              
-              
-              
-              
-              
-*/
+ * Copyright © 2019 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.
+ */
 
-       [1] = 0x0102,
-/*
-CHAR 33 '!'
-              
-       |      
-       |      
-              
-       |      
-       |      
-              
-*/
-
-       [2] = 0x000a,
-/*
-CHAR 34 '"'
-              
-       |  |   
-       |  |   
-              
-              
-              
-              
-*/
-
-       [3] = 0x05e8,
-/*
-CHAR 35 '#'
-              
-          |  |
-          |  |
-        -- -- 
-       |  |   
-       |  |   
-              
-*/
-
-       [4] = 0x34cb,
-/*
-CHAR 36 '$'
-        ----- 
-       |  |   
-       |  |   
-        -- -- 
-          |  |
-          |  |
-        ----- 
-*/
-
-       [5] = 0x1212,
-/*
-CHAR 37 '%'
-              
-       |    / 
-       |   /  
-              
-         /   |
-        /    |
-              
-*/
-
-       [6] = 0x2955,
-/*
-CHAR 38 '&'
-        ----- 
-        \   / 
-         \ /  
-        --    
-       |   \  
-       |    \ 
-        ----- 
-*/
-
-       [7] = 0x0008,
-/*
-CHAR 39 '''
-              
-          |   
-          |   
-              
-              
-              
-              
-*/
-
-       [8] = 0x2103,
-/*
-CHAR 40 '('
-        ----- 
-       |      
-       |      
-              
-       |      
-       |      
-        ----- 
-*/
-
-       [9] = 0x3021,
-/*
-CHAR 41 ')'
-        ----- 
-             |
-             |
-              
-             |
-             |
-        ----- 
-*/
-
-       [10] = 0x0e1c,
-/*
-CHAR 42 '*'
-              
-        \ | / 
-         \|/  
-              
-         /|\  
-        / | \ 
-              
-*/
-
-       [11] = 0x04c8,
-/*
-CHAR 43 '+'
-              
-          |   
-          |   
-        -- -- 
-          |   
-          |   
-              
-*/
-
-       [12] = 0x0200,
-/*
-CHAR 44 ','
-              
-              
-              
-              
-         /    
-        /     
-              
-*/
-
-       [13] = 0x00c0,
-/*
-CHAR 45 '-'
-              
-              
-              
-        -- -- 
-              
-              
-              
-*/
-
-       [14] = 0x0800,
-/*
-CHAR 46 '.'
-              
-              
-              
-              
-           \  
-            \ 
-              
-*/
-
-       [15] = 0x0210,
-/*
-CHAR 47 '/'
-              
-            / 
-           /  
-              
-         /    
-        /     
-              
-*/
-
-       [16] = 0x3333,
-/*
-CHAR 48 '0'
-        ----- 
-       |    /|
-       |   / |
-              
-       | /   |
-       |/    |
-        ----- 
-*/
-
-       [17] = 0x1030,
-/*
-CHAR 49 '1'
-              
-            /|
-           / |
-              
-             |
-             |
-              
-*/
-
-       [18] = 0x21e1,
-/*
-CHAR 50 '2'
-        ----- 
-             |
-             |
-        -- -- 
-       |      
-       |      
-        ----- 
-*/
-
-       [19] = 0x30a1,
-/*
-CHAR 51 '3'
-        ----- 
-             |
-             |
-           -- 
-             |
-             |
-        ----- 
-*/
-
-       [20] = 0x10e2,
-/*
-CHAR 52 '4'
-              
-       |     |
-       |     |
-        -- -- 
-             |
-             |
-              
-*/
-
-       [21] = 0x30c3,
-/*
-CHAR 53 '5'
-        ----- 
-       |      
-       |      
-        -- -- 
-             |
-             |
-        ----- 
-*/
-
-       [22] = 0x31c3,
-/*
-CHAR 54 '6'
-        ----- 
-       |      
-       |      
-        -- -- 
-       |     |
-       |     |
-        ----- 
-*/
-
-       [23] = 0x0411,
-/*
-CHAR 55 '7'
-        ----- 
-            / 
-           /  
-              
-          |   
-          |   
-              
-*/
-
-       [24] = 0x31e3,
-/*
-CHAR 56 '8'
-        ----- 
-       |     |
-       |     |
-        -- -- 
-       |     |
-       |     |
-        ----- 
-*/
-
-       [25] = 0x10e3,
-/*
-CHAR 57 '9'
-        ----- 
-       |     |
-       |     |
-        -- -- 
-             |
-             |
-              
-*/
-
-       [26] = 0x0408,
-/*
-CHAR 58 ':'
-              
-          |   
-          |   
-              
-          |   
-          |   
-              
-*/
-
-       [27] = 0x0208,
-/*
-CHAR 59 ';'
-              
-          |   
-          |   
-              
-         /    
-        /     
-              
-*/
-
-       [28] = 0x0810,
-/*
-CHAR 60 '<'
-              
-            / 
-           /  
-              
-           \  
-            \ 
-              
-*/
-
-       [29] = 0x20c0,
-/*
-CHAR 61 '='
-              
-              
-              
-        -- -- 
-              
-              
-        ----- 
-*/
-
-       [30] = 0x0204,
-/*
-CHAR 62 '>'
-              
-        \     
-         \    
-              
-         /    
-        /     
-              
-*/
-
-       [31] = 0x0413,
-/*
-CHAR 63 '?'
-        ----- 
-       |    / 
-       |   /  
-              
-          |   
-          |   
-              
-*/
-
-       [32] = 0x39b3,
-/*
-CHAR 64 '@'
-        ----- 
-       |    /|
-       |   / |
-           -- 
-       |   \ |
-       |    \|
-        ----- 
-*/
-
-       [33] = 0x11e3,
-/*
-CHAR 65 'A'
-        ----- 
-       |     |
-       |     |
-        -- -- 
-       |     |
-       |     |
-              
-*/
-
-       [34] = 0x34a9,
-/*
-CHAR 66 'B'
-        ----- 
-          |  |
-          |  |
-           -- 
-          |  |
-          |  |
-        ----- 
-*/
-
-       [35] = 0x2103,
-/*
-CHAR 67 'C'
-        ----- 
-       |      
-       |      
-              
-       |      
-       |      
-        ----- 
-*/
-
-       [36] = 0x3429,
-/*
-CHAR 68 'D'
-        ----- 
-          |  |
-          |  |
-              
-          |  |
-          |  |
-        ----- 
-*/
-
-       [37] = 0x2143,
-/*
-CHAR 69 'E'
-        ----- 
-       |      
-       |      
-        --    
-       |      
-       |      
-        ----- 
-*/
-
-       [38] = 0x0143,
-/*
-CHAR 70 'F'
-        ----- 
-       |      
-       |      
-        --    
-       |      
-       |      
-              
-*/
-
-       [39] = 0x3183,
-/*
-CHAR 71 'G'
-        ----- 
-       |      
-       |      
-           -- 
-       |     |
-       |     |
-        ----- 
-*/
-
-       [40] = 0x11e2,
-/*
-CHAR 72 'H'
-              
-       |     |
-       |     |
-        -- -- 
-       |     |
-       |     |
-              
-*/
-
-       [41] = 0x2409,
-/*
-CHAR 73 'I'
-        ----- 
-          |   
-          |   
-              
-          |   
-          |   
-        ----- 
-*/
-
-       [42] = 0x3120,
-/*
-CHAR 74 'J'
-              
-             |
-             |
-              
-       |     |
-       |     |
-        ----- 
-*/
-
-       [43] = 0x0952,
-/*
-CHAR 75 'K'
-              
-       |    / 
-       |   /  
-        --    
-       |   \  
-       |    \ 
-              
-*/
-
-       [44] = 0x2102,
-/*
-CHAR 76 'L'
-              
-       |      
-       |      
-              
-       |      
-       |      
-        ----- 
-*/
-
-       [45] = 0x1136,
-/*
-CHAR 77 'M'
-              
-       |\   /|
-       | \ / |
-              
-       |     |
-       |     |
-              
-*/
-
-       [46] = 0x1926,
-/*
-CHAR 78 'N'
-              
-       |\    |
-       | \   |
-              
-       |   \ |
-       |    \|
-              
-*/
-
-       [47] = 0x3123,
-/*
-CHAR 79 'O'
-        ----- 
-       |     |
-       |     |
-              
-       |     |
-       |     |
-        ----- 
-*/
+#ifndef _AO_LCD_FONT_H_
+#define _AO_LCD_FONT_H_
 
-       [48] = 0x01e3,
-/*
-CHAR 80 'P'
-        ----- 
-       |     |
-       |     |
-        -- -- 
-       |      
-       |      
-              
-*/
-
-       [49] = 0x3923,
-/*
-CHAR 81 'Q'
-        ----- 
-       |     |
-       |     |
-              
-       |   \ |
-       |    \|
-        ----- 
-*/
-
-       [50] = 0x09e3,
-/*
-CHAR 82 'R'
-        ----- 
-       |     |
-       |     |
-        -- -- 
-       |   \  
-       |    \ 
-              
-*/
-
-       [51] = 0x3085,
-/*
-CHAR 83 'S'
-        ----- 
-        \     
-         \    
-           -- 
-             |
-             |
-        ----- 
-*/
-
-       [52] = 0x0409,
-/*
-CHAR 84 'T'
-        ----- 
-          |   
-          |   
-              
-          |   
-          |   
-              
-*/
-
-       [53] = 0x3122,
-/*
-CHAR 85 'U'
-              
-       |     |
-       |     |
-              
-       |     |
-       |     |
-        ----- 
-*/
-
-       [54] = 0x0312,
-/*
-CHAR 86 'V'
-              
-       |    / 
-       |   /  
-              
-       | /    
-       |/     
-              
-*/
-
-       [55] = 0x1b22,
-/*
-CHAR 87 'W'
-              
-       |     |
-       |     |
-              
-       | / \ |
-       |/   \|
-              
-*/
-
-       [56] = 0x0a14,
-/*
-CHAR 88 'X'
-              
-        \   / 
-         \ /  
-              
-         / \  
-        /   \ 
-              
-*/
-
-       [57] = 0x0414,
-/*
-CHAR 89 'Y'
-              
-        \   / 
-         \ /  
-              
-          |   
-          |   
-              
-*/
-
-       [58] = 0x2211,
-/*
-CHAR 90 'Z'
-        ----- 
-            / 
-           /  
-              
-         /    
-        /     
-        ----- 
-*/
+void
+ao_lcd_font_init(void);
 
-       [59] = 0x2103,
-/*
-CHAR 91 '['
-        ----- 
-       |      
-       |      
-              
-       |      
-       |      
-        ----- 
-*/
-
-       [60] = 0x0804,
-/*
-CHAR 92 '\'
-              
-        \     
-         \    
-              
-           \  
-            \ 
-              
-*/
+void
+ao_lcd_font_string(char *s);
 
-       [61] = 0x3021,
-/*
-CHAR 93 ']'
-        ----- 
-             |
-             |
-              
-             |
-             |
-        ----- 
-*/
-
-       [62] = 0x0023,
-/*
-CHAR 94 '^'
-        ----- 
-       |     |
-       |     |
-              
-              
-              
-              
-*/
-
-       [63] = 0x2000,
-/*
-CHAR 95 '_'
-              
-              
-              
-              
-              
-              
-        ----- 
-*/
-
-       [64] = 0x0004,
-/*
-CHAR 96 '`'
-              
-        \     
-         \    
-              
-              
-              
-              
-*/
-
-       [65] = 0x2540,
-/*
-CHAR 97 'a'
-              
-              
-              
-        --    
-       |  |   
-       |  |   
-        ----- 
-*/
-
-       [66] = 0x2942,
-/*
-CHAR 98 'b'
-              
-       |      
-       |      
-        --    
-       |   \  
-       |    \ 
-        ----- 
-*/
-
-       [67] = 0x21c0,
-/*
-CHAR 99 'c'
-              
-              
-              
-        -- -- 
-       |      
-       |      
-        ----- 
-*/
-
-       [68] = 0x32a0,
-/*
-CHAR 100 'd'
-              
-             |
-             |
-           -- 
-         /   |
-        /    |
-        ----- 
-*/
-
-       [69] = 0x2340,
-/*
-CHAR 101 'e'
-              
-              
-              
-        --    
-       | /    
-       |/     
-        ----- 
-*/
-
-       [70] = 0x0143,
-/*
-CHAR 102 'f'
-        ----- 
-       |      
-       |      
-        --    
-       |      
-       |      
-              
-*/
-
-       [71] = 0x10a5,
-/*
-CHAR 103 'g'
-        ----- 
-        \    |
-         \   |
-           -- 
-             |
-             |
-              
-*/
-
-       [72] = 0x11c2,
-/*
-CHAR 104 'h'
-              
-       |      
-       |      
-        -- -- 
-       |     |
-       |     |
-              
-*/
-
-       [73] = 0x0400,
-/*
-CHAR 105 'i'
-              
-              
-              
-              
-          |   
-          |   
-              
-*/
-
-       [74] = 0x3000,
-/*
-CHAR 106 'j'
-              
-              
-              
-              
-             |
-             |
-        ----- 
-*/
-
-       [75] = 0x0c88,
-/*
-CHAR 107 'k'
-              
-          |   
-          |   
-           -- 
-          |\  
-          | \ 
-              
-*/
-
-       [76] = 0x0408,
-/*
-CHAR 108 'l'
-              
-          |   
-          |   
-              
-          |   
-          |   
-              
-*/
-
-       [77] = 0x15c0,
-/*
-CHAR 109 'm'
-              
-              
-              
-        -- -- 
-       |  |  |
-       |  |  |
-              
-*/
-
-       [78] = 0x0940,
-/*
-CHAR 110 'n'
-              
-              
-              
-        --    
-       |   \  
-       |    \ 
-              
-*/
-
-       [79] = 0x31c0,
-/*
-CHAR 111 'o'
-              
-              
-              
-        -- -- 
-       |     |
-       |     |
-        ----- 
-*/
-
-       [80] = 0x0146,
-/*
-CHAR 112 'p'
-              
-       |\     
-       | \    
-        --    
-       |      
-       |      
-              
-*/
-
-       [81] = 0x10b0,
-/*
-CHAR 113 'q'
-              
-            /|
-           / |
-           -- 
-             |
-             |
-              
-*/
-
-       [82] = 0x0140,
-/*
-CHAR 114 'r'
-              
-              
-              
-        --    
-       |      
-       |      
-              
-*/
-
-       [83] = 0x2880,
-/*
-CHAR 115 's'
-              
-              
-              
-           -- 
-           \  
-            \ 
-        ----- 
-*/
-
-       [84] = 0x2142,
-/*
-CHAR 116 't'
-              
-       |      
-       |      
-        --    
-       |      
-       |      
-        ----- 
-*/
-
-       [85] = 0x3100,
-/*
-CHAR 117 'u'
-              
-              
-              
-              
-       |     |
-       |     |
-        ----- 
-*/
-
-       [86] = 0x0300,
-/*
-CHAR 118 'v'
-              
-              
-              
-              
-       | /    
-       |/     
-              
-*/
-
-       [87] = 0x1b00,
-/*
-CHAR 119 'w'
-              
-              
-              
-              
-       | / \ |
-       |/   \|
-              
-*/
-
-       [88] = 0x0a14,
-/*
-CHAR 120 'x'
-              
-        \   / 
-         \ /  
-              
-         / \  
-        /   \ 
-              
-*/
-
-       [89] = 0x3800,
-/*
-CHAR 121 'y'
-              
-              
-              
-              
-           \ |
-            \|
-        ----- 
-*/
-
-       [90] = 0x2240,
-/*
-CHAR 122 'z'
-              
-              
-              
-        --    
-         /    
-        /     
-        ----- 
-*/
-
-       [91] = 0x2245,
-/*
-CHAR 123 '{'
-        ----- 
-        \     
-         \    
-        --    
-         /    
-        /     
-        ----- 
-*/
-
-       [92] = 0x0408,
-/*
-CHAR 124 '|'
-              
-          |   
-          |   
-              
-          |   
-          |   
-              
-*/
-
-       [93] = 0x2891,
-/*
-CHAR 125 '}'
-        ----- 
-            / 
-           /  
-           -- 
-           \  
-            \ 
-        ----- 
-*/
-
-       [94] = 0x000e,
-/*
-CHAR 126 '~'
-              
-       |\ |   
-       | \|   
-              
-              
-              
-              
-*/
-
-       [95] = 0x3fff,
-/*
-CHAR 127 'DEL'
-        ----- 
-       |\ | /|
-       | \|/ |
-        -- -- 
-       | /|\ |
-       |/ | \|
-        ----- 
-*/
+void
+ao_lcd_font_char(uint8_t pos, char c, uint16_t flags);
 
+#endif /* _AO_LCD_FONT_H_ */
diff --git a/src/stm/ao_lcd_font_bits.h b/src/stm/ao_lcd_font_bits.h
new file mode 100644 (file)
index 0000000..08adc9a
--- /dev/null
@@ -0,0 +1,1152 @@
+       [0] = 0x0000,
+/*
+CHAR 32 ' '
+              
+              
+              
+              
+              
+              
+              
+*/
+
+       [1] = 0x0102,
+/*
+CHAR 33 '!'
+              
+       |      
+       |      
+              
+       |      
+       |      
+              
+*/
+
+       [2] = 0x000a,
+/*
+CHAR 34 '"'
+              
+       |  |   
+       |  |   
+              
+              
+              
+              
+*/
+
+       [3] = 0x05e8,
+/*
+CHAR 35 '#'
+              
+          |  |
+          |  |
+        -- -- 
+       |  |   
+       |  |   
+              
+*/
+
+       [4] = 0x34cb,
+/*
+CHAR 36 '$'
+        ----- 
+       |  |   
+       |  |   
+        -- -- 
+          |  |
+          |  |
+        ----- 
+*/
+
+       [5] = 0x1212,
+/*
+CHAR 37 '%'
+              
+       |    / 
+       |   /  
+              
+         /   |
+        /    |
+              
+*/
+
+       [6] = 0x2955,
+/*
+CHAR 38 '&'
+        ----- 
+        \   / 
+         \ /  
+        --    
+       |   \  
+       |    \ 
+        ----- 
+*/
+
+       [7] = 0x0008,
+/*
+CHAR 39 '''
+              
+          |   
+          |   
+              
+              
+              
+              
+*/
+
+       [8] = 0x2103,
+/*
+CHAR 40 '('
+        ----- 
+       |      
+       |      
+              
+       |      
+       |      
+        ----- 
+*/
+
+       [9] = 0x3021,
+/*
+CHAR 41 ')'
+        ----- 
+             |
+             |
+              
+             |
+             |
+        ----- 
+*/
+
+       [10] = 0x0e1c,
+/*
+CHAR 42 '*'
+              
+        \ | / 
+         \|/  
+              
+         /|\  
+        / | \ 
+              
+*/
+
+       [11] = 0x04c8,
+/*
+CHAR 43 '+'
+              
+          |   
+          |   
+        -- -- 
+          |   
+          |   
+              
+*/
+
+       [12] = 0x0200,
+/*
+CHAR 44 ','
+              
+              
+              
+              
+         /    
+        /     
+              
+*/
+
+       [13] = 0x00c0,
+/*
+CHAR 45 '-'
+              
+              
+              
+        -- -- 
+              
+              
+              
+*/
+
+       [14] = 0x0800,
+/*
+CHAR 46 '.'
+              
+              
+              
+              
+           \  
+            \ 
+              
+*/
+
+       [15] = 0x0210,
+/*
+CHAR 47 '/'
+              
+            / 
+           /  
+              
+         /    
+        /     
+              
+*/
+
+       [16] = 0x3333,
+/*
+CHAR 48 '0'
+        ----- 
+       |    /|
+       |   / |
+              
+       | /   |
+       |/    |
+        ----- 
+*/
+
+       [17] = 0x1030,
+/*
+CHAR 49 '1'
+              
+            /|
+           / |
+              
+             |
+             |
+              
+*/
+
+       [18] = 0x21e1,
+/*
+CHAR 50 '2'
+        ----- 
+             |
+             |
+        -- -- 
+       |      
+       |      
+        ----- 
+*/
+
+       [19] = 0x30a1,
+/*
+CHAR 51 '3'
+        ----- 
+             |
+             |
+           -- 
+             |
+             |
+        ----- 
+*/
+
+       [20] = 0x10e2,
+/*
+CHAR 52 '4'
+              
+       |     |
+       |     |
+        -- -- 
+             |
+             |
+              
+*/
+
+       [21] = 0x30c3,
+/*
+CHAR 53 '5'
+        ----- 
+       |      
+       |      
+        -- -- 
+             |
+             |
+        ----- 
+*/
+
+       [22] = 0x31c3,
+/*
+CHAR 54 '6'
+        ----- 
+       |      
+       |      
+        -- -- 
+       |     |
+       |     |
+        ----- 
+*/
+
+       [23] = 0x0411,
+/*
+CHAR 55 '7'
+        ----- 
+            / 
+           /  
+              
+          |   
+          |   
+              
+*/
+
+       [24] = 0x31e3,
+/*
+CHAR 56 '8'
+        ----- 
+       |     |
+       |     |
+        -- -- 
+       |     |
+       |     |
+        ----- 
+*/
+
+       [25] = 0x10e3,
+/*
+CHAR 57 '9'
+        ----- 
+       |     |
+       |     |
+        -- -- 
+             |
+             |
+              
+*/
+
+       [26] = 0x0408,
+/*
+CHAR 58 ':'
+              
+          |   
+          |   
+              
+          |   
+          |   
+              
+*/
+
+       [27] = 0x0208,
+/*
+CHAR 59 ';'
+              
+          |   
+          |   
+              
+         /    
+        /     
+              
+*/
+
+       [28] = 0x0810,
+/*
+CHAR 60 '<'
+              
+            / 
+           /  
+              
+           \  
+            \ 
+              
+*/
+
+       [29] = 0x20c0,
+/*
+CHAR 61 '='
+              
+              
+              
+        -- -- 
+              
+              
+        ----- 
+*/
+
+       [30] = 0x0204,
+/*
+CHAR 62 '>'
+              
+        \     
+         \    
+              
+         /    
+        /     
+              
+*/
+
+       [31] = 0x0413,
+/*
+CHAR 63 '?'
+        ----- 
+       |    / 
+       |   /  
+              
+          |   
+          |   
+              
+*/
+
+       [32] = 0x39b3,
+/*
+CHAR 64 '@'
+        ----- 
+       |    /|
+       |   / |
+           -- 
+       |   \ |
+       |    \|
+        ----- 
+*/
+
+       [33] = 0x11e3,
+/*
+CHAR 65 'A'
+        ----- 
+       |     |
+       |     |
+        -- -- 
+       |     |
+       |     |
+              
+*/
+
+       [34] = 0x34a9,
+/*
+CHAR 66 'B'
+        ----- 
+          |  |
+          |  |
+           -- 
+          |  |
+          |  |
+        ----- 
+*/
+
+       [35] = 0x2103,
+/*
+CHAR 67 'C'
+        ----- 
+       |      
+       |      
+              
+       |      
+       |      
+        ----- 
+*/
+
+       [36] = 0x3429,
+/*
+CHAR 68 'D'
+        ----- 
+          |  |
+          |  |
+              
+          |  |
+          |  |
+        ----- 
+*/
+
+       [37] = 0x2143,
+/*
+CHAR 69 'E'
+        ----- 
+       |      
+       |      
+        --    
+       |      
+       |      
+        ----- 
+*/
+
+       [38] = 0x0143,
+/*
+CHAR 70 'F'
+        ----- 
+       |      
+       |      
+        --    
+       |      
+       |      
+              
+*/
+
+       [39] = 0x3183,
+/*
+CHAR 71 'G'
+        ----- 
+       |      
+       |      
+           -- 
+       |     |
+       |     |
+        ----- 
+*/
+
+       [40] = 0x11e2,
+/*
+CHAR 72 'H'
+              
+       |     |
+       |     |
+        -- -- 
+       |     |
+       |     |
+              
+*/
+
+       [41] = 0x2409,
+/*
+CHAR 73 'I'
+        ----- 
+          |   
+          |   
+              
+          |   
+          |   
+        ----- 
+*/
+
+       [42] = 0x3120,
+/*
+CHAR 74 'J'
+              
+             |
+             |
+              
+       |     |
+       |     |
+        ----- 
+*/
+
+       [43] = 0x0952,
+/*
+CHAR 75 'K'
+              
+       |    / 
+       |   /  
+        --    
+       |   \  
+       |    \ 
+              
+*/
+
+       [44] = 0x2102,
+/*
+CHAR 76 'L'
+              
+       |      
+       |      
+              
+       |      
+       |      
+        ----- 
+*/
+
+       [45] = 0x1136,
+/*
+CHAR 77 'M'
+              
+       |\   /|
+       | \ / |
+              
+       |     |
+       |     |
+              
+*/
+
+       [46] = 0x1926,
+/*
+CHAR 78 'N'
+              
+       |\    |
+       | \   |
+              
+       |   \ |
+       |    \|
+              
+*/
+
+       [47] = 0x3123,
+/*
+CHAR 79 'O'
+        ----- 
+       |     |
+       |     |
+              
+       |     |
+       |     |
+        ----- 
+*/
+
+       [48] = 0x01e3,
+/*
+CHAR 80 'P'
+        ----- 
+       |     |
+       |     |
+        -- -- 
+       |      
+       |      
+              
+*/
+
+       [49] = 0x3923,
+/*
+CHAR 81 'Q'
+        ----- 
+       |     |
+       |     |
+              
+       |   \ |
+       |    \|
+        ----- 
+*/
+
+       [50] = 0x09e3,
+/*
+CHAR 82 'R'
+        ----- 
+       |     |
+       |     |
+        -- -- 
+       |   \  
+       |    \ 
+              
+*/
+
+       [51] = 0x3085,
+/*
+CHAR 83 'S'
+        ----- 
+        \     
+         \    
+           -- 
+             |
+             |
+        ----- 
+*/
+
+       [52] = 0x0409,
+/*
+CHAR 84 'T'
+        ----- 
+          |   
+          |   
+              
+          |   
+          |   
+              
+*/
+
+       [53] = 0x3122,
+/*
+CHAR 85 'U'
+              
+       |     |
+       |     |
+              
+       |     |
+       |     |
+        ----- 
+*/
+
+       [54] = 0x0312,
+/*
+CHAR 86 'V'
+              
+       |    / 
+       |   /  
+              
+       | /    
+       |/     
+              
+*/
+
+       [55] = 0x1b22,
+/*
+CHAR 87 'W'
+              
+       |     |
+       |     |
+              
+       | / \ |
+       |/   \|
+              
+*/
+
+       [56] = 0x0a14,
+/*
+CHAR 88 'X'
+              
+        \   / 
+         \ /  
+              
+         / \  
+        /   \ 
+              
+*/
+
+       [57] = 0x0414,
+/*
+CHAR 89 'Y'
+              
+        \   / 
+         \ /  
+              
+          |   
+          |   
+              
+*/
+
+       [58] = 0x2211,
+/*
+CHAR 90 'Z'
+        ----- 
+            / 
+           /  
+              
+         /    
+        /     
+        ----- 
+*/
+
+       [59] = 0x2103,
+/*
+CHAR 91 '['
+        ----- 
+       |      
+       |      
+              
+       |      
+       |      
+        ----- 
+*/
+
+       [60] = 0x0804,
+/*
+CHAR 92 '\'
+              
+        \     
+         \    
+              
+           \  
+            \ 
+              
+*/
+
+       [61] = 0x3021,
+/*
+CHAR 93 ']'
+        ----- 
+             |
+             |
+              
+             |
+             |
+        ----- 
+*/
+
+       [62] = 0x0023,
+/*
+CHAR 94 '^'
+        ----- 
+       |     |
+       |     |
+              
+              
+              
+              
+*/
+
+       [63] = 0x2000,
+/*
+CHAR 95 '_'
+              
+              
+              
+              
+              
+              
+        ----- 
+*/
+
+       [64] = 0x0004,
+/*
+CHAR 96 '`'
+              
+        \     
+         \    
+              
+              
+              
+              
+*/
+
+       [65] = 0x2540,
+/*
+CHAR 97 'a'
+              
+              
+              
+        --    
+       |  |   
+       |  |   
+        ----- 
+*/
+
+       [66] = 0x2942,
+/*
+CHAR 98 'b'
+              
+       |      
+       |      
+        --    
+       |   \  
+       |    \ 
+        ----- 
+*/
+
+       [67] = 0x21c0,
+/*
+CHAR 99 'c'
+              
+              
+              
+        -- -- 
+       |      
+       |      
+        ----- 
+*/
+
+       [68] = 0x32a0,
+/*
+CHAR 100 'd'
+              
+             |
+             |
+           -- 
+         /   |
+        /    |
+        ----- 
+*/
+
+       [69] = 0x2340,
+/*
+CHAR 101 'e'
+              
+              
+              
+        --    
+       | /    
+       |/     
+        ----- 
+*/
+
+       [70] = 0x0143,
+/*
+CHAR 102 'f'
+        ----- 
+       |      
+       |      
+        --    
+       |      
+       |      
+              
+*/
+
+       [71] = 0x10a5,
+/*
+CHAR 103 'g'
+        ----- 
+        \    |
+         \   |
+           -- 
+             |
+             |
+              
+*/
+
+       [72] = 0x11c2,
+/*
+CHAR 104 'h'
+              
+       |      
+       |      
+        -- -- 
+       |     |
+       |     |
+              
+*/
+
+       [73] = 0x0400,
+/*
+CHAR 105 'i'
+              
+              
+              
+              
+          |   
+          |   
+              
+*/
+
+       [74] = 0x3000,
+/*
+CHAR 106 'j'
+              
+              
+              
+              
+             |
+             |
+        ----- 
+*/
+
+       [75] = 0x0c88,
+/*
+CHAR 107 'k'
+              
+          |   
+          |   
+           -- 
+          |\  
+          | \ 
+              
+*/
+
+       [76] = 0x0408,
+/*
+CHAR 108 'l'
+              
+          |   
+          |   
+              
+          |   
+          |   
+              
+*/
+
+       [77] = 0x15c0,
+/*
+CHAR 109 'm'
+              
+              
+              
+        -- -- 
+       |  |  |
+       |  |  |
+              
+*/
+
+       [78] = 0x0940,
+/*
+CHAR 110 'n'
+              
+              
+              
+        --    
+       |   \  
+       |    \ 
+              
+*/
+
+       [79] = 0x31c0,
+/*
+CHAR 111 'o'
+              
+              
+              
+        -- -- 
+       |     |
+       |     |
+        ----- 
+*/
+
+       [80] = 0x0146,
+/*
+CHAR 112 'p'
+              
+       |\     
+       | \    
+        --    
+       |      
+       |      
+              
+*/
+
+       [81] = 0x10b0,
+/*
+CHAR 113 'q'
+              
+            /|
+           / |
+           -- 
+             |
+             |
+              
+*/
+
+       [82] = 0x0140,
+/*
+CHAR 114 'r'
+              
+              
+              
+        --    
+       |      
+       |      
+              
+*/
+
+       [83] = 0x2880,
+/*
+CHAR 115 's'
+              
+              
+              
+           -- 
+           \  
+            \ 
+        ----- 
+*/
+
+       [84] = 0x2142,
+/*
+CHAR 116 't'
+              
+       |      
+       |      
+        --    
+       |      
+       |      
+        ----- 
+*/
+
+       [85] = 0x3100,
+/*
+CHAR 117 'u'
+              
+              
+              
+              
+       |     |
+       |     |
+        ----- 
+*/
+
+       [86] = 0x0300,
+/*
+CHAR 118 'v'
+              
+              
+              
+              
+       | /    
+       |/     
+              
+*/
+
+       [87] = 0x1b00,
+/*
+CHAR 119 'w'
+              
+              
+              
+              
+       | / \ |
+       |/   \|
+              
+*/
+
+       [88] = 0x0a14,
+/*
+CHAR 120 'x'
+              
+        \   / 
+         \ /  
+              
+         / \  
+        /   \ 
+              
+*/
+
+       [89] = 0x3800,
+/*
+CHAR 121 'y'
+              
+              
+              
+              
+           \ |
+            \|
+        ----- 
+*/
+
+       [90] = 0x2240,
+/*
+CHAR 122 'z'
+              
+              
+              
+        --    
+         /    
+        /     
+        ----- 
+*/
+
+       [91] = 0x2245,
+/*
+CHAR 123 '{'
+        ----- 
+        \     
+         \    
+        --    
+         /    
+        /     
+        ----- 
+*/
+
+       [92] = 0x0408,
+/*
+CHAR 124 '|'
+              
+          |   
+          |   
+              
+          |   
+          |   
+              
+*/
+
+       [93] = 0x2891,
+/*
+CHAR 125 '}'
+        ----- 
+            / 
+           /  
+           -- 
+           \  
+            \ 
+        ----- 
+*/
+
+       [94] = 0x000e,
+/*
+CHAR 126 '~'
+              
+       |\ |   
+       | \|   
+              
+              
+              
+              
+*/
+
+       [95] = 0x3fff,
+/*
+CHAR 127 'DEL'
+        ----- 
+       |\ | /|
+       | \|/ |
+        -- -- 
+       | /|\ |
+       |/ | \|
+        ----- 
+*/
+
index 7dcbb661b8a65899860d895025fa8639c99e22e8..ed4ec1610de3dde8e645725d851231a4b1051671 100644 (file)
@@ -87,7 +87,7 @@ ao_led_toggle(AO_LED_TYPE colors)
 }
 
 void
-ao_led_for(AO_LED_TYPE colors, AO_LED_TYPE ticks) 
+ao_led_for(AO_LED_TYPE colors, AO_TICK_TYPE ticks) 
 {
        ao_led_on(colors);
        ao_delay(ticks);
index 3bf8c0b036cbe182abc344ad8dab02ee31d3e332..68aac0019c3c5f052eddd946ea35a3fac7e17198 100644 (file)
@@ -19,7 +19,7 @@
 #ifndef _AO_PROFILE_H_
 #define _AO_PROFILE_H_
 
-void   ao_profile_init();
+void   ao_profile_init(void);
 
 static inline uint32_t ao_profile_tick(void) {
        uint16_t        hi, lo, second_hi;
index c1a2f1bdda0c1a509db01993f0a7fa6f71b6b98e..7a552e5d86a5884d0e5653081b11c3921a3b8999 100644 (file)
@@ -339,7 +339,7 @@ ao_serial2_set_speed(uint8_t speed)
 }
 
 #if HAS_SERIAL_SW_FLOW
-void
+static void
 ao_serial2_cts(void)
 {
        _ao_usart_cts(&ao_stm_usart2);
index 9e9436cfa685dae451ae27ff59b8c9af6b32be1c..d00deffab2161b80e0333f6524567deefdb87052 100644 (file)
@@ -36,6 +36,23 @@ ao_time(void)
 {
        return ao_tick_count;
 }
+
+uint64_t
+ao_time_ns(void)
+{
+       AO_TICK_TYPE    before, after;
+       uint32_t        cvr;
+
+       do {
+               before = ao_tick_count;
+               cvr = stm_systick.cvr;
+               after = ao_tick_count;
+       } while (before != after);
+
+       return (uint64_t) after * (1000000000ULL / AO_HERTZ) +
+               (uint64_t) cvr * (1000000000ULL / AO_SYSTICK);
+}
+
 #endif
 
 #if AO_DATA_ALL
index d7cbd5b7616902ba6fb2ad504c010d14b3ef1bdf..7f81e20e67c01b948f9703659ffc3c1acf4b87ca 100644 (file)
@@ -829,7 +829,7 @@ stm_usb_lp_isr(void)
 }
 
 void
-stm_usb_fs_wkup(void)
+stm_usb_fs_wkup_isr(void)
 {
        /* USB wakeup, just clear the bit for now */
        stm_usb.istr &= ~(1 << STM_USB_ISTR_WKUP);
@@ -932,7 +932,7 @@ _ao_usb_out_recv(void)
        _ao_usb_set_stat_rx(AO_USB_OUT_EPR, STM_USB_EPR_STAT_RX_VALID);
 }
 
-int
+static int
 _ao_usb_pollchar(void)
 {
        uint8_t c;
index 0109ec815525b2acdf3c6abe36cf5c86822794e6..310b334bae22a64171e66eb6cd6596f9e49240f7 100644 (file)
@@ -1103,64 +1103,67 @@ extern struct stm_mpu stm_mpu;
 #define  STM_MPU_RASR_SIZE_MASK                0x1f
 #define STM_MPU_RASR_ENABLE    0
 
-#define isr(name) void stm_ ## name ## _isr(void);
-
-isr(nmi)
-isr(hardfault)
-isr(memmanage)
-isr(busfault)
-isr(usagefault)
-isr(svc)
-isr(debugmon)
-isr(pendsv)
-isr(systick)
-isr(wwdg)
-isr(pvd)
-isr(tamper_stamp)
-isr(rtc_wkup)
-isr(flash)
-isr(rcc)
-isr(exti0)
-isr(exti1)
-isr(exti2)
-isr(exti3)
-isr(exti4)
-isr(dma1_channel1)
-isr(dma1_channel2)
-isr(dma1_channel3)
-isr(dma1_channel4)
-isr(dma1_channel5)
-isr(dma1_channel6)
-isr(dma1_channel7)
-isr(adc1)
-isr(usb_hp)
-isr(usb_lp)
-isr(dac)
-isr(comp)
-isr(exti9_5)
-isr(lcd)
-isr(tim9)
-isr(tim10)
-isr(tim11)
-isr(tim2)
-isr(tim3)
-isr(tim4)
-isr(i2c1_ev)
-isr(i2c1_er)
-isr(i2c2_ev)
-isr(i2c2_er)
-isr(spi1)
-isr(spi2)
-isr(usart1)
-isr(usart2)
-isr(usart3)
-isr(exti15_10)
-isr(rtc_alarm)
-isr(usb_fs_wkup)
-isr(tim6)
-isr(tim7)
-
-#undef isr
+#define isr_decl(name) void stm_ ## name ## _isr(void)
+
+isr_decl(halt);
+isr_decl(ignore);
+
+isr_decl(nmi);
+isr_decl(hardfault);
+isr_decl(memmanage);
+isr_decl(busfault);
+isr_decl(usagefault);
+isr_decl(svc);
+isr_decl(debugmon);
+isr_decl(pendsv);
+isr_decl(systick);
+isr_decl(wwdg);
+isr_decl(pvd);
+isr_decl(tamper_stamp);
+isr_decl(rtc_wkup);
+isr_decl(flash);
+isr_decl(rcc);
+isr_decl(exti0);
+isr_decl(exti1);
+isr_decl(exti2);
+isr_decl(exti3);
+isr_decl(exti4);
+isr_decl(dma1_channel1);
+isr_decl(dma1_channel2);
+isr_decl(dma1_channel3);
+isr_decl(dma1_channel4);
+isr_decl(dma1_channel5);
+isr_decl(dma1_channel6);
+isr_decl(dma1_channel7);
+isr_decl(adc1);
+isr_decl(usb_hp);
+isr_decl(usb_lp);
+isr_decl(dac);
+isr_decl(comp);
+isr_decl(exti9_5);
+isr_decl(lcd);
+isr_decl(tim9);
+isr_decl(tim10);
+isr_decl(tim11);
+isr_decl(tim2);
+isr_decl(tim3);
+isr_decl(tim4);
+isr_decl(i2c1_ev);
+isr_decl(i2c1_er);
+isr_decl(i2c2_ev);
+isr_decl(i2c2_er);
+isr_decl(spi1);
+isr_decl(spi2);
+isr_decl(usart1);
+isr_decl(usart2);
+isr_decl(usart3);
+isr_decl(exti15_10);
+isr_decl(rtc_alarm);
+isr_decl(usb_fs_wkup);
+isr_decl(tim6);
+isr_decl(tim7);
+
+#undef isr_decl
 
 #define STM_ISR_WWDG_POS               0
 #define STM_ISR_PVD_POS                        1
@@ -1796,6 +1799,14 @@ extern struct stm_tim234 stm_tim2, stm_tim3, stm_tim4;
 #define  STM_TIM234_SMCR_SMS_EXTERNAL_CLOCK    7
 #define  STM_TIM234_SMCR_SMS_MASK              7
 
+#define STM_TIM234_DIER_TDE            14
+#define STM_TIM234_DIER_CC4DE          12
+#define STM_TIM234_DIER_CC3DE          11
+#define STM_TIM234_DIER_CC2DE          10
+#define STM_TIM234_DIER_CC1DE          9
+#define STM_TIM234_DIER_UDE            8
+
+#define STM_TIM234_DIER_TIE            6
 #define STM_TIM234_DIER_CC4IE          4
 #define STM_TIM234_DIER_CC3IE          3
 #define STM_TIM234_DIER_CC2IE          2
@@ -1860,6 +1871,51 @@ extern struct stm_tim234 stm_tim2, stm_tim3, stm_tim4;
 #define  STM_TIM234_CCMR1_CC1S_INPUT_TRC               3
 #define  STM_TIM234_CCMR1_CC1S_MASK                    3
 
+#define STM_TIM234_CCMR1_IC2F  12
+#define  STM_TIM234_CCMR1_IC2F_NONE                    0
+#define  STM_TIM234_CCMR1_IC2F_CK_INT_N_2              1
+#define  STM_TIM234_CCMR1_IC2F_CK_INT_N_4              2
+#define  STM_TIM234_CCMR1_IC2F_CK_INT_N_8              3
+#define  STM_TIM234_CCMR1_IC2F_DTS_2_N_6               4
+#define  STM_TIM234_CCMR1_IC2F_DTS_2_N_8               5
+#define  STM_TIM234_CCMR1_IC2F_DTS_4_N_6               6
+#define  STM_TIM234_CCMR1_IC2F_DTS_4_N_8               7
+#define  STM_TIM234_CCMR1_IC2F_DTS_8_N_6               8
+#define  STM_TIM234_CCMR1_IC2F_DTS_8_N_8               9
+#define  STM_TIM234_CCMR1_IC2F_DTS_16_N_5              10
+#define  STM_TIM234_CCMR1_IC2F_DTS_16_N_6              11
+#define  STM_TIM234_CCMR1_IC2F_DTS_16_N_8              12
+#define  STM_TIM234_CCMR1_IC2F_DTS_32_N_5              13
+#define  STM_TIM234_CCMR1_IC2F_DTS_32_N_6              14
+#define  STM_TIM234_CCMR1_IC2F_DTS_32_N_8              15
+#define STM_TIM234_CCMR1_IC2PSC        10
+#define  STM_TIM234_CCMR1_IC2PSC_NONE                  0
+#define  STM_TIM234_CCMR1_IC2PSC_2                     1
+#define  STM_TIM234_CCMR1_IC2PSC_4                     2
+#define  STM_TIM234_CCMR1_IC2PSC_8                     3
+#define STM_TIM234_CCMR1_IC1F  4
+#define  STM_TIM234_CCMR1_IC1F_NONE                    0
+#define  STM_TIM234_CCMR1_IC1F_CK_INT_N_2              1
+#define  STM_TIM234_CCMR1_IC1F_CK_INT_N_4              2
+#define  STM_TIM234_CCMR1_IC1F_CK_INT_N_8              3
+#define  STM_TIM234_CCMR1_IC1F_DTS_2_N_6               4
+#define  STM_TIM234_CCMR1_IC1F_DTS_2_N_8               5
+#define  STM_TIM234_CCMR1_IC1F_DTS_4_N_6               6
+#define  STM_TIM234_CCMR1_IC1F_DTS_4_N_8               7
+#define  STM_TIM234_CCMR1_IC1F_DTS_8_N_6               8
+#define  STM_TIM234_CCMR1_IC1F_DTS_8_N_8               9
+#define  STM_TIM234_CCMR1_IC1F_DTS_16_N_5              10
+#define  STM_TIM234_CCMR1_IC1F_DTS_16_N_6              11
+#define  STM_TIM234_CCMR1_IC1F_DTS_16_N_8              12
+#define  STM_TIM234_CCMR1_IC1F_DTS_32_N_5              13
+#define  STM_TIM234_CCMR1_IC1F_DTS_32_N_6              14
+#define  STM_TIM234_CCMR1_IC1F_DTS_32_N_8              15
+#define STM_TIM234_CCMR1_IC1PSC        2
+#define  STM_TIM234_CCMR1_IC1PSC_NONE                  0
+#define  STM_TIM234_CCMR1_IC1PSC_2                     1
+#define  STM_TIM234_CCMR1_IC1PSC_4                     2
+#define  STM_TIM234_CCMR1_IC1PSC_8                     3
+
 #define STM_TIM234_CCMR2_OC4CE 15
 #define STM_TIM234_CCMR2_OC4M  12
 #define  STM_TIM234_CCMR2_OC4M_FROZEN                  0
index de30316c7bb4d8ec6d8d5c7a9c0d3d0158620eed..ca612159a043770d06e0d08ad79966bc50ad6ac7 100644 (file)
@@ -1,9 +1,5 @@
 include ../stm32f4/Makefile-raw.defs
 
-aoschemelib=$(shell pkg-config --variable=aoschemelib ao-scheme)
-
-include $(aoschemelib)/Makefile-scheme
-
 IDVENDOR=0xfffe
 IDPRODUCT=0xfffa
 PRODUCT=stm32f4-disco
@@ -17,8 +13,6 @@ INC = \
        ao_pins.h \
        ao_task.h \
        ao_product.h \
-       $(SCHEME_HDRS) \
-       ao_scheme_const.h \
        stm32f4.h \
        Makefile
 
@@ -36,10 +30,9 @@ ALTOS_SRC = \
        ao_usb_gen.c \
        ao_usb_stm32f4.c \
        ao_led.c \
-       ao_impure.c \
-       $(SCHEME_SRCS)
+       ao_impure.c
 
-CFLAGS = $(STM32F4_CFLAGS) -I$(aoschemelib)
+CFLAGS = $(STM32F4_CFLAGS)
 
 PROG=stm32f4-disco-$(VERSION)
 ELF=$(PROG).elf
@@ -56,21 +49,6 @@ $(ELF): Makefile $(OBJ)
 
 $(OBJ): $(INC)
 
-ao_product.h: ao-make-product.5c ../Version Makefile
-       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -V $(IDVENDOR) -s $(SERIAL) -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
-
-SCHEME_SCHEME=\
-       ao_scheme_basic_syntax.scheme \
-       ao_scheme_list.scheme \
-       ao_scheme_advanced_syntax.scheme \
-       ao_scheme_vector.scheme \
-       ao_scheme_string.scheme \
-       ao_scheme_char.scheme \
-       ao_scheme_number.scheme
-
-ao_scheme_const.h: ao-scheme-make-const-big $(SCHEME_SCHEME)
-       $^ -o $@ -d POSIX,PORT,SAVE
-
 distclean:     clean
 
 clean:
index ab3c03404d413678629f109db08b811a2c0ed75b..47948a6525e7f4ee9998301adcd4b0fd413a87ce 100644 (file)
  */
 
 #include <ao.h>
-#include <ao_scheme.h>
 #include <ao_usb.h>
 
-static void scheme_cmd() {
-       ao_scheme_read_eval_print(stdin, stdout, false);
-}
-
-static const struct ao_cmds scheme_cmds[] = {
-       { scheme_cmd,   "l\0Run scheme interpreter" },
-       { 0, 0 }
-};
-
-int
-_ao_scheme_getc(void)
-{
-       static uint8_t  at_eol;
-       int c;
-
-       if (at_eol) {
-               ao_cmd_readline(ao_scheme_read_list ? "- " : "> ");
-               at_eol = 0;
-       }
-       c = (unsigned char) ao_cmd_lex();
-       if (c == '\n')
-               at_eol = 1;
-       return c;
-}
-
 void main(void)
 {
        ao_clock_init();
@@ -51,6 +25,5 @@ void main(void)
        ao_usart_init();
        ao_usb_init();
        ao_cmd_init();
-       ao_cmd_register(scheme_cmds);
        ao_start_scheduler();
 }
index 1a2aa75c153cd12e419bdafe3392dbb6c9d6f034..bc5aa1acb3c4eb24dc40ba236bc7da584c2cec84 100644 (file)
@@ -33,7 +33,7 @@ PRODUCT=AltosFlash
 PRODUCT_DEF=-DALTOS_FLASH
 IDPRODUCT=0x000a
 
-CFLAGS = $(PRODUCT_DEF) $(STM32F4_CFLAGS) -g -Os
+CFLAGS = $(PRODUCT_DEF) $(STM32F4_CFLAGS)
 
 LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stm32f4 -Wl,-Taltos-loader.ld
 
@@ -52,9 +52,6 @@ $(PROG): Makefile $(OBJ) altos-loader.ld
 $(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)
 
 distclean:     clean
index c39633c794dbeb42878561889c3ee571ac44bd89..9c2e870e94bb902e62bc71a0cdaf844a01908e73 100644 (file)
@@ -2,51 +2,12 @@ ifndef TOPDIR
 TOPDIR=..
 endif
 
-include $(TOPDIR)/Makedefs
+include $(TOPDIR)/Makefile.defs
 
-vpath % $(TOPDIR)/stm32f4:$(TOPDIR)/product:$(TOPDIR)/drivers:$(TOPDIR)/kernel:$(TOPDIR)/util:$(TOPDIR)/kalman:$(TOPDIR)/aes:$(TOPDIR):$(TOPDIR)/math
-vpath make-altitude $(TOPDIR)/util
-vpath make-kalman $(TOPDIR)/util
-vpath kalman.5c $(TOPDIR)/kalman
-vpath kalman_filter.5c $(TOPDIR)/kalman
-vpath load_csv.5c $(TOPDIR)/kalman
-vpath matrix.5c $(TOPDIR)/kalman
-vpath ao-make-product.5c $(TOPDIR)/util
+vpath % $(TOPDIR)/stm32f4:$(AO_VPATH)
 
-.SUFFIXES: .elf .ihx
-
-.elf.ihx:
-       $(ELFTOHEX) --output=$@ $*.elf
-
-ifndef VERSION
-include $(TOPDIR)/Version
-endif
-
-ELFTOHEX=$(TOPDIR)/../ao-tools/ao-elftohex/ao-elftohex
 CC=$(ARM_CC)
-
-WARN_FLAGS=-Wall -Wextra -Werror -Wcast-align
-
-AO_CFLAGS=-I. -I$(TOPDIR)/stm32f4 -I$(TOPDIR)/kernel -I$(TOPDIR)/drivers \
-       -Os -g \
-       -I$(TOPDIR)/product -I$(TOPDIR) -I$(TOPDIR)/math \
-       -isystem $(NEWLIB_NANO)/arm-none-eabi/include
-
-STM32F4_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m4 -mthumb \
-       -mfloat-abi=hard -mfpu=fpv4-sp-d16 \
-       -ffreestanding -nostdlib $(AO_CFLAGS) $(WARN_FLAGS)
-
-NICKLE=nickle
-
 LIBS=-L$(NEWLIB_NANO)/arm-none-eabi/lib/thumb/v7e-m/fpv4-sp/hard -lc -lm -lgcc
 
-V=0
-# The user has explicitly enabled quiet compilation.
-ifeq ($(V),0)
-quiet = @printf "  $1 $2 $@\n"; $($1)
-endif
-# Otherwise, print the full command line.
-quiet ?= $($1)
-
-.c.o:
-       $(call quiet,CC) -c $(CFLAGS) -o $@ $<
+STM32F4_CFLAGS=-mlittle-endian -mcpu=cortex-m4 -mthumb -mfloat-abi=hard \
+       -I$(TOPDIR)/stm32f4 $(AO_CFLAGS) $(NEWLIB_CFLAGS)
index be185a5955b6e5d78a02671cd4ed0ac0516f414b..8c0e88429988e595972dd76ec4d63f14f3467371 100644 (file)
@@ -4,10 +4,4 @@ endif
 
 include $(TOPDIR)/stm32f4/Makefile-stm32f4.defs
 
-LOADER=flash-loader/$(PROGNAME)-altos-flash-$(VERSION).elf
-MAKEBIN=$(TOPDIR)/../ao-tools/ao-makebin/ao-makebin
-FLASH_ADDR=0x08000000
-
 LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stm32f4 -Wl,-Taltos.ld -n
-
-.DEFAULT_GOAL=all
index 73dc3e9359e57f107c63c281028784c3496e6fdb..7dd4c80d79266b00856f43677a5fe1cfc04f476f 100644 (file)
@@ -38,9 +38,6 @@
 
 #define AO_ROMCONFIG_SYMBOL __attribute__((section(".romconfig"))) const
 
-#define ao_arch_task_members\
-       uint32_t *sp;                   /* saved stack pointer */
-
 #define ao_arch_naked_declare  __attribute__((naked))
 #define ao_arch_naked_define
 
index b1ffb5b6bc2378a6e00475a6d94fd9aa142b235b..6fa654973842877a59325e94cd3a991e6d1750d0 100644 (file)
@@ -61,7 +61,7 @@ ao_arch_irqrestore(uint32_t basepri) {
 }
 
 static inline void
-ao_arch_memory_barrier() {
+ao_arch_memory_barrier(void) {
        asm volatile("" ::: "memory");
 }
 
@@ -84,7 +84,7 @@ ao_arch_irq_check(void) {
 static inline void
 ao_arch_init_stack(struct ao_task *task, void *start)
 {
-       uint32_t        *sp = (uint32_t *) ((void*) task->stack + AO_STACK_SIZE);
+       uint32_t        *sp = &task->stack32[AO_STACK_SIZE>>2];
        uint32_t        a = (uint32_t) start;
        int             i;
 
@@ -110,7 +110,7 @@ ao_arch_init_stack(struct ao_task *task, void *start)
        /* BASEPRI with interrupts enabled */
        ARM_PUSH32(sp, 0);
 
-       task->sp = sp;
+       task->sp32 = sp;
 }
 
 static inline void ao_arch_save_regs(void) {
@@ -142,12 +142,12 @@ static inline void ao_arch_save_regs(void) {
 static inline void ao_arch_save_stack(void) {
        uint32_t        *sp;
        asm("mov %0,sp" : "=&r" (sp) );
-       ao_cur_task->sp = (sp);
+       ao_cur_task->sp32 = (sp);
 }
 
 static inline void ao_arch_restore_stack(void) {
        /* Switch stacks */
-       asm("mov sp, %0" : : "r" (ao_cur_task->sp) );
+       asm("mov sp, %0" : : "r" (ao_cur_task->sp32) );
 
 #ifdef AO_NONMASK_INTERRUPTS
        /* Restore BASEPRI */
@@ -251,28 +251,28 @@ ao_arch_wait_interrupt(void) {
 static inline void ao_enable_port(struct stm_gpio *port)
 {
        if ((port) == &stm_gpioa) {
-               stm_rcc.ahb1enr |= (1 << STM_RCC_AHB1ENR_IOPAEN);
+               stm_rcc_ahb1_clk_enable(1 << STM_RCC_AHB1ENR_IOPAEN);
                ao_power_register(&ao_power_gpioa);
        } else if ((port) == &stm_gpiob) {
-               stm_rcc.ahb1enr |= (1 << STM_RCC_AHB1ENR_IOPBEN);
+               stm_rcc_ahb1_clk_enable(1 << STM_RCC_AHB1ENR_IOPBEN);
                ao_power_register(&ao_power_gpiob);
        } else if ((port) == &stm_gpioc) {
-               stm_rcc.ahb1enr |= (1 << STM_RCC_AHB1ENR_IOPCEN);
+               stm_rcc_ahb1_clk_enable(1 << STM_RCC_AHB1ENR_IOPCEN);
                ao_power_register(&ao_power_gpioc);
        } else if ((port) == &stm_gpiod) {
-               stm_rcc.ahb1enr |= (1 << STM_RCC_AHB1ENR_IOPDEN);
+               stm_rcc_ahb1_clk_enable(1 << STM_RCC_AHB1ENR_IOPDEN);
                ao_power_register(&ao_power_gpiod);
        } else if ((port) == &stm_gpioe) {
-               stm_rcc.ahb1enr |= (1 << STM_RCC_AHB1ENR_IOPEEN);
+               stm_rcc_ahb1_clk_enable(1 << STM_RCC_AHB1ENR_IOPEEN);
                ao_power_register(&ao_power_gpioe);
        } else if ((port) == &stm_gpiof) {
-               stm_rcc.ahb1enr |= (1 << STM_RCC_AHB1ENR_IOPFEN);
+               stm_rcc_ahb1_clk_enable(1 << STM_RCC_AHB1ENR_IOPFEN);
                ao_power_register(&ao_power_gpiof);
        } else if ((port) == &stm_gpiog) {
-               stm_rcc.ahb1enr |= (1 << STM_RCC_AHB1ENR_IOPGEN);
+               stm_rcc_ahb1_clk_enable(1 << STM_RCC_AHB1ENR_IOPGEN);
                ao_power_register(&ao_power_gpiog);
        } else if ((port) == &stm_gpioh) {
-               stm_rcc.ahb1enr |= (1 << STM_RCC_AHB1ENR_IOPHEN);
+               stm_rcc_ahb1_clk_enable(1 << STM_RCC_AHB1ENR_IOPHEN);
                ao_power_register(&ao_power_gpioh);
        }
 }
@@ -280,28 +280,28 @@ static inline void ao_enable_port(struct stm_gpio *port)
 static inline void ao_disable_port(struct stm_gpio *port)
 {
        if ((port) == &stm_gpioa) {
-               stm_rcc.ahb1enr &= ~(1 << STM_RCC_AHB1ENR_IOPAEN);
+               stm_rcc_ahb1_clk_disable(1 << STM_RCC_AHB1ENR_IOPAEN);
                ao_power_unregister(&ao_power_gpioa);
        } else if ((port) == &stm_gpiob) {
-               stm_rcc.ahb1enr &= ~(1 << STM_RCC_AHB1ENR_IOPBEN);
+               stm_rcc_ahb1_clk_disable(1 << STM_RCC_AHB1ENR_IOPBEN);
                ao_power_unregister(&ao_power_gpiob);
        } else if ((port) == &stm_gpioc) {
-               stm_rcc.ahb1enr &= ~(1 << STM_RCC_AHB1ENR_IOPCEN);
+               stm_rcc_ahb1_clk_disable(1 << STM_RCC_AHB1ENR_IOPCEN);
                ao_power_unregister(&ao_power_gpioc);
        } else if ((port) == &stm_gpiod) {
-               stm_rcc.ahb1enr &= ~(1 << STM_RCC_AHB1ENR_IOPDEN);
+               stm_rcc_ahb1_clk_disable(1 << STM_RCC_AHB1ENR_IOPDEN);
                ao_power_unregister(&ao_power_gpiod);
        } else if ((port) == &stm_gpioe) {
-               stm_rcc.ahb1enr &= ~(1 << STM_RCC_AHB1ENR_IOPEEN);
+               stm_rcc_ahb1_clk_disable(1 << STM_RCC_AHB1ENR_IOPEEN);
                ao_power_unregister(&ao_power_gpioe);
        } else if ((port) == &stm_gpiof) {
-               stm_rcc.ahb1enr &= ~(1 << STM_RCC_AHB1ENR_IOPFEN);
+               stm_rcc_ahb1_clk_disable(1 << STM_RCC_AHB1ENR_IOPFEN);
                ao_power_unregister(&ao_power_gpiof);
        } else if ((port) == &stm_gpiog) {
-               stm_rcc.ahb1enr &= ~(1 << STM_RCC_AHB1ENR_IOPGEN);
+               stm_rcc_ahb1_clk_disable(1 << STM_RCC_AHB1ENR_IOPGEN);
                ao_power_unregister(&ao_power_gpiog);
        } else if ((port) == &stm_gpioh) {
-               stm_rcc.ahb1enr &= ~(1 << STM_RCC_AHB1ENR_IOPHEN);
+               stm_rcc_ahb1_clk_disable(1 << STM_RCC_AHB1ENR_IOPHEN);
                ao_power_unregister(&ao_power_gpioh);
        }
 }
@@ -336,5 +336,25 @@ static inline void ao_disable_port(struct stm_gpio *port)
 void
 ao_usart_init(void);
 
+void
+start(void);
+
+char
+ao_serial6_getchar(void);
+
+void
+ao_serial6_putchar(char c);
+
+int
+_ao_serial6_pollchar(void);
+
+uint8_t
+_ao_serial6_sleep_for(uint16_t timeout);
+
+void
+ao_serial6_set_speed(uint32_t speed);
+
+void
+ao_serial6_drain(void);
 
 #endif /* _AO_ARCH_FUNCS_H_ */
index 0216f3528822d0271d42dff1716ae72577983637..032466058ed2cb7a4afb55db3e77669142c4ba56 100644 (file)
 #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);
 
 void
-ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)());
+ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)(void));
 
 void
 ao_exti_enable(struct stm_gpio *gpio, uint8_t pin);
index 1e288f9c6ef5b4b1308782a6498105c0f3b5d81b..900fe90318623635436dd18229567c839d4ad1f8 100644 (file)
@@ -135,7 +135,7 @@ ao_exti_set_mode(struct stm_gpio *gpio, uint8_t pin, uint8_t mode) {
 }
 
 void
-ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)()) {
+ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)(void)) {
        (void) gpio;
        ao_exti_callback[pin] = callback;
 }
index d6ef9bc379e5d074b68bb98506957f46ce94e599..fb83db003aa46085f37a3b294e2da02402dc49b3 100644 (file)
@@ -262,13 +262,12 @@ ao_clock_init(void)
 #if DEBUG_THE_CLOCK
        /* Output PLL clock on PA8 and SYCLK on PC9 for measurments */
 
-       stm_rcc.ahb1enr |= ((1 << STM_RCC_AHB1ENR_IOPAEN) |
-                           (1 << STM_RCC_AHB1ENR_IOPCEN));
-
+       ao_enable_port(&stm_gpioa);
        stm_afr_set(&stm_gpioa, 8, STM_AFR_AF0);
        stm_moder_set(&stm_gpioa, 8, STM_MODER_ALTERNATE);
        stm_ospeedr_set(&stm_gpioa, 8, STM_OSPEEDR_HIGH);
 
+       ao_enable_port(&stm_gpioc);
        stm_afr_set(&stm_gpioc, 9, STM_AFR_AF0);
        stm_moder_set(&stm_gpioc, 9, STM_MODER_ALTERNATE);
        stm_ospeedr_set(&stm_gpioc, 9, STM_OSPEEDR_HIGH);
index 760afad9b90fb759b26d4cbf1dab036fb5708fd2..7659dabea9b680320619334bdee1427a43cc4163 100644 (file)
@@ -449,7 +449,7 @@ ao_usb_int_interrupt(uint32_t mask)
 }
 
 void
-stm_usb_fs_wkup(void)
+stm_otg_fs_wkup_isr(void)
 {
        /* USB wakeup, just clear the bit for now */
 //     stm_usb.istr &= ~(1 << STM_USB_ISTR_WKUP);
@@ -547,7 +547,7 @@ _ao_usb_out_recv(void)
        ao_usb_rx_pos = 0;
 }
 
-int
+static int
 _ao_usb_pollchar(void)
 {
        uint8_t c;
@@ -601,7 +601,6 @@ void
 ao_usb_enable(void)
 {
        ao_usb_dev_enable();
-
        ao_usb_configuration = 0;
 }
 
index b059ddb7c473136cd2947ce886f522a48741ec21..d9a9cf92466192ce6e7948cda7797b174fbb3da3 100644 (file)
@@ -106,5 +106,8 @@ ao_usb_in_interrupt(uint32_t mask);
 void
 ao_usb_out_interrupt(uint32_t mask);
 
+void
+ao_usb_int_interrupt(uint32_t mask);
+
 #endif /* _AO_USB_GEN_H_ */
 
index e65c3656fa0de3863690dad1981f3c5c75ed75f8..7ad83e13f967e3951a5b8d259b36914bb4e43553 100644 (file)
@@ -231,12 +231,15 @@ ao_usb_dev_ep0_out(void *data, uint16_t len)
 
 /* Queue IN bytes to EPn */
 void
-ao_usb_dev_ep_in(uint8_t ep, const void *data, uint16_t len)
+ao_usb_dev_ep_in(uint8_t ep, const void *_data, uint16_t len)
 {
+       const uint8_t *data = _data;
        int     l = len;
 
        while (l > 0) {
-               stm_usb.dfifo[ep].fifo = *((__packed uint32_t *) data);
+               uint32_t d;
+               memcpy(&d, data, 4);
+               stm_usb.dfifo[ep].fifo = d;
                l -= 4;
                data += 4;
        }
@@ -261,8 +264,9 @@ ao_usb_dev_ep_in_busy(uint8_t ep)
 
 /* Receive OUT bytes from EPn */
 uint16_t
-ao_usb_dev_ep_out(uint8_t ep, void *data, uint16_t len)
+ao_usb_dev_ep_out(uint8_t ep, void *_data, uint16_t len)
 {
+       uint8_t         *data = _data;
        uint16_t        received;
        int             l = len;
        uint32_t        t;
@@ -275,7 +279,9 @@ ao_usb_dev_ep_out(uint8_t ep, void *data, uint16_t len)
                received = len;
 
        while (l >= 4) {
-               *((__packed uint32_t *) data) = stm_usb.dfifo[0].fifo;
+               uint32_t d;
+               d = stm_usb.dfifo[0].fifo;
+               memcpy(data, &d, 4);
                l -= 4;
                data += 4;
        }
@@ -358,6 +364,8 @@ static void
 ao_usb_device_init(void)
 {
        /* deactivate vbus sensing */
+       stm_usb.gccfg |= (1 << STM_USB_GCCFG_VBDEN);
+
        stm_usb.gccfg &= ~(1 << STM_USB_GCCFG_VBDEN);
 
        /* Force device mode */
@@ -393,8 +401,10 @@ ao_usb_device_init(void)
                else
                        stm_usb.diep[i].diepctl = 0;
                stm_usb.diep[i].dieptsiz = 0;
-               stm_usb.diep[i].diepint = 0xfffffffful;
+               stm_usb.diep[i].diepint = 0xffu;
+       }
 
+       for (int i = 0; i < 6; i++) {
                /* Reset OUT endpoint */
                if (stm_usb.doep[i].doepctl & (1 << STM_USB_DOEPCTL_EPENA))
                        stm_usb.doep[i].doepctl = ((1 << STM_USB_DOEPCTL_EPDIS) |
@@ -403,9 +413,11 @@ ao_usb_device_init(void)
                        stm_usb.doep[i].doepctl = 0;
 
                stm_usb.doep[i].doeptsiz = 0;
-               stm_usb.doep[i].doepint = 0xfffffffful;
+               stm_usb.doep[i].doepint = 0xffu;
        }
 
+       stm_usb.diepmsk &= ~(1 << STM_USB_DIEPMSK_TXFURM);
+
        /* Disable all interrupts */
        stm_usb.gintmsk = 0;
 
@@ -449,7 +461,6 @@ ao_usb_device_connect(void)
        ao_usb_delay(20);
 }
 
-#if 0
 static void
 ao_usb_device_disconnect(void)
 {
@@ -457,7 +468,13 @@ ao_usb_device_disconnect(void)
        stm_usb.dctl |= (1 << STM_USB_DCTL_SDIS);
        ao_usb_delay(20);
 }
-#endif
+
+static void
+ao_usb_dev_start(void)
+{
+       ao_usb_device_connect();
+       stm_usb.gahbcfg |= (1 << STM_USB_GAHBCFG_GINTMSK);
+}
 
 void
 ao_usb_dev_enable(void)
@@ -474,17 +491,20 @@ ao_usb_dev_enable(void)
        stm_afr_set(&stm_gpioa, 11, STM_AFR_AF10);
        stm_ospeedr_set(&stm_gpioa, 11, STM_OSPEEDR_HIGH);
        stm_pupdr_set(&stm_gpioa, 11, STM_PUPDR_NONE);
+
        stm_afr_set(&stm_gpioa, 12, STM_AFR_AF10);
        stm_ospeedr_set(&stm_gpioa, 12, STM_OSPEEDR_HIGH);
        stm_pupdr_set(&stm_gpioa, 12, STM_PUPDR_NONE);
 
        /* Power on USB */
-       stm_rcc.ahb2enr |= (1 << STM_RCC_AHB2ENR_OTGFSEN);
+       stm_rcc_ahb2_clk_enable(1 << STM_RCC_AHB2ENR_OTGFSEN);
 
        /* Route interrupts */
        stm_nvic_set_priority(STM_ISR_OTG_FS_POS, AO_STM_NVIC_LOW_PRIORITY);
        stm_nvic_set_enable(STM_ISR_OTG_FS_POS);
 
+       ao_arch_release_interrupts();
+
        /* Core init */
        ao_usb_core_init();
 
@@ -497,13 +517,18 @@ ao_usb_dev_enable(void)
 
        ao_usb_device_init();
 
-       /* Connect */
-       ao_usb_device_connect();
+       /* Disconnect */
+       ao_usb_device_disconnect();
+
+       /* Start */
+       ao_usb_dev_start();
 }
 
 void
 ao_usb_dev_disable(void)
 {
+       ao_usb_device_disconnect();
+
        stm_usb.gusbcfg = ((1 << STM_USB_GUSBCFG_FDMOD) |
                           (0 << STM_USB_GUSBCFG_FHMOD) |
                           (6 << STM_USB_GUSBCFG_TRDT) |
@@ -519,7 +544,7 @@ ao_usb_dev_disable(void)
        stm_usb.dctl = ((0 << STM_USB_DCTL_POPRGDNE) |
                        (1 << STM_USB_DCTL_SDIS));
 
-       stm_rcc.ahb2enr &= ~(1 << STM_RCC_AHB2ENR_OTGFSEN);
+       stm_rcc_ahb2_clk_disable(1 << STM_RCC_AHB2ENR_OTGFSEN);
 }
 
 void
@@ -1138,7 +1163,129 @@ $5 = {
        CK48MSEL = 1            PLLI2S_Q
        I2CFMP1SEL = 0          APB
 }
-      
-
 
 */
+
+/*
+ *
+ * altos clock configuration
+ * (gdb) print/x stm_rcc
+ * $8 = {
+ *       altos                 demo firmware
+ * cr = 0x0307 7d80,           0x0f077d83, 
+ *
+ *   PLLI2SRDY 0               1
+ *   PLLI2SON  0               1
+ *   PLLRDY    1               1
+ *   PLLON     1               1
+ *   CSSON     0               0
+ *   HSEBYP    1               1
+ *   HSERDY    1               1
+ *   HSEON     1               1
+ *   HSICAL    0x7d            0x7d
+ *   HSITRIM   0x10            0x10
+ *   HSIRDY    0               1
+ *   HSION     0               1
+ *
+ * pllcfgr = 0x24403008,       0x27403208,
+ *   PLLR      2               2
+ *   PLLQ      4               7
+ *   PLLSRC    1               1
+ *   PLLP      0 (/2)          0 (/2)
+ *   PLLN      192             200
+ *   PLLM      8               8
+ *
+ * cfgr = 0x3640100a,          0x0000100a,
+ *   upper bits are just MCO
+ *
+ *   cir = 0x0,                        0x0
+ *   ahb1rstr = 0x0,           0x0
+ *   ahb2rstr = 0x0,           0x0
+ *   ahb3rstr = 0x0,
+ *   pad_1c = 0x0,
+ *   apb1rstr = 0x0,
+ *   apb2rstr = 0x0,
+ *   pad_28 = 0x0,
+ *   pad_2c = 0x0,
+ *   _ahb1enr = 0x55,          0x80
+ *   _ahb2enr = 0x80,          0xc800
+ *   ahbdnr = 0x0,
+ *   pad_3c = 0x0,
+ *   apb1enr = 0x10000400,
+ *   apb2enr = 0x8020,
+ *   pad_48 = 0x0,
+ *   pad_4c = 0x0,
+ *   ahb1lpenr = 0x6390ff,     0x6390ff
+ *   ahb2lpenr = 0xd0,         0xd0
+ *   ahb3lpenr = 0x3,          0x3
+ *   pad_5c = 0x0,
+ *   apb1lpenr = 0xfffecfff,   0xfffecfff,
+ *   apb2lpenr = 0x357f9f3,    0x357f9f3,
+ *   pad_68 = 0x0,
+ *   pad_6c = 0x0,
+ *   bdcr = 0x0,               0x8200,
+ *   csr = 0x0,                        0x1e000003,
+ *   pad_78 = 0x0,
+ *   pad_7c = 0x0,
+ *   sscgr = 0x0,
+ *   plli2scfgr = 0x24003010,  0x44003008,
+ *   pad_88 = 0x0,
+ *   dckcfgr = 0x0,
+ *   ckgatenr = 0x0,
+ *   dckcfgr2 = 0x8000000      0x08000000
+ * }
+ *
+ *
+ */
+
+/*
+ *
+ * main
+ *     HAL_Init
+ *     SystemClock_Config
+ *   
+ *     USBD_Init
+ *             USBD_LL_Init
+ *                     HAL_PCD_Init
+ *                                     HAL_PCD_MspInit
+ *                                     __HAL_RCC_GPIOA_CLK_ENABLE
+ *                                     HAL_GPIO_Init
+ *                                     __HAL_RCC_USB_OTG_FS_CLK_ENABLE
+ *                                     HAL_NVIC_SetPriority
+ *                                     HAL_NVIC_EnableIRQ
+ *                                     USB_CoreInit
+ *                                     Select FS Embedded PHY
+ *                                     USB_CoreReset
+ *                                     Deactivate the power down
+ *                                     USB_SetCurrentMode
+ *                                     USB_DevInit
+ *                                     VBUS sensing stuff
+ *                                     Restart PHY clock
+ *                                     USB_SetDevSpeed
+ *                                     USB_FlushTxFifo
+ *                                     USB_FlushRxFifo
+ *                                     Clear pending interrupts
+ *                                     Disable all endpoints
+ *                                     Disable all interrupts
+ *                                     Clear pending interrupts
+ *                                     enable interrupts
+ *                                     USB_DevDisconnect
+ *                                     Turn on SDIS bit
+ *                                     delay 3ms
+ *                     HAL_PCDEx_SeRxFifo
+ *                     HAL_PCDEx_SetTxFifo
+ *     USBD_RegisterClass
+ *     USBD_MSC_RegisterStorage
+ *     USBD_Start
+ *             USBD_LL_Start
+ *                     HAL_PCD_Start
+ *                             __HAL_LOCK
+ *                             USB_DevConnect
+ *                                     Turn off SDIS bit
+ *                                     delay 3ms
+ *                             __HAL_PCD_ENABLE
+ *                                     USB_EnableGlobalInt
+ *                                             USBx->GAHBCFG |= USB_OTG_GAHBCFG_GINT;
+ *                             __HAL_UNLOCK
+ *
+ */
index dcdce66790237e2ad5cff0f7ba50c850ef2010e9..94ee23bf9e83e25b55154fdb7014cfabdd696e25 100644 (file)
@@ -66,8 +66,8 @@ struct stm_rcc {
        vuint32_t       pad_28;
        vuint32_t       pad_2c;
 
-       vuint32_t       ahb1enr;
-       vuint32_t       ahb2enr;
+       vuint32_t       _ahb1enr;
+       vuint32_t       _ahb2enr;
        vuint32_t       ahbdnr;
        vuint32_t       pad_3c;
 
@@ -269,7 +269,7 @@ extern struct stm_rcc stm_rcc;
 #define  STM_RCC_DCKCFGR2_SDIOSEL_CK_48MHZ     0
 #define  STM_RCC_DCKCFGR2_SDIOSEL_SYSTEM_CLOCK 1
 #define STM_RCC_DCKCFGR2_CK48MSEL      27
-#define  STM_RCC_DCKCFGR2_CK48MSEL_PLL_Q       1
+#define  STM_RCC_DCKCFGR2_CK48MSEL_PLL_Q       0
 #define  STM_RCC_DCKCFGR2_CK48MSEL_PLLI2S_Q    1
 #define STM_RCC_DCKCFGR2_I2CFMP1SEL    22
 #define  STM_RCC_DCKCFGR2_I2CFMP1SEL_APB               0
@@ -277,6 +277,38 @@ extern struct stm_rcc stm_rcc;
 #define  STM_RCC_DCKCFGR2_I2CFMP1SEL_HSI               2
 #define  STM_RCC_DCKCFGR2_I2CFMP1SEL_APB_ALSO          3
 
+static inline void
+stm_rcc_ahb1_clk_enable(uint32_t bit)
+{
+       stm_rcc._ahb1enr |= bit;
+       uint32_t value = stm_rcc._ahb1enr;
+       (void) value;
+}
+
+static inline void
+stm_rcc_ahb1_clk_disable(uint32_t bit)
+{
+       stm_rcc._ahb1enr &= ~bit;
+       uint32_t value = stm_rcc._ahb1enr;
+       (void) value;
+}
+
+static inline void
+stm_rcc_ahb2_clk_enable(uint32_t bit)
+{
+       stm_rcc._ahb2enr |= bit;
+       uint32_t value = stm_rcc._ahb2enr;
+       (void) value;
+}
+
+static inline void
+stm_rcc_ahb2_clk_disable(uint32_t bit)
+{
+       stm_rcc._ahb2enr &= ~bit;
+       uint32_t value = stm_rcc._ahb2enr;
+       (void) value;
+}
+
 struct stm_ictr {
        vuint32_t       ictr;
 };
@@ -378,6 +410,8 @@ stm_nvic_get_priority(int irq) {
 
 #define isr(name) void stm_ ## name ## _isr(void)
 
+isr(halt);
+isr(ignore);
 isr(nmi);
 isr(hardfault);
 isr(memmanage);
index 804595bda3f7789e96b35f8ddc27a64f919d0bab..b6e44990b5a0f1fbd88ff98934d10855a48cb39b 100644 (file)
@@ -33,7 +33,7 @@ PRODUCT=AltosFlash
 PRODUCT_DEF=-DALTOS_FLASH
 IDPRODUCT=0x000a
 
-CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -g -Os
+CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS)
 
 LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stmf0 -Wl,-Taltos-loader.ld
 
@@ -51,9 +51,6 @@ $(PROG): Makefile $(OBJ) altos-loader.ld
 
 $(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)
 
index 447ddf131b4a3b223413328252a175db2728a0c0..5a883adf1345bdd72593ca23f50321ba5068f4b8 100644 (file)
@@ -2,50 +2,13 @@ ifndef TOPDIR
 TOPDIR=..
 endif
 
-include $(TOPDIR)/Makedefs
+include $(TOPDIR)/Makefile.defs
 
-vpath % $(TOPDIR)/stmf0:$(TOPDIR)/product:$(TOPDIR)/drivers:$(TOPDIR)/kernel:$(TOPDIR)/util:$(TOPDIR)/kalman:$(TOPDIR)/aes:$(TOPDIR):$(TOPDIR)/math
-vpath make-altitude $(TOPDIR)/util
-vpath make-kalman $(TOPDIR)/util
-vpath kalman.5c $(TOPDIR)/kalman
-vpath kalman_filter.5c $(TOPDIR)/kalman
-vpath load_csv.5c $(TOPDIR)/kalman
-vpath matrix.5c $(TOPDIR)/kalman
-vpath ao-make-product.5c $(TOPDIR)/util
+vpath % $(TOPDIR)/stmf0:$(AO_VPATH)
 
-.SUFFIXES: .elf .ihx
-
-.elf.ihx:
-       $(ELFTOHEX) --output=$@ $*.elf
-
-ifndef VERSION
-include $(TOPDIR)/Version
-endif
-
-ELFTOHEX=$(TOPDIR)/../ao-tools/ao-elftohex/ao-elftohex
 CC=$(ARM_CC)
 
-WARN_FLAGS=-Wall -Wextra -Werror -Wcast-align
-
-AO_CFLAGS=-I. -I$(TOPDIR)/stmf0 -I$(TOPDIR)/kernel -I$(TOPDIR)/drivers \
-       -DNEWLIB_INTEGER_PRINTF_SCANF \
-       -I$(TOPDIR)/product -I$(TOPDIR) -I$(TOPDIR)/math \
-       -isystem $(NEWLIB_NANO)/arm-none-eabi/include
-
-STMF0_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m0 -mthumb\
-       -ffreestanding -nostdlib $(AO_CFLAGS) $(WARN_FLAGS)
-
-NICKLE=nickle
+STMF0_CFLAGS=-mlittle-endian -mcpu=cortex-m0 -mthumb\
+       -I$(TOPDIR)/stmf0 $(AO_CFLAGS) $(NEWLIB_CFLAGS)
 
 LIBS=-L$(NEWLIB_NANO)/arm-none-eabi/lib/thumb/v6-m -lc -lm -lgcc
-
-V=0
-# The user has explicitly enabled quiet compilation.
-ifeq ($(V),0)
-quiet = @printf "  $1 $2 $@\n"; $($1)
-endif
-# Otherwise, print the full command line.
-quiet ?= $($1)
-
-.c.o:
-       $(call quiet,CC) -c $(CFLAGS) -o $@ $<
index a0aa558bef5caff38e570c9bf856c0ed50fa53ac..2baba4f2b3536360cb03933929fd825c62c9d425 100644 (file)
@@ -4,10 +4,10 @@ endif
 
 include $(TOPDIR)/stmf0/Makefile-stmf0.defs
 
+LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stmf0 -Wl,-Taltos.ld -n
+
 LOADER=flash-loader/$(PROGNAME)-altos-flash-$(VERSION).elf
 MAKEBIN=$(TOPDIR)/../ao-tools/ao-makebin/ao-makebin
 FLASH_ADDR=0x08000000
 
-LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stmf0 -Wl,-Taltos.ld -n
-
 .DEFAULT_GOAL=all
index 22e706b2a975bca6cdb24b210dfbfc56ac52bf32..d70a9110e91fa02ac481ced1e928fa1868b0ca6d 100644 (file)
 
 #define AO_LED_TYPE    uint16_t
 
-#ifndef AO_TICK_TYPE
-#define AO_TICK_TYPE   uint16_t
-#define AO_TICK_SIGNED int16_t
-#endif
-
 #define AO_PORT_TYPE   uint16_t
 
 /* Various definitions to make GCC look more like SDCC */
@@ -65,9 +60,6 @@ extern const uint16_t ao_romconfig_check;
 extern const uint16_t ao_serial_number;
 extern const uint32_t ao_radio_cal;
 
-#define ao_arch_task_members\
-       uint32_t *sp;                   /* saved stack pointer */
-
 #define ao_arch_block_interrupts()     asm("cpsid i")
 #define ao_arch_release_interrupts()   asm("cpsie i")
 
@@ -127,7 +119,7 @@ void ao_lcd_font_string(char *s);
 extern const uint32_t  ao_radio_cal;
 
 void
-ao_adc_init();
+ao_adc_init(void);
 
 /* ADC maximum reported value */
 #define AO_ADC_MAX                     4095
index 70f273d3ba46ce081ca8326113c16582668ca627..591ca8a07576fb01a2888754d5f372fc9ab0ac47 100644 (file)
@@ -381,7 +381,7 @@ ao_arch_irqrestore(uint32_t primask) {
 }
 
 static inline void
-ao_arch_memory_barrier() {
+ao_arch_memory_barrier(void) {
        asm volatile("" ::: "memory");
 }
 
@@ -389,7 +389,7 @@ ao_arch_memory_barrier() {
 static inline void
 ao_arch_init_stack(struct ao_task *task, void *start)
 {
-       uint32_t        *sp = (uint32_t *) ((void *) task->stack + AO_STACK_SIZE);
+       uint32_t        *sp = &task->stack32[AO_STACK_SIZE >> 2];
        uint32_t        a = (uint32_t) start;
        int             i;
 
@@ -407,7 +407,7 @@ ao_arch_init_stack(struct ao_task *task, void *start)
        /* PRIMASK with interrupts enabled */
        ARM_PUSH32(sp, 0);
 
-       task->sp = sp;
+       task->sp32 = sp;
 }
 
 static inline void ao_arch_save_regs(void) {
@@ -426,17 +426,14 @@ static inline void ao_arch_save_regs(void) {
 static inline void ao_arch_save_stack(void) {
        uint32_t        *sp;
        asm("mov %0,sp" : "=&r" (sp) );
-       ao_cur_task->sp = (sp);
-       if ((uint8_t *) sp < &ao_cur_task->stack[0])
+       ao_cur_task->sp32 = (sp);
+       if (sp < &ao_cur_task->stack32[0])
                ao_panic (AO_PANIC_STACK);
 }
 
 static inline void ao_arch_restore_stack(void) {
-       uint32_t        sp;
-       sp = (uint32_t) ao_cur_task->sp;
-
        /* Switch stacks */
-       asm("mov sp, %0" : : "r" (sp) );
+       asm("mov sp, %0" : : "r" (ao_cur_task->sp32) );
 
        /* Restore PRIMASK */
        asm("pop {r0}");
@@ -450,6 +447,34 @@ static inline void ao_arch_restore_stack(void) {
        asm("pop {r0-r7,pc}\n");
 }
 
+static inline void ao_sleep_mode(void) {
+
+       /*
+         WFI (Wait for Interrupt) or WFE (Wait for Event) while:
+          – Set SLEEPDEEP in Cortex ® -M0 System Control register
+          – Set PDDS bit in Power Control register (PWR_CR)
+          – Clear WUF bit in Power Control/Status register (PWR_CSR)
+       */
+
+       ao_arch_block_interrupts();
+
+       /* Enable power interface clock */
+       stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN);
+       ao_arch_nop();
+       stm_scb.scr |= (1 << STM_SCB_SCR_SLEEPDEEP);
+       ao_arch_nop();
+       stm_pwr.cr |= (1 << STM_PWR_CR_PDDS) | (1 << STM_PWR_CR_LPDS);
+       ao_arch_nop();
+       stm_pwr.cr |= (1 << STM_PWR_CR_CWUF);
+       ao_arch_nop();
+       ao_arch_nop();
+       ao_arch_nop();
+       ao_arch_nop();
+       ao_arch_nop();
+       asm("wfi");
+       ao_arch_nop();
+}
+
 #ifndef HAS_SAMPLE_PROFILE
 #define HAS_SAMPLE_PROFILE 0
 #endif
@@ -503,4 +528,9 @@ uint8_t
 ao_usb_write2(uint16_t len);
 #endif /* AO_USB_DIRECTIO */
 
+void start(void);
+
+void
+ao_debug_out(char c);
+
 #endif /* _AO_ARCH_FUNCS_H_ */
index 7045514cd206d51adc53f0390c30b383afab9ce4..f3fa13b4f5c11557d8c817565529db9cc7024188 100644 (file)
@@ -64,7 +64,7 @@ void stm_dma_ch2_3_isr(void) {
                   ch_mask(STM_DMA_INDEX(3)));
 }
 
-void stm_dma1_ch4_5_6_isr(void) {
+void stm_dma_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)) |
index 36c3f7ca7e5e2a6697f82e81c46a42b147c2bae8..1d19a48f60dcd63b99a3b964d318710197b9f72a 100644 (file)
@@ -36,7 +36,7 @@ void
 ao_exti_set_mode(struct stm_gpio *gpio, uint8_t pin, uint8_t mode);
 
 void
-ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)());
+ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)(void));
 
 void
 ao_exti_enable(struct stm_gpio *gpio, uint8_t pin);
index 910a36f29221e0ab10e9d0536f88d3698e5d4a78..77c59d05ff2cebb72e0b3c503adb6a98ffc237a3 100644 (file)
@@ -123,7 +123,7 @@ ao_exti_set_mode(struct stm_gpio *gpio, uint8_t pin, uint8_t mode) {
 }
 
 void
-ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)()) {
+ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)(void)) {
        (void) gpio;
        ao_exti_callback[pin] = callback;
 }
index 81878d895ffaebbf9f19422cdc60abf6b7d03a8c..0025de47153445bbf6d5df961c54726dab0d4c23 100644 (file)
@@ -145,6 +145,9 @@ isr(usart3_4_5_6_7_8)
 isr(cec_can)
 isr(usb)
 
+#undef isr
+#undef isr_halt
+
 #define i(addr,name)   [(addr)/4] = stm_ ## name ## _isr
 
 __attribute__ ((section(".interrupt")))
index 5097041a7e10693cb55a25598acb06490087745b..ef35394aab53dec6bbf9f64d816d11ab2c5b5186 100644 (file)
@@ -375,6 +375,17 @@ ao_serial_set_sw_rts_cts(struct ao_stm_usart *usart,
 }
 #endif
 
+void
+ao_serial_shutdown(void)
+{
+#if HAS_SERIAL_1
+       stm_rcc.apb2enr &= ~(1 << STM_RCC_APB2ENR_USART1EN);
+#endif
+#if HAS_SERIAL_2
+       stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_USART2EN);
+#endif
+}
+
 void
 ao_serial_init(void)
 {
index 5e76d6c3946c31ff534a6006b76d3987d7908bbf..d83f06580380014fb0a09583ee276e9b19dc5b49 100644 (file)
@@ -412,6 +412,18 @@ 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;
 
+       switch (id) {
+#if SPI_1_POWER_MANAGE
+       case 0:
+               stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SPI1EN);
+               break;
+#endif
+#if SPI_2_POWER_MANAGE
+       case 1:
+               stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_SPI2EN);
+               break;
+#endif
+       }
        if (spi_index != ao_spi_index[id]) {
 
                /* Disable old config
@@ -469,6 +481,18 @@ ao_spi_put(uint8_t spi_index)
        struct stm_spi  *stm_spi = ao_spi_stm_info[id].stm_spi;
 
        stm_spi->cr1 = 0;
+       switch (id) {
+#if SPI_1_POWER_MANAGE
+       case 0:
+               stm_rcc.apb2enr &= ~(1 << STM_RCC_APB2ENR_SPI1EN);
+               break;
+#endif
+#if SPI_2_POWER_MANAGE
+       case 1:
+               stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_SPI2EN);
+               break;
+#endif
+       }
        ao_mutex_put(&ao_spi_mutex[id]);
 }
 
index 17c934a53e5b4a06f3ec9b45c523a55c5bf5191c..c6f1defe8e67b3f8efe97a3424804e9eac470126 100644 (file)
@@ -127,9 +127,24 @@ _ao_flash_write(uint32_t pos, void *sv, uint16_t len)
        stm_flash.cr &= ~(1 << STM_FLASH_CR_PG);
 }
 
+static bool
+ao_storage_is_erased(uint32_t pos)
+{
+       uint16_t *flash = _ao_flash_addr(pos);
+       uint32_t i = ao_storage_block >> 1;
+
+       while (i--)
+               if (*flash++ != 0xffff)
+                       return false;
+       return true;
+}
+
 uint8_t
 ao_storage_erase(uint32_t pos)
 {
+       if (ao_storage_is_erased(pos))
+               return 1;
+
        ao_arch_block_interrupts();
        ao_flash_unlock();
 
index 1def5f69f8e1c1d77d7a6a9d7344e4adcc1001fc..be333754cfa37298d669f57572eb4783d4999093 100644 (file)
@@ -35,6 +35,22 @@ ao_time(void)
        return ao_tick_count;
 }
 
+uint64_t
+ao_time_ns(void)
+{
+       AO_TICK_TYPE    before, after;
+       uint32_t        cvr;
+
+       do {
+               before = ao_tick_count;
+               cvr = stm_systick.cvr;
+               after = ao_tick_count;
+       } while (before != after);
+
+       return (uint64_t) after * (1000000000ULL / AO_HERTZ) +
+               (uint64_t) cvr * (1000000000ULL / AO_SYSTICK);
+}
+
 #if AO_DATA_ALL
 volatile uint8_t       ao_data_interval = 1;
 volatile uint8_t       ao_data_count;
@@ -278,9 +294,6 @@ ao_clock_init(void)
        /* Enable 1 wait state so the CPU can run at 48MHz */
        stm_flash.acr |= (STM_FLASH_ACR_LATENCY_1 << STM_FLASH_ACR_LATENCY);
 
-       /* Enable power interface clock */
-       stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN);
-
        /* HCLK to 48MHz -> AHB prescaler = /1 */
        cfgr = stm_rcc.cfgr;
        cfgr &= ~(STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE);
index ff294849d73534c6c9037f2da842bdbf6b0eb090..b736d389c95002e0eae33bcf40028b8d557909b5 100644 (file)
@@ -245,7 +245,7 @@ static inline uint32_t ao_usb_epr_sw_buf_rx(uint32_t epr) {
  * Set current device address and mark the
  * interface as active
  */
-void
+static void
 ao_usb_set_address(uint8_t address)
 {
        debug("ao_usb_set_address %02x\n", address);
@@ -957,7 +957,7 @@ ao_usb_ep0_handle(uint8_t receive)
 }
 
 #if AO_POWER_MANAGEMENT
-void
+static void
 ao_usb_suspend(void)
 {
        stm_usb.cntr |= (1 << STM_USB_CNTR_FSUSP);
@@ -966,7 +966,7 @@ ao_usb_suspend(void)
        ao_clock_suspend();
 }
 
-void
+static void
 ao_usb_wakeup(void)
 {
        ao_clock_resume();
@@ -1371,7 +1371,7 @@ _ao_usb_out_recv(void)
        _rx_dbg1("out_recv count", ao_usb_rx_count);
 }
 
-int
+static int
 _ao_usb_pollchar(void)
 {
        uint8_t c;
index 968c1295cda4072e2c7cc0766dd8efeecadf07ca..075fd6a90abae403ab4501aa7fa674fea374fe52 100644 (file)
@@ -568,6 +568,8 @@ struct stm_pwr {
 
 extern struct stm_pwr stm_pwr;
 
+#define stm_pwr (*(struct stm_pwr *) 0x40007000)
+
 #define STM_PWR_CR_DBP         (8)
 
 #define STM_PWR_CR_PLS         (5)
@@ -585,7 +587,7 @@ extern struct stm_pwr stm_pwr;
 #define STM_PWR_CR_CSBF                (3)
 #define STM_PWR_CR_CWUF                (2)
 #define STM_PWR_CR_PDDS                (1)
-#define STM_PWR_CR_LPSDSR      (0)
+#define STM_PWR_CR_LPDS                (0)
 
 #define STM_PWR_CSR_EWUP3      (10)
 #define STM_PWR_CSR_EWUP2      (9)
@@ -746,6 +748,8 @@ struct stm_scb {
 
 extern struct stm_scb stm_scb;
 
+#define stm_scb (*(struct stm_scb *) 0xe000ed00)
+
 #define STM_SCB_AIRCR_VECTKEY          16
 #define  STM_SCB_AIRCR_VECTKEY_KEY             0x05fa
 #define STM_SCB_AIRCR_PRIGROUP         8
@@ -753,64 +757,9 @@ extern struct stm_scb stm_scb;
 #define STM_SCB_AIRCR_VECTCLRACTIVE    1
 #define STM_SCB_AIRCR_VECTRESET                0
 
-#define isr(name) void stm_ ## name ## _isr(void);
-
-isr(nmi)
-isr(hardfault)
-isr(memmanage)
-isr(busfault)
-isr(usagefault)
-isr(svc)
-isr(debugmon)
-isr(pendsv)
-isr(systick)
-isr(wwdg)
-isr(pvd)
-isr(tamper_stamp)
-isr(rtc_wkup)
-isr(flash)
-isr(rcc)
-isr(exti0)
-isr(exti1)
-isr(exti2)
-isr(exti3)
-isr(exti4)
-isr(dma1_channel1)
-isr(dma1_channel2)
-isr(dma1_channel3)
-isr(dma1_channel4)
-isr(dma1_channel5)
-isr(dma1_channel6)
-isr(dma1_channel7)
-isr(adc1)
-isr(usb_hp)
-isr(usb_lp)
-isr(dac)
-isr(comp)
-isr(exti9_5)
-isr(lcd)
-isr(tim9)
-isr(tim10)
-isr(tim11)
-isr(tim2)
-isr(tim3)
-isr(tim4)
-isr(i2c1_ev)
-isr(i2c1_er)
-isr(i2c2_ev)
-isr(i2c2_er)
-isr(spi1)
-isr(spi2)
-isr(usart1)
-isr(usart2)
-isr(usart3)
-isr(exti15_10)
-isr(rtc_alarm)
-isr(usb_fs_wkup)
-isr(tim6)
-isr(tim7)
-
-#undef isr
+#define STM_SCB_SCR_SEVONPEND          4
+#define STM_SCB_SCR_SLEEPDEEP          2
+#define STM_SCB_SCR_SLEEPONEXIT                1
 
 #define STM_ISR_WWDG_POS               0
 #define STM_ISR_PVD_VDDIO2_POS         1
@@ -2144,4 +2093,51 @@ struct stm_usart {
 extern struct stm_usart        stm_usart1;
 extern struct stm_usart stm_usart2;
 
+#define isr_decl(name) \
+       void stm_ ## name ## _isr(void)
+
+isr_decl(halt);
+isr_decl(ignore);
+isr_decl(nmi);
+isr_decl(hardfault);
+isr_decl(memmanage);
+isr_decl(busfault);
+isr_decl(usagefault);
+isr_decl(svc);
+isr_decl(debugmon);
+isr_decl(pendsv);
+isr_decl(systick);
+isr_decl(wwdg);
+isr_decl(pvd);
+isr_decl(rtc);
+isr_decl(flash);
+isr_decl(rcc_crs);
+isr_decl(exti0_1);
+isr_decl(exti2_3);
+isr_decl(exti4_15);
+isr_decl(tsc);
+isr_decl(dma_ch1);
+isr_decl(dma_ch2_3);
+isr_decl(dma_ch4_5_6);
+isr_decl(adc_comp);
+isr_decl(tim1_brk_up_trg_com);
+isr_decl(tim1_cc);
+isr_decl(tim2);
+isr_decl(tim3);
+isr_decl(tim6_dac);
+isr_decl(tim7);
+isr_decl(tim14);
+isr_decl(tim15);
+isr_decl(tim16);
+isr_decl(tim17);
+isr_decl(i2c1);
+isr_decl(i2c2);
+isr_decl(spi1);
+isr_decl(spi2);
+isr_decl(usart1);
+isr_decl(usart2);
+isr_decl(usart3_4_5_6_7_8);
+isr_decl(cec_can);
+isr_decl(usb);
+
 #endif /* _STM32F0_H_ */
index ddbfaf5f7e2fa52a33456b97897ff04e9a3d8e35..4230d1b98909fe6853eadccecac4f9cef59ffdaa 100644 (file)
@@ -93,7 +93,7 @@ PRODUCT=TeleBalloon-v2.0
 PRODUCT_DEF=-DTELEMETRUM_V_2_0
 IDPRODUCT=0x000b
 
-CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF)
 
 PROGNAME=teleballoon-v2.0
 PROG=$(PROGNAME)-$(VERSION).elf
@@ -105,16 +105,10 @@ OBJ=$(SRC:.c=.o)
 all: $(PROG) $(HEX)
 
 $(PROG): Makefile $(OBJ) altos.ld
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
-
-../altitude-pa.h: make-altitude-pa
-       nickle $< > $@
+       $(call quiet,CC) $(LDFLAGS) -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:
index 9892ad5fcc7cef849d5a1a3779f04dc82bf9dc4c..49b70aafd48d4fd42526d01fdd02d0b44a10c8c6 100644 (file)
@@ -70,7 +70,7 @@ PRODUCT=TeleBT-v3.0
 PRODUCT_DEF=-DTELEBT_V_3_0
 IDPRODUCT=0x000e
 
-CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF)
 
 PROGNAME=telebt-v3.0
 PROG=$(PROGNAME)-$(VERSION).elf
@@ -82,13 +82,10 @@ OBJ=$(SRC:.c=.o)
 all: $(PROG) $(HEX)
 
 $(PROG): Makefile $(OBJ) altos.ld
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+       $(call quiet,CC) $(LDFLAGS) -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:
index 4ad3287dd86d27b0c0a1bb4b49d125d947ba6598..eba83fbceed3444adfd816a99abe2ac02119b6c2 100644 (file)
@@ -51,7 +51,7 @@ PRODUCT=TeleBT-v4.0
 PRODUCT_DEF=-DTELEBT_V_4_0
 IDPRODUCT=0x000e
 
-CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -Os -g
+CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS)
 
 PROGNAME=telebt-v4.0
 PROG=$(PROGNAME)-$(VERSION).elf
@@ -63,13 +63,10 @@ OBJ=$(SRC:.c=.o)
 all: $(PROG) $(HEX)
 
 $(PROG): Makefile $(OBJ) altos.ld
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+       $(call quiet,CC) $(LDFLAGS) -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:
index a656cde5593e4df93e5d5ed06c6294104940ad9f..abb97baf3aecf3e23d88db7f59fff72fb3411623 100644 (file)
@@ -46,7 +46,7 @@ PRODUCT=TeleDongle-v3.0
 PRODUCT_DEF=-DTELEDONGLE
 IDPRODUCT=0x000c
 
-CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) -Os -g
+CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS)
 
 PROGNAME=teledongle-v3.0
 PROG=$(PROGNAME)-$(VERSION).elf
@@ -58,13 +58,10 @@ OBJ=$(SRC:.c=.o)
 all: $(PROG) $(HEX)
 
 $(PROG): Makefile $(OBJ) altos.ld
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+       $(call quiet,CC) $(LDFLAGS) -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) > $@
-
 load: $(PROG)
        lpc-load $(PROG)
 
index 200c3150632897622b97deda7c59d70881c96daa..1ec0dccf903d3549660031df0d16c0ae5b99a1b6 100644 (file)
@@ -59,7 +59,7 @@ PRODUCT=TeleFireEight-v1.0
 PRODUCT_DEF=-DTELEFIREEIGHT_V_1_0
 IDPRODUCT=0x000f
 
-CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF)
 
 PROGNAME = telefireeight-v1.0
 PROG = $(PROGNAME)-$(VERSION).elf
@@ -71,13 +71,10 @@ OBJ=$(SRC:.c=.o)
 all: $(PROG) $(HEX)
 
 $(PROG): Makefile $(OBJ) altos.ld
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+       $(call quiet,CC) $(LDFLAGS) -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:
index 89541a024636504284ab0e12e220e2b51bdded75..b266cfe809494ef39b4595984f99765541aedcdb 100644 (file)
@@ -21,7 +21,7 @@
 #include <ao_exti.h>
 #include <ao_radio_cmac_cmd.h>
 
-void
+int
 main(void)
 {
        ao_clock_init();
diff --git a/src/telefireeight-v2.0/.gitignore b/src/telefireeight-v2.0/.gitignore
new file mode 100644 (file)
index 0000000..22f7e9e
--- /dev/null
@@ -0,0 +1,2 @@
+telefireeight-*
+ao_product.h
diff --git a/src/telefireeight-v2.0/Makefile b/src/telefireeight-v2.0/Makefile
new file mode 100644 (file)
index 0000000..48a7123
--- /dev/null
@@ -0,0 +1,86 @@
+#
+# 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_telefireeight.c
+
+PRODUCT=TeleFireEight-v2.0
+PRODUCT_DEF=-DTELEFIREEIGHT_V_2_0
+IDPRODUCT=0x000f
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF)
+
+PROGNAME = telefireeight-v2.0
+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) -o $(PROG) $(OBJ) $(LIBS)
+
+$(OBJ): $(INC)
+
+distclean:     clean
+
+clean:
+       rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx $(PROGNAME).map
+       rm -f ao_product.h
+
+install:
+
+uninstall:
+
diff --git a/src/telefireeight-v2.0/ao_pins.h b/src/telefireeight-v2.0/ao_pins.h
new file mode 100644 (file)
index 0000000..046514b
--- /dev/null
@@ -0,0 +1,314 @@
+/*
+ * Copyright © 2019 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define 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 AO_DATA_RING           32
+#define USE_EEPROM_CONFIG      1
+#define USE_STORAGE_CONFIG     0
+#define HAS_AES                        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_SPI_1              1
+#define SPI_1_PA5_PA6_PA7      0
+#define SPI_1_PB3_PB4_PB5      0
+#define SPI_1_PE13_PE14_PE15   1
+#define SPI_1_GPIO             (&stm_gpioe)
+#define SPI_1_OSPEEDR          STM_OSPEEDR_10MHz
+
+#define HAS_SPI_2              0
+#define SPI_2_PB13_PB14_PB15   0
+#define SPI_2_PD1_PD3_PD4      0
+
+#define HAS_I2C_1              0
+
+#define HAS_I2C_2              0
+
+/*
+ * Radio is a cc1200 connected via SPI
+ */
+
+#define AO_RADIO_CAL_DEFAULT   5695733
+
+#define AO_CC1200_SPI_CS_PORT  (&stm_gpioe)
+#define AO_CC1200_SPI_CS_PIN   11
+#define AO_CC1200_SPI_BUS      AO_SPI_1_PE13_PE14_PE15
+#define AO_CC1200_SPI          stm_spi1
+#define AO_CC1200_SPI_SPEED    AO_SPI_SPEED_FAST
+
+#define AO_CC1200_INT_PORT     (&stm_gpioe)
+#define AO_CC1200_INT_PIN      (12)
+
+#define AO_CC1200_INT_GPIO     2
+#define AO_CC1200_INT_GPIO_IOCFG       CC1200_IOCFG2
+
+#define HAS_LED                        1
+#define LED_TYPE               uint16_t
+
+/* Continuity leds 1-8 */
+#define LED_0_PORT             (&stm_gpiob)
+#define LED_0_PIN              13
+#define LED_1_PORT             (&stm_gpiob)
+#define LED_1_PIN              12
+#define LED_2_PORT             (&stm_gpiob)
+#define LED_2_PIN              11
+#define LED_3_PORT             (&stm_gpiob)
+#define LED_3_PIN              10
+#define LED_4_PORT             (&stm_gpioc)
+#define LED_4_PIN              9
+#define LED_5_PORT             (&stm_gpioa)
+#define LED_5_PIN              8
+#define LED_6_PORT             (&stm_gpioa)
+#define LED_6_PIN              9
+#define LED_7_PORT             (&stm_gpioa)
+#define LED_7_PIN              10
+
+#define AO_LED_CONTINUITY(c)   (1 << (c))
+#define AO_LED_CONTINUITY_MASK (0xff)
+
+/* ARM */
+#define LED_8_PORT             (&stm_gpioe)
+#define LED_8_PIN              3
+
+#define AO_LED_ARMED           AO_LED_8
+
+/* RF good/marginal/poor */
+#define LED_9_PORT             (&stm_gpioe)
+#define LED_9_PIN              4
+#define LED_10_PORT            (&stm_gpioe)
+#define LED_10_PIN             5
+#define LED_11_PORT            (&stm_gpioe)
+#define LED_11_PIN             6
+
+#define AO_LED_GREEN           AO_LED_9
+#define AO_LED_AMBER           AO_LED_10
+#define AO_LED_RED             AO_LED_11
+
+/* Alarm A */
+#define AO_SIREN
+#define AO_SIREN_PORT          (&stm_gpiod)
+#define AO_SIREN_PIN           10
+
+/* Alarm B */
+#define AO_STROBE
+#define AO_STROBE_PORT         (&stm_gpiod)
+#define AO_STROBE_PIN          11
+
+/* Pad selector is on PD0-7 */
+
+#define HAS_FIXED_PAD_BOX      1
+#define AO_PAD_SELECTOR_PORT   (&stm_gpiod)
+#define AO_PAD_SELECTOR_PINS   (0xff)
+
+#define SPI_CONST      0x00
+
+#define AO_PAD_NUM             8
+#define        AO_PAD_PORT_0           (&stm_gpiod)
+#define        AO_PAD_PORT_1           (&stm_gpiob)
+
+#define AO_PAD_PIN_0           9
+#define AO_PAD_0_PORT          (&stm_gpiod)
+#define AO_ADC_SENSE_PAD_0     3
+#define AO_ADC_SENSE_PAD_0_PORT        (&stm_gpioa)
+#define AO_ADC_SENSE_PAD_0_PIN 3
+
+#define AO_PAD_PIN_1           8
+#define AO_PAD_1_PORT          (&stm_gpiod)
+#define AO_ADC_SENSE_PAD_1     2
+#define AO_ADC_SENSE_PAD_1_PORT        (&stm_gpioa)
+#define AO_ADC_SENSE_PAD_1_PIN 2
+
+#define AO_PAD_PIN_2           15
+#define AO_PAD_2_PORT          (&stm_gpiob)
+#define AO_ADC_SENSE_PAD_2     1
+#define AO_ADC_SENSE_PAD_2_PORT        (&stm_gpioa)
+#define AO_ADC_SENSE_PAD_2_PIN 1
+
+#define AO_PAD_PIN_3           14
+#define AO_PAD_3_PORT          (&stm_gpiob)
+#define AO_ADC_SENSE_PAD_3     0
+#define AO_ADC_SENSE_PAD_3_PORT        (&stm_gpioa)
+#define AO_ADC_SENSE_PAD_3_PIN 0
+
+#define AO_PAD_PIN_4           12
+#define AO_PAD_4_PORT          (&stm_gpiod)
+#define AO_ADC_SENSE_PAD_4     7
+#define AO_ADC_SENSE_PAD_4_PORT        (&stm_gpioa)
+#define AO_ADC_SENSE_PAD_4_PIN 7
+
+#define AO_PAD_PIN_5           13
+#define AO_PAD_5_PORT          (&stm_gpiod)
+#define AO_ADC_SENSE_PAD_5     6
+#define AO_ADC_SENSE_PAD_5_PORT        (&stm_gpioa)
+#define AO_ADC_SENSE_PAD_5_PIN 6
+
+#define AO_PAD_PIN_6           14
+#define AO_PAD_6_PORT          (&stm_gpiod)
+#define AO_ADC_SENSE_PAD_6     5
+#define AO_ADC_SENSE_PAD_6_PORT        (&stm_gpioa)
+#define AO_ADC_SENSE_PAD_6_PIN 5
+
+#define AO_PAD_PIN_7           15
+#define AO_PAD_7_PORT          (&stm_gpiod)
+#define AO_ADC_SENSE_PAD_7     4
+#define AO_ADC_SENSE_PAD_7_PORT        (&stm_gpioa)
+#define AO_ADC_SENSE_PAD_7_PIN 4
+
+#define AO_ADC_PYRO            8
+#define AO_ADC_PYRO_PORT       (&stm_gpiob)
+#define AO_ADC_PYRO_PIN                0
+
+#define AO_ADC_BATT            15
+#define AO_ADC_BATT_PORT       (&stm_gpioc)
+#define AO_ADC_BATT_PIN                5
+
+#define AO_ADC_PIN0_PORT       AO_ADC_SENSE_PAD_0_PORT
+#define AO_ADC_PIN0_PIN                AO_ADC_SENSE_PAD_0_PIN
+
+#define AO_ADC_PIN1_PORT       AO_ADC_SENSE_PAD_1_PORT
+#define AO_ADC_PIN1_PIN                AO_ADC_SENSE_PAD_1_PIN
+
+#define AO_ADC_PIN2_PORT       AO_ADC_SENSE_PAD_2_PORT
+#define AO_ADC_PIN2_PIN                AO_ADC_SENSE_PAD_2_PIN
+
+#define AO_ADC_PIN3_PORT       AO_ADC_SENSE_PAD_3_PORT
+#define AO_ADC_PIN3_PIN                AO_ADC_SENSE_PAD_3_PIN
+
+#define AO_ADC_PIN4_PORT       AO_ADC_SENSE_PAD_4_PORT
+#define AO_ADC_PIN4_PIN                AO_ADC_SENSE_PAD_4_PIN
+
+#define AO_ADC_PIN5_PORT       AO_ADC_SENSE_PAD_5_PORT
+#define AO_ADC_PIN5_PIN                AO_ADC_SENSE_PAD_5_PIN
+
+#define AO_ADC_PIN6_PORT       AO_ADC_SENSE_PAD_6_PORT
+#define AO_ADC_PIN6_PIN                AO_ADC_SENSE_PAD_6_PIN
+
+#define AO_ADC_PIN7_PORT       AO_ADC_SENSE_PAD_7_PORT
+#define AO_ADC_PIN7_PIN                AO_ADC_SENSE_PAD_7_PIN
+
+#define AO_ADC_PIN8_PORT       AO_ADC_PYRO_PORT
+#define AO_ADC_PIN8_PIN                AO_ADC_PYRO_PIN
+
+#define AO_ADC_PIN9_PORT       AO_ADC_BATT_PORT
+#define AO_ADC_PIN9_PIN                AO_ADC_BATT_PIN
+
+#define AO_PAD_ALL_CHANNELS    (0xff)
+
+/* 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_ADC_FIRST_PIN       0
+
+#define AO_NUM_ADC             10
+
+#define AO_ADC_SQ1             AO_ADC_SENSE_PAD_0
+#define AO_ADC_SQ2             AO_ADC_SENSE_PAD_1
+#define AO_ADC_SQ3             AO_ADC_SENSE_PAD_2
+#define AO_ADC_SQ4             AO_ADC_SENSE_PAD_3
+#define AO_ADC_SQ5             AO_ADC_SENSE_PAD_4
+#define AO_ADC_SQ6             AO_ADC_SENSE_PAD_5
+#define AO_ADC_SQ7             AO_ADC_SENSE_PAD_6
+#define AO_ADC_SQ8             AO_ADC_SENSE_PAD_7
+#define AO_ADC_SQ9             AO_ADC_PYRO
+#define AO_ADC_SQ10            AO_ADC_BATT
+
+#define AO_ADC_REFERENCE_DV    33
+
+#define AO_ADC_RCC_AHBENR      ((1 << STM_RCC_AHBENR_GPIOAEN) | \
+                                (1 << STM_RCC_AHBENR_GPIOBEN) | \
+                                (1 << STM_RCC_AHBENR_GPIOCEN))
+
+
+#define AO_PAD_R_V_BATT_BATT_SENSE     200
+#define AO_PAD_R_BATT_SENSE_GND                22
+
+#define AO_PAD_R_V_BATT_V_PYRO         200
+#define AO_PAD_R_V_PYRO_PYRO_SENSE     200
+#define AO_PAD_R_PYRO_SENSE_GND                22
+
+#undef AO_PAD_R_V_PYRO_IGNITER
+#define AO_PAD_R_IGNITER_IGNITER_SENSE 200
+#define AO_PAD_R_IGNITER_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 2: %5d 3: %5d "                          \
+               "4: %5d 5: %5d 6: %5d 7: %5d "                          \
+               "pyro: %5d batt: %5d\n",                                \
+               (p)->tick,                                              \
+               (p)->adc.sense[0],                                      \
+               (p)->adc.sense[1],                                      \
+               (p)->adc.sense[2],                                      \
+               (p)->adc.sense[3],                                      \
+               (p)->adc.sense[4],                                      \
+               (p)->adc.sense[5],                                      \
+               (p)->adc.sense[6],                                      \
+               (p)->adc.sense[7],                                      \
+               (p)->adc.pyro,                                          \
+               (p)->adc.batt)
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/telefireeight-v2.0/ao_telefireeight.c b/src/telefireeight-v2.0/ao_telefireeight.c
new file mode 100644 (file)
index 0000000..b266cfe
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_pad.h>
+#include <ao_exti.h>
+#include <ao_radio_cmac_cmd.h>
+
+int
+main(void)
+{
+       ao_clock_init();
+
+       ao_led_init();
+       ao_led_on(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_led_off(LEDS_AVAILABLE);
+
+       ao_start_scheduler();
+}
diff --git a/src/telefireeight-v2.0/flash-loader/.gitignore b/src/telefireeight-v2.0/flash-loader/.gitignore
new file mode 100644 (file)
index 0000000..65fe7ea
--- /dev/null
@@ -0,0 +1,2 @@
+*.elf
+*.ihx
diff --git a/src/telefireeight-v2.0/flash-loader/Makefile b/src/telefireeight-v2.0/flash-loader/Makefile
new file mode 100644 (file)
index 0000000..ae582fe
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=telefireeight-v2.0
+include $(TOPDIR)/stm/Makefile-flash.defs
diff --git a/src/telefireeight-v2.0/flash-loader/ao_pins.h b/src/telefireeight-v2.0/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..f3ae76f
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright © 2019 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+/* External crystal at 8MHz */
+#define AO_HSE         8000000
+
+#include <ao_flash_stm_pins.h>
+
+#define AO_BOOT_PIN                    1
+#define AO_BOOT_APPLICATION_GPIO       stm_gpioe
+#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_ */
diff --git a/src/telefireone-v1.0/.gitignore b/src/telefireone-v1.0/.gitignore
new file mode 100644 (file)
index 0000000..64b5469
--- /dev/null
@@ -0,0 +1,2 @@
+telefireone-*
+ao_product.h
index 773c8f69c685066b5d8248557354000a96b47d43..afcdcd67e6932e3654cd28a05f47a75b13b2b2dc 100644 (file)
@@ -42,7 +42,6 @@ ALTOS_SRC = \
        ao_freq.c \
        ao_dma_stm.c \
        ao_spi_stm.c \
-       ao_beep_stm.c \
        ao_eeprom_stm.c \
        ao_storage.c \
        ao_m25.c \
@@ -64,7 +63,7 @@ PRODUCT=TeleFireOne-v1.0
 PRODUCT_DEF=-DTELEFIREONE_V_1_0
 IDPRODUCT=0x000f
 
-CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF)
 
 PROGNAME = telefireone-v1.0
 PROG = $(PROGNAME)-$(VERSION).elf
@@ -76,13 +75,10 @@ OBJ=$(SRC:.c=.o)
 all: $(PROG) $(HEX)
 
 $(PROG): Makefile $(OBJ) altos.ld
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+       $(call quiet,CC) $(LDFLAGS) -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:
@@ -93,3 +89,5 @@ install:
 
 uninstall:
 
+echo:
+       echo $(PROG) $(VERSION)
index 15b158effc9ce12f21aac2d2a357a78f39b2a712..cd8eb65861d3b4b7d8bc460a3fa489524c1246fd 100644 (file)
@@ -25,7 +25,7 @@
 
 #define HAS_FLIGHT             0
 #define HAS_USB                        1
-#define HAS_BEEP               1
+#define HAS_BEEP               0
 #define BEEPER_CHANNEL         4
 #define BEEPER_TIMER           3
 #define HAS_GPS                        0
 #define HAS_EEPROM             1
 #define HAS_LOG                        1
 #define HAS_PAD                        1
-#define USE_INTERNAL_FLASH     1
+#define USE_INTERNAL_FLASH     0
 #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
 
+#define AO_LOG_FORMAT          AO_LOG_FORMAT_TELEFIRETWO
+
 #define LOG_ERASE_MARK         0x55
 
 /* 8MHz High speed external crystal */
 
 #define AO_ADC_FIRST_PIN       0
 
+#define AO_ADC_REFERENCE_DV    33
+
 #define AO_NUM_ADC             5
 
 #define AO_ADC_SQ1             AO_PAD_ADC_0
 #define AO_ADC_SQ4             AO_PAD_ADC_THRUST
 #define AO_ADC_SQ5             AO_PAD_ADC_PRESSURE
 
+#define AO_PAD_R_V_BATT_BATT_SENSE     200
+#define AO_PAD_R_BATT_SENSE_GND                22
+
+#define AO_PAD_R_V_BATT_V_PYRO         200
+#define AO_PAD_R_V_PYRO_PYRO_SENSE     200
+#define AO_PAD_R_PYRO_SENSE_GND                22
+
+#undef AO_PAD_R_V_PYRO_IGNITER
+#define AO_PAD_R_IGNITER_IGNITER_SENSE 200
+#define AO_PAD_R_IGNITER_SENSE_GND     22
+
 #define AO_PYRO_R_PYRO_SENSE   200
 #define AO_PYRO_R_SENSE_GND    22
 
index 6506235a975be2c596c401cd254498a5f783c76e..d9c6586c7fac04417f9a139977340a3ea2938574 100644 (file)
@@ -35,12 +35,12 @@ const struct ao_cmds ao_firetwo_cmds[] = {
         { 0,    NULL },
 };
 
-void
+int
 main(void)
 {
        ao_clock_init();
 
-       ao_led_init(LEDS_AVAILABLE);
+       ao_led_init();
 
        ao_task_init();
 
diff --git a/src/telefireone-v2.0/Makefile b/src/telefireone-v2.0/Makefile
new file mode 100644 (file)
index 0000000..af273a5
--- /dev/null
@@ -0,0 +1,97 @@
+#
+# TeleFire build file
+#
+
+include ../stm/Makefile.defs
+
+INC = \
+       ao.h \
+       ao_pins.h \
+       ao_log.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_stm.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_storage.c \
+       ao_m25.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 \
+       ao_log.c \
+       ao_log_fireone.c \
+       ao_ads124s0x.c \
+       ao_max6691.c
+
+PRODUCT_SRC = \
+       ao_telefireone.c
+
+PRODUCT=TeleFireOne-v2.0
+PRODUCT_DEF=-DTELEFIREONE_V_2_0
+IDPRODUCT=0x000f
+
+# Include floating-point enabled printf
+
+NEWLIB_PRINTF_CFLAGS = 
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF)
+
+PROGNAME = telefireone-v2.0
+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) -o $(PROG) $(OBJ) $(LIBS)
+
+$(OBJ): $(INC)
+
+distclean:     clean
+
+clean:
+       rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx $(PROGNAME)-*.map
+       rm -f ao_product.h
+
+install:
+
+uninstall:
+
diff --git a/src/telefireone-v2.0/ao_pins.h b/src/telefireone-v2.0/ao_pins.h
new file mode 100644 (file)
index 0000000..8025ace
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * Copyright © 2019 Bdale Garbee <bdale@gag.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define 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                        1
+#define HAS_PAD                        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
+
+#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX       (512 * 1024)
+#define AO_CONFIG_MAX_SIZE                     1024
+#define LOG_ERASE_MARK                         0x55
+#define LOG_MAX_ERASE                          128
+#define AO_LOG_FORMAT                          AO_LOG_FORMAT_TELEMETRUM
+
+/* 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     0
+#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              1       /* ADS124S0X */ 
+#define SPI_1_PA5_PA6_PA7      1
+#define SPI_1_PB3_PB4_PB5      0
+#define SPI_1_PE13_PE14_PE15   0
+#define SPI_1_OSPEEDR          STM_OSPEEDR_10MHz
+
+#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 */
+
+/*
+ * ADS124S0X analog to digital converter
+ */
+
+#define AO_ADS124S0X_SPI_CS_PORT       (&stm_gpioa)
+#define AO_ADS124S0X_SPI_CS_PIN                4
+#define AO_ADS124S0X_SPI_CS_MASK       (1 << AO_ADS124S0X_SPI_CS_PIN)
+#define AO_ADS124S0X_SPI_BUS           (AO_SPI_1_PA5_PA6_PA7 | AO_SPI_MODE_1)
+#define AO_ADS124S0X_SPI_SPEED         AO_SPI_SPEED_8MHz
+
+#define AO_ADS124S0X_DRDY_PORT         (&stm_gpioc)
+#define AO_ADS124S0X_DRDY_PIN          13
+
+#define AO_ADS124S0X_START_PORT                (&stm_gpioc)
+#define AO_ADS124S0X_START_PIN         14
+
+#define AO_ADS124S0X_RESET_PORT                (&stm_gpioc)
+#define AO_ADS124S0X_RESET_PIN         15
+
+#define AO_ADS124S0X_CHANNELS          4       /* how many inputs in use */
+
+/*
+ * SPI Flash memory
+ */
+
+#define M25_MAX_CHIPS           1
+#define AO_M25_SPI_CS_PORT      (&stm_gpioa)
+#define AO_M25_SPI_CS_MASK      (1 << 15)
+#define AO_M25_SPI_BUS          AO_SPI_2_PB13_PB14_PB15
+
+/*
+ * 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   3
+#define AO_CC1200_SPI_BUS      AO_SPI_2_PB13_PB14_PB15
+#define AO_CC1200_SPI          stm_spi2
+#define AO_CC1200_SPI_SPEED    AO_SPI_SPEED_FAST
+
+#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 8-10 */
+#define LED_PORT_0_SHIFT       8
+#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 5-6 */
+#define LED_PORT_1_SHIFT       0
+#define LED_PORT_1_MASK                (0x3 << 5)
+#define LED_PIN_CONT_0         5
+#define LED_PIN_ARMED          6
+
+#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
+
+/*
+ * ADC reference in decivolts
+ */
+#define AO_ADC_REFERENCE_DV     33
+
+#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_PAD_ADC_THRUST   3       /* FIXME - external ADC now! */
+// #define AO_PAD_ADC_PRESSURE 18      /* FIXME - external ADC now! */
+
+#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_ADC_SQ4          AO_PAD_ADC_THRUST
+// #define AO_ADC_SQ5          AO_PAD_ADC_PRESSURE
+
+#define AO_PAD_R_V_BATT_BATT_SENSE      200
+#define AO_PAD_R_BATT_SENSE_GND         22
+
+#define AO_PAD_R_V_BATT_V_PYRO          200
+#define AO_PAD_R_V_PYRO_PYRO_SENSE      200
+#define AO_PAD_R_PYRO_SENSE_GND         22
+
+#undef AO_PAD_R_V_PYRO_IGNITER
+#define AO_PAD_R_IGNITER_IGNITER_SENSE  200
+#define AO_PAD_R_IGNITER_SENSE_GND      22
+
+#define HAS_ADC_TEMP           0
+
+struct ao_adc {
+       int16_t         sense[AO_PAD_NUM];
+       int16_t         pyro;
+       int16_t         batt;
+       int16_t         thrust;
+       int16_t         pressure;
+};
+
+#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))
+
+/* MAX6691 thermistor chip */
+#define HAS_MAX6691            1
+#define AO_MAX6691_GPIO                (&stm_gpiob)
+#define AO_MAX6691_PIN         3
+#define AO_MAX6691_TIMER       (&stm_tim2)
+#define AO_MAX6691_TIMER_ENABLE        STM_RCC_APB1ENR_TIM2EN
+#define AO_MAX6691_CH          2
+#define AO_MAX6691_DMA         STM_DMA_INDEX(7)
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/telefireone-v2.0/ao_telefireone.c b/src/telefireone-v2.0/ao_telefireone.c
new file mode 100644 (file)
index 0000000..ff2f11d
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_log.h>
+#include <ao_pad.h>
+#include <ao_exti.h>
+#include <ao_radio_cmac_cmd.h>
+#include <ao_eeprom.h>
+#include <ao_ads124s0x.h>
+#include <ao_max6691.h>
+
+static void
+set_logging(void)
+{
+       ao_log_running = ao_cmd_hex();
+       ao_wakeup(&ao_log_running);
+}
+
+const struct ao_cmds ao_firetwo_cmds[] = {
+        { set_logging,  "L <0 off, 1 on>\0Log sensors to flash" },
+        { 0,    NULL },
+};
+
+void
+main(void)
+{
+       ao_clock_init();
+
+       ao_led_init();
+
+       ao_task_init();
+
+       ao_timer_init();
+       ao_spi_init();
+       ao_dma_init();
+       ao_exti_init();
+
+       ao_cmd_register(&ao_firetwo_cmds[0]);
+       ao_cmd_init();
+
+       ao_adc_init();
+
+       ao_max6691_init();
+
+       ao_eeprom_init();
+       ao_storage_init();
+       ao_log_init();
+
+       ao_radio_init();
+
+       ao_usb_init();
+
+       ao_config_init();
+
+       ao_pad_init();
+
+//     ao_radio_cmac_cmd_init();
+
+       ao_ads124s0x_init();
+
+       ao_start_scheduler();
+}
diff --git a/src/telefireone-v2.0/flash-loader/.gitignore b/src/telefireone-v2.0/flash-loader/.gitignore
new file mode 100644 (file)
index 0000000..65fe7ea
--- /dev/null
@@ -0,0 +1,2 @@
+*.elf
+*.ihx
diff --git a/src/telefireone-v2.0/flash-loader/Makefile b/src/telefireone-v2.0/flash-loader/Makefile
new file mode 100644 (file)
index 0000000..bd2f9f8
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=telefireone-v2.0
+include $(TOPDIR)/stm/Makefile-flash.defs
diff --git a/src/telefireone-v2.0/flash-loader/ao_pins.h b/src/telefireone-v2.0/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..96150e9
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright © 2019 Bdale Garbee <bdale@gag.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+/* 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                4
+#define AO_BOOT_APPLICATION_VALUE      1
+#define AO_BOOT_APPLICATION_MODE       AO_EXTI_MODE_PULL_UP
+
+#endif /* _AO_PINS_H_ */
index 72171fac51429baf365d2c4a9514dbbc3f50c197..a462d5b5407f3733257592cd1c9452a8ffdf7554 100644 (file)
@@ -58,7 +58,7 @@ PRODUCT=TeleFire-v0.1
 PRODUCT_DEF=-DTELEFIRETWO_V_0_1
 IDPRODUCT=0x000f
 
-CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF)
 
 PROGNAME = telefiretwo-v0.1
 PROG = $(PROGNAME)-$(VERSION).elf
@@ -70,13 +70,10 @@ OBJ=$(SRC:.c=.o)
 all: $(PROG) $(HEX)
 
 $(PROG): Makefile $(OBJ) altos.ld
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+       $(call quiet,CC) $(LDFLAGS) -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:
index 89541a024636504284ab0e12e220e2b51bdded75..b266cfe809494ef39b4595984f99765541aedcdb 100644 (file)
@@ -21,7 +21,7 @@
 #include <ao_exti.h>
 #include <ao_radio_cmac_cmd.h>
 
-void
+int
 main(void)
 {
        ao_clock_init();
index f43ece71eb647e72f9bc2bd613fa54bb0b263556..d48dcc377f4beb76e0a766987ddcf36e44d28665 100644 (file)
@@ -59,7 +59,7 @@ PRODUCT=TeleFire-v0.2
 PRODUCT_DEF=-DTELEFIRETWO_V_0_2
 IDPRODUCT=0x000f
 
-CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF)
 
 PROGNAME = telefiretwo-v0.2
 PROG = $(PROGNAME)-$(VERSION).elf
index 0365f91f354e64f5b9c808d35adcc282dbaf2021..90fd8a503c76168e177012d564cd58b37d9ffc39 100644 (file)
@@ -75,7 +75,7 @@ PRODUCT=TeleGPS-v0.1
 PRODUCT_DEF=-DTELEGPS
 IDPRODUCT=0x0025
 
-CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF)
 
 PROGNAME=telegps-v0.1
 PROG=$(PROGNAME)-$(VERSION).elf
index 834609d9ff3c7938ec899672f341ae31d42e7850..73d8c2455bd4554666c7883bed1a995538c878cd 100644 (file)
@@ -56,7 +56,7 @@ PRODUCT=TeleGPS-v0.3
 PRODUCT_DEF=-DTELEGPS
 IDPRODUCT=0x0025
 
-CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) $(PROFILE_DEF) -Os -g
+CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) $(PROFILE_DEF)
 
 PROGNAME=telegps-v0.3
 PROG=$(PROGNAME)-$(VERSION).elf
@@ -68,13 +68,10 @@ OBJ=$(SRC:.c=.o)
 all: $(PROG) $(HEX)
 
 $(PROG): Makefile $(OBJ) altos.ld
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+       $(call quiet,CC) $(LDFLAGS) -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:
index 76dc037147c398e53b01366b272076fd6cd48f0d..fc1b1f28c8de9396a72e1fd38ea69bd9bb95b23b 100644 (file)
@@ -59,7 +59,7 @@ PRODUCT=TeleGPS-v1.0
 PRODUCT_DEF=-DTELEGPS
 IDPRODUCT=0x0025
 
-CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) $(PROFILE_DEF) -Os -g
+CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) $(PROFILE_DEF)
 
 PROGNAME=telegps-v1.0
 PROG=$(PROGNAME)-$(VERSION).elf
@@ -71,13 +71,10 @@ OBJ=$(SRC:.c=.o)
 all: $(PROG) $(HEX)
 
 $(PROG): Makefile $(OBJ) altos.ld
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+       $(call quiet,CC) $(LDFLAGS) -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:
index 617efa65a346e482b55ef13721f7dc39b669180a..7ce2847154b4483e433f4c26504af8dcad00af3d 100644 (file)
@@ -3,7 +3,9 @@
 #
 #
 
-include ../stmf0/Makefile.defs
+TOPDIR=..
+
+include $(TOPDIR)/stmf0/Makefile.defs
 
 INC = \
        ao.h \
@@ -59,7 +61,7 @@ PRODUCT=TeleGPS-v2.0
 PRODUCT_DEF=-DTELEGPS
 IDPRODUCT=0x0025
 
-CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) $(PROFILE_DEF) -g -Os
+CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) $(PROFILE_DEF)
 
 PROGNAME=telegps-v2.0
 PROG=$(PROGNAME)-$(VERSION).elf
@@ -75,9 +77,6 @@ $(PROG): Makefile $(OBJ) altos.ld
 
 $(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:
diff --git a/src/telelco-v0.2-cc1200/.gitignore b/src/telelco-v0.2-cc1200/.gitignore
new file mode 100644 (file)
index 0000000..a32ec26
--- /dev/null
@@ -0,0 +1,2 @@
+ao_product.h
+telelco*.elf
index 9307aa2daa7861a20ada6a52f3f414d9b782e268..04f3b8ff9942bfdc98d025994bced25add2026ed 100644 (file)
@@ -76,7 +76,7 @@ PRODUCT=TeleLCO-v0.2
 PRODUCT_DEF=-DTELELCO
 IDPRODUCT=0x0023
 
-CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF)
 
 PROGNAME=telelco-v0.2
 PROG=$(PROGNAME)-$(VERSION).elf
@@ -88,16 +88,10 @@ OBJ=$(SRC:.c=.o)
 all: $(PROG) $(HEX)
 
 $(PROG): Makefile $(OBJ) altos.ld
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
-
-../altitude.h: make-altitude
-       nickle $< > $@
+       $(call quiet,CC) $(LDFLAGS) -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:
index 91ae67f092aa851677d69d65e864ee3cf6c27723..2b8af054fc328aa20a0b913d7c10a9c0a29dbbf8 100644 (file)
@@ -70,10 +70,10 @@ ALTOS_SRC = \
        ao_radio_cmac_cmd.c
 
 PRODUCT=TeleLCO-v0.2
-PRODUCT_DEF=-DTELEMEGA
+PRODUCT_DEF=-DTELELCO
 IDPRODUCT=0x0023
 
-CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF)
 
 PROGNAME=telelco-v0.2
 PROG=$(PROGNAME)-$(VERSION).elf
@@ -85,16 +85,10 @@ OBJ=$(SRC:.c=.o)
 all: $(PROG) $(HEX)
 
 $(PROG): Makefile $(OBJ) altos.ld
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
-
-../altitude.h: make-altitude
-       nickle $< > $@
+       $(call quiet,CC) $(LDFLAGS) -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:
index 567ddf419ad167f32ec760ed24b562679c54a9e3..87e5d72dceae096ca527de611c269930cc80ab5b 100644 (file)
@@ -74,7 +74,7 @@ PRODUCT=TeleLCO-v0.3
 PRODUCT_DEF=-DTELELCO
 IDPRODUCT=0x0023
 
-CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF)
 
 PROGNAME=telelco-v0.3
 PROG=$(PROGNAME)-$(VERSION).elf
@@ -86,16 +86,10 @@ OBJ=$(SRC:.c=.o)
 all: $(PROG) $(HEX)
 
 $(PROG): Makefile $(OBJ) altos.ld
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
-
-../altitude.h: make-altitude
-       nickle $< > $@
+       $(call quiet,CC) $(LDFLAGS) -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:
index 43295fd30a8087eecf72ddcfaa69e6c97e8cc89e..1ae5981fa7fdb7f85088b69775acf4ad63f7c14f 100644 (file)
@@ -76,7 +76,7 @@ PRODUCT=TeleLCO-v2.0
 PRODUCT_DEF=-DTELELCO
 IDPRODUCT=0x0023
 
-CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF)
 
 PROGNAME=telelco-v2.0
 PROG=$(PROGNAME)-$(VERSION).elf
@@ -88,13 +88,10 @@ OBJ=$(SRC:.c=.o)
 all: $(PROG) $(HEX)
 
 $(PROG): Makefile $(OBJ) altos.ld
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+       $(call quiet,CC) $(LDFLAGS) -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:
index daecf380260a2e82e277e6091a267921c5d06c5f..904dea0fe501f039e685366ae4b1d4664b916576 100644 (file)
@@ -236,7 +236,7 @@ ao_lco_input(void)
  * visually inspect the system for correct operation
  */
 static void
-ao_lco_display_test()
+ao_lco_display_test(void)
 {
        ao_mutex_get(&ao_lco_display_mutex);
        ao_seven_segment_set(AO_LCO_PAD_DIGIT, 8 | 0x10);
@@ -279,7 +279,7 @@ ao_lco_main(void)
 }
 
 #if DEBUG
-void
+static void
 ao_lco_set_debug(void)
 {
        uint16_t r = ao_cmd_decimal();
index 6a114aae2658085a308a642312cecfd3c9bc54b8..c0a90d9d5d18504cb835d2ee1d6a5228266e5e04 100644 (file)
@@ -67,7 +67,7 @@ PRODUCT=TeleLCOTwo-v0.1
 PRODUCT_DEF=-DTELELCOTWO
 IDPRODUCT=0x0023
 
-CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF)
 
 PROGNAME=telelcotwo-v0.1
 PROG=$(PROGNAME)-$(VERSION).elf
@@ -79,13 +79,10 @@ OBJ=$(SRC:.c=.o)
 all: $(PROG) $(HEX)
 
 $(PROG): Makefile $(OBJ) altos.ld
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+       $(call quiet,CC) $(LDFLAGS) -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:
index fde35aae52b6a45574375d1e2ecc8e0f52a828d5..3357a92bda4e0dda8818f3589b2ee1375fca8159 100644 (file)
@@ -104,7 +104,7 @@ PRODUCT=TeleMega-v0.1
 PRODUCT_DEF=-DTELEMEGA
 IDPRODUCT=0x0023
 
-CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF)
 
 PROGNAME=telemega-v0.1
 PROG=$(PROGNAME)-$(VERSION).elf
@@ -116,16 +116,10 @@ OBJ=$(SRC:.c=.o)
 all: $(PROG) $(HEX)
 
 $(PROG): Makefile $(OBJ) altos.ld
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
-
-../altitude-pa.h: make-altitude-pa
-       nickle $< > $@
+       $(call quiet,CC) $(LDFLAGS) -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:
index 62eda4ad2192a3efb49e676cc417c62c3c4b499d..c88ff42fb056421396e69ed2b74a3cb74362ff1c 100644 (file)
@@ -106,7 +106,7 @@ PRODUCT=TeleMega-v1.0
 PRODUCT_DEF=-DTELEMEGA
 IDPRODUCT=0x0023
 
-CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF)
 
 PROGNAME=telemega-v1.0
 PROG=$(PROGNAME)-$(VERSION).elf
@@ -118,16 +118,10 @@ OBJ=$(SRC:.c=.o)
 all: $(PROG) $(HEX)
 
 $(PROG): Makefile $(OBJ) altos.ld
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
-
-../altitude-pa.h: make-altitude-pa
-       nickle $< > $@
+       $(call quiet,CC) $(LDFLAGS) -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:
index 78829fff4452aa120f084eaa03e6f9bb6f091b9a..6c84792efd28f853caced2286df9c5f2417c8bc1 100644 (file)
@@ -105,7 +105,7 @@ PRODUCT=TeleMega-v2.0
 PRODUCT_DEF=-DTELEMEGA
 IDPRODUCT=0x0023
 
-CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF)
 
 PROGNAME=telemega-v2.0
 PROG=$(PROGNAME)-$(VERSION).elf
@@ -117,16 +117,10 @@ OBJ=$(SRC:.c=.o)
 all: $(PROG) $(HEX)
 
 $(PROG): Makefile $(OBJ) altos.ld
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
-
-../altitude-pa.h: make-altitude-pa
-       nickle $< > $@
+       $(call quiet,CC) $(LDFLAGS) -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:
index b449b397accb99b2c620e8bc4169ae7a2d264670..87a59c6464ba9a5ea4aaab0c118c4e1b39253217 100644 (file)
@@ -102,7 +102,7 @@ PRODUCT=TeleMega-v3.0
 PRODUCT_DEF=-DTELEMEGA
 IDPRODUCT=0x0023
 
-CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF)
 
 PROGNAME=telemega-v3.0
 PROG=$(PROGNAME)-$(VERSION).elf
@@ -114,16 +114,10 @@ OBJ=$(SRC:.c=.o)
 all: $(PROG) $(HEX)
 
 $(PROG): Makefile $(OBJ) altos.ld
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
-
-../altitude-pa.h: make-altitude-pa
-       nickle $< > $@
+       $(call quiet,CC) $(LDFLAGS) -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:
index e0192f610721fc5221422d7ad634e55cbb1ca412..c1e220e3df54ca7a10edab50cc5c25a5c794c974 100644 (file)
@@ -93,7 +93,7 @@ PRODUCT=TeleMetrum-v2.0
 PRODUCT_DEF=-DTELEMETRUM_V_2_0
 IDPRODUCT=0x000b
 
-CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF)
 
 PROGNAME=telemetrum-v2.0
 PROG=$(PROGNAME)-$(VERSION).elf
@@ -105,16 +105,10 @@ OBJ=$(SRC:.c=.o)
 all: $(PROG) $(HEX)
 
 $(PROG): Makefile $(OBJ) altos.ld
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
-
-../altitude-pa.h: make-altitude-pa
-       nickle $< > $@
+       $(call quiet,CC) $(LDFLAGS) -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:
index 071fd8dd17f889031634365980ebcc7bff064729..68a540c48c2b31a09b504acf8b566e4d5522a9a2 100644 (file)
@@ -18,7 +18,7 @@ INC = \
        ao_kalman.h \
        ao_product.h \
        ao_ms5607.h \
-       ao_mma655x.h \
+       ao_adxl375.h \
        ao_cc1200_CC1200.h \
        ao_profile.h \
        ao_task.h \
@@ -64,7 +64,7 @@ ALTOS_SRC = \
        ao_fec_rx.c \
        ao_data.c \
        ao_ms5607.c \
-       ao_mma655x.c \
+       ao_adxl375.c \
        ao_adc_stm.c \
        ao_beep_stm.c \
        ao_storage.c \
@@ -93,7 +93,7 @@ PRODUCT=TeleMetrum-v3.0
 PRODUCT_DEF=-DTELEMETRUM_V_3_0
 IDPRODUCT=0x000b
 
-CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF)
 
 PROGNAME=telemetrum-v3.0
 PROG=$(PROGNAME)-$(VERSION).elf
@@ -105,16 +105,10 @@ OBJ=$(SRC:.c=.o)
 all: $(PROG) $(HEX)
 
 $(PROG): Makefile $(OBJ) altos.ld
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
-
-../altitude-pa.h: make-altitude-pa
-       nickle $< > $@
+       $(call quiet,CC) $(LDFLAGS) -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:
index f4ccc9f3a93b7abf342586eefa2a3c79fe30219f..68bec1be3f789066f031121b983f5d2454a39d70 100644 (file)
@@ -277,15 +277,16 @@ struct ao_adc {
 
 #define HAS_HIGHG_ACCEL                1
 
-/*
- * mma655x
- */
+/* ADXL375 */
+
+#define HAS_ADXL375            1
+#define AO_ADXL375_SPI_INDEX   (AO_SPI_1_PB3_PB4_PB5 | AO_SPI_MODE_3)
+#define AO_ADXL375_CS_PORT     (&stm_gpiob)
+#define AO_ADXL375_CS_PIN      9
+#define AO_ADXL375_SPI_SPEED   AO_SPI_SPEED_4MHz
 
-#define HAS_MMA655X            1
-#define AO_MMA655X_SPI_INDEX   AO_SPI_1_PB3_PB4_PB5
-#define AO_MMA655X_CS_PORT     (&stm_gpiob)
-#define AO_MMA655X_CS_PIN      9
-#define AO_MMA655X_INVERT      1
+#define AO_ADXL375_AXIS                x
+#define AO_ADXL375_INVERT      1
 
 #define NUM_CMDS               16
 
index d75f339df3886f2edbe3fa30dfbebbbb7b7ee7c6..148e1f708c1f0d11572333d7d26001d3d40c760e 100644 (file)
@@ -18,7 +18,7 @@
 
 #include <ao.h>
 #include <ao_ms5607.h>
-#include <ao_mma655x.h>
+#include <ao_adxl375.h>
 #include <ao_log.h>
 #include <ao_exti.h>
 #include <ao_packet.h>
@@ -52,17 +52,11 @@ main(void)
        ao_exti_init();
 
        ao_adc_init();
-#if HAS_BEEP
        ao_beep_init();
-#endif
        ao_cmd_init();
 
-#if HAS_MS5607
        ao_ms5607_init();
-#endif
-#if HAS_MMA655X
-       ao_mma655x_init();
-#endif
+       ao_adxl375_init();
 
        ao_eeprom_init();
 
index 4713b3ad62eda719f4c1053dca664d3b74687fb9..1ed25c1842358e20624c58e80a4cadc6407e1378 100644 (file)
@@ -60,7 +60,7 @@ PRODUCT=TeleMini-v3.0
 PRODUCT_DEF=-DTELEMINI_V_3_0
 IDPRODUCT=0x0027
 
-CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -g -Os
+CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS)
 
 PROGNAME=telemini-v3.0
 PROG=$(PROGNAME)-$(VERSION).elf
@@ -72,10 +72,7 @@ OBJ=$(SRC:.c=.o)
 all: $(PROG) $(HEX)
 
 $(PROG): Makefile $(OBJ)
-       $(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) > $@
+       $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS)
 
 $(OBJ): $(INC)
 
index 66f75f0ab0dc182fb523e0199aa4d0520dd374d8..bb3bc05424e2083eee81bc61cbde082a8b5a8876 100644 (file)
@@ -34,7 +34,7 @@ ao_check_recovery(void)
        ao_disable_port(AO_RECOVERY_PORT);
 }
 
-void
+int
 main(void)
 {
        ao_check_recovery();
diff --git a/src/telestatic-v3.0/.gitignore b/src/telestatic-v3.0/.gitignore
new file mode 100644 (file)
index 0000000..9f0191e
--- /dev/null
@@ -0,0 +1,2 @@
+ao_product.h
+telestatic-*.elf
diff --git a/src/telestatic-v3.0/Makefile b/src/telestatic-v3.0/Makefile
new file mode 100644 (file)
index 0000000..124b47f
--- /dev/null
@@ -0,0 +1,96 @@
+#
+# TeleStatic build file
+#
+
+include ../stm/Makefile.defs
+
+INC = \
+       ao.h \
+       ao_pins.h \
+       ao_log.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_storage.c \
+       ao_m25.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 \
+       ao_log.c \
+       ao_log_telestatic.c \
+       ao_max6691.c
+
+PRODUCT_SRC = \
+       ao_telestatic.c
+
+PRODUCT=TeleStatic-v3.0
+PRODUCT_DEF=-DTELESTATIC_V_3_0
+IDPRODUCT=0x000f
+
+# Include floating-point enabled printf
+
+NEWLIB_PRINTF_CFLAGS = 
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF)
+
+PROGNAME = telestatic-v3.0
+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) -o $(PROG) $(OBJ) $(LIBS)
+
+$(OBJ): $(INC)
+
+distclean:     clean
+
+clean:
+       rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx $(PROGNAME)-*.map
+       rm -f ao_product.h
+
+install:
+
+uninstall:
+
diff --git a/src/telestatic-v3.0/ao_pins.h b/src/telestatic-v3.0/ao_pins.h
new file mode 100644 (file)
index 0000000..aad1766
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+ * Copyright © 2019 Bdale Garbee <bdale@gag.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define 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                        1
+#define HAS_PAD                        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
+
+#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX       (512 * 1024)
+#define AO_CONFIG_MAX_SIZE                     1024
+#define LOG_ERASE_MARK                         0x55
+#define LOG_MAX_ERASE                          128
+#define AO_LOG_FORMAT                          AO_LOG_FORMAT_TELEMETRUM
+
+/* 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     0
+#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              1       /* ADS131A0X */
+#define SPI_1_PA5_PA6_PA7      1
+#define SPI_1_PB3_PB4_PB5      0
+#define SPI_1_PE13_PE14_PE15   0
+#define SPI_1_OSPEEDR          STM_OSPEEDR_10MHz
+
+#define HAS_SPI_2              1       /* CC1200 and W25Q64 */
+#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 */
+
+/*
+ * ADS131A0X analog to digital converter
+ */
+
+#define HAS_ADS131A0X                  0
+#define AO_ADS131A0X_SPI_CS_PORT       (&stm_gpioa)
+#define AO_ADS131A0X_SPI_CS_PIN                4
+#define AO_ADS131A0X_SPI_CS_MASK       (1 << AO_ADS131A0X_SPI_CS_PIN)
+#define AO_ADS131A0X_SPI_BUS           (AO_SPI_1_PA5_PA6_PA7 | AO_SPI_MODE_1)
+#define AO_ADS131A0X_SPI_SPEED         AO_SPI_SPEED_8MHz
+
+#define AO_ADS131A0X_DRDY_PORT         (&stm_gpioc)
+#define AO_ADS131A0X_DRDY_PIN          13
+
+#define AO_ADS131A0X_DONE_PORT         (&stm_gpioc)
+#define AO_ADS131A0X_DONE_PIN          14
+
+#define AO_ADS131A0X_CHANNELS          4       /* how many inputs in use */
+
+/*
+ * SPI Flash memory
+ */
+
+#define M25_MAX_CHIPS           1
+#define AO_M25_SPI_CS_PORT      (&stm_gpioa)
+#define AO_M25_SPI_CS_MASK      (1 << 1)
+#define AO_M25_SPI_BUS          AO_SPI_2_PB13_PB14_PB15
+
+/*
+ * 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   3
+#define AO_CC1200_SPI_BUS      AO_SPI_2_PB13_PB14_PB15
+#define AO_CC1200_SPI          stm_spi2
+#define AO_CC1200_SPI_SPEED    AO_SPI_SPEED_FAST
+
+#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 HAS_LED                        1
+
+#define LED_0_PORT             (&stm_gpioa)
+#define LED_0_PIN              8
+#define AO_LED_RED             (1 << 0)
+
+#define LED_1_PORT             (&stm_gpioa)
+#define LED_1_PIN              9
+#define AO_LED_AMBER           (1 << 1)
+
+#define LED_2_PORT             (&stm_gpioa)
+#define LED_2_PIN              10
+#define AO_LED_GREEN           (1 << 2)
+
+#define LED_3_PORT             (&stm_gpiob)
+#define LED_3_PIN              5
+#define AO_LED_ARMED           (1 << 3)
+
+#define LED_4_PORT             (&stm_gpiob)
+#define LED_4_PIN              6
+#define AO_LED_CONTINUITY(c)   (1 << 4)
+
+/* 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
+
+/*
+ * ADC reference in decivolts
+ */
+#define AO_ADC_REFERENCE_DV     33
+
+#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_PAD_R_V_BATT_BATT_SENSE      200
+#define AO_PAD_R_BATT_SENSE_GND         22
+
+#define AO_PAD_R_V_BATT_V_PYRO          200
+#define AO_PAD_R_V_PYRO_PYRO_SENSE      200
+#define AO_PAD_R_PYRO_SENSE_GND         22
+
+#undef AO_PAD_R_V_PYRO_IGNITER
+#define AO_PAD_R_IGNITER_IGNITER_SENSE  200
+#define AO_PAD_R_IGNITER_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))
+
+/* MAX6691 thermistor chip */
+#define HAS_MAX6691            1
+#define AO_MAX6691_GPIO                (&stm_gpiob)
+#define AO_MAX6691_PIN         3
+#define AO_MAX6691_TIMER       (&stm_tim2)
+#define AO_MAX6691_TIMER_ENABLE        STM_RCC_APB1ENR_TIM2EN
+#define AO_MAX6691_CH          2
+#define AO_MAX6691_DMA         STM_DMA_INDEX(7)
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/telestatic-v3.0/ao_telestatic.c b/src/telestatic-v3.0/ao_telestatic.c
new file mode 100644 (file)
index 0000000..7e9cd35
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_log.h>
+#include <ao_pad.h>
+#include <ao_exti.h>
+#include <ao_radio_cmac_cmd.h>
+#include <ao_eeprom.h>
+#include <ao_max6691.h>
+
+static void
+set_logging(void)
+{
+       ao_log_running = ao_cmd_hex();
+       ao_wakeup(&ao_log_running);
+}
+
+const struct ao_cmds ao_firetwo_cmds[] = {
+        { set_logging,  "L <0 off, 1 on>\0Log sensors to flash" },
+        { 0,    NULL },
+};
+
+void
+main(void)
+{
+       ao_clock_init();
+
+       ao_led_init();
+
+       ao_task_init();
+
+       ao_timer_init();
+       ao_spi_init();
+       ao_dma_init();
+       ao_exti_init();
+
+       ao_cmd_register(&ao_firetwo_cmds[0]);
+       ao_cmd_init();
+
+       ao_adc_init();
+
+       ao_max6691_init();
+
+       ao_eeprom_init();
+       ao_storage_init();
+       ao_log_init();
+
+       ao_radio_init();
+
+       ao_usb_init();
+
+       ao_config_init();
+
+       ao_pad_init();
+
+#if HAS_ADS131A0X
+       ao_ads131a0x_init();
+#endif
+
+       ao_start_scheduler();
+}
diff --git a/src/telestatic-v3.0/flash-loader/.gitignore b/src/telestatic-v3.0/flash-loader/.gitignore
new file mode 100644 (file)
index 0000000..65fe7ea
--- /dev/null
@@ -0,0 +1,2 @@
+*.elf
+*.ihx
diff --git a/src/telestatic-v3.0/flash-loader/Makefile b/src/telestatic-v3.0/flash-loader/Makefile
new file mode 100644 (file)
index 0000000..78993b4
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=telestatic-v3.0
+include $(TOPDIR)/stm/Makefile-flash.defs
diff --git a/src/telestatic-v3.0/flash-loader/ao_pins.h b/src/telestatic-v3.0/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..c8e13f6
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright © 2019 Bdale Garbee <bdale@gag.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+/* 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_gpioc
+#define AO_BOOT_APPLICATION_PIN                15
+#define AO_BOOT_APPLICATION_VALUE      1
+#define AO_BOOT_APPLICATION_MODE       AO_EXTI_MODE_PULL_UP
+
+#endif /* _AO_PINS_H_ */
index 941bf95471d1c14abfa891cd434ba951127f136c..f9cda60b183f99f8639a034217de2b6b0769b51a 100644 (file)
@@ -60,6 +60,7 @@ ao_aprs_bit(uint8_t bit)
 void
 ao_radio_send_aprs(ao_radio_fill_func fill);
 
+#if 0
 static void
 aprs_bit_debug(uint8_t tx_bit)
 {
@@ -71,8 +72,10 @@ aprs_byte_debug(uint8_t tx_byte)
 {
        fprintf(stderr, "byte %02x\n", tx_byte);
 }
+
 #define APRS_BIT_DEBUG(x) aprs_bit_debug(x)
 #define APRS_BYTE_DEBUG(y) aprs_byte_debug(y)
+#endif
 
 #include <ao_aprs.c>
 
@@ -103,6 +106,7 @@ aprs_byte_debug(uint8_t tx_byte)
 
  */
 
+#if 0
 static void
 audio_gap(int secs)
 {
@@ -113,6 +117,7 @@ audio_gap(int secs)
                ao_aprs_bit(0);
 #endif
 }
+#endif
 
 // This is where we go after reset.
 int main(int argc, char **argv)
index 6d007575c7f91d2871ce0a223f15ada7261890c9..ff480e2db9fd7ff7890ebbc46f309870c51e9c64 100644 (file)
@@ -126,6 +126,15 @@ struct ao_adc {
 #define HAS_USB 1
 #define HAS_GPS 1
 
+int16_t
+ao_time(void);
+
+void
+ao_dump_state(void);
+
+#define ao_tick_count  (ao_time())
+#define ao_wakeup(wchan) ao_dump_state()
+
 #include <ao_data.h>
 #include <ao_log.h>
 #include <ao_telemetry.h>
@@ -237,7 +246,6 @@ int ao_summary = 0;
 #define ao_led_on(l)
 #define ao_led_off(l)
 #define ao_timer_set_adc_interval(i)
-#define ao_wakeup(wchan) ao_dump_state()
 #define ao_cmd_register(c)
 #define ao_usb_disable()
 #define ao_telemetry_set_interval(x)
@@ -315,9 +323,6 @@ char *emulator_info;
 double emulator_error_max = 4;
 double emulator_height_error_max = 20; /* noise in the baro sensor */
 
-void
-ao_dump_state(void);
-
 void
 ao_sleep(void *wchan);
 
@@ -331,10 +336,6 @@ struct ao_cmds {
        const char      *help;
 };
 
-#define ao_xmemcpy(d,s,c) memcpy(d,s,c)
-#define ao_xmemset(d,v,c) memset(d,v,c)
-#define ao_xmemcmp(d,s,c) memcmp(d,s,c)
-
 #define AO_NEED_ALTITUDE_TO_PRES 1
 #if TELEMEGA || TELEMETRUM_V2 || EASYMINI
 #include "ao_convert_pa.c"
@@ -358,9 +359,6 @@ struct ao_ms5607_prom       ao_ms5607_prom;
 
 struct ao_config ao_config;
 
-#define x (x)
-
-
 extern int16_t ao_ground_accel, ao_flight_accel;
 extern int16_t ao_accel_2g;
 
@@ -654,6 +652,7 @@ ao_insert(void)
 #if TELEMEGA
                               " angle %5d "
                               "accel_x %8.3f accel_y %8.3f accel_z %8.3f gyro_x %8.3f gyro_y %8.3f gyro_z %8.3f mag_x %8d mag_y %8d, mag_z %8d mag_angle %4d "
+                              "avg_accel %8.3f "
 #endif
                               "\n",
                               time,
@@ -680,7 +679,8 @@ ao_insert(void)
                               ao_data_static.hmc5883.x,
                               ao_data_static.hmc5883.y,
                               ao_data_static.hmc5883.z,
-                              ao_mag_angle
+                              ao_mag_angle,
+                              ao_coast_avg_accel / 16.0
 #endif
                                );
 #endif
index 8a1293d2f0627e0b93f210f6bbfa7f41c598a71a..015fea7fcdc81c2d55f09b8883a706f64218d797 100644 (file)
@@ -84,7 +84,7 @@ PRODUCT=TMGPS-v2.0
 PRODUCT_DEF=-DTMGPS_V_2_0
 IDPRODUCT=0x0025
 
-CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF)
 
 PROGNAME=tmgps-v2.0
 PROG=$(PROGNAME)-$(VERSION).elf
index 327614bc7ebf9155268e62ec74b8350df4a0423e..f8e47a3f67369c530d7a86f97c164f3b75d51688 100644 (file)
@@ -35,7 +35,7 @@ PRODUCT=VidTime
 PRODUCT_DEF=-DVIDTIME
 IDPRODUCT=0x002b
 
-CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -Os -g
+CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS)
 
 PROGNAME=vidtime-v1.0
 PROG=$(PROGNAME)-$(VERSION).elf
index 3443b288142d9b28ee407a94440aaee2e8fae301..0e75abf1480996fadb88763f938a99d4d4173a2f 100644 (file)
@@ -1,5 +1,5 @@
 JAVAROOT=classes
-AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked -source 6
+AM_JAVACFLAGS=$(JAVAC_VERSION_FLAGS) -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked
 
 man_MANS=telegps.1
 
@@ -227,12 +227,18 @@ $(JAR): classtelegps.stamp Manifest.txt $(JAVA_ICONS) $(ALTOSLIB_CLASS) $(ALTOSU
                $(ICONJAR) \
                -C classes org \
                -C ../libaltos libaltosJNI
+if STRIP_NONDETERMINISM
+       $(STRIP_NONDETERMINISM) $@
+endif
 
 $(FATJAR): classtelegps.stamp Manifest-fat.txt $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(JAVA_ICONS)
        jar cfm $@ Manifest-fat.txt \
                $(ICONJAR) \
                -C classes org \
                -C ../libaltos libaltosJNI
+if STRIP_NONDETERMINISM
+       $(STRIP_NONDETERMINISM) $@
+endif
 
 libaltos.so: build-libaltos
        -rm -f "$@"
index 24cc379fcec9a1879068d5154de8fcfc60c3c4fb..5df47202067e805c6467af2d40ada4628c725fd8 100644 (file)
@@ -307,26 +307,14 @@ public class TeleGPS
        void graph() {
                AltosDataChooser chooser = new AltosDataChooser(this);
                AltosRecordSet set = chooser.runDialog();
-               if (set == null)
-                       return;
-               try {
-                       new TeleGPSGraphUI(set, chooser.file());
-               } catch (InterruptedException ie) {
-               } catch (IOException ie) {
-               }
+               graph_file(this, set, chooser.file());
        }
 
        public void graph_flights(AltosEepromList list) {
                for (AltosEepromLog log : list) {
                        if (log.file != null) {
                                AltosRecordSet set = record_set(log.file);
-                               if (set != null) {
-                                       try {
-                                               new TeleGPSGraphUI(set, log.file);
-                                       } catch (InterruptedException ie) {
-                                       } catch (IOException ie) {
-                                       }
-                               }
+                               graph_file(this, set, log.file);
                        }
                }
        }
@@ -650,18 +638,32 @@ public class TeleGPS
                return new AltosReplayReader(set, file);
        }
 
-       static boolean process_graph(File file) {
-               AltosRecordSet set = record_set(file);
+       private static boolean graph_file(TeleGPS telegps, AltosRecordSet set, File file) {
                if (set == null)
                        return false;
+               if (!set.valid()) {
+                       JOptionPane.showMessageDialog(telegps,
+                                                     String.format("Failed to parse file %s", file),
+                                                     "Graph Failed",
+                                                     JOptionPane.ERROR_MESSAGE);
+                       return false;
+               }
                try {
                        new TeleGPSGraphUI(set, file);
-               } catch (Exception e) {
+               } catch (IOException e) {
+                       System.out.printf("Exception %s\n", e.toString());
+               } catch (InterruptedException e) {
+                       System.out.printf("Exception %s\n", e.toString());
                        return false;
                }
                return true;
        }
 
+       static boolean process_graph(File file) {
+               AltosRecordSet set = record_set(file);
+               return graph_file(null, set, file);
+       }
+
        static boolean process_replay(File file) {
                AltosReplayReader new_reader = replay_file(file);
                if (new_reader == null)
index 5d4fc9cf8be5137500ada48aaa7d0cf867876fe0..b5a135c59d3ad3e90a1cf10b9914753125e63d2c 100644 (file)
@@ -49,6 +49,7 @@ public class TeleGPSGraphUI extends AltosUIFrame implements AltosFontListener, A
        void fill_map(AltosFlightSeries flight_series) {
                boolean                 any_gps = false;
                AltosGPSTimeValue       gtv_last = null;
+               double gps_pad_altitude = flight_series.cal_data().gps_pad_altitude;;
 
                if (flight_series.gps_series != null) {
                        for (AltosGPSTimeValue gtv : flight_series.gps_series) {
@@ -59,7 +60,9 @@ public class TeleGPSGraphUI extends AltosUIFrame implements AltosFontListener, A
                                    gps.nsat >= 4) {
                                        if (map == null)
                                                map = new AltosUIMap();
-                                       map.show(gps, (int) flight_series.value_before(AltosFlightSeries.state_name, gtv.time));
+                                       double gps_height = gps.alt - gps_pad_altitude;
+                                       int state = (int) flight_series.value_before(AltosFlightSeries.state_name, gtv.time);
+                                       map.show(gps, gtv.time, state, gps_height);
                                        this.gps = gps;
                                        has_gps = true;
                                }
@@ -67,8 +70,9 @@ public class TeleGPSGraphUI extends AltosUIFrame implements AltosFontListener, A
                }
                if (gtv_last != null) {
                        int state = (int) flight_series.value_after(AltosFlightSeries.state_name, gtv_last.time);
+                       double gps_height = gps.alt - gps_pad_altitude;
                        if (state == AltosLib.ao_flight_landed)
-                               map.show(gtv_last.gps, state);
+                               map.show(gtv_last.gps, gtv_last.time, state, gps_height);
                }
        }
 
@@ -113,17 +117,19 @@ public class TeleGPSGraphUI extends AltosUIFrame implements AltosFontListener, A
                super(file.getName());
                AltosCalData cal_data = set.cal_data();
 
+               pane = new JTabbedPane();
+
                flight_series = new AltosUIFlightSeries(cal_data);
-               set.capture_series(flight_series);
-               flight_series.finish();
 
-               pane = new JTabbedPane();
+               enable = new AltosUIEnable(this);
 
-               graph = new AltosGraph(enable, stats, flight_series);
+               set.capture_series(flight_series);
+
+               flight_series.finish();
 
                stats = new AltosFlightStats(flight_series);
 
-               enable = new AltosUIEnable(this);
+               graph = new AltosGraph(enable, stats, flight_series);
 
                statsTable = new AltosFlightStatsTable(stats);