Merge branch 'branch-1.6' into debian
authorBdale Garbee <bdale@gag.com>
Sun, 8 Feb 2015 05:39:54 +0000 (22:39 -0700)
committerBdale Garbee <bdale@gag.com>
Sun, 8 Feb 2015 05:39:54 +0000 (22:39 -0700)
Conflicts:
ChangeLog
altoslib/AltosTelemetryReader.java
configure.ac

380 files changed:
ChangeLog
Makefile.am
Releasing
altosdroid/AndroidManifest.xml
altosdroid/Makefile.am
altosdroid/Notebook
altosdroid/release-note-1.5 [new file with mode: 0644]
altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java
altosdroid/src/org/altusmetrum/AltosDroid/TabAscent.java
altosdroid/src/org/altusmetrum/AltosDroid/TabDescent.java
altosdroid/src/org/altusmetrum/AltosDroid/TabLanded.java
altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java
altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java
altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java
altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java
altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java
altosdroid/src/org/altusmetrum/AltosDroid/TelemetryState.java
altoslib/AltosAccel.java
altoslib/AltosCRCException.java
altoslib/AltosCSV.java
altoslib/AltosCompanion.java
altoslib/AltosConfigData.java
altoslib/AltosConfigDataException.java
altoslib/AltosConfigValues.java
altoslib/AltosConvert.java
altoslib/AltosDebug.java
altoslib/AltosDistance.java
altoslib/AltosEeprom.java
altoslib/AltosEepromChunk.java
altoslib/AltosEepromDownload.java
altoslib/AltosEepromFile.java
altoslib/AltosEepromGPS.java
altoslib/AltosEepromHeader.java
altoslib/AltosEepromIterable.java
altoslib/AltosEepromList.java
altoslib/AltosEepromLog.java
altoslib/AltosEepromMega.java
altoslib/AltosEepromMetrum2.java
altoslib/AltosEepromMini.java
altoslib/AltosEepromMonitor.java
altoslib/AltosEepromTM.java
altoslib/AltosEepromTm.java
altoslib/AltosFile.java
altoslib/AltosFlash.java
altoslib/AltosFlashListener.java
altoslib/AltosFlightReader.java
altoslib/AltosFlightStats.java
altoslib/AltosFrequency.java
altoslib/AltosGPS.java
altoslib/AltosGPSSat.java
altoslib/AltosGreatCircle.java
altoslib/AltosHeight.java
altoslib/AltosHexfile.java
altoslib/AltosHexsym.java
altoslib/AltosIMU.java
altoslib/AltosIdle.java
altoslib/AltosIdleFetch.java
altoslib/AltosIdleMonitor.java
altoslib/AltosIdleMonitorListener.java
altoslib/AltosIgnite.java
altoslib/AltosKML.java
altoslib/AltosLatitude.java
altoslib/AltosLib.java
altoslib/AltosLine.java
altoslib/AltosLink.java
altoslib/AltosListenerState.java
altoslib/AltosLocation.java
altoslib/AltosLog.java
altoslib/AltosLongitude.java
altoslib/AltosMag.java
altoslib/AltosMma655x.java
altoslib/AltosMs5607.java
altoslib/AltosNoSymbol.java
altoslib/AltosOrient.java
altoslib/AltosParse.java
altoslib/AltosPreferences.java
altoslib/AltosPreferencesBackend.java
altoslib/AltosProgrammer.java
altoslib/AltosPyro.java
altoslib/AltosQuaternion.java [new file with mode: 0644]
altoslib/AltosReplayReader.java
altoslib/AltosRomconfig.java
altoslib/AltosRotation.java [new file with mode: 0644]
altoslib/AltosSavedState.java [new file with mode: 0644]
altoslib/AltosSelfFlash.java
altoslib/AltosSensorEMini.java
altoslib/AltosSensorMM.java
altoslib/AltosSensorMega.java
altoslib/AltosSensorMetrum.java
altoslib/AltosSensorTGPS.java [new file with mode: 0644]
altoslib/AltosSensorTM.java
altoslib/AltosSensorTMini.java
altoslib/AltosSpeed.java
altoslib/AltosState.java
altoslib/AltosStateIterable.java
altoslib/AltosStateUpdate.java
altoslib/AltosTelemetry.java
altoslib/AltosTelemetryConfiguration.java
altoslib/AltosTelemetryFile.java
altoslib/AltosTelemetryIterable.java
altoslib/AltosTelemetryLegacy.java
altoslib/AltosTelemetryLocation.java
altoslib/AltosTelemetryMap.java
altoslib/AltosTelemetryMegaData.java
altoslib/AltosTelemetryMegaSensor.java
altoslib/AltosTelemetryMetrumData.java
altoslib/AltosTelemetryMetrumSensor.java
altoslib/AltosTelemetryMini.java
altoslib/AltosTelemetryRaw.java
altoslib/AltosTelemetryReader.java
altoslib/AltosTelemetrySatellite.java
altoslib/AltosTelemetrySensor.java
altoslib/AltosTelemetryStandard.java
altoslib/AltosTemperature.java
altoslib/AltosUnits.java
altoslib/AltosUnitsListener.java
altoslib/AltosVoltage.java
altoslib/AltosWriter.java
altoslib/Makefile.am
altosui/.gitignore
altosui/Altos.java
altosui/AltosAscent.java
altosui/AltosCompanionInfo.java
altosui/AltosConfig.java
altosui/AltosConfigPyroUI.java
altosui/AltosConfigTD.java
altosui/AltosConfigTDUI.java
altosui/AltosConfigUI.java
altosui/AltosConfigureUI.java
altosui/AltosDescent.java
altosui/AltosFlightStatus.java
altosui/AltosFlightStatusTableModel.java
altosui/AltosFlightStatusUpdate.java
altosui/AltosFlightUI.java
altosui/AltosGraphUI.java
altosui/AltosIdleMonitorUI.java
altosui/AltosIgniteUI.java
altosui/AltosIgnitor.java
altosui/AltosLanded.java
altosui/AltosLaunch.java
altosui/AltosLaunchUI.java
altosui/AltosPad.java
altosui/AltosUI.java
altosui/AltosUIPreferencesBackend.java [deleted file]
altosui/Instdrv/NSIS/Includes/java.nsh
altosui/Makefile.am
altosui/altos-windows.nsi.in
altosuilib/AltosBTDevice.java
altosuilib/AltosBTDeviceIterator.java
altosuilib/AltosBTKnown.java
altosuilib/AltosBTManage.java
altosuilib/AltosCSVUI.java
altosuilib/AltosConfigFreqUI.java
altosuilib/AltosDataChooser.java
altosuilib/AltosDevice.java
altosuilib/AltosDeviceDialog.java
altosuilib/AltosDeviceUIDialog.java
altosuilib/AltosDisplayThread.java
altosuilib/AltosEepromDelete.java
altosuilib/AltosEepromManage.java
altosuilib/AltosEepromMonitor.java
altosuilib/AltosEepromMonitorUI.java
altosuilib/AltosEepromSelect.java
altosuilib/AltosFlashUI.java
altosuilib/AltosFlightDisplay.java
altosuilib/AltosFlightInfoTableModel.java
altosuilib/AltosFlightStatsTable.java
altosuilib/AltosFontListener.java
altosuilib/AltosGraph.java
altosuilib/AltosGraphDataPoint.java
altosuilib/AltosGraphDataSet.java
altosuilib/AltosInfoTable.java
altosuilib/AltosLed.java
altosuilib/AltosLights.java
altosuilib/AltosPositionListener.java
altosuilib/AltosRomconfigUI.java
altosuilib/AltosScanUI.java
altosuilib/AltosSerial.java
altosuilib/AltosSerialInUseException.java
altosuilib/AltosUIAxis.java
altosuilib/AltosUIConfigure.java
altosuilib/AltosUIDataMissing.java
altosuilib/AltosUIDataPoint.java
altosuilib/AltosUIDataSet.java
altosuilib/AltosUIDialog.java
altosuilib/AltosUIEnable.java
altosuilib/AltosUIFlightTab.java
altosuilib/AltosUIFrame.java
altosuilib/AltosUIFreqList.java
altosuilib/AltosUIGraph.java
altosuilib/AltosUIGrapher.java
altosuilib/AltosUIIndicator.java
altosuilib/AltosUILatLon.java
altosuilib/AltosUILib.java
altosuilib/AltosUIListener.java
altosuilib/AltosUIMap.java
altosuilib/AltosUIMapCache.java
altosuilib/AltosUIMapCacheListener.java
altosuilib/AltosUIMapImage.java
altosuilib/AltosUIMapLine.java
altosuilib/AltosUIMapMark.java
altosuilib/AltosUIMapPath.java
altosuilib/AltosUIMapPreload.java
altosuilib/AltosUIMapRectangle.java
altosuilib/AltosUIMapStore.java
altosuilib/AltosUIMapStoreListener.java
altosuilib/AltosUIMapTile.java
altosuilib/AltosUIMapTileListener.java
altosuilib/AltosUIMapTransform.java
altosuilib/AltosUIMapView.java
altosuilib/AltosUIMapZoomListener.java
altosuilib/AltosUIMarker.java
altosuilib/AltosUIPreferences.java
altosuilib/AltosUIPreferencesBackend.java
altosuilib/AltosUIRateList.java
altosuilib/AltosUISeries.java
altosuilib/AltosUITelemetryList.java
altosuilib/AltosUIUnitsIndicator.java
altosuilib/AltosUIVersion.java.in
altosuilib/AltosUIVoltageIndicator.java
altosuilib/AltosUSBDevice.java
altosuilib/AltosVoice.java
altosuilib/GrabNDrag.java
altosuilib/OSXAdapter.java
ao-bringup/cal-freq
ao-bringup/cal-freq-file [new file with mode: 0755]
ao-bringup/test-easymega
ao-bringup/test-easymini
ao-bringup/test-igniters [new file with mode: 0755]
ao-bringup/test-telegps
ao-bringup/test-telemega [new file with mode: 0755]
ao-bringup/test-telemetrum [new file with mode: 0755]
ao-bringup/turnon_teledongle
ao-bringup/turnon_teledonglev3 [new file with mode: 0755]
ao-bringup/turnon_telemega
ao-bringup/turnon_telemetrum
ao-tools/Makefile.am
ao-tools/ao-send-telem/ao-send-telem.c
ao-tools/ao-test-gps/.gitignore [new file with mode: 0644]
ao-tools/ao-test-gps/Makefile.am [new file with mode: 0644]
ao-tools/ao-test-gps/ao-test-gps.1 [new file with mode: 0644]
ao-tools/ao-test-gps/ao-test-gps.c [new file with mode: 0644]
ao-tools/ao-test-igniter/ao-test-igniter.c
ao-tools/ao-usbload/ao-usbload.c
ao-tools/ao-usbtrng/.gitignore [new file with mode: 0644]
ao-tools/ao-usbtrng/Makefile.am [new file with mode: 0644]
ao-tools/ao-usbtrng/ao-usbtrng.1 [new file with mode: 0644]
ao-tools/ao-usbtrng/ao-usbtrng.c [new file with mode: 0644]
ao-tools/lib/cc-usb.c
ao-tools/lib/cc-usb.h
configure.ac
doc/Makefile
doc/altusmetrum.xsl
doc/release-notes-1.6.xsl [new file with mode: 0644]
doc/telegps.xsl
libaltos/libaltos.c
micropeak/MicroData.java
micropeak/MicroDataPoint.java
micropeak/MicroDeviceDialog.java
micropeak/MicroDownload.java
micropeak/MicroExport.java
micropeak/MicroFile.java
micropeak/MicroFileChooser.java
micropeak/MicroFrame.java
micropeak/MicroGraph.java
micropeak/MicroPeak.java
micropeak/MicroRaw.java
micropeak/MicroSave.java
micropeak/MicroSerial.java
micropeak/MicroSerialLog.java
micropeak/MicroStats.java
micropeak/MicroStatsTable.java
micropeak/MicroUSB.java
micropeak/micropeak-windows.nsi.in
src/.gitignore
src/Makefile
src/attiny/ao_arch.h
src/avr/ao_arch.h
src/cc1111/ao_arch.h
src/drivers/ao_btm.c
src/drivers/ao_cc1120.c
src/drivers/ao_cc115l.c
src/drivers/ao_cc1200.c [new file with mode: 0644]
src/drivers/ao_cc1200.h [new file with mode: 0644]
src/drivers/ao_cc1200_CC1200.h [new file with mode: 0644]
src/drivers/ao_packet_master.c
src/easymini-v1.0/ao_pins.h
src/kernel/ao.h
src/kernel/ao_config.c
src/kernel/ao_gps_print.c
src/kernel/ao_log.h
src/kernel/ao_monitor.c
src/kernel/ao_serial.h
src/kernel/ao_stdio.c
src/kernel/ao_telemetry.c
src/kernel/ao_telemetry.h
src/kernel/ao_tracker.c
src/lpc/ao_arch.h
src/lpc/ao_arch_funcs.h
src/lpc/ao_led_lpc.c
src/lpc/ao_spi_lpc.c
src/lpc/ao_usb_lpc.c
src/microsplash/.gitignore [new file with mode: 0644]
src/microsplash/Makefile [new file with mode: 0644]
src/microsplash/ao_pins.h [new file with mode: 0644]
src/microwater/.gitignore [deleted file]
src/microwater/Makefile [deleted file]
src/microwater/ao_pins.h [deleted file]
src/stm/ao_arch_funcs.h
src/stm/ao_led.c
src/stm/ao_serial_stm.c
src/stm/ao_spi_stm.c
src/stmf0/Makefile-flash.defs [new file with mode: 0644]
src/stmf0/Makefile-stmf0.defs [new file with mode: 0644]
src/stmf0/Makefile.defs [new file with mode: 0644]
src/stmf0/altos-loader.ld [new file with mode: 0644]
src/stmf0/altos.ld [new file with mode: 0644]
src/stmf0/ao_adc_fast.c [new file with mode: 0644]
src/stmf0/ao_adc_fast.h [new file with mode: 0644]
src/stmf0/ao_arch.h [new file with mode: 0644]
src/stmf0/ao_arch_funcs.h [new file with mode: 0644]
src/stmf0/ao_boot_chain.c [new file with mode: 0644]
src/stmf0/ao_boot_pin.c [new file with mode: 0644]
src/stmf0/ao_crc.h [new file with mode: 0644]
src/stmf0/ao_dma_stm.c [new file with mode: 0644]
src/stmf0/ao_flash.h [new file with mode: 0644]
src/stmf0/ao_flash_loader_stm.c [new file with mode: 0644]
src/stmf0/ao_flash_stm.c [new file with mode: 0644]
src/stmf0/ao_flash_stm_pins.h [new file with mode: 0644]
src/stmf0/ao_interrupt.c [new file with mode: 0644]
src/stmf0/ao_led.c [new file with mode: 0644]
src/stmf0/ao_romconfig.c [new file with mode: 0644]
src/stmf0/ao_timer.c [new file with mode: 0644]
src/stmf0/ao_usb_stm.c [new file with mode: 0644]
src/stmf0/registers.ld [new file with mode: 0644]
src/stmf0/stm32f0.h [new file with mode: 0644]
src/telebt-v3.0/Makefile [new file with mode: 0644]
src/telebt-v3.0/ao_pins.h [new file with mode: 0644]
src/telebt-v3.0/ao_telebt.c [new file with mode: 0644]
src/telebt-v3.0/flash-loader/Makefile [new file with mode: 0644]
src/telebt-v3.0/flash-loader/ao_pins.h [new file with mode: 0644]
src/teledongle-v1.8/.gitignore [new file with mode: 0644]
src/teledongle-v1.8/Makefile [new file with mode: 0644]
src/teledongle-v1.8/ao_pins.h [new file with mode: 0644]
src/teledongle-v1.8/ao_teledongle.c [new file with mode: 0644]
src/teledongle-v3.0/.gitignore [new file with mode: 0644]
src/teledongle-v3.0/Makefile [new file with mode: 0644]
src/teledongle-v3.0/ao_pins.h [new file with mode: 0644]
src/teledongle-v3.0/ao_teledongle.c [new file with mode: 0644]
src/teledongle-v3.0/flash-loader/Makefile [new file with mode: 0644]
src/teledongle-v3.0/flash-loader/ao_pins.h [new file with mode: 0644]
src/test/.gitignore
src/test/ao_flight_test.c
src/test/ao_gps_test_ublox.c
src/usbtrng-v2.0/.gitignore [new file with mode: 0644]
src/usbtrng-v2.0/Makefile [new file with mode: 0644]
src/usbtrng-v2.0/ao_pins.h [new file with mode: 0644]
src/usbtrng-v2.0/ao_usbtrng.c [new file with mode: 0644]
src/usbtrng-v2.0/flash-loader/.gitignore [new file with mode: 0644]
src/usbtrng-v2.0/flash-loader/Makefile [new file with mode: 0644]
src/usbtrng-v2.0/flash-loader/ao_pins.h [new file with mode: 0644]
src/usbtrng/ao_pins.h
src/usbtrng/ao_usbtrng.c
telegps/Makefile.am
telegps/TeleGPS.java
telegps/TeleGPSConfig.java
telegps/TeleGPSConfigUI.java
telegps/TeleGPSDisplayThread.java
telegps/TeleGPSGraphUI.java
telegps/TeleGPSInfo.java
telegps/TeleGPSPreferences.java
telegps/TeleGPSState.java
telegps/TeleGPSStatus.java
telegps/TeleGPSStatusUpdate.java
telegps/telegps-windows.nsi.in

index 6c4f1dd9000380204560784b4e44fbee51f27b52..c4808abd6781f5a697024f4983cf636d80c2f58c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
-commit d16e60858427bf7dbe83a858728ebf097a09207a
+commit 26f61380ce6b4df80fa0b5a8a242cef79d5ae339
 Author: Bdale Garbee <bdale@gag.com>
-Date:   Sat Sep 13 11:29:19 2014 -0600
+Date:   Sat Feb 7 22:23:38 2015 -0700
 
-    ignore cal_values file in bringup directory
+    document addition of TeleDongle to the set of ARM targets to save binaries for
 
-commit 40885ae5e6be66faf08cdb9b481d1d998856ca4b
+commit 4231d68bae69d9a7d1f52205002db452cd5f986d
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Feb 7 20:42:15 2015 -0800
+
+    Bump java library versions
+    
+    Lots of minor API/ABI changes; make sure people can install both 1.5
+    and 1.6 at the same time.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c72d83ccd207b5300a90f2e84de6c5c96642478c
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Feb 7 20:36:10 2015 -0800
+
+    altosuilib: Don't offer to graph some GPS details that TM doesn't log
+    
+    When using a TM eeprom file, various minor GPS details are logged
+    (course, ground speed, climb rate, etc). Make sure these aren't
+    offered up for graphing.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 426bacbbd6e0573b143e7c48d71db977e53181fc
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Feb 7 20:22:19 2015 -0800
+
+    altosuilib: Get the Eeprom download progress bar working again
+    
+    The eeprom download code wasn't computing the start of each state
+    transition correctly, so the progress bar was snapping to the end of
+    the chunk for each state.
+    
+    Invalid state values would snap the bar to the right side.
+    
+    Landed state wasn't ever seen, so the bar would not ever fill.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit aea188e4227993c508c7045d02f2bc87abd4e428
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Feb 7 18:10:34 2015 -0800
+
+    doc: update 1.6 release notes with recent bug fixes
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0dd733efdbb66535889aafecbba45f49266ed886
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Feb 7 17:49:39 2015 -0800
+
+    altosuilib: Set the icon and title of the telemetry scanning dialog
+    
+    Just need to call 'super' to get the window configured correctly.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9d5a6914982a29d22103e0202735c9e01ee9e831
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Feb 7 17:35:15 2015 -0800
+
+    altoslib: Clear saved TelemetryReader state instead of resetting in ScanUI
+    
+    Instead of attempting to mash the saved state from AltosScanUI, just
+    throw it away in AltosTelemetryReader.reset. Much cleaner, and more reliable.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit cbc9ecd960d0dd27a2275b4550c30c5c88ccf5bb
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Feb 7 17:09:40 2015 -0800
+
+    altosuilib: Reset telemetry state after processing it
+    
+    This avoids re-using stale state after switching telemetry reception
+    parameters around, which otherwise generates spurious entries for the
+    wrong frequencies in the scan results list.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c0ce45100dd205f59cd84465138c74d9b31df0bb
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Feb 7 17:08:03 2015 -0800
+
+    altoslib: Drop telemetry packets processed while monitoring is disabled
+    
+    A lag between the thread queuing telemetry packets and one pulling
+    them out can result in stale telemetry data being returned to the
+    reader. Fix this by dropping telemetry read while monitoring is disabled.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8a2be4d36a3b116d82529805430c5fb665688267
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Feb 7 15:09:57 2015 -0800
+
+    altosuilib: Wait for product data while scanning
+    
+    Now that Altos only sends config information once every 5 seconds, we
+    want to keep waiting for that if we're receiving packets successfully.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e70f3dca01b15b75b0b8795eb71bd12817af4800
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Feb 7 14:43:11 2015 -0800
+
+    altoslib: Mark listener as 'not running' on EOF.
+    
+    This adds a 'running' member to the AltosListenerState class, and when
+    the replay reader reaches EOF, marks the listener as no longer
+    running.
+    
+    AltosUI and TeleGPS now display 'done' in the 'Age' field when this
+    occurs, to let the user know that the replay is over.
+    
+    Also make sure that the display timers are stopped when this happens,
+    or when the window is closed.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 08f07d0af123e1c307bc4c0c973da07fae8246b1
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Feb 7 14:40:17 2015 -0800
+
+    altosui: Remove the dregs of AltosDroid load-old-telem code
+    
+    AltosDroid used to scan the old .telem file to return to the previous
+    flight state on restart. Now it just loads the old state object
+    instead, a vast improvement in performance.
+    
+    To do that, there were some changes in the altoslib code
+    required. This patch just removes those, fixing replay bugs in TeleGPS
+    along the way.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0d08c427188f7b748d9ea7651143bc843e9c2691
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Feb 7 13:09:18 2015 -0800
+
+    altos: ao_packet_getchar needs to return 'int' so AO_READ_AGAIN works
+    
+    With ao_packet_getchar returning 'char', AO_READ_AGAIN would get
+    converted to 0xff instead of -1 on return, making ao_packet_echo
+    either produce a bogus character on output, breaking command
+    responses, or wedge and never exit when the link was dropped.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4a5c64bef6952f25cadebc3e1f9909a5f513e015
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Feb 7 02:37:36 2015 -0800
+
+    Update version 1.6 release notes with more bug fixes
+    
+    A few bugs found during release testing are notable enough to be
+    included in the release notes.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 211cb482e4da04dc032432abc236ef8b5a5e732f
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Feb 7 01:30:21 2015 -0800
+
+    altos: Separate out ao_tracker force from dbg
+    
+    Allow enabling telemetry when USB is connected without also enabling
+    the motion debugging output.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f9f235bce84df3a6c0261e9d256aac544f87f70f
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Feb 7 01:05:57 2015 -0800
+
+    altos/lpc: Give up on interrupt-driven SPI driver
+    
+    There are just too many limitations in when interrupts are delivered
+    to make them useful. Instead, just drive the SPI directly with the
+    CPU. At higher spi speeds (6Mhz or more), it's probably faster to do
+    it this way anyways.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4b52f67abd0f9ed6d8208556007d75e7ee735cf0
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Feb 7 01:05:03 2015 -0800
+
+    altos/drivers: Increase SPI speed of CC115L to 6MHz
+    
+    The datasheet says that the maximum for back-to-back data is 6.5MHz.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ba22e2dbf87b139f0349f4dd8a7e6046514f5bad
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Feb 6 23:50:49 2015 -0800
+
+    altoslib: Initialize GPS data to MISSING for Monitor Idle mode
+    
+    Make sure any un-set values are flagged correctly for the Monitor Idle
+    UI by using the init() method.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 31fd32cd75f4f22458f0dc82823934672e16b988
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Feb 6 21:50:47 2015 -0800
+
+    altoslib: Use 'stateless' for Monitor Idle
+    
+    This reflects the lack of flight state progression during Monitor Idle
+    and ensures that the GPS 'ready' indicator will light after 10 solid
+    GPS fixes.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 449c6731b1977c7623dd006ec2db56f383f8d85a
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Feb 6 20:45:28 2015 -0800
+
+    altoslib: Support TeleGPS for Monitor Idle
+    
+    TeleGPS has ADC and GPS values, so build the necessary ADC parser and
+    then hook up GPS parsing.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 58f06706383418ebfa56d88ba51411e6185e09df
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Feb 6 20:40:05 2015 -0800
+
+    altosuilib: Don't show 'Sats in view' for TeleGPS eeprom graphing
+    
+    We don't log the visible sats from TeleGPS, only the basic GPS
+    info. Have AltosFlightStats track whether sat info is present, then
+    use that to elide the Sats In View graph entry as needed.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 35ad1833b10595564de84c88f44a214b1c134ccf
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Feb 6 20:36:44 2015 -0800
+
+    altosuilib: EEProm download from TeleGPS doesn't have states
+    
+    As TeleGPS doesn't have flight states, the EEProm download progress
+    bar shouldn't show 'state invalid', and it should use a different
+    scale for each block.
+    
+    Fix this by having AltosConfigData know which devices have state based
+    on their log format, then mark the progress bar state limits as
+    'invalid/invalid' instead of 'boost/landed'. Then have the progress
+    bar use that to set a more reasonable scale for each block.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 66e7a8081c07d0d96a31ae34963d430f06dccdfb
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Feb 6 04:45:17 2015 -0800
+
+    altoslib: Store MS5607 data in AltosConfigData for use by AltosMs5607
+    
+    When doing 'Monitor Idle', we fetch new config data each iteration and
+    pass that to each of the readers, including ms5607. Instead of
+    re-fetching the config data there, just store the ms5607 parameters
+    when we fetch it the first time and copy it over.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 14d524782af4f06d7f3722dcc852772ec493c2cc
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Feb 6 03:36:10 2015 -0800
+
+    Package TeleDongle-v3.0 firmware with TeleGPS and AltosUI apps
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit df47839824dd4e708c22fbf8f4a3054b9c45b9c3
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Feb 6 03:34:30 2015 -0800
+
+    altosuilib: New teledongle and telebt devices are not pair-programmed
+    
+    Only list telebt-v1 and teledongle-v0 as pair-programmed devices so
+    that newer versions go through the self-programming process
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 21ff52befb27decc4b23458315620c47d7a07b21
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Feb 6 03:33:28 2015 -0800
+
+    micropeak: Install Windows AltusMetrum driver bits
+    
+    Make AltOS-based µPUSB devices work with MicroPeak
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a3f26f6d0c7574b8cdaecbccd7cfe89aaeb736b0
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Feb 6 03:32:27 2015 -0800
+
+    micropeak: Support both FTDI and Altus Metrum USB IDs
+    
+    The windows driver only returns FTDI devices when
+    altos_ftdi_list_start is invoked, so we need to call both that and the
+    regular altos_list_start to get all of the devices.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit cc707432c6eaedb9587bb63ac570146b356b6bfd
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Feb 6 03:31:07 2015 -0800
+
+    micropeak: Fix file association registry install on Windows
+    
+    Need to invoke DisableX64FSRedirection before setting file association
+    registry entries or Windows won't find our application.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1fc5c8625f649b43d93f23a5fa1ba16773f2d0db
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Feb 6 03:03:58 2015 -0800
+
+    windows: Look for current Java version in \SOFTWARE\Wow6432Node
+    
+    I have no idea what this is, but I found the Java version down in
+    there...
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 83d3d967f576a57285d40e77c4a17303edeef4f1
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Feb 6 03:03:00 2015 -0800
+
+    Add 'keithp-fat' target for uploading temporary builds to keithp's machine
+    
+    This lets me quickly prepare a new test version for Windows/Mac in a
+    single command.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7a7d60d72e2e742fbc364489721f356806966c03
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Feb 6 01:29:56 2015 -0800
+
+    libaltos: Use more SetupDi API to get Windows 7 listing devices
+    
+    My Windows 7 box doesn't include 'SymbolicName' in the registry, but
+    SetupDiGetDeviceInstanceId *does* return something that includes
+    vid/pid/serial, so use that in preference.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 98db372758470cdaf7b517d670a7ce9186c787bc
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Feb 5 22:25:35 2015 -0800
+
+    Update docs for 1.6
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9fac8b639d2142c90eb95771cda1f6559e987db2
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Jan 16 22:09:26 2015 +1300
+
+    altos/lpc: Double buffer USB data transfers
+    
+    This allocates twice the space in the USB memory so that transactions
+    can be double buffered without using separate CPU memory.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+    
+    Conflicts:
+       src/lpc/ao_usb_lpc.c
+
+commit 0671b3c8c24c9f33be77a10315c4669f33c516d7
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Feb 5 16:08:44 2015 -0800
+
+    altos/lpc: Clean up USB endpoint access functions
+    
+    The USB device endpoints can have two pointers in them, but we use
+    only the first. Fix the access functions to take an index as to which
+    we want so that we can disable the other address registers with them
+    instead of requiring open-coded access.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a01ce949611b0c18df54c3f3877a43d27699c258
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Feb 5 15:34:05 2015 -0800
+
+    altos/easymini-v1.0: Shrink stack to deal with USB changes
+    
+    Reverting the USB double buffering means using more RAM, need to
+    shrink the EasyMini stack to accomodate that.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2bde76fe852d7908a968168580be4cd4dc0333d6
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Feb 5 15:01:03 2015 -0800
+
+    altos/teledongle-v3.0: Shrink stacks to 320 bytes to fit in ram
+    
+    The old USB code had static in/out buffers in ram
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5bf39f674b3d5ee98b55f42562a5ba1a9328ff07
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Feb 5 14:56:13 2015 -0800
+
+    Revert LPC usb performance improvements
+    
+    There's something screwy going on, sticking garbage in the input
+    buffer at boot time
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ef69872c824668146a3876f1f3d0d2e51d3e4c8d
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Feb 5 14:54:27 2015 -0800
+
+    Revert "altos/lpc: Fix double-buffered USB changes"
+    
+    This reverts commit 41a0604ad1ea1a03e2db7d41731dbadf466b45db.
+
+commit aeca3b46bc1726a06952cc2ff86f50c6d80ed1e1
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Feb 4 22:55:24 2015 -0800
+
+    ao-bringup: Add turnon_teledonglev3
+    
+    TeleDongle v3 uses the LPC11U14 processor which has no on-chip eeprom,
+    so we must reflash the device to set the default radio calibration value.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit bc41ab47b928b837724f8bc6b84d0b5b47c25df3
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Feb 4 20:33:04 2015 -0800
+
+    altos: Rename teledongle-v1.9 as teledongle-v3.0
+    
+    No hardware changes from the 1.9 prototypes to the 3.0 final version.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit dbafa16cfa897b2a5c6cf455cf8675e83eb0d7d6
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Feb 4 20:30:15 2015 -0800
+
+    altos/telebt-v3.0: Set initial radio cal to a sensible value
+    
+    CC1200 uses a different xtal than CC1120, so the default calibration
+    needs to change. This value hit 434.550 on SN 2407, so it seems like a
+    reasonable place to start.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit be443d8d50ad8f59a74bf2f4e810a7359ff72132
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Feb 1 16:57:14 2015 +0100
+
+    altos/telebt-v3.0: Add monitor bits
+    
+    Will be useful to actually be able to receive telemetry
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6eb145d48cfcabf757093433bd2314a80e490a17
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Feb 1 16:46:40 2015 +0100
+
+    altos/usbtrng-v2.0: Select PA11/PA12 mapping config value
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8f9e192e9d1c6fab9843939ff9117f6bb3725943
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Feb 1 16:44:52 2015 +0100
+
+    altos/stmf0: Support PA11/PA12 remapping
+    
+    Small pin-count versions of the STMF0 can remap PA11/PA12 on the same
+    pins as PA9/PA10. These are used by USB, so have the USB driver deal
+    with remapping them.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 466d3e977ca279f97944141fcc12c04f4f58212e
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Feb 1 16:44:07 2015 +0100
+
+    altos/telebt-v3.0: Turn red LED off after initialization
+    
+    This lets the user know the device successfully initialized.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 845ae016d700c37948e053ead5f7e2778356fda3
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Feb 1 16:43:06 2015 +0100
+
+    altos/telebt-v3.0: Fix stdio setup for BTM
+    
+    Make sure the BTM module is allowed to be included in stdio, but delay
+    adding that until the BT link is running.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a138e05ae6241a6743ca9f64528124f5f6c8e0ee
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Feb 1 16:42:01 2015 +0100
+
+    altos: Always include a check for stdio overflow
+    
+    For some reason, the check for running out of space to record stdio
+    devices was disabled when only one device was expected.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 870428a909025988a8cd834755ea166e2d1e34ca
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Feb 1 16:39:17 2015 +0100
+
+    altos/btm: Add fancier debug. Pull serial reset port low.
+    
+    Adds an interactive debugging mode to help diagnose BTM issues.
+    
+    Discovered that the serial reset pin on the BTM needs to be pulled low
+    for the device to work correctly.
+    
+    Leave the bt link interrupt disabled until things are initialized.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 44a503a8cf3778cad5469c592e8ccbae58e44b97
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Feb 1 16:36:51 2015 +0100
+
+    altos/stm: Add ability to delay STDIO usage for serial ports
+    
+    Bluetooth needs to delay adding the serial port to stdio until the
+    link is up and running. The cc1111 serial driver had
+    DELAY_SERIAL_*_STDIN bits which have been added to the STM serial driver.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 252211e9e54a1e6f4efe2df6382ce60c909de70c
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Jan 30 14:04:50 2015 +0100
+
+    And, also add the TeleBT v3.0 flash loader Makefile
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit bfa5c70a827ac8be23ca48797edc14e13461d6ac
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Jan 30 14:03:55 2015 +0100
+
+    Oops, forgot the TeleBT-v3.0 Makefile
+    
+    git doesn't warn about files named 'Makefile' because they're supposed
+    to be generated...
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8ca1f234586225caea1040bc229b63491dadc1cb
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jan 27 20:41:15 2015 -0800
+
+    altos/stmf0: Re-implement fast ADC code for stmf0
+    
+    This creates a ring buffer for ADC data so that ADC fetching can run
+    in parallel with other activities.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3749426af1e900a1b3354922fdd7e8b3bfa38084
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jan 27 17:18:42 2015 -0800
+
+    altos/usbtrng-v2.0: Use stmf042 hardware CRC unit
+    
+    Switch from software to hardware for CRC computation. I think this
+    must be faster, right?
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a95d6776dea86cdc4bdc3512505ba7e75365c127
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jan 27 16:55:27 2015 -0800
+
+    altos/stmf0: Add CRC driver
+    
+    Sets up the stm32f0 CRC hardware, exposing inline functions to access
+    it. DMA access is possible, but usbtrng can't use that.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 79f3434013650fe4e3d76e5eb56a10000ee34249
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jan 27 09:36:19 2015 -0800
+
+    altos/stmf0: Remove remaining stm32l bits from stm32f0 code
+    
+    These were left over from the stm32f0 initial implementation work; now
+    it's more useful to list only the bits which are valid.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit bf08397202860a73417cd1711012eb3e33f308c3
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jan 26 22:23:19 2015 -0800
+
+    ao-tools: Add ao-usbtrng to dump RNG data for testing
+    
+    ao-usbtrng reads a specified number of kilobytes of random data from
+    a random number generator.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ee91e1da606c8a8fade278a3aeae9c1cc9014b84
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jan 26 22:22:00 2015 -0800
+
+    altos/stm: Fix typo in stm32l.h
+    
+    This crept in while working on the stmf0 bits. oops.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ac1a58af4d281a9bc3572dc503982a94e439a4c1
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jan 26 22:16:18 2015 -0800
+
+    altos/usbtrng-v2.0: Add random output command
+    
+    Read chunks of random ADC data, do some CRC16 computations to de-bias
+    and merge 4 bytes of input data into 2 bytes of output data, then dump
+    that out over USB.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 729bb7a405460db8d44c9ff6ee903b28c7499a02
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jan 26 22:14:57 2015 -0800
+
+    altos/stmf0: Add ADC and DMA APIs
+    
+    The ADC api is what USBtrng wants; a way to repeatedly read a single
+    ADC input as fast as possible.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a01effc2f64c757c907e0f4937b4d3710b97bde0
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jan 26 22:12:40 2015 -0800
+
+    altos/stmf0: Add faster USB path
+    
+    This adds a way to allocate private USB buffers for sending data
+    without needing to copy it again. It requires ensuring that all
+    accesses are 16 bits aligned to 16 bit boundaries.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e1d5bcb1968e280b8ebdf6c8b12e8a87167fd890
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jan 26 22:10:47 2015 -0800
+
+    altos/stmf0: Fix linker scripts to make ao_boot work
+    
+    The flash loader ended up assuming ao_boot was at the start of ram,
+    while the application stuck it after the interrupt table (where it
+    needs to go).
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 32c68670af9f8aa690c64d64502e559c0df0c1db
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Jan 25 19:58:38 2015 -0800
+
+    ao-tools: Add --wait option to ao-usbload
+    
+    This waits forever for USB writes to complete, instead of timing out
+    after five seconds. Useful when debugging the device.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 02b07a202839d6e68b3f0db7f8965478661db140
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Jan 25 19:37:05 2015 -0800
+
+    altos: Add flash-loader to usbtrng-v2.0
+    
+    Uses the new STM32F042 flash loading bits.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit df881bce8576f091b2d8cb53b8ce8a43aeedecde
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Jan 25 19:35:19 2015 -0800
+
+    altos: Add self-flash support for STM32F042 processor
+    
+    Also moves the usual address for applications out of the way of the
+    flash loader.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 02e1058fa52ee7c867ea6c9031ebb9e21d14889c
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Jan 25 16:43:48 2015 -0800
+
+    altos: USBtrng v2.0 hardware bringup
+    
+    Gets the USB connection running and blinks the LEDs.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 02f03df6d089cafae99f8ce15dcbd87f6e78d749
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Jan 25 16:42:39 2015 -0800
+
+    altos: Initial STMF04x support
+    
+    Basic clock configuration, OS support, LED and USB drivers.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0e7d1c89fea98eabca738f10cbfebec631be3bb7
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Jan 24 11:18:59 2015 -0800
+
+    altos: Add support for TeleBT v3.0
+    
+    Add support to the BTM driver for non-CC1111 interrupts
+    Add HW flow control to STM serial driver
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 41a0604ad1ea1a03e2db7d41731dbadf466b45db
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Jan 22 21:31:45 2015 -0800
+
+    altos/lpc: Fix double-buffered USB changes
+    
+    These got merged when we were down in Auckland, but before they'd been
+    finished. Transmitting worked fine, but receiving was mis-configuring
+    the OUT buffer size in the hardware.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 291eec859606b73b43072cd2debfbb92659e0d95
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Jan 22 20:34:43 2015 -0800
+
+    altos: Get rid of some accidental debug code
+    
+    I was debugging the accelerometer calibration code and left some
+    printfs in it, which made TM run out of flash space.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e05e0c6b71a1df65f188e00622e9632eb27510fd
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Jan 16 22:09:26 2015 +1300
+
+    Set version to 1.5.9.1
+
+commit 2a053d3d157e00b6a6406f4f78ddb8e298b6c4b7
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Dec 22 17:27:09 2014 -0800
+
+    altos/lpc: Switch LPC SPI driver to interrupt-driven
+    
+    This improves performance for SPI transfers, while allowing other
+    tasks to get work done during longer SPI transfers.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 213a6604ec225e843f30244e6f94d0ebb3d27e46
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Dec 22 17:11:51 2014 -0800
+
+    altos: Adjust CC1200 RSSI reporting value
+    
+    On the test setup, we were about 13dB off, so tweak the settings to
+    suit. This result wasn't tested; it's just a rough offset until we get
+    a production run of TeleDongle boards back to do more systematic
+    measurements.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 014dcc1f179237dc247fafa4a2cff91809260681
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Dec 22 17:10:33 2014 -0800
+
+    altos: Document cc115l power measured at RF setting 0x03 as -31.75dBm
+    
+    We built a custom TeleGPS load for radio sensitivity measurements with
+    the lowest documented power level setting (0x03), and measured the
+    power out at that value of -31.75dBm on the test board.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit cf09ee2a4b093c56b64260c3db3f5e07143aa888
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Dec 9 21:44:53 2014 -0800
+
+    ao-bringup: Clear pending output before setting frequency.
+    
+    Maybe this will unwedge things
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5b7ec0c69343db3793c0317939b5eff1f2d04752
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Dec 6 15:08:53 2014 -0800
+
+    micropeak: Support µPUSB with our own USB ids
+    
+    This matches the new µPUSB id as well as the FTDI USB id.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7e52ef59082cb2afdba498233c429321c37a6ac3
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Dec 6 15:08:29 2014 -0800
+
+    altoslib: Add usbtrng, usbrelay and mpusb USB ids
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7339d2379713b5b7e4c4fe6bad89ed93f9d39e82
+Merge: d1f9121 b6462ca
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Sat Dec 6 15:39:53 2014 -0700
+
+    Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos
+
+commit d1f9121593fe30b924223e89ef4d596b5bec2b25
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Sat Dec 6 15:39:35 2014 -0700
+
+    improve test procedures for TeleMega
+
+commit b6462ca3a7e99fe390ec97f94c23d36fab8c294d
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Nov 23 18:56:40 2014 -0800
+
+    altos/cc1200: With PQT wide open, we can't use PQT_REACHED for start
+    
+    Because we're allowing even signals only weakly correlated with the
+    preamble through to sync detection, we can't use the PQT_REACHED
+    symbol to tell when a packet header has been seen. Instead, just look
+    for SYNC_FOUND.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0e3eeaf59688dac92eb3a27d589923126cb34e00
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Nov 23 18:50:57 2014 -0800
+
+    altos/cc1200: Open up preamble detect to improve sensitivity
+    
+    Increase soft decision PQT value to max (15) to ensure that we detect
+    even weak packets.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit eabeb76a2a9acb624ae364c4f0f315bfc3549d98
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Nov 23 18:31:15 2014 -0800
+
+    altos/cc1200: Wait for packet to be placed in FIFO during receive
+    
+    This changes the receive code to use MCU_STATUS, waiting for
+    MARC_STATUS1 to indicate that the packet is in the fifo before reading
+    it out.
+    
+    It also fixes the receive timeout code to keep receiving if the
+    preamble or sync have been seen when the timeout fires. This makes
+    TeleLCO able to use short timeouts during scanning while still
+    successfully receiving packets.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2163f6e6b341b7840f03e89d568699b8ea186435
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Nov 16 16:39:18 2014 -0800
+
+    altos/teledongle-v1.8: Make this the same as teledongle v1.9
+    
+    Remove RSSI LED blinking, add CRC error LED
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 54f7ab842a8cba3003cd5a9deb2515151263ca2e
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Nov 16 16:38:12 2014 -0800
+
+    altos: Allow TeleMega to be built without MPU6000
+    
+    Robert Braibish's board has a dead MPU6000; this fix lets the TeleMega
+    firmware build without that driver so the rest of the board could be verified.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f16ea9abfaac9eee3b0935c586e383ae046d6cf5
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Nov 16 16:37:15 2014 -0800
+
+    altosui: Remove duplicate AltosUIPreferencesBackend.java
+    
+    There's a copy in altosuilib
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit abdf3177293c57e659017b64819c13f11c126011
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Nov 16 13:41:27 2014 -0800
+
+    altos/microsplash: fix .gitignore to ignore resulting binary
+
+commit 97a321692c2e41a1d3f77fb541780ada945eff52
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Nov 16 13:40:15 2014 -0800
+
+    Add AltosDroid release note for version 1.5
+
+commit 47956ac01397c0a7fafc6b0a4840113186924b2e
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Nov 16 13:17:55 2014 -0800
+
+    altosdroid: East and West were flipped in all GPS output
+    
+    East is positive, West is negative
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5aae1446026a08bf8f09c56b960545eff30a8bd1
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Nov 15 22:52:42 2014 -0800
+
+    altosdroid: Save AltosState and restore at startup
+    
+    Instead of re-parsing the old logfile, save the current state in the
+    preferences database and restore at restart of the
+    TelemetryService. This makes the state get restored even before the BT
+    connection is recovered.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 52ce23327bd81e2d40a1817442e75bd6b60ffe95
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Nov 15 22:50:31 2014 -0800
+
+    altoslib: add AltosPreferences state save/restore interfaces
+    
+    This serializes an entire AltosState object and stores it in the
+    preferences database for later retrieval. AltosDroid uses this to
+    recover the old state data when restarting.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a488da3ca72fe0778b2d79a8cac935621d1d789d
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Nov 15 22:49:06 2014 -0800
+
+    altosdroid: TabMap needs to expose () constructor
+    
+    Otherwise we get an exception at startup time for some reason.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit deda23963586eb07a32f9a3c83a0355178e19340
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Nov 15 22:48:15 2014 -0800
+
+    altoslib: Add getBytes/putBytes interface to AltosPreferencesBackend
+    
+    This lets us store arbitrary binary data in the preferences database
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e5dd00ef0014364fc059970cc020f209b3b16cf8
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Nov 15 22:46:01 2014 -0800
+
+    altosdroid: Don't display MISSING flight number
+    
+    Just check and clear the entry if we end up seeing that value
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 60edcfe410e7fa848813d6c1ed8dc9808887d041
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Nov 15 16:03:32 2014 -0800
+
+    altoslib: Make AltosState serializable
+    
+    This involved making every class it references serializable as well
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4d4fee0b0091a1b6257a06f62b1078778cdb417f
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Nov 10 14:41:17 2014 -0800
+
+    altoslib: Missing headers for mag sensor in CSV output
+    
+    Kelsey Black <nmonic@gmail.com> reported that the TeleMega CSV output
+    was missing the header labels for the mag sensor data.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 437eba2ff27b2b7dfd0f363819b9a43ab8b28ead
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Nov 6 20:04:47 2014 -0800
+
+    altos: Reset interrupt flags before TX in CC1200 driver
+    
+    Failing to reset the flags set during interrupt leads to
+    short-circuiting transmission and not a lot of packets going out.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7f742824673e5e6034defdb09b66d4d56eb8d4fe
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Nov 6 16:05:49 2014 -0800
+
+    altos/teledongle-v1.9: Switch to NXP processor as on prototype boards
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6a082d9b5ed169b9d4153885f3535987e5ae5d84
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Nov 6 16:04:56 2014 -0800
+
+    altos/lpc: Disable JTAG when using pins for GPIO
+    
+    JTAG is enabled by default, making those pins not support GPIO unless
+    specifically configured.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 58db263cc835be0abb972654c2d7369718c88b37
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Nov 6 16:04:14 2014 -0800
+
+    altos/lpc: Declare SPI send parameters as const
+    
+    This matches STM
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d3dd45b060c996153ff8195bd371e9e1f3b15efb
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Nov 6 16:02:47 2014 -0800
+
+    altos: Use other TeleDongle LED for CRC-invalid packet reporting
+    
+    Instead of blinking out some fake-o RSSI indication, just blink the
+    red LED when a packet with a bad CRC is received.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2313cdacefb2139bc68cd98e782c54d706af0704
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Nov 6 16:02:07 2014 -0800
+
+    altosuilib: GPS errors are recorded in floating point, not integers
+    
+    Fix the format used to present them in the info table.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2f0ff9675017655846a8abc617b4dc9a3666d0b9
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Nov 6 16:01:24 2014 -0800
+
+    altos: Use AO_SPO_SPEED_FAST for CC1200
+    
+    This asks for the fastest available SPI speed, instead of fixing it to
+    8MHz, which may not be supported on every architecture.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 80a0397dde2f787fb20fd2520b274b826c68ed5a
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Nov 6 16:00:06 2014 -0800
+
+    altos: Stop attempting to ramp power on CC115L
+    
+    The PA register on the 115L isn't in any way monotonic, making the old
+    code broken. Just rempve it instead of fixing it; we don't ramp
+    anywhere else...
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f2e5ffd839fe5be99359e4c86a96f03148bac698
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Nov 6 15:58:42 2014 -0800
+
+    altos: Declare port register type only in arch header
+    
+    Instead of defaulting to 8 bits, explicitly require declaration of the
+    type of the port register for each architecture.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f2060d6ca222a04608e598baf59757f12ea2ec70
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Nov 6 13:27:29 2014 -0800
+
+    Move teledongle 1.9 to 1.8; there's a new 1.9
+    
+    1.9 is now the lpc11u14-based form-factor prototype board.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b67556949aa080fc5e70771e972de880e44eca12
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Nov 5 22:11:44 2014 -0800
+
+    altos: Rename microwater to microsplash
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b0e903a76276e33f531eade42ac721c9490c6758
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Oct 30 21:59:45 2014 -0700
+
+    altosui: Pop up 'Connecting' dialog during Monitor Idle
+    
+    This was a bit harder than expected as I had to wire up a way to shut
+    down the whole monitor idle window when you clicked on the cancel button.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ef00182c79bd7a56fbc5d782cb8f4aa0079bb86f
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Oct 25 21:14:25 2014 -0700
+
+    altos: Increase CC1200 SPI data rate to 8MHz
+    
+    This got set to 125kHz to make debugging with a logic analyzer easier
+    and never changed back to a reasonable speed.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4d51570ed8776461d084726149923c5be43d622e
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Oct 25 19:56:25 2014 -0700
+
+    altos: Fix up telemetry delay computations
+    
+    With RDF, APRS and telemetry all being sent at varying rates,
+    computing when to send the next radio data is not as simple as sending
+    telemetry and then figuring out whether to send RDF and/or APRS.
+    
+    Fix this by computing times for the next telemetry/rdf/aprs packet,
+    and only sending each when that time has passed. Compute the delay
+    until the next radio activity as the minimum time to any transmission.
+    
+    This also adds code to the config bits to reset the radio times
+    whenever something changes that might affect which radio data to send
+    next.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c831f1ffb378c20b7513d209d60cdd5dee9db85b
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Oct 25 17:44:48 2014 -0700
+
+    altos: Perform cc1200 calibration less often. Tweak radio params
+    
+    This performs calibration after every 4 operations, or when the
+    frequency changes. This reduces the time it takes to get to receive
+    mode.
+    
+    This also makes the sync and preamble qualifiers more strict to reject
+    bad packets.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3f7263f57b1b697d92ed6c3d62956e5bdfc11f24
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Oct 25 11:20:44 2014 -0700
+
+    altos: Remove old AO_SEND_ALL_BARO bits
+    
+    This was used for testing the original TeleMini which couldn't log
+    data at full speed.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ae4be19f8ab0899a879a10aec28dc381f44dd2c7
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Oct 25 10:21:30 2014 -0700
+
+    altos: Build TeleDongle v1.9 by default
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 51ef3fad6435c0b21945d48fbbaa5a4c092c4960
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Oct 25 10:20:07 2014 -0700
+
+    altos: Increase PQT value for cc1200 improving sensitivity
+    
+    The PQT value indicates how 'good' the preamble is; higher values
+    allow a lower quality of preamble to pass the test, permitting more
+    packets to be decoded.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9102183b40f0b32d4fb6d24502b79a6431184310
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Oct 25 10:17:48 2014 -0700
+
+    altos: Sort out ao_gps_print altitude fetching
+    
+    ao_gps_print is used by both teledongle/telebt and the host-based GPS
+    test code. The first instance uses the old internal GPS structure,
+    containing just a 16-bit altitude while the second uses an
+    ao_telemetry structure, which contains 32 bits split into two
+    members.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit cb83b5432e1320726ad496ded78cced7274618b0
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Oct 7 05:36:18 2014 +0200
+
+    altos/teledongle-v1.9: Add remaining code to complete the project
+    
+    This turns the prototype board into a full teledongle
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4a3fe79266a77f8fc001117f49db1d2f14f9e6b6
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Oct 7 05:34:06 2014 +0200
+
+    altos: Complete cc1200 driver
+    
+    Deal with differences between cc1120 and cc1200, including built-in
+    packet support and various register changes.
+    
+    This now works to send and receive telemetry, as well as send APRS and
+    RDF.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7fea8b245cdccc1ec77aa559433952f339676473
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Oct 7 05:35:10 2014 +0200
+
+    altos: Expose telemetry altitude macros even without GPS
+    
+    This allows for APRS testing in the new teledongle code
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 484b530a16a54ca8fde412c3f466bfe7eed978cd
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Oct 7 05:32:00 2014 +0200
+
+    altos: Mark STM ao_spi_send as taking const pointer
+    
+    We don't write to this, so let it be const for type checking
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c17dff05b70d98e3193e8e68cc9599f3a30270b5
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Oct 24 19:10:45 2014 -0700
+
+    ao-tools/ao-send-telem: Add verbose, fake and rate options
+    
+    Verbose dumps some data while sending packets.
+    Fake sends constructed packets, once every 500ms.
+    Rate sets the transmit bit rate.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e2562ee43b8558df0836217ea3a187b36e2669b3
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Oct 15 16:10:11 2014 -0700
+
+    altosuilib: Try to detect the architecture when loading JNI lib
+    
+    Look at sun.arch.data.model and os.arch to try and load the right
+    libaltos file the first time.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 88df7cd314269fa1debe226b49b7e4e9dc238d8e
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Oct 24 21:21:19 2014 -0700
+
+    altoslib: synchronize access to serial debug output list
+    
+    This list is access by both the receiver and the monitor task, so it
+    needs to be locked to prevent collisions.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 221824b038bf18ca43a38c82d18b0ae9586ba565
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Thu Oct 9 13:11:16 2014 -0600
+
+    document pyro current limits in an appendix
+
+commit ffda6989e856e66a1bea253e82cb70f51ada3e7a
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Oct 5 00:07:10 2014 -0700
+
+    altos: Add prototype TeleDongle v1.9 code
+    
+    Lights up the hardware, sends carrier and RDF tones. A bit more cc1200
+    work to be done still.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 27a467d802a80a33ea20eb5cda2558d03caa2c00
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Oct 5 00:03:28 2014 -0700
+
+    altos: Copy cc1120 driver to cc1200 driver and hack a bit
+    
+    The cc1200 is similar to the cc1120, although many registers have
+    changed.
+    
+    This driver can send a bare carrier and an RDF tone, but does not yet
+    receive or transmit telemetry data.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 62628c8b429d06ee834f0b6511c430cbeaab9303
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Oct 4 00:30:54 2014 -0700
+
+    altos: Fix syntax error with ao_log_mega change.
+    
+    Missed a semi-colon.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 00ae706dab6e8fddef4c5730a17c433a022228b7
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Oct 4 00:11:13 2014 -0700
+
+    altoslib: Compute tilt angle from eeprom data
+    
+    This copies the computation of tilt angle from the firmware so that
+    post-flight analysis can also show the data.
+    
+    This change also renames all of the imu values to make them easier to
+    understand:
+    
+       accel   gyro    axis
+    
+       along   roll    length of the board
+       across  pitch   across the board
+       through yaw     through the board.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a757fd5af53f5721a949181372548afa4757d6c9
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Oct 4 00:10:03 2014 -0700
+
+    altosui: Update 'Imperial Units' checkbox when units change
+    
+    If you have two graphs running, make sure the imperial units
+    checkboxes agree.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 656d8fe17532ca6c7d1d43996f187df2f14f5395
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Oct 4 00:07:39 2014 -0700
+
+    altoslib: Deal with new Mega log format that has 32-bit gyro cal
+    
+    This adds parsing for the new log format type to get all 32 bits of
+    the gyro calibration data.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9521dc63671b69065d27fc1ccba6d20cc90643cb
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Oct 4 00:04:39 2014 -0700
+
+    altos: Record 32-bits for gyro calibration values
+    
+    The gyro ground calibration values are scaled by 512 to provide a bit
+    more precision for the computations. This means they don't fit in 16
+    bits, so change the format of the flight log record. Also change the
+    reported format so that AltosUI has a chance of figuring it out.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 95d9248da78f86240dbe77e2c206420dc509c9cf
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Sep 29 12:57:27 2014 -0700
+
+    altosui: Check for map and stats table when changing units/fonts in graph
+    
+    AltosGraphUI wasn't making sure the map and stats tables were present
+    before attempting to adjust font size and units.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 40c5535b65a75374fb1dbbd994c29324db814f5b
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Sep 29 12:56:04 2014 -0700
+
+    altos: Handle antenna down in ao_flight_test
+    
+    Parse the Pad orientation config value and flip the accelerometer
+    value back around in antenna down configuration.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b97a125a9f8bd9619833647a9b6aa6329103e136
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Sep 26 22:58:13 2014 -0700
+
+    ao-bringup: Auto-select programmer for teledongle turnon
+    
+    Bdale's programmer is SN 100, Keith's is SN 186. Use the username to
+    figure out which one to use.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b4eba3f3a58a9c35e3699ff14405b997c1318d91
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Sep 26 22:53:39 2014 -0700
+
+    altos: Make sure we drop the SPI mutex when aborting cc1120 recv
+    
+    The cc1120 receive code is 'twisty', in that it acquires the SPI mutex
+    in the middle of an interrupt handler so that it can quickly start the
+    radio when the signal comes in. This means we have to be careful to
+    drop that mutex in all paths which leave the receive code, including
+    when the packet receive is aborted mid-way through the process.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 22661ba69b8919116092382f1f5aa0dc79d02cc9
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Sat Sep 13 17:56:51 2014 -0600
+
+    store cal value correctly even when we didn't need to change it
+
+commit b0eb63205223e2982d0ded08503c3f128420270f
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Sep 13 15:59:18 2014 -0700
+
+    altosdroid: Update notebook to reflect current status
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9dc426756742fb967fdd21e1fcec54edeb4b12ac
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Sep 13 15:52:56 2014 -0700
+
+    altosui: Bring up main window when doing --replay or --graph
+    
+    This shows the main window when replaying or graphing files so that
+    you can interact with that, changing the global configuration or doing
+    other stuff.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 75d5368cb2a95f3f7385952669a14765460f549d
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Sep 13 15:51:50 2014 -0700
+
+    altosui: Fix --replay to run in realtime after boost
+    
+    I added the ability to rapidly replay files for AltosDroid to recover
+    from a crash, but didn't change AltosUI to use realtime mode again.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 04b5cc37659b1b3d6b62f1ef17b17c0492434cba
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Sat Sep 13 16:37:42 2014 -0600
+
+    reflect filename changes in LLC repo
+
+commit 93d1cedc94358ebf5c2af537a25a242f6c19954c
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Sep 13 15:23:40 2014 -0700
+
+    altosdroid: Automatically sign the released version if the key is available
+    
+    Look in ~/altusmetrumllc for release.keystore and Passphrase and
+    enable building and signing of the release binary.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2731486c12678a7d3bd7ec79e74a2fcaf20845bd
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Sep 13 13:38:31 2014 -0700
+
+    altosdroid: Update version code and name for 1.5
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e151c144fcdb1da96e715f29c049dc4869e1d53d
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Sep 13 13:00:58 2014 -0700
+
+    Mark master branch as past the 1.5 point
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ff7c006e50515040d43399899fac26a3fe26d8a7
 Author: Bdale Garbee <bdale@gag.com>
-Date:   Sat Sep 13 11:28:19 2014 -0600
+Date:   Sat Sep 13 12:31:08 2014 -0600
+
+    updated to reflect changes from 1.5 release
+
+commit 20d640ec504afbfdb69dba1b241d84af1e62abed
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Sep 12 20:58:26 2014 -0700
+
+    ao-bringup: Improve igniter testing. Add TeleMega and TeleMetrum testing.
+    
+    The script lets you re-try each one when they fail, which is nice if
+    you're hand-holding the setup.
+    
+    The TeleMetrum and TeleMega tests are adapted from the EasyMega tests
+    and are hooked up to the turnon scripts.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e0077866138a1e29ede7181e39f04860b866543a
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Sep 12 20:57:05 2014 -0700
+
+    ao-tools/ao-test-igniter: Remove bogus printf
+    
+    This must have been left over from testing; it prints "device (null)",
+    which isn't very useful.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6681d31929266fec9711b3d89a4f074cd2afcc6e
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Sep 12 20:56:29 2014 -0700
+
+    ao-tools/ao-test-gps: Improve output formatting
+    
+    Add a newline before printing out the flags and sats at exit time
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f2d045570d2cda0abde67a68506cb3fc2e119ec3
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Sep 12 17:22:37 2014 -0700
+
+    ao-bringup: Use C version of ao-test-gps in test-telegps
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d0e597789ac298b108ea04cc1a2c999bcf14bc9c
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Sep 12 17:22:03 2014 -0700
+
+    ao-tools: Add ao-test-gps program
+    
+    This waits for GPS to report lock
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit def036794f1460a5457e6b86350712c336e296d6
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Sep 12 16:38:59 2014 -0700
+
+    ao-bringup: Use C version of test-flash for telegps
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1630a8e458f174d6df1aa30ff30e3f02a10bdbf7
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Sep 11 19:59:58 2014 -0700
 
-    need multi-arch in fat build
+    altosui: Ignore built .desktop file
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
 
-commit e969172a81e24f70c349b10f429e69817900c307
+commit 807e62ccebc83eb6427a63431d06effa074e5e76
 Author: Keith Packard <keithp@keithp.com>
 Date:   Thu Sep 11 19:56:13 2014 -0700
 
@@ -28,7 +1627,21 @@ Date:   Thu Sep 11 19:56:13 2014 -0700
     
     Signed-off-by: Keith Packard <keithp@keithp.com>
 
-commit 800f3377b1a374ad5cf826aa897efdcb08059040
+commit d7ad490a33900a788b15d1600ebaa2a71e6f35ff
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Sep 11 15:57:21 2014 -0700
+
+    altos: Add smaller altitude table file to .gitignore
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7ad8921b164103629b246c25860297454aa7ec6b
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Sep 11 15:56:14 2014 -0700
+
+    altos/test: Add TMv2 test program to .gitignore
+
+commit 0cedc27e22a9fbc9ccfe1b403c84d728bb23220d
 Author: Keith Packard <keithp@keithp.com>
 Date:   Thu Sep 11 15:00:25 2014 -0700
 
@@ -41,7 +1654,7 @@ Date:   Thu Sep 11 15:00:25 2014 -0700
     
     Signed-off-by: Keith Packard <keithp@keithp.com>
 
-commit 793588e218102204e69755a16bc32ea5c67f29c7
+commit 6dafd7bf947d892e430cd565eb92a3366abb3604
 Author: Keith Packard <keithp@keithp.com>
 Date:   Thu Sep 11 14:23:29 2014 -0700
 
@@ -52,7 +1665,7 @@ Date:   Thu Sep 11 14:23:29 2014 -0700
     
     Signed-off-by: Keith Packard <keithp@keithp.com>
 
-commit 19730b872c61f34724b0f187f71cccb6a65251dd
+commit 368c7d583380b4453f432d5a965a1e4c45a92f92
 Author: Keith Packard <keithp@keithp.com>
 Date:   Thu Sep 11 14:14:07 2014 -0700
 
@@ -68,19 +1681,6 @@ Date:   Thu Sep 11 14:14:07 2014 -0700
     
     Signed-off-by: Keith Packard <keithp@keithp.com>
 
-commit 10e31d84ee5cdf10248988079df91354ae6ed612
-Author: Bdale Garbee <bdale@gag.com>
-Date:   Wed Sep 10 01:33:33 2014 -0600
-
-    update changelog for release
-
-commit 05e4094411f861bf29bea2e9c39c1b66f8f267f8
-Merge: acb2791 2ee937b
-Author: Bdale Garbee <bdale@gag.com>
-Date:   Wed Sep 10 01:32:27 2014 -0600
-
-    Merge branch 'master' into branch-1.5
-
 commit 2ee937b603b181bb24768eb4d0e2f918a5377fd3
 Author: Bdale Garbee <bdale@gag.com>
 Date:   Wed Sep 10 01:29:56 2014 -0600
@@ -123,32 +1723,12 @@ Date:   Tue Sep 9 23:43:10 2014 -0700
     
     Signed-off-by: Keith Packard <keithp@keithp.com>
 
-commit acb279125c0fa377c8b1dbbb8634fba60f7f845b
-Author: Bdale Garbee <bdale@gag.com>
-Date:   Wed Sep 10 00:05:07 2014 -0600
-
-    update ChangeLog
-
-commit 5de00e9e39cff2d3b409c2ce99caa994f0a36202
-Merge: b3fba98 a72b768
-Author: Bdale Garbee <bdale@gag.com>
-Date:   Wed Sep 10 00:02:57 2014 -0600
-
-    Merge branch 'master' into branch-1.5
-
 commit a72b7683606d3e741043011c929482a0a168a5c9
 Author: Bdale Garbee <bdale@gag.com>
 Date:   Tue Sep 9 23:44:45 2014 -0600
 
     more build dependencies for processing icons
 
-commit b3fba989a84db7d904e09a8f47e3a86d4e0f9577
-Merge: 28bd505 1fb200d
-Author: Bdale Garbee <bdale@gag.com>
-Date:   Wed Sep 10 00:01:33 2014 -0600
-
-    Merge branch 'master' into branch-1.5
-
 commit 1fb200d18cc385230b3af574816ec354682cc5c9
 Author: Keith Packard <keithp@keithp.com>
 Date:   Tue Sep 9 23:00:14 2014 -0700
@@ -159,18 +1739,6 @@ Date:   Tue Sep 9 23:00:14 2014 -0700
     
     Signed-off-by: Keith Packard <keithp@keithp.com>
 
-commit 28bd5057252e61bc5b1a35a00bc1f9fdfde097f7
-Author: Bdale Garbee <bdale@gag.com>
-Date:   Tue Sep 9 23:23:27 2014 -0600
-
-    updated ChangeLog for 1.5 release
-
-commit 45f50ad3a8ce69c708974711a5939c42a74bf53b
-Author: Bdale Garbee <bdale@gag.com>
-Date:   Tue Sep 9 23:22:58 2014 -0600
-
-    releasing version 1.5
-
 commit a8c799c48a52bf13466536db627b66bfe2a435cd
 Author: Keith Packard <keithp@keithp.com>
 Date:   Tue Sep 9 09:38:03 2014 -0700
index 2f8a5ee182d1e63c5e5da951cacf73f3a702c636..1af40358ae7e04ad170aa97cc2e3ea4759cedcb3 100644 (file)
@@ -15,7 +15,7 @@ dist-hook: ChangeLog
 fat:
        cd src && $(MAKE) all
        cd doc && $(MAKE) all
-       cd libaltos && $(MAKE) all
+       cd libaltos && $(MAKE) fat
        cd altoslib && $(MAKE) all
        cd altosuilib && $(MAKE) all
        cd icon && $(MAKE) fat
@@ -23,5 +23,23 @@ fat:
        cd micropeak && $(MAKE) fat
        cd telegps && $(MAKE) fat
 
+fat_linux = \
+       altosui/Altos-Linux-$(VERSION).sh altosui/Altos-Linux-$(VERSION).tar.bz2 \
+       telegps/TeleGPS-Linux-$(VERSION).sh telegps/TeleGPS-Linux-$(VERSION).tar.bz2 \
+       micropeak/MicroPeak-Linux-$(VERSION).sh micropeak/MicroPeak-Linux-$(VERSION).tar.bz2
+
+fat_mac = \
+       altosui/Altos-Mac-$(VERSION).dmg \
+       telegps/TeleGPS-Mac-$(VERSION).dmg \
+       micropeak/MicroPeak-Mac-$(VERSION).dmg
+
+fat_windows = \
+       altosui/Altos-Windows-$(VERSION_DASH).exe \
+       telegps/TeleGPS-Windows-$(VERSION_DASH).exe \
+       micropeak/MicroPeak-Windows-$(VERSION_DASH).exe
+
+keithp-fat: fat
+       scp -p $(fat_linux) $(fat_mac) $(fat_windows) keithp.com:public_html/altos-$(VERSION)
+
 set-java-versions:
        $(top_srcdir)/fix-java-versions org.altusmetrum.altoslib=$(ALTOSLIB_VERSION) org.altusmetrum.altosuilib=$(ALTOSUILIB_VERSION)
index dc14a44f81c8f34d62f095ff0938b5ab5e3d75e8..f374fa004504ab99d8e845525daea6895a83903d 100644 (file)
--- a/Releasing
+++ b/Releasing
@@ -68,12 +68,16 @@ These are Bdale's notes on how to do a release.
                this pushes packages for each platform to web site
 
        # store a stable copy of ARM binaries for production use
-       cp src/easymini-v1.0/*.elf \
+       cp src/easymega-v1.0/*.elf \
+          src/easymini-v1.0/*.elf \
+          src/teledongle-v3.0/*.elf \
           src/telegps-v1.0/*.elf \
           src/telemega-v1.0/*.elf \
           src/telemetrum-v2.0/*.elf \
           ~/altusmetrumllc/Binaries/
-       cp src/easymini-v1.0/flash-loader/*.elf \
+       cp src/easymega-v1.0/flash-loader/*.elf \
+          src/easymini-v1.0/flash-loader/*.elf \
+          src/teledongle-v3.0/flash-loader/*.elf \
           src/telegps-v1.0/flash-loader/*.elf \
           src/telemega-v1.0/flash-loader/*.elf \
           src/telemetrum-v2.0/flash-loader/*.elf \
@@ -88,7 +92,7 @@ These are Bdale's notes on how to do a release.
          and move the MicroPeak installers from AltOS/releases to there
                
        - create /home/bdale/web/altusmetrum/TeleGPS/releases/<rev>,
-         and move the MicroPeak installers from AltOS/releases to there
+         and move the TeleGPS installers from AltOS/releases to there
                
        - go edit ~/web/altusmetrum/AltOS/releases/<rev>.mdwn, 
          /home/bdale/web/altusmetrum/MicroPeak/releases/<rev>.mdwn, and
index 02507bb9b8afeb61dc41aef632e3ac099b3d93e3..19e5a6dc5e0e4f390a8ee8d4b98f2b1a9fdbeece 100644 (file)
@@ -17,8 +17,8 @@
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="org.altusmetrum.AltosDroid"
-          android:versionCode="5"
-          android:versionName="1.3">
+          android:versionCode="6"
+          android:versionName="1.5">
     <uses-sdk android:targetSdkVersion="10" android:minSdkVersion="10"/>
     <!-- Google Maps -->
     <uses-feature android:glEsVersion="0x00020000" android:required="true"/>
index d5784483e74663a869df6a1cdb3611563537bb2a..361de13cb3b917a44d2ece35ec733fdda91b1c06 100644 (file)
@@ -1,5 +1,8 @@
 if ANDROID
-all_target=bin/AltosDroid-debug.apk bin/AltosDroid-release-unsigned.apk
+all_target=bin/AltosDroid-debug.apk
+if ANDROID_RELEASE
+all_target+=bin/AltosDroid-release.apk
+endif
 else
 all_target=
 endif
@@ -76,7 +79,8 @@ bin/AltosDroid-release-unsigned.apk: $(SRC) $(ALTOSLIB) $(SUPPORT_V4) $(GOOGLE_P
 
 bin/AltosDroid-release.apk: bin/AltosDroid-release-unsigned.apk
        jarsigner -sigalg SHA1withDSA -digestalg SHA1 \
-          -keystore release.keystore \
+          -keystore ~/altusmetrumllc/google-play-release.keystore \
+          -storepass:file ~/altusmetrumllc/google-play-passphrase \
           -signedjar bin/AltosDroid-release-signed.apk \
           bin/AltosDroid-release-unsigned.apk AltosDroid
        $(ZIPALIGN) -f 4 \
index 5a4df032ef35a36b6a0511a3c7721cd352f61aa8..6a246df7fe3dca22e5cc60632ee0ca8c8ed0697d 100644 (file)
@@ -6,10 +6,6 @@ Desired AltosDroid feature list
  *) Channel scanning. Provide the ability to search for telemetry
     signals like AltosUI does.
 
- *) Highlight current frequency in the frequency list.
-
-       Placed current frequency in title bar
-
  *) Random frequency selection. Provide some mechanism to input
     arbitrary radio frequencies. Could be like AltosUI which allows
     you to edit the list of frequencies and assign names to them,
@@ -23,6 +19,20 @@ Desired AltosDroid feature list
 
  *) Select satellite imaging mode
 
+ *) TeleBT battery voltage
+
+ *) Deal with long bluetooth list. Currently, a list longer than
+    the screen makes it impossible to use entries off the bottom.
+
+ *) Pickle/unpickle state instead of reloading entire history from
+    file. Current restart time is lengthy.
+
+Completed features
+
+ *) Highlight current frequency in the frequency list.
+
+       Placed current frequency in title bar
+
  *) Remember most-recently-used TBT and frequency, perhaps
     auto-connect at startup.
 
@@ -37,4 +47,3 @@ Desired AltosDroid feature list
 
        Done
 
- *) TeleBT battery voltage
diff --git a/altosdroid/release-note-1.5 b/altosdroid/release-note-1.5
new file mode 100644 (file)
index 0000000..98f88d9
--- /dev/null
@@ -0,0 +1,7 @@
+Version 1.5
+
+ * TeleGPS support
+ * Reloads previous flight data at startup
+ * Fixes crash when touching map
+ * Reconnect to TeleBT at startup
+ * Remember radio settings
index 51ef5e94652d2c2dfe47a3d0b774497d873a1f7c..3740f55d7f83a44d49cf7eabe08a150a4222fef6 100644 (file)
@@ -31,7 +31,7 @@ import android.os.Handler;
 //import android.os.Message;
 import android.util.Log;
 
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosBluetooth extends AltosLink {
 
index f6cceac947dbab97cc6b6d838a7fd22e2f21f960..53963f25a2c5ac27a5599c12ded0ad7e71d5cdb9 100644 (file)
@@ -52,7 +52,7 @@ import android.widget.Toast;
 import android.app.AlertDialog;
 import android.location.Location;
 
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
        // Debugging
@@ -337,7 +337,10 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
                        }
                        if (saved_state == null || state.flight != saved_state.flight) {
                                Log.d(TAG, "update flight");
-                               mFlightView.setText(String.format("%d", state.flight));
+                               if (state.flight == AltosLib.MISSING)
+                                       mFlightView.setText("");
+                               else
+                                       mFlightView.setText(String.format("%d", state.flight));
                        }
                        if (saved_state == null || state.state != saved_state.state) {
                                Log.d(TAG, "update state");
index 9cef131905abad0c1437dc1722aa155a0cbfba38..7ab701472bca37208d7bdb177b41266e46346548 100644 (file)
@@ -17,7 +17,7 @@
 package org.altusmetrum.AltosDroid;
 
 import android.content.Context;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosDroidPreferences extends AltosPreferences {
 
index be41ae7cf35b345b157d11127730c73971618bdc..bc5300fdc36a3fd3cf0466f5939a368813500eb9 100644 (file)
@@ -22,8 +22,9 @@ import java.util.Map;
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.os.Environment;
+import android.util.*;
 
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosDroidPreferencesBackend implements AltosPreferencesBackend {
        public final static String        NAME    = "org.altusmetrum.AltosDroid";
@@ -71,6 +72,16 @@ public class AltosDroidPreferencesBackend implements AltosPreferencesBackend {
                return prefs.getString(key, def);
        }
 
+       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);
        }
@@ -87,6 +98,11 @@ public class AltosDroidPreferencesBackend implements AltosPreferencesBackend {
                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) {
                editor.remove(key);
        }
index 8e625da6563b8268242d9166a6019cc23e47fac3..cbb200450dc0b81270ca1d7e8b8092e746d29180 100644 (file)
@@ -17,7 +17,7 @@
 
 package org.altusmetrum.AltosDroid;
 
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 import android.location.Location;
 import android.app.Activity;
 import android.graphics.Color;
index 969992d3026c20f4fa1d94793353dd03457d6956..2d32dc071ffdc5240443cf72a0433279c7036ea2 100644 (file)
@@ -21,7 +21,7 @@ package org.altusmetrum.AltosDroid;
 import android.speech.tts.TextToSpeech;
 import android.speech.tts.TextToSpeech.OnInitListener;
 
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosVoice {
 
index fa4e3c8b3da13e7c5c957a422bf7e85ab1da9d62..23de962209d79d52dcc54ec55a3028c961f65930 100644 (file)
@@ -17,7 +17,7 @@
 
 package org.altusmetrum.AltosDroid;
 
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 import android.app.Activity;
 import android.os.Bundle;
@@ -101,7 +101,7 @@ public class TabAscent extends AltosDroidTab {
 
                        if (state.gps != null) {
                                mLatitudeView.setText(AltosDroid.pos(state.gps.lat, "N", "S"));
-                               mLongitudeView.setText(AltosDroid.pos(state.gps.lon, "W", "E"));
+                               mLongitudeView.setText(AltosDroid.pos(state.gps.lon, "E", "W"));
                        } else {
                                mLatitudeView.setText("");
                                mLongitudeView.setText("");
index 28068666a4df627de6302450d8182936706205fa..4ec6f4097cba4ad68d4fec49db76f8290b74e1e4 100644 (file)
@@ -17,7 +17,7 @@
 
 package org.altusmetrum.AltosDroid;
 
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 import android.app.Activity;
 import android.os.Bundle;
@@ -110,7 +110,7 @@ public class TabDescent extends AltosDroidTab {
                        }
                        if (state.gps != null) {
                                mLatitudeView.setText(AltosDroid.pos(state.gps.lat, "N", "S"));
-                               mLongitudeView.setText(AltosDroid.pos(state.gps.lon, "W", "E"));
+                               mLongitudeView.setText(AltosDroid.pos(state.gps.lon, "E", "W"));
                        }
 
                        mApogeeVoltageView.setText(AltosDroid.number("%4.2f V", state.apogee_voltage));
index b257b9365d652c51fc67a3db2676138bb1fe53c6..4c69d869c8b4839ed8ab38deccbdc2bf933480bc 100644 (file)
@@ -17,7 +17,7 @@
 
 package org.altusmetrum.AltosDroid;
 
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 import android.app.Activity;
 import android.os.Bundle;
@@ -82,12 +82,12 @@ public class TabLanded extends AltosDroidTab {
                }
                if (state != null && state.gps != null) {
                        mTargetLatitudeView.setText(AltosDroid.pos(state.gps.lat, "N", "S"));
-                       mTargetLongitudeView.setText(AltosDroid.pos(state.gps.lon, "W", "E"));
+                       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(), "W", "E"));
+                       mReceiverLongitudeView.setText(AltosDroid.pos(receiver.getLongitude(), "E", "W"));
                }
 
                if (state != null) {
index ab338ac26284cc45370a291d1edd99999435dee0..871b94a1bb57703a1a81bc32426ff97e045939b9 100644 (file)
@@ -19,7 +19,7 @@ package org.altusmetrum.AltosDroid;
 
 import java.util.Arrays;
 
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 import com.google.android.gms.maps.CameraUpdateFactory;
 import com.google.android.gms.maps.GoogleMap;
@@ -179,7 +179,7 @@ public class TabMap extends AltosDroidTab {
                        }
                        if (state.gps != null) {
                                mTargetLatitudeView.setText(AltosDroid.pos(state.gps.lat, "N", "S"));
-                               mTargetLongitudeView.setText(AltosDroid.pos(state.gps.lon, "W", "E"));
+                               mTargetLongitudeView.setText(AltosDroid.pos(state.gps.lon, "E", "W"));
                                if (state.gps.locked && state.gps.nsat >= 4)
                                        center (state.gps.lat, state.gps.lon, 10);
                        }
@@ -193,9 +193,12 @@ public class TabMap extends AltosDroidTab {
                        else
                                accuracy = 1000;
                        mReceiverLatitudeView.setText(AltosDroid.pos(receiver.getLatitude(), "N", "S"));
-                       mReceiverLongitudeView.setText(AltosDroid.pos(receiver.getLongitude(), "W", "E"));
+                       mReceiverLongitudeView.setText(AltosDroid.pos(receiver.getLongitude(), "E", "W"));
                        center (receiver.getLatitude(), receiver.getLongitude(), accuracy);
                }
 
        }
+
+       public TabMap() {
+       }
 }
index 32df71d760a2543d55945f967ce2edfcd4a99a5f..0ac78219bf1f047c0deae317c9bb7be72e5ae866 100644 (file)
@@ -17,7 +17,7 @@
 
 package org.altusmetrum.AltosDroid;
 
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 import android.app.Activity;
 import android.os.Bundle;
@@ -163,7 +163,7 @@ public class TabPad extends AltosDroidTab {
                        if (receiver.hasAltitude())
                                altitude = receiver.getAltitude();
                        mPadLatitudeView.setText(AltosDroid.pos(receiver.getLatitude(), "N", "S"));
-                       mPadLongitudeView.setText(AltosDroid.pos(receiver.getLongitude(), "W", "E"));
+                       mPadLongitudeView.setText(AltosDroid.pos(receiver.getLongitude(), "E", "W"));
                        set_value(mPadAltitudeView, AltosConvert.height, 6, altitude);
                }
        }
index 49bcfb884d6fc94792b44746a8d48aae0cf81095..9764ab72c2f62f78630d45cb0df0021a8c7e278b 100644 (file)
@@ -1,6 +1,6 @@
 package org.altusmetrum.AltosDroid;
 
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 import android.content.BroadcastReceiver;
 import android.content.Context;
index 971c3e80ddab085af28e729d9e34e3197c25641c..4e4408d5edc0c44b5865f2a0520c8d84e23f246c 100644 (file)
@@ -25,7 +25,7 @@ import java.util.concurrent.*;
 import android.util.Log;
 import android.os.Handler;
 
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 
 public class TelemetryReader extends Thread {
@@ -40,8 +40,6 @@ public class TelemetryReader extends Thread {
        AltosLink   link;
        AltosState  state = null;
 
-       AltosFlightReader       stacked;
-
        LinkedBlockingQueue<AltosLine> telemQueue;
 
        public AltosState read() throws ParseException, AltosCRCException, InterruptedException, IOException {
@@ -59,10 +57,6 @@ public class TelemetryReader extends Thread {
 
        public void close() {
                state = null;
-               if (stacked != null) {
-                       stacked.close(false);
-                       stacked = null;
-               }
                link.remove_monitor(telemQueue);
                link = null;
                telemQueue.clear();
@@ -73,25 +67,6 @@ public class TelemetryReader extends Thread {
                AltosState  state = null;
 
                try {
-                       if (D) Log.d(TAG, "starting reader");
-                       while (stacked != null) {
-                               AltosState      stacked_state = null;
-                               try {
-                                       stacked_state = stacked.read();
-                               } catch (ParseException pe) {
-                                       continue;
-                               } catch (AltosCRCException ce) {
-                                       continue;
-                               }
-                               if (stacked_state != null)
-                                       state = stacked_state;
-                               else
-                                       stacked = null;
-                       }
-                       if (state != null) {
-                               if (D) Log.d(TAG, "Send initial state");
-                               handler.obtainMessage(TelemetryService.MSG_TELEMETRY, state).sendToTarget();
-                       }
                        if (D) Log.d(TAG, "starting loop");
                        while (telemQueue != null) {
                                try {
@@ -111,34 +86,16 @@ public class TelemetryReader extends Thread {
                }
        }
 
-       public TelemetryReader (AltosLink in_link, Handler in_handler, AltosFlightReader in_stacked) {
+       public TelemetryReader (AltosLink in_link, Handler in_handler, AltosState in_state) {
                if (D) Log.d(TAG, "connected TelemetryReader create started");
                link    = in_link;
                handler = in_handler;
-               stacked = in_stacked;
 
-               state = null;
+               state = in_state;
                telemQueue = new LinkedBlockingQueue<AltosLine>();
                link.add_monitor(telemQueue);
                link.set_telemetry(AltosLib.ao_telemetry_standard);
 
                if (D) Log.d(TAG, "connected TelemetryReader created");
        }
-
-       private static AltosFlightReader existing_data(AltosLink link) {
-               if (link == null)
-                       return null;
-
-               File    file = AltosPreferences.logfile(link.serial);
-               if (file != null) {
-                       AltosStateIterable      iterable = AltosStateIterable.iterable(file);
-                       if (iterable != null)
-                               return new AltosReplayReader(iterable.iterator(), file, false);
-               }
-               return null;
-       }
-
-       public TelemetryReader(AltosLink link, Handler handler) {
-               this(link, handler, existing_data(link));
-       }
 }
index 30d94409a917a339aeeed88b4de31ca560a843b5..d4ac66aabe76ba7c1168e556f249196267f451da 100644 (file)
@@ -45,7 +45,7 @@ import android.location.LocationManager;
 import android.location.LocationListener;
 import android.location.Criteria;
 
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 
 public class TelemetryService extends Service implements LocationListener {
@@ -139,6 +139,10 @@ public class TelemetryService extends Service implements LocationListener {
                        case MSG_TELEMETRY:
                                // forward telemetry messages
                                s.telemetry_state.state = (AltosState) msg.obj;
+                               if (s.telemetry_state.state != null) {
+                                       if (D) Log.d(TAG, "Save state");
+                                       AltosPreferences.set_state(0, s.telemetry_state.state, null);
+                               }
                                if (D) Log.d(TAG, "MSG_TELEMETRY");
                                s.sendMessageToClients();
                                break;
@@ -179,6 +183,8 @@ public class TelemetryService extends Service implements LocationListener {
        private Message message() {
                if (telemetry_state == null)
                        Log.d(TAG, "telemetry_state null!");
+               if (telemetry_state.state == null)
+                       Log.d(TAG, "telemetry_state.state null!");
                return Message.obtain(null, AltosDroid.MSG_STATE, telemetry_state);
        }
 
@@ -262,7 +268,7 @@ public class TelemetryService extends Service implements LocationListener {
                if (D) Log.d(TAG, "connected bluetooth configured");
                telemetry_state.connect = TelemetryState.CONNECT_CONNECTED;
 
-               mTelemetryReader = new TelemetryReader(mAltosBluetooth, mHandler);
+               mTelemetryReader = new TelemetryReader(mAltosBluetooth, mHandler, telemetry_state.state);
                mTelemetryReader.start();
 
                if (D) Log.d(TAG, "connected TelemetryReader started");
@@ -306,6 +312,13 @@ public class TelemetryService extends Service implements LocationListener {
 
                telemetry_state.connect = TelemetryState.CONNECT_READY;
 
+               AltosSavedState saved_state = AltosPreferences.state(0);
+
+               if (saved_state != null) {
+                       if (D) Log.d(TAG, String.format("recovered old state flight %d\n", saved_state.state.flight));
+                       telemetry_state.state = saved_state.state;
+               }
+
                // Start our timer - first event in 10 seconds, then every 10 seconds after that.
                timer.scheduleAtFixedRate(new TimerTask(){ public void run() {onTimerTick();}}, 10000L, 10000L);
 
index d3341739afb28bf53c75f0cc65afb3a589c5b2ff..862847d2b9af0982424e3ce20842fa47a466d842 100644 (file)
@@ -17,7 +17,7 @@
 
 package org.altusmetrum.AltosDroid;
 
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 import android.location.Location;
 
 public class TelemetryState {
index d91da4dab0235ec35742e142ad2b60dec8cb8165..b11dc3a119bebdf30423e061e3be625cae081c72 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
-public class AltosAccel extends AltosUnits {
+import java.io.*;
+
+public class AltosAccel extends AltosUnits implements Serializable {
 
        public double value(double v, boolean imperial_units) {
                if (imperial_units)
@@ -46,4 +48,4 @@ public class AltosAccel extends AltosUnits {
        public int show_fraction(int width, boolean imperial_units) {
                return width / 9;
        }
-}
\ No newline at end of file
+}
index 507c446bdbe05a6c550b2cfd56f8747dfd7c492d..4167aecfc201a0f706d52045c819cb7f88ec46d6 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 public class AltosCRCException extends Exception {
        public int rssi;
index 4a9278d901fefd1348120d4a5d72d4f75991cf8f..02f7806f0274636b30290c3565521bf645aa4f69 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.*;
 import java.util.*;
@@ -158,21 +158,14 @@ public class AltosCSV implements AltosWriter {
        }
 
        void write_advanced_header() {
-               out.printf("accel_x,accel_y,accel_z,gyro_x,gyro_y,gyro_z");
+               out.printf("accel_x,accel_y,accel_z,gyro_x,gyro_y,gyro_z,mag_x,mag_y,mag_z");
        }
 
        void write_advanced(AltosState state) {
-               AltosIMU        imu = state.imu;
-               AltosMag        mag = state.mag;
-
-               if (imu == null)
-                       imu = new AltosIMU();
-               if (mag == null)
-                       mag = new AltosMag();
                out.printf("%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f",
-                          imu.accel_x, imu.accel_y, imu.accel_z,
-                          imu.gyro_x, imu.gyro_y, imu.gyro_z,
-                          mag.x, mag.y, mag.z);
+                          state.accel_along(), state.accel_across(), state.accel_through(),
+                          state.gyro_roll(), state.gyro_pitch(), state.gyro_yaw(),
+                          state.mag_along(), state.mag_across(), state.mag_through());
        }
 
        void write_gps_header() {
@@ -381,7 +374,7 @@ public class AltosCSV implements AltosWriter {
                                has_basic = true;
                        if (state.battery_voltage != AltosLib.MISSING)
                                has_battery = true;
-                       if (state.imu != null || state.mag != null)
+                       if (state.accel_across() != AltosLib.MISSING)
                                has_advanced = true;
                        if (state.gps != null) {
                                has_gps = true;
index 47deb2a3dd1be6bb0212eb5ce767bd7d931ed8d2..8992b018775f2468913c91c604599fac5a8470d1 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
-public class AltosCompanion {
+import java.io.*;
+
+public class AltosCompanion implements Serializable {
        public final static int board_id_telescience = 0x0a;
        public final static int MAX_CHANNELS = 12;
 
index fc1f2442ebfa04fd66074a096449eda21022fdc3..d8f4d945e466bf5d9d8e61f35b721bd414e6ae31 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.util.*;
 import java.text.*;
@@ -90,6 +90,19 @@ public class AltosConfigData implements Iterable<String> {
        public int      tracker_motion;
        public int      tracker_interval;
 
+       /* HAS_GYRO */
+       public int      accel_zero_along, accel_zero_across, accel_zero_through;
+
+       /* ms5607 data */
+       public int      ms5607_reserved;
+       public int      ms5607_sens;
+       public int      ms5607_off;
+       public int      ms5607_tcs;
+       public int      ms5607_tco;
+       public int      ms5607_tref;
+       public int      ms5607_tempsens;
+       public int      ms5607_crc;
+
        public static String get_string(String line, String label) throws  ParseException {
                if (line.startsWith(label)) {
                        String  quoted = line.substring(label.length()).trim();
@@ -266,6 +279,10 @@ public class AltosConfigData implements Iterable<String> {
                storage_size = -1;
                storage_erase_unit = -1;
                stored_flight = 0;
+
+               accel_zero_along = -1;
+               accel_zero_across = -1;
+               accel_zero_through = -1;
        }
 
        public void parse_line(String line) {
@@ -282,6 +299,15 @@ public class AltosConfigData implements Iterable<String> {
 
                /* Version also contains MS5607 info, which we ignore here */
 
+               try { ms5607_reserved = get_int(line, "ms5607 reserved:"); } catch (Exception e) {}
+               try { ms5607_sens = get_int(line, "ms5607 sens:"); } catch (Exception e) {}
+               try { ms5607_off = get_int(line, "ms5607 off:"); } catch (Exception e) {}
+               try { ms5607_tcs = get_int(line, "ms5607 tcs:"); } catch (Exception e) {}
+               try { ms5607_tco = get_int(line, "ms5607 tco:"); } catch (Exception e) {}
+               try { ms5607_tref = get_int(line, "ms5607 tref:"); } catch (Exception e) {}
+               try { ms5607_tempsens = get_int(line, "ms5607 tempsens:"); } catch (Exception e) {}
+               try { ms5607_crc = get_int(line, "ms5607 crc:"); } catch (Exception e) {}
+
                /* Config show replies */
 
                /* HAS_FLIGHT */
@@ -361,6 +387,18 @@ public class AltosConfigData implements Iterable<String> {
 
                /* Log listing replies */
                try { get_int(line, "flight"); stored_flight++; }  catch (Exception e) {}
+
+               /* HAS_GYRO */
+               try {
+                       if (line.startsWith("IMU call along")) {
+                               String[] bits = line.split("\\s+");
+                               if (bits.length >= 8) {
+                                       accel_zero_along = Integer.parseInt(bits[3]);
+                                       accel_zero_across = Integer.parseInt(bits[5]);
+                                       accel_zero_through = Integer.parseInt(bits[7]);
+                               }
+                       }
+               } catch (Exception e) {}
        }
 
        public AltosConfigData() {
@@ -539,6 +577,14 @@ public class AltosConfigData implements Iterable<String> {
                dest.set_tracker_interval(tracker_interval);
        }
 
+       public boolean log_has_state() {
+               switch (log_format) {
+               case AltosLib.AO_LOG_FORMAT_TELEGPS:
+                       return false;
+               }
+               return true;
+       }
+
        public void save(AltosLink link, boolean remote) throws InterruptedException, TimeoutException {
 
                /* HAS_FLIGHT */
@@ -637,6 +683,9 @@ public class AltosConfigData implements Iterable<String> {
                if (tracker_motion >= 0 && tracker_interval >= 0)
                        link.printf("c t %d %d\n", tracker_motion, tracker_interval);
 
+               /* HAS_GYRO */
+               /* UI doesn't support accel cal */
+
                link.printf("c w\n");
                link.flush_output();
        }
index a932d3e38e6adf79be9c9b444279c652f0469e82..11aa4d24bcebdda00b17c3b8566749397eb86264 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 public class AltosConfigDataException extends Exception {
 
index 3f0a70758bf20ede9539ec3912f968b16079bab2..cfe9fc8b960302b3a0fe443c25e6d4bf3b07e3bc 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 public interface AltosConfigValues {
        /* set and get all of the dialog values */
index 18878c026dd01115501e87f8880a9bcb613feea6..a5eb7ff8258c578b5ffc2f28a1d2a94c72bb1d5e 100644 (file)
@@ -18,7 +18,7 @@
 /*
  * Sensor data conversion functions
  */
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 public class AltosConvert {
        /*
index e58fbaf2eafa12f5f1fd765dbc9ab1c0ddd18029..ef5edc6ac6b364924f12f81538aeacf13086e40f 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.*;
 
index 67bb58e9e65f5717a82f56b1ca0c3cca8a55a7ff..b0666f339317e04d46fd1430863a6ba2277b4db8 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 public class AltosDistance extends AltosUnits {
 
index 532c9f1d9c64f03a8c32391607edb77ab9b1ab7d..777988e74a554237b60ee79ccbafb9a1a0f6a62e 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.*;
 import java.util.*;
index 4d12f564057bc92e35ed21ec712269e6bb18f55c..19a8807df22b31bc3e490d6b8e3dd7bbfe29c028 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.text.*;
 import java.util.concurrent.*;
@@ -75,7 +75,8 @@ public class AltosEepromChunk {
                case AltosLib.AO_LOG_FORMAT_TELESCIENCE:
                        break;
                case AltosLib.AO_LOG_FORMAT_TELEMEGA:
-                       eeprom = new AltosEepromMega(this, offset);
+               case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
+                       eeprom = new AltosEepromMega(this, offset, log_format);
                        break;
                case AltosLib.AO_LOG_FORMAT_TELEMETRUM:
                        eeprom = new AltosEepromMetrum2(this, offset);
index a448ee645270ce6283ca743f0e3ce5bfaac03631..9598bd93e88456cc5f946ad6a3496f2a0103f424 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.*;
 import java.util.*;
@@ -75,7 +75,8 @@ public class AltosEepromDownload implements Runnable {
        }
 
        boolean                 done;
-       boolean                 start;
+       int                     prev_state;
+       int                     state_block;
 
        void LogEeprom(AltosEeprom r) throws IOException {
                if (r.cmd != AltosLib.AO_LOG_INVALID) {
@@ -140,7 +141,6 @@ public class AltosEepromDownload implements Runnable {
                state = new AltosState();
 
                done = false;
-               start = true;
 
                if (flights.config_data.serial < 0)
                        throw new IOException("no serial number found");
@@ -154,12 +154,8 @@ public class AltosEepromDownload implements Runnable {
                /* Now scan the eeprom, reading blocks of data and converting to .eeprom file form */
 
                state_block = log.start_block;
+               prev_state = AltosLib.ao_flight_startup;
                for (block = log.start_block; !done && block < log.end_block; block++) {
-                       monitor.set_value(state.state_name(),
-                                         state.state,
-                                         block - state_block,
-                                         block - log.start_block);
-
                        AltosEepromChunk        eechunk = new AltosEepromChunk(link, block, block == log.start_block);
 
                        /*
@@ -177,6 +173,16 @@ public class AltosEepromDownload implements Runnable {
                        }
 
                        CaptureEeprom (eechunk, log_format);
+
+                       if (state.state != prev_state && state.state != AltosLib.ao_flight_invalid) {
+                               state_block = block;
+                               prev_state = state.state;
+                       }
+
+                       monitor.set_value(state.state_name(),
+                                         state.state,
+                                         block - state_block,
+                                         block - log.start_block);
                }
                CheckFile(true);
                if (eeprom_file != null) {
@@ -254,7 +260,10 @@ public class AltosEepromDownload implements Runnable {
                flights = given_flights;
                success = false;
 
-               monitor.set_states(AltosLib.ao_flight_boost, AltosLib.ao_flight_landed);
+               if (flights.config_data.log_has_state())
+                       monitor.set_states(AltosLib.ao_flight_boost, AltosLib.ao_flight_landed);
+               else
+                       monitor.set_states(AltosLib.ao_flight_invalid, AltosLib.ao_flight_invalid);
 
                monitor.start();
        }
index a1579b550d86a0e0ce3c925cff7815d3505d7eaa..c8443549d10a9c267a04821787800238dfc31b42 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.*;
 import java.util.*;
@@ -94,7 +94,8 @@ public class AltosEepromFile extends AltosStateIterable {
                case AltosLib.AO_LOG_FORMAT_TELEMETRY:
                case AltosLib.AO_LOG_FORMAT_TELESCIENCE:
                case AltosLib.AO_LOG_FORMAT_TELEMEGA:
-                       body = new AltosEepromIterable(AltosEepromMega.read(input));
+               case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
+                       body = new AltosEepromIterable(AltosEepromMega.read(input, start.log_format));
                        break;
                case AltosLib.AO_LOG_FORMAT_TELEMETRUM:
                        body = new AltosEepromIterable(AltosEepromMetrum2.read(input));
index 8c991a6e392a822a5094c406a77f27967f158437..96cfc0e1fbc5c3b282578089fae0539d433d66f5 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.*;
 import java.util.*;
index 7103065526aa693283f38587ee474cae75791c61..fc4e9caadf79b56f3610988c6ca820cc60f0638c 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.*;
 import java.util.*;
@@ -25,7 +25,7 @@ public class AltosEepromHeader extends AltosEeprom {
 
        public int      cmd;
        public String   data;
-       public int      config_a, config_b;
+       public int      config_a, config_b, config_c;
        public boolean  last;
        public boolean  valid;
 
@@ -93,6 +93,9 @@ public class AltosEepromHeader extends AltosEeprom {
                        state.make_baro();
                        state.baro.crc = config_a;
                        break;
+               case AltosLib.AO_LOG_IMU_CAL:
+                       state.set_accel_zero(config_a, config_b, config_c);
+                       break;
                case AltosLib.AO_LOG_SOFTWARE_VERSION:
                        state.set_firmware_version(data);
                        break;
@@ -100,7 +103,10 @@ public class AltosEepromHeader extends AltosEeprom {
                case AltosLib.AO_LOG_APOGEE_LOCKOUT:
                case AltosLib.AO_LOG_RADIO_RATE:
                case AltosLib.AO_LOG_IGNITE_MODE:
+                       break;
                case AltosLib.AO_LOG_PAD_ORIENTATION:
+                       state.set_pad_orientation(config_a);
+                       break;
                case AltosLib.AO_LOG_RADIO_ENABLE:
                case AltosLib.AO_LOG_AES_KEY:
                case AltosLib.AO_LOG_APRS:
@@ -177,11 +183,17 @@ public class AltosEepromHeader extends AltosEeprom {
                case AltosLib.AO_LOG_BARO_CRC:
                        out.printf ("# Baro crc: %d\n", config_a);
                        break;
+               case AltosLib.AO_LOG_IMU_CAL:
+                       out.printf ("# IMU cal: %d %d %d\n", config_a, config_b, config_c);
+                       break;
                case AltosLib.AO_LOG_FREQUENCY:
                case AltosLib.AO_LOG_APOGEE_LOCKOUT:
                case AltosLib.AO_LOG_RADIO_RATE:
                case AltosLib.AO_LOG_IGNITE_MODE:
+                       break;
                case AltosLib.AO_LOG_PAD_ORIENTATION:
+                       out.printf("# Pad orientation: %d\n", config_a);
+                       break;
                case AltosLib.AO_LOG_RADIO_ENABLE:
                case AltosLib.AO_LOG_AES_KEY:
                case AltosLib.AO_LOG_APRS:
@@ -273,6 +285,14 @@ public class AltosEepromHeader extends AltosEeprom {
                                        cmd = AltosLib.AO_LOG_INVALID;
                                        data = tokens[2];
                                }
+                       } else if (tokens[0].equals("IMU") && tokens[1].equals("cal")) {
+                               cmd = AltosLib.AO_LOG_IMU_CAL;
+                               config_a = Integer.parseInt(tokens[3]);
+                               config_b = Integer.parseInt(tokens[5]);
+                               config_c = Integer.parseInt(tokens[7]);
+                       } else if (tokens[0].equals("Pad") && tokens[1].equals("orientation:")) {
+                               cmd = AltosLib.AO_LOG_PAD_ORIENTATION;
+                               config_a = Integer.parseInt(tokens[2]);
                        } else
                                valid = false;
                } catch (Exception e) {
index dd0afd9f1501bd347683f5cd10871e78a12669f8..94487ab52ee04f53fb982ae0e5cce8907fcbae85 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.*;
 import java.util.*;
index 740499d302139f7c353110e8006291815ca52e5e..39768a21b6dc87cde3985e671f5b27f55d0b6e50 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.*;
 import java.util.*;
index 5a11fa5441196d1a409eeb278d1e20586fc00424..0fc82ab453732d61b4d9f3c40a20872b1694279e 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.text.*;
 import java.util.concurrent.*;
index adaa7f3197f84a1a0d1a5a9b99518fed9bcfa53d..c2edcf233926d842824cb7f8c6b8c28df0a2aa01 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.*;
 import java.util.*;
@@ -26,6 +26,8 @@ public class AltosEepromMega extends AltosEeprom {
 
        public static final int max_sat = 12;
 
+       private int log_format;
+
        public int record_length() { return record_length; }
 
        /* AO_LOG_FLIGHT elements */
@@ -35,9 +37,36 @@ public class AltosEepromMega extends AltosEeprom {
        public int ground_accel_along() { return data16(8); }
        public int ground_accel_across() { return data16(10); }
        public int ground_accel_through() { return data16(12); }
-       public int ground_roll() { return data16(14); }
-       public int ground_pitch() { return data16(16); }
-       public int ground_yaw() { return data16(18); }
+       public int ground_roll() {
+               switch (log_format) {
+               case AltosLib.AO_LOG_FORMAT_TELEMEGA:
+                       return data32(16);
+               case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
+                       return data16(14);
+               default:
+                       return AltosLib.MISSING;
+               }
+       }
+       public int ground_pitch() {
+               switch (log_format) {
+               case AltosLib.AO_LOG_FORMAT_TELEMEGA:
+                       return data32(20);
+               case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
+                       return data16(16);
+               default:
+                       return AltosLib.MISSING;
+               }
+       }
+       public int ground_yaw() {
+               switch (log_format) {
+               case AltosLib.AO_LOG_FORMAT_TELEMEGA:
+                       return data32(24);
+               case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
+                       return data16(18);
+               default:
+                       return AltosLib.MISSING;
+               }
+       }
 
        /* AO_LOG_STATE elements */
        public int state() { return data16(0); }
@@ -89,7 +118,8 @@ public class AltosEepromMega extends AltosEeprom {
        public int svid(int n) { return data8(2 + n * 2); }
        public int c_n(int n) { return data8(2 + n * 2 + 1); }
 
-       public AltosEepromMega (AltosEepromChunk chunk, int start) throws ParseException {
+       public AltosEepromMega (AltosEepromChunk chunk, int start, int log_format) throws ParseException {
+               this.log_format = log_format;
                parse_chunk(chunk, start);
        }
 
@@ -119,6 +149,12 @@ public class AltosEepromMega extends AltosEeprom {
                        state.set_flight(flight());
                        state.set_ground_accel(ground_accel());
                        state.set_ground_pressure(ground_pres());
+                       state.set_accel_ground(ground_accel_along(),
+                                              ground_accel_across(),
+                                              ground_accel_through());
+                       state.set_gyro_zero(ground_roll() / 512.0,
+                                           ground_pitch() / 512.0,
+                                           ground_yaw() / 512.0);
                        break;
                case AltosLib.AO_LOG_STATE:
                        state.set_tick(tick);
@@ -128,22 +164,21 @@ public class AltosEepromMega extends AltosEeprom {
                        state.set_tick(tick);
                        state.set_ms5607(pres(), temp());
 
-                       AltosIMU imu = new AltosIMU();
-                       imu.accel_x = AltosIMU.convert_accel(accel_x());
-                       imu.accel_y = AltosIMU.convert_accel(accel_y());
-                       imu.accel_z = AltosIMU.convert_accel(accel_z());
+                       AltosIMU        imu = new AltosIMU(accel_y(),   /* along */
+                                                          accel_x(),   /* across */
+                                                          accel_z(),   /* through */
+                                                          gyro_y(),    /* roll */
+                                                          gyro_x(),    /* pitch */
+                                                          gyro_z());   /* yaw */
 
-                       imu.gyro_x = AltosIMU.convert_gyro(gyro_x());
-                       imu.gyro_y = AltosIMU.convert_gyro(gyro_y());
-                       imu.gyro_z = AltosIMU.convert_gyro(gyro_z());
-                       state.imu = imu;
+                       if (log_format == AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD)
+                               state.check_imu_wrap(imu);
 
-                       AltosMag mag = new AltosMag();
-                       mag.x = AltosMag.convert_gauss(mag_x());
-                       mag.y = AltosMag.convert_gauss(mag_y());
-                       mag.z = AltosMag.convert_gauss(mag_z());
+                       state.set_imu(imu);
 
-                       state.mag = mag;
+                       state.set_mag(new AltosMag(mag_x(),
+                                                  mag_y(),
+                                                  mag_z()));
 
                        state.set_accel(accel());
 
@@ -221,11 +256,12 @@ public class AltosEepromMega extends AltosEeprom {
                }
        }
 
-       public AltosEepromMega (String line) {
+       public AltosEepromMega (String line, int log_format) {
+               this.log_format = log_format;
                parse_string(line);
        }
 
-       static public LinkedList<AltosEeprom> read(FileInputStream input) {
+       static public LinkedList<AltosEeprom> read(FileInputStream input, int log_format) {
                LinkedList<AltosEeprom> megas = new LinkedList<AltosEeprom>();
 
                for (;;) {
@@ -234,7 +270,7 @@ public class AltosEepromMega extends AltosEeprom {
                                if (line == null)
                                        break;
                                try {
-                                       AltosEepromMega mega = new AltosEepromMega(line);
+                                       AltosEepromMega mega = new AltosEepromMega(line, log_format);
                                        if (mega.cmd != AltosLib.AO_LOG_INVALID)
                                                megas.add(mega);
                                } catch (Exception e) {
index d9a65989d8f19bd4e833506d50d97424cbf541b9..39425e100c0aa5ac82d6f353dd2dc5286fa49544 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.*;
 import java.util.*;
index f197539eb5c6bf0d66775c217a6a072adff2e5fd..ef13d0a72ffcbc45d084f67eb3d49399ac039c3c 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.*;
 import java.util.*;
index 173a2cd82f680dca096838f710328d28ec18f14f..35ed5a6e0fb8107c06aad08cd04dab568f385611 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 public interface AltosEepromMonitor {
 
index 6d36cf47a9e1ed87169c71641e9d19c1106bb6d0..2bdd64f0da171aed6e58b038367f8f9217ac648b 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.*;
 import java.util.*;
index 81b42f21eb74e0de9eb2f7721eafa7b08113cf38..36500393ebd1e076c11a83f2d3c4e9f837747c4c 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.*;
 import java.util.*;
index ba639a046fd95516983a104624fb58c5676255ca..a79216a2682d3eddf518c78882d63cd2ce1d983d 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.File;
 import java.util.*;
index a8519550d98b62dd4e757243ce5f435a4d51409e..e58b652e702477ebc12f3701c9f0cffe5b260e14 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.*;
 
index 7a51c3305c2c7ef6ed210d3ad90cad72f8142474..1c7cd77db0d6fec54b77a4efbea4224d191a1056 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 public interface AltosFlashListener {
        public void position(String label, int percent);
index be103838a2ccd683df7dd48f47c1d9a91a142b9d..03c53ff4d8f7c580ecfdf126723048663b8d29ab 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.text.*;
 import java.io.*;
index 1b88cb9fc7e56e7b8b2abf7ae308571837c862ad..82e477f8e2fd1d2b6d3d63889e30665c7d4eb2d8 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.*;
 
@@ -37,6 +37,8 @@ public class AltosFlightStats {
        public double           pad_lat, pad_lon;
        public boolean          has_flight_data;
        public boolean          has_gps;
+       public boolean          has_gps_sats;
+       public boolean          has_gps_detail;
        public boolean          has_flight_adc;
        public boolean          has_battery;
        public boolean          has_rssi;
@@ -113,6 +115,7 @@ public class AltosFlightStats {
                lat = lon = AltosLib.MISSING;
                has_flight_data = false;
                has_gps = false;
+               has_gps_sats = false;
                has_flight_adc = false;
                has_battery = false;
                has_rssi = false;
@@ -174,6 +177,10 @@ public class AltosFlightStats {
                                lat = state.gps.lat;
                                lon = state.gps.lon;
                                has_gps = true;
+                               if (state.gps.cc_gps_sat != null)
+                                       has_gps_sats = true;
+                               if (state.gps.course != AltosLib.MISSING)
+                                       has_gps_detail = true;
                        }
                        if (state.imu != null)
                                has_imu = true;
index 6093df495700498ce8646795b545a277c4552001..1dd4819dbff1335c4f6a98c6f4ebaa89566ecd5c 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 public class AltosFrequency {
        public double   frequency;
index 0154e95d7c96d3231d831d18973010a32f1989f9..2139efb22fe3e6c106c963a43dab2a1b308dba5f 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.text.*;
 import java.util.concurrent.*;
+import java.io.*;
 
-public class AltosGPS implements Cloneable {
+public class AltosGPS implements Cloneable, Serializable {
 
        public final static int MISSING = AltosLib.MISSING;
 
@@ -377,6 +378,7 @@ public class AltosGPS implements Cloneable {
 
        public AltosGPS (AltosLink link, AltosConfigData config_data) throws TimeoutException, InterruptedException {
                boolean says_done = config_data.compare_version("1.0") >= 0;
+               init();
                link.printf("g\n");
                for (;;) {
                        String line = link.get_reply_no_dialog(5000);
index adbcbe61ad2bfbec023fad34b721fd948414ff46..57491f4d91553cda5feba62a4ce36e118bbc2f22 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 public class AltosGPSSat {
        public int      svid;
index 716eeef98396c61ad3ec3d6f063143ad4cfe1d8e..c48755be4f73e11d8d3c8f301b159ac0fafe90c3 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.lang.Math;
+import java.io.*;
 
-public class AltosGreatCircle implements Cloneable {
+public class AltosGreatCircle implements Cloneable, Serializable {
        public double   distance;
        public double   bearing;
        public double   range;
index 8c67e043960ecbb7cb37463a3d758714aa05452c..c4419ae6d385c994deaaf2b65b1062c7a0d75cd0 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 public class AltosHeight extends AltosUnits {
 
index 9ee64bdc72e585871bbeabc63e63c0a5e96229f6..9f45d65ac52bc8dac7fd62e7dbf020bc8d85f553 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.*;
 import java.util.LinkedList;
index 52eb81db0354e1a0cea00dd4ba627277f7b67853..0c61fd02461740c337a86570d39252310ff50d2c 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 public class AltosHexsym {
        String  name;
index 89d7def4a3bb2066b5ff1adbdd364107dd575ad3..8c219d9f163464eec3d796ce28adfeb50e816ef7 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.util.concurrent.*;
+import java.io.*;
 
-public class AltosIMU implements Cloneable {
-       public double           accel_x;
-       public double           accel_y;
-       public double           accel_z;
+public class AltosIMU implements Cloneable, Serializable {
+       public int              accel_along;
+       public int              accel_across;
+       public int              accel_through;
 
-       public double           gyro_x;
-       public double           gyro_y;
-       public double           gyro_z;
+       public int              gyro_roll;
+       public int              gyro_pitch;
+       public int              gyro_yaw;
 
-/*
- * XXX use ground measurements to adjust values
-
-       public double           ground_accel_x;
-       public double           ground_accel_y;
-       public double           ground_accel_z;
-
-       public double           ground_gyro_x;
-       public double           ground_gyro_y;
-       public double           ground_gyro_z;
-*/
-
-       public static int       counts_per_g = 2048;
+       public static double    counts_per_g = 2048.0;
 
-       public static double convert_accel(int counts) {
-               return (double) counts / (double) counts_per_g * (-AltosConvert.GRAVITATIONAL_ACCELERATION);
+       public static double convert_accel(double counts) {
+               return counts / counts_per_g * (-AltosConvert.GRAVITATIONAL_ACCELERATION);
        }
 
        public static double    counts_per_degsec = 16.4;
 
-       public static double convert_gyro(int counts) {
-               return (double) counts / counts_per_degsec;
+       public static double convert_gyro(double counts) {
+               return counts / counts_per_degsec;
        }
 
        public boolean parse_string(String line) {
@@ -59,12 +48,12 @@ public class AltosIMU implements Cloneable {
                String[] items = line.split("\\s+");
 
                if (items.length >= 8) {
-                       accel_x = convert_accel(Integer.parseInt(items[1]));
-                       accel_y = convert_accel(Integer.parseInt(items[2]));
-                       accel_z = convert_accel(Integer.parseInt(items[3]));
-                       gyro_x = convert_gyro(Integer.parseInt(items[5]));
-                       gyro_y = convert_gyro(Integer.parseInt(items[6]));
-                       gyro_z = convert_gyro(Integer.parseInt(items[7]));
+                       accel_along = Integer.parseInt(items[1]);
+                       accel_across = Integer.parseInt(items[2]);
+                       accel_through = Integer.parseInt(items[3]);
+                       gyro_roll = Integer.parseInt(items[5]);
+                       gyro_pitch = Integer.parseInt(items[6]);
+                       gyro_yaw = Integer.parseInt(items[7]);
                }
                return true;
        }
@@ -72,13 +61,13 @@ public class AltosIMU implements Cloneable {
        public AltosIMU clone() {
                AltosIMU        n = new AltosIMU();
 
-               n.accel_x = accel_x;
-               n.accel_y = accel_y;
-               n.accel_z = accel_z;
+               n.accel_along = accel_along;
+               n.accel_across = accel_across;
+               n.accel_through = accel_through;
 
-               n.gyro_x = gyro_x;
-               n.gyro_y = gyro_y;
-               n.gyro_z = gyro_z;
+               n.gyro_roll = gyro_roll;
+               n.gyro_pitch = gyro_pitch;
+               n.gyro_yaw = gyro_yaw;
                return n;
        }
 
@@ -93,13 +82,25 @@ public class AltosIMU implements Cloneable {
        }
 
        public AltosIMU() {
-               accel_x = AltosLib.MISSING;
-               accel_y = AltosLib.MISSING;
-               accel_z = AltosLib.MISSING;
+               accel_along = AltosLib.MISSING;
+               accel_across = AltosLib.MISSING;
+               accel_through = AltosLib.MISSING;
+
+               gyro_roll = AltosLib.MISSING;
+               gyro_pitch = AltosLib.MISSING;
+               gyro_yaw = AltosLib.MISSING;
+       }
+
+       public AltosIMU(int accel_along, int accel_across, int accel_through,
+                       int gyro_roll, int gyro_pitch, int gyro_yaw) {
+
+               this.accel_along = accel_along;
+               this.accel_across = accel_across;
+               this.accel_through = accel_through;
 
-               gyro_x = AltosLib.MISSING;
-               gyro_y = AltosLib.MISSING;
-               gyro_z = AltosLib.MISSING;
+               this.gyro_roll = gyro_roll;
+               this.gyro_pitch = gyro_pitch;
+               this.gyro_yaw = gyro_yaw;
        }
 
        public AltosIMU(AltosLink link) throws InterruptedException, TimeoutException {
index 0f723d142293e299e1d1ccf7fdd84b4a04132efa..82b18ca23934d583b9d43a660a808632bbb79e22 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.*;
 import java.util.*;
index 50745d9755d9be1436932d62c848615bdb51f255..4c5e8285a7d3c7459b85a9484f55dc17ee978f11 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.*;
 import java.util.*;
@@ -38,6 +38,7 @@ class AltosIdler {
        static final int        idle_sensor_mega = 12;
        static final int        idle_sensor_emini = 13;
        static final int        idle_sensor_tmini = 14;
+       static final int        idle_sensor_tgps = 15;
 
        public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException, TimeoutException {
                for (int idler : idlers) {
@@ -72,6 +73,10 @@ class AltosIdler {
                                break;
                        case idle_sensor_tmini:
                                AltosSensorTMini.update_state(state, link, config_data);
+                               break;
+                       case idle_sensor_tgps:
+                               AltosSensorTGPS.update_state(state, link, config_data);
+                               break;
                        }
                        if (idle != null)
                                idle.update_state(state);
@@ -122,6 +127,9 @@ public class AltosIdleFetch implements AltosStateUpdate {
                               AltosIdler.idle_ms5607, AltosIdler.idle_mma655x,
                               AltosIdler.idle_imu, AltosIdler.idle_mag,
                               AltosIdler.idle_sensor_mega),
+               new AltosIdler("TeleGPS",
+                              AltosIdler.idle_gps,
+                              AltosIdler.idle_sensor_tgps),
        };
 
        AltosLink               link;
@@ -131,8 +139,9 @@ public class AltosIdleFetch implements AltosStateUpdate {
 
        public void update_state(AltosState state) throws InterruptedException {
                try {
+                       /* Fetch config data from remote */
                        AltosConfigData config_data = new AltosConfigData(link);
-                       state.set_state(AltosLib.ao_flight_startup);
+                       state.set_state(AltosLib.ao_flight_stateless);
                        state.set_serial(config_data.serial);
                        state.set_callsign(config_data.callsign);
                        state.set_ground_accel(config_data.accel_cal_plus);
index 85bcff10d295e3a7920ba511b29b72727858123b..4d0968bf3d26c3e36f95173c4efde83afcbc1e84 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.*;
 import java.util.concurrent.*;
@@ -35,20 +35,6 @@ public class AltosIdleMonitor extends Thread {
        AltosConfigData         config_data;
        AltosGPS                gps;
 
-       int AltosRSSI() throws TimeoutException, InterruptedException {
-               link.printf("s\n");
-               String line = link.get_reply_no_dialog(5000);
-               if (line == null)
-                       throw new TimeoutException();
-               String[] items = line.split("\\s+");
-               if (items.length < 2)
-                       return 0;
-               if (!items[0].equals("RSSI:"))
-                       return 0;
-               int rssi = Integer.parseInt(items[1]);
-               return rssi;
-       }
-
        void start_link() throws InterruptedException, TimeoutException {
                if (remote) {
                        link.set_radio_frequency(frequency);
@@ -58,26 +44,30 @@ public class AltosIdleMonitor extends Thread {
                        link.flush_input();
        }
 
-       void stop_link() throws InterruptedException, TimeoutException {
+       boolean stop_link() throws InterruptedException, TimeoutException {
                if (remote)
                        link.stop_remote();
+               return link.reply_abort;
        }
 
-       void update_state(AltosState state) throws InterruptedException, TimeoutException {
+       boolean update_state(AltosState state) throws InterruptedException, TimeoutException {
                boolean         worked = false;
+               boolean         aborted = false;
 
                try {
                        start_link();
                        fetch.update_state(state);
-                       worked = true;
+                       if (!link.has_error && !link.reply_abort)
+                               worked = true;
                } finally {
-                       stop_link();
+                       aborted = stop_link();
                        if (worked) {
                                if (remote)
                                        state.set_rssi(link.rssi(), 0);
                                listener_state.battery = link.monitor_battery();
                        }
                }
+               return aborted;
        }
 
        public void set_frequency(double in_frequency) {
@@ -102,13 +92,17 @@ public class AltosIdleMonitor extends Thread {
        public void run() {
                AltosState state = new AltosState();
                try {
-                       while (!link.has_error) {
+                       for (;;) {
                                try {
                                        link.config_data();
                                        update_state(state);
                                        listener.update(state, listener_state);
                                } catch (TimeoutException te) {
                                }
+                               if (link.has_error || link.reply_abort) {
+                                       listener.failed();
+                                       break;
+                               }
                                Thread.sleep(1000);
                        }
                } catch (InterruptedException ie) {
index 4382430c667634acb9995078e0d5ec009e7cdee5..fdf4be9d6469813d7ce9380dd77d9971e41de9b4 100644 (file)
@@ -15,8 +15,9 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 public interface AltosIdleMonitorListener {
        public void update(AltosState state, AltosListenerState listener_state);
-}
\ No newline at end of file
+       public void failed();
+}
index b458911ec61884d4bd144a5b50d934d8fd2fc454..ffb6ed158d1e74d6bef8afaef9fa1ac80ade351b 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.util.*;
 import java.io.*;
index e701fda3ade3f3791b71f0271ec1d221f8688e8c..aa80fc21dd8465ee5ac17769c5179343ef440cdf 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.*;
 
index 2b5071734bcd618f700e5158e9abcfbe30728f18..191a46eeb011a40e93692226664accba8aecf243 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 public class AltosLatitude extends AltosLocation {
        public String pos() { return "N"; }
index 2e9dc6486a1907f2dc7027de20f3157adba84556..b19f9f524c8385206d87edc2b6a77bdb22ad6054 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.util.*;
 import java.io.*;
@@ -74,6 +74,7 @@ public class AltosLib {
        public static final int AO_LOG_BARO_TREF = 3006;
        public static final int AO_LOG_BARO_TEMPSENS = 3007;
        public static final int AO_LOG_BARO_CRC = 3008;
+       public static final int AO_LOG_IMU_CAL = 3009;
 
        public static final int AO_LOG_SOFTWARE_VERSION = 9999;
 
@@ -113,6 +114,9 @@ public class AltosLib {
        public final static int product_easymini = 0x0026;
        public final static int product_telemini = 0x0027;
        public final static int product_easymega = 0x0028;
+       public final static int product_usbtrng = 0x0029;
+       public final static int product_usbrelay = 0x002a;
+       public final static int product_mpusb = 0x002b;
        public final static int product_altusmetrum_min = 0x000a;
        public final static int product_altusmetrum_max = 0x002c;
 
@@ -187,6 +191,7 @@ public class AltosLib {
        };
 
        public static final String launch_sites_url = "http://www.altusmetrum.org/AltOS/launch-sites.txt";
+//     public static final String launch_sites_url = "file:///home/keithp/misc/text/altusmetrum/AltOS/launch-sites.txt";
 
        public static final int ao_telemetry_standard_len = 32;
        public static final int ao_telemetry_0_9_len = 95;
@@ -315,11 +320,12 @@ public class AltosLib {
        public static final int AO_LOG_FORMAT_TINY = 2;
        public static final int AO_LOG_FORMAT_TELEMETRY = 3;
        public static final int AO_LOG_FORMAT_TELESCIENCE = 4;
-       public static final int AO_LOG_FORMAT_TELEMEGA = 5;
+       public static final int AO_LOG_FORMAT_TELEMEGA_OLD = 5;
        public static final int AO_LOG_FORMAT_EASYMINI = 6;
        public static final int AO_LOG_FORMAT_TELEMETRUM = 7;
        public static final int AO_LOG_FORMAT_TELEMINI = 8;
        public static final int AO_LOG_FORMAT_TELEGPS = 9;
+       public static final int AO_LOG_FORMAT_TELEMEGA = 10;
        public static final int AO_LOG_FORMAT_NONE = 127;
 
        public static boolean isspace(int c) {
index f56938c6a116201c5035e7c820874aef1300215b..a65ba59314237f10f86d1a71e2615ed7d59d8821 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 public class AltosLine {
        public String   line;
index 62bd82b93c2ae617c4d67a305696e99a32bd3ba7..01c378645d23c52fe3bee3416be39b605de05383 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.*;
 import java.util.concurrent.*;
@@ -55,8 +55,11 @@ public abstract class AltosLink implements Runnable {
 
        public void printf(String format, Object ... arguments) {
                String  line = String.format(format, arguments);
-               if (debug)
-                       pending_output.add(line);
+               if (debug) {
+                       synchronized (pending_output) {
+                               pending_output.add(line);
+                       }
+               }
                try {
                        print(line);
                } catch (InterruptedException ie) {
@@ -286,12 +289,14 @@ public abstract class AltosLink implements Runnable {
                binary_queue.put(dup);
        }
 
-       public void flush_output() {
+       public synchronized void flush_output() {
                if (pending_output == null)
                        return;
-               for (String s : pending_output)
-                       System.out.print(s);
-               pending_output.clear();
+               synchronized (pending_output) {
+                       for (String s : pending_output)
+                               System.out.print(s);
+                       pending_output.clear();
+               }
        }
 
        public void flush_input(int timeout) throws InterruptedException {
@@ -381,7 +386,7 @@ public abstract class AltosLink implements Runnable {
                flush_output();
        }
 
-       public void set_monitor(boolean monitor) {
+       public synchronized void set_monitor(boolean monitor) {
                monitor_mode = monitor;
                if (monitor)
                        printf("m %x\n", telemetry_len());
@@ -390,6 +395,10 @@ public abstract class AltosLink implements Runnable {
                flush_output();
        }
 
+       public synchronized boolean get_monitor() {
+               return monitor_mode;
+       }
+
        private void set_channel(int channel) {
                if (monitor_mode)
                        printf("m 0\nc r %d\nm %x\n",
@@ -422,8 +431,10 @@ public abstract class AltosLink implements Runnable {
 
        public void set_callsign(String callsign) {
                this.callsign = callsign;
-               printf ("c c %s\n", callsign);
-               flush_output();
+               if (callsign != null) {
+                       printf ("c c %s\n", callsign);
+                       flush_output();
+               }
        }
 
        public boolean is_loader() throws InterruptedException {
@@ -462,7 +473,7 @@ public abstract class AltosLink implements Runnable {
                if (telemetry_rate < 0)
                        telemetry_rate = AltosPreferences.telemetry_rate(serial);
                set_telemetry_rate(telemetry_rate);
-               if (callsign.equals(""))
+               if (callsign == null || callsign.equals(""))
                        callsign = AltosPreferences.callsign();
                set_callsign(callsign);
                printf("p\nE 0\n");
index 054ff1d06431d12bab7eb88bbc02c4012be94c9b..d7e180080aaf9c67f0a68e48bd3503ea522ec592 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
-public class AltosListenerState {
+import java.io.*;
+
+public class AltosListenerState implements Serializable {
        public int      crc_errors;
        public double   battery;
+       public boolean  running;
 
        public AltosListenerState() {
                crc_errors = 0;
                battery = AltosLib.MISSING;
+               running = true;
        }
 }
index 9bbbb8990c2ae948d542e194a483595ac46a5589..b21014db0a416a4398fb2a81e49c38d8a83829b3 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 public abstract class AltosLocation extends AltosUnits {
 
index 28116e3dcdb801a062199a8c7c8f070b1a72b1f8..9241581a2049e0f8c303307173c5a611cd5799b5 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.*;
 import java.text.*;
index dbcd6bf026cf9afa6b447e95ec8539f3c8df9674..ff4f0c2b01ea5419c94597c01a967591639a4b7f 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 public class AltosLongitude extends AltosLocation {
        public String pos() { return "E"; }
index 690241f13e53c98ed97da0a8a76a0ef2c51aaaf6..f7595639378c489726170b5d4dd23f76f243862e 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.util.concurrent.*;
+import java.io.*;
 
-public class AltosMag implements Cloneable {
-       public double           x;
-       public double           y;
-       public double           z;
+public class AltosMag implements Cloneable, Serializable {
+       public int              along;
+       public int              across;
+       public int              through;
 
        public static double counts_per_gauss = 1090;
 
-       public static double convert_gauss(int counts) {
-               return (double) counts / counts_per_gauss;
+       public static double convert_gauss(double counts) {
+               return counts / counts_per_gauss;
        }
 
        public boolean parse_string(String line) {
 //             if (line.startsWith("Syntax error")) {
-//                     x = y = z = 0;
+//                     along = across = through = 0;
 //                     return true;
 //             }
 
@@ -42,9 +43,9 @@ public class AltosMag implements Cloneable {
                String[] items = line.split("\\s+");
 
                if (items.length >= 6) {
-                       x = convert_gauss(Integer.parseInt(items[1]));
-                       y = convert_gauss(Integer.parseInt(items[3]));
-                       z = convert_gauss(Integer.parseInt(items[5]));
+                       along = Integer.parseInt(items[1]);
+                       across = Integer.parseInt(items[3]);
+                       through = Integer.parseInt(items[5]);
                }
                return true;
        }
@@ -52,16 +53,22 @@ public class AltosMag implements Cloneable {
        public AltosMag clone() {
                AltosMag n = new AltosMag();
 
-               n.x = x;
-               n.y = y;
-               n.z = z;
+               n.along = along;
+               n.across = across;
+               n.through = through;
                return n;
        }
 
        public AltosMag() {
-               x = AltosLib.MISSING;
-               y = AltosLib.MISSING;
-               z = AltosLib.MISSING;
+               along = AltosLib.MISSING;
+               across = AltosLib.MISSING;
+               through = AltosLib.MISSING;
+       }
+
+       public AltosMag(int along, int across, int through) {
+               this.along = along;
+               this.across = across;
+               this.through = through;
        }
 
        static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException {
index 7f0dab98f421621c70aea8d063f6dd5299fa2b07..c0b94b8cc7ef7dcbdaac671dae6b70eee6e01650 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.util.concurrent.*;
 
index 81e0641c2d9a8f42301dffbfba4fb29483ca8e49..2bd4ba8fe717d194dc9eb1f1006a375b0ad0edda 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.util.concurrent.*;
+import java.io.*;
 
-public class AltosMs5607 {
+public class AltosMs5607 implements Serializable {
        public int      reserved;
        public int      sens;
        public int      off;
@@ -126,7 +127,7 @@ public class AltosMs5607 {
 
        static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException {
                try {
-                       AltosMs5607     ms5607 = new AltosMs5607(link);
+                       AltosMs5607     ms5607 = new AltosMs5607(link, config_data);
 
                        if (ms5607 != null) {
                                state.set_ms5607(ms5607);
@@ -143,9 +144,17 @@ public class AltosMs5607 {
                cc = AltosLib.MISSING;
        }
 
-       public AltosMs5607 (AltosLink link) throws InterruptedException, TimeoutException {
+       public AltosMs5607 (AltosLink link, AltosConfigData config_data) throws InterruptedException, TimeoutException {
                this();
-               link.printf("c s\nB\n");
+               reserved = config_data.ms5607_reserved;
+               sens = config_data.ms5607_sens;
+               off = config_data.ms5607_off;
+               tcs = config_data.ms5607_tcs;
+               tco = config_data.ms5607_tco;
+               tref = config_data.ms5607_tref;
+               tempsens = config_data.ms5607_tempsens;
+               crc = config_data.ms5607_crc;
+               link.printf("B\n");
                for (;;) {
                        String line = link.get_reply_no_dialog(5000);
                        if (line == null) {
index d436c3f1a78d577abe5d03f035c31c640b44d5dd..77410a258c348d966eca946939eefa8054505c4f 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 public class AltosNoSymbol extends Exception {
        public AltosNoSymbol(String name) {
index 348c6844a6d5894bd50dbe24c77890443eea0eaa..8cdde75006c645fe9a64904757dc6c5d936bce39 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 public class AltosOrient extends AltosUnits {
 
index 9cb99a0d452e3689270f4432247fe798d3e0257d..2fb69c15ce40de247537c22377f422d15afcbf18 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.text.*;
 
index dba57dcb73d055f0509257e809346c721dacde92..5aa45d3f5d992745bf03afceddd983bde97ecb37 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.*;
 import java.util.*;
@@ -41,6 +41,9 @@ public class AltosPreferences {
        /* log file format preference name */
        public final static String logfilePreferenceFormat = "LOGFILE-%d";
 
+       /* state preference name */
+       public final static String statePreferenceFormat = "STATE-%d";
+
        /* voice preference name */
        public final static String voicePreference = "VOICE";
 
@@ -333,6 +336,48 @@ public class AltosPreferences {
                }
        }
 
+       public static void set_state(int serial, AltosState state, AltosListenerState listener_state) {
+
+               ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+               try {
+                       ObjectOutputStream oos = new ObjectOutputStream(baos);
+
+                       AltosSavedState saved_state = new AltosSavedState(state, listener_state);
+                       oos.writeObject(saved_state);
+
+                       byte[] bytes = baos.toByteArray();
+
+                       synchronized(backend) {
+                               backend.putBytes(String.format(statePreferenceFormat, serial), bytes);
+                               flush_preferences();
+                       }
+               } catch (IOException ie) {
+               }
+       }
+
+       public static AltosSavedState state(int serial) {
+               byte[] bytes = null;
+
+               synchronized(backend) {
+                       bytes = backend.getBytes(String.format(statePreferenceFormat, serial), null);
+               }
+
+               if (bytes == null)
+                       return null;
+
+               ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+
+               try {
+                       ObjectInputStream ois = new ObjectInputStream(bais);
+                       AltosSavedState saved_state = (AltosSavedState) ois.readObject();
+                       return saved_state;
+               } catch (IOException ie) {
+               } catch (ClassNotFoundException ce) {
+               }
+               return null;
+       }
+
        public static void set_scanning_telemetry(int new_scanning_telemetry) {
                synchronized (backend) {
                        scanning_telemetry = new_scanning_telemetry;
index 76a99acbb1ef82187d034d34885e457c37649a5f..c83eaa478c0ecceca4dbf9278b316221e8b63a87 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.File;
 
@@ -33,6 +33,9 @@ public interface AltosPreferencesBackend {
        public boolean getBoolean(String key, boolean def);
        public void    putBoolean(String key, boolean value);
 
+       public byte[]  getBytes(String key, byte[] def);
+       public void    putBytes(String key, byte[] value);
+
        public boolean nodeExists(String key);
        public AltosPreferencesBackend node(String key);
 
index 443082d50b08f01a8e5c7a450faadbb6c9a24535..7a92c2d07c1b6961800d078cbb63bf349f8eb1a5 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.*;
 
index 60b8fe5242648c14eaccf96fe7133d1fab80a3f8..502e34def0d386270237cfe84c2423b609ea03a9 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.util.*;
 import java.text.*;
diff --git a/altoslib/AltosQuaternion.java b/altoslib/AltosQuaternion.java
new file mode 100644 (file)
index 0000000..4ad1f3d
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * Copyright © 2014 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altoslib_6;
+
+public class AltosQuaternion {
+       double  r;              /* real bit */
+       double  x, y, z;        /* imaginary bits */
+
+       public AltosQuaternion multiply(AltosQuaternion b) {
+               return new AltosQuaternion(
+                       this.r * b.r - this.x * b.x - this.y * b.y - this.z * b.z,
+                       this.r * b.x + this.x * b.r + this.y * b.z - this.z * b.y,
+                       this.r * b.y - this.x * b.z + this.y * b.r + this.z * b.x,
+                       this.r * b.z + this.x * b.y - this.y * b.x + this.z * b.r);
+       }
+
+       public AltosQuaternion conjugate() {
+               return new AltosQuaternion(
+                       this.r,
+                       -this.x,
+                       -this.y,
+                       -this.z);
+       }
+
+       public double normal() {
+               return (this.r * this.r +
+                       this.x * this.x +
+                       this.y * this.y +
+                       this.z * this.z);
+       }
+
+       public AltosQuaternion scale(double b) {
+               return new AltosQuaternion(
+                       this.r * b,
+                       this.x * b,
+                       this.y * b,
+                       this.z * b);
+       }
+
+       public AltosQuaternion normalize() {
+               double  n = normal();
+               if (n <= 0)
+                       return this;
+               return scale(1/Math.sqrt(n));
+       }
+
+       public double dot(AltosQuaternion b) {
+               return (this.r * b.r +
+                       this.x * b.x +
+                       this.y * b.y +
+                       this.z * b.z);
+       }
+
+       public AltosQuaternion rotate(AltosQuaternion b) {
+               return (b.multiply(this)).multiply(b.conjugate());
+       }
+
+       public AltosQuaternion vectors_to_rotation(AltosQuaternion b) {
+               /*
+                * The cross product will point orthogonally to the two
+                * vectors, forming our rotation axis. The length will be
+                * sin(θ), so these values are already multiplied by that.
+                */
+
+               double x = this.y * b.z - this.z * b.y;
+               double y = this.z * b.x - this.x * b.z;
+               double z = this.x * b.y - this.y * b.x;
+
+               double s_2 = x*x + y*y + z*z;
+               double s = Math.sqrt(s_2);
+
+               /* cos(θ) = a · b / (|a| |b|).
+                *
+                * a and b are both unit vectors, so the divisor is one
+                */
+               double c = this.x*b.x + this.y*b.y + this.z*b.z;
+
+               double c_half = Math.sqrt ((1 + c) / 2);
+               double s_half = Math.sqrt ((1 - c) / 2);
+
+               /*
+                * Divide out the sine factor from the
+                * cross product, then multiply in the
+                * half sine factor needed for the quaternion
+                */
+               double s_scale = s_half / s;
+
+               AltosQuaternion r = new AltosQuaternion(c_half,
+                                                       x * s_scale,
+                                                       y * s_scale,
+                                                       z * s_scale);
+               return r.normalize();
+       }
+
+       public AltosQuaternion(double r, double x, double y, double z) {
+               this.r = r;
+               this.x = x;
+               this.y = y;
+               this.z = z;
+       }
+
+       public AltosQuaternion(AltosQuaternion q) {
+               this.r = q.r;
+               this.x = q.x;
+               this.y = q.y;
+               this.z = q.z;
+       }
+
+       static public AltosQuaternion vector(double x, double y, double z) {
+               return new AltosQuaternion(0, x, y, z);
+       }
+
+       static public AltosQuaternion rotation(double x, double y, double z,
+                                              double s, double c) {
+               return new AltosQuaternion(c,
+                                          s*x,
+                                          s*y,
+                                          s*z);
+       }
+
+       static public AltosQuaternion zero_rotation() {
+               return new AltosQuaternion(1, 0, 0, 0);
+       }
+
+       static public AltosQuaternion half_euler(double x, double y, double z) {
+               double  s_x = Math.sin(x), c_x = Math.cos(x);
+               double  s_y = Math.sin(y), c_y = Math.cos(y);
+               double  s_z = Math.sin(z), c_z = Math.cos(z);;
+
+               return new AltosQuaternion(c_x * c_y * c_z + s_x * s_y * s_z,
+                                          s_x * c_y * c_z - c_x * s_y * s_z,
+                                          c_x * s_y * c_z + s_x * c_y * s_z,
+                                          c_x * c_y * s_z - s_x * s_y * c_z);
+       }
+}
index 2864e02a272bb0ba60f27407b0fdf03d27803c0d..98f0e7d59f45a3a59f1d5d8feecd3cec97f68597 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.*;
 import java.util.*;
@@ -27,7 +27,6 @@ import java.util.*;
 public class AltosReplayReader extends AltosFlightReader {
        Iterator<AltosState>    iterator;
        File    file;
-       boolean real_time;
 
        public AltosState read() {
                if (iterator.hasNext())
@@ -40,22 +39,16 @@ public class AltosReplayReader extends AltosFlightReader {
 
        public void update(AltosState state) throws InterruptedException {
                /* Make it run in realtime after the rocket leaves the pad */
-               if (real_time && state.state > AltosLib.ao_flight_pad && state.time_change > 0)
-                       Thread.sleep((int) (Math.min(state.time_change,10) * 1000));
+               if (state.state > AltosLib.ao_flight_pad && state.time_change > 0)
+                       Thread.sleep((int) (Math.min(state.time_change,10) * 100));
                state.set_received_time(System.currentTimeMillis());
        }
 
        public File backing_file() { return file; }
 
-       public AltosReplayReader(Iterator<AltosState> in_iterator, File in_file,
-                                boolean in_real_time) {
+       public AltosReplayReader(Iterator<AltosState> in_iterator, File in_file) {
                iterator = in_iterator;
                file = in_file;
-               real_time = in_real_time;
                name = file.getName();
        }
-
-       public AltosReplayReader(Iterator<AltosState> in_iterator, File in_file) {
-               this(in_iterator, in_file, false);
-       }
 }
index d0de5492752e9de6ee3f8417d047f764dc4135c4..c93a01c3b1bfda4fb783f06ce1359f9dba028d46 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.*;
 
diff --git a/altoslib/AltosRotation.java b/altoslib/AltosRotation.java
new file mode 100644 (file)
index 0000000..49225f7
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright © 2014 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altoslib_6;
+
+public class AltosRotation {
+       private AltosQuaternion         rotation;
+
+       public double tilt() {
+               double  rotz = rotation.z * rotation.z - rotation.y * rotation.y - rotation.x * rotation.x + rotation.r * rotation.r;
+
+               double tilt = Math.acos(rotz) * 180.0 / Math.PI;
+               return tilt;
+       }
+
+       public void rotate(double dt, double x, double y, double z) {
+               AltosQuaternion rot = AltosQuaternion.half_euler(x * dt, y * dt, z * dt);
+               rotation = rot.multiply(rotation).normalize();
+       }
+
+       /* Clone an existing rotation value */
+       public AltosRotation (AltosRotation old) {
+               this.rotation = new AltosQuaternion(old.rotation);
+       }
+
+       /* Create a new rotation value given an acceleration vector pointing down */
+       public AltosRotation(double x,
+                            double y,
+                            double z,
+                            int pad_orientation) {
+               AltosQuaternion orient = AltosQuaternion.vector(x, y, z).normalize();
+               double sky = pad_orientation == 0 ? 1 : -1;
+               AltosQuaternion up = new AltosQuaternion(0, 0, 0, sky);
+               rotation = up.vectors_to_rotation(orient);
+       }
+}
diff --git a/altoslib/AltosSavedState.java b/altoslib/AltosSavedState.java
new file mode 100644 (file)
index 0000000..552e453
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright © 2014 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altoslib_6;
+
+import java.io.*;
+
+public class AltosSavedState implements Serializable {
+       public AltosState               state;
+       public AltosListenerState       listener_state;
+
+       public AltosSavedState(AltosState state, AltosListenerState listener_state) {
+               this.state = state;
+               this.listener_state = listener_state;
+       }
+}
index 3ec692132ebfc1999674f5001d841696454baed5..83be4be16ac938bc294790572c6bf529adae5eb3 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.*;
 
index 53a8e998845aab74ccbc70c058ae769dceb5e59d..cb8356a199f7a75c55069c1edd6d9efb7483e424 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.util.concurrent.TimeoutException;
 
index cdc2ac42ace48eef971dd55ff6ed372f91220f5e..9d5649aa56cee7b959b2f07d2d8e5c236a724981 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.util.concurrent.TimeoutException;
 
index 3c7213eb370b0e40c0e62847ce2b0495dd0d6085..a3c2a033abbdb279fcefd1ea3af163b9e13f1fe0 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.util.concurrent.TimeoutException;
 
index d977e886c7d762717719b95f241ba2725153e818..39592b50f27e72da555ca68a48c366b4bb86a357 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.util.concurrent.TimeoutException;
 
diff --git a/altoslib/AltosSensorTGPS.java b/altoslib/AltosSensorTGPS.java
new file mode 100644 (file)
index 0000000..32607fb
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright © 2015 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altoslib_6;
+
+import java.util.concurrent.TimeoutException;
+
+public class AltosSensorTGPS {
+       public int      tick;
+       public int      batt;
+
+       static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException {
+               try {
+                       AltosSensorTGPS sensor_tgps = new AltosSensorTGPS(link);
+
+                       if (sensor_tgps == null)
+                               return;
+                       state.set_battery_voltage(AltosConvert.tele_gps_voltage(sensor_tgps.batt));
+
+               } catch (TimeoutException te) {
+               }
+       }
+
+       public AltosSensorTGPS(AltosLink link) throws InterruptedException, TimeoutException {
+               String[] items = link.adc();
+               for (int i = 0; i < items.length - 1;) {
+                       if (items[i].equals("tick:")) {
+                               tick = Integer.parseInt(items[i+1]);
+                               i += 2;
+                               continue;
+                       }
+                       if (items[i].equals("batt:")) {
+                               batt = Integer.parseInt(items[i+1]);
+                               i += 2;
+                               continue;
+                       }
+                       i++;
+               }
+       }
+}
+
index 344e7449d6ce909abe4666d731f0432af2aa24af..c82ba93c92eb1890b531dd9183e8c993da361862 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.util.concurrent.TimeoutException;
 
index edd76da2e00dcd5c50d3562953f62b7fd772dab5..0fc70e7191f60a9aa8833abe37f3c5eb8b0df610 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.util.concurrent.TimeoutException;
 
index d2f86214f228b9206ada035f9193d9a60dc10e53..b714412fa49e77b317f08ca23bdc479e1c8949e3 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 public class AltosSpeed extends AltosUnits {
 
index 5fce15c43865e63b43447db93f59faf725f838f7..d363027cb214242c88799fc98bc8d4cdedd58291 100644 (file)
  * Track flight state from telemetry or eeprom data stream
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
-public class AltosState implements Cloneable {
+import java.io.*;
+
+public class AltosState implements Cloneable, Serializable {
 
        public static final int set_position = 1;
        public static final int set_gps = 2;
@@ -43,9 +45,9 @@ public class AltosState implements Cloneable {
        private int     prev_tick;
        public int      boost_tick;
 
-       class AltosValue {
-               private double  value;
-               private double  prev_value;
+       class AltosValue implements Serializable{
+               double  value;
+               double  prev_value;
                private double  max_value;
                private double  set_time;
                private double  prev_set_time;
@@ -179,9 +181,20 @@ public class AltosState implements Cloneable {
                }
        }
 
-       class AltosCValue {
-               AltosValue      measured;
-               AltosValue      computed;
+       class AltosCValue implements Serializable {
+
+               class AltosIValue extends AltosValue implements Serializable {
+                       boolean can_max() {
+                               return c_can_max();
+                       }
+               };
+
+               public AltosIValue      measured;
+               public AltosIValue      computed;
+
+               boolean can_max() { return true; }
+
+               boolean c_can_max() { return can_max(); }
 
                double value() {
                        double v = measured.value();
@@ -263,8 +276,8 @@ public class AltosState implements Cloneable {
                }
 
                AltosCValue() {
-                       measured = new AltosValue();
-                       computed = new AltosValue();
+                       measured = new AltosIValue();
+                       computed = new AltosIValue();
                }
        }
 
@@ -301,7 +314,7 @@ public class AltosState implements Cloneable {
                ground_altitude.set_measured(a, time);
        }
 
-       class AltosGpsGroundAltitude extends AltosValue {
+       class AltosGpsGroundAltitude extends AltosValue implements Serializable {
                void set(double a, double t) {
                        super.set(a, t);
                        pad_alt = value();
@@ -325,7 +338,7 @@ public class AltosState implements Cloneable {
                gps_ground_altitude.set(a, time);
        }
 
-       class AltosGroundPressure extends AltosCValue {
+       class AltosGroundPressure extends AltosCValue implements Serializable {
                void set_filtered(double p, double time) {
                        computed.set_filtered(p, time);
                        if (!is_measured())
@@ -348,7 +361,7 @@ public class AltosState implements Cloneable {
                ground_pressure.set_measured(pressure, time);
        }
 
-       class AltosAltitude extends AltosCValue {
+       class AltosAltitude extends AltosCValue implements Serializable {
 
                private void set_speed(AltosValue v) {
                        if (!acceleration.is_measured() || !ascent)
@@ -370,7 +383,7 @@ public class AltosState implements Cloneable {
 
        private AltosAltitude   altitude;
 
-       class AltosGpsAltitude extends AltosValue {
+       class AltosGpsAltitude extends AltosValue implements Serializable {
 
                private void set_gps_height() {
                        double  a = value();
@@ -453,7 +466,7 @@ public class AltosState implements Cloneable {
                return gps_speed.max();
        }
 
-       class AltosPressure extends AltosValue {
+       class AltosPressure extends AltosValue implements Serializable {
                void set(double p, double time) {
                        super.set(p, time);
                        if (state == AltosLib.ao_flight_pad)
@@ -523,7 +536,7 @@ public class AltosState implements Cloneable {
                return AltosLib.MISSING;
        }
 
-       class AltosSpeed extends AltosCValue {
+       class AltosSpeed extends AltosCValue implements Serializable {
 
                boolean can_max() {
                        return state < AltosLib.ao_flight_fast || state == AltosLib.ao_flight_stateless;
@@ -577,7 +590,7 @@ public class AltosState implements Cloneable {
                return AltosLib.MISSING;
        }
 
-       class AltosAccel extends AltosCValue {
+       class AltosAccel extends AltosCValue implements Serializable {
 
                boolean can_max() {
                        return state < AltosLib.ao_flight_fast || state == AltosLib.ao_flight_stateless;
@@ -600,10 +613,10 @@ public class AltosState implements Cloneable {
                return acceleration.max();
        }
 
-       public AltosValue       orient;
+       public AltosCValue      orient;
 
        public void set_orient(double new_orient) {
-               orient.set(new_orient, time);
+               orient.set_measured(new_orient, time);
        }
 
        public double orient() {
@@ -713,7 +726,7 @@ public class AltosState implements Cloneable {
                pressure = new AltosPressure();
                speed = new AltosSpeed();
                acceleration = new AltosAccel();
-               orient = new AltosValue();
+               orient = new AltosCValue();
 
                temperature = AltosLib.MISSING;
                battery_voltage = AltosLib.MISSING;
@@ -733,7 +746,24 @@ public class AltosState implements Cloneable {
                gps_pending = false;
 
                imu = null;
+               last_imu_time = AltosLib.MISSING;
+               rotation = null;
+               ground_rotation = null;
+
                mag = null;
+               accel_zero_along = AltosLib.MISSING;
+               accel_zero_across = AltosLib.MISSING;
+               accel_zero_through = AltosLib.MISSING;
+
+               accel_ground_along = AltosLib.MISSING;
+               accel_ground_across = AltosLib.MISSING;
+               accel_ground_through = AltosLib.MISSING;
+
+               pad_orientation = AltosLib.MISSING;
+
+               gyro_zero_roll = AltosLib.MISSING;
+               gyro_zero_pitch = AltosLib.MISSING;
+               gyro_zero_yaw = AltosLib.MISSING;
 
                set_npad(0);
                ngps = 0;
@@ -861,6 +891,27 @@ public class AltosState implements Cloneable {
                        imu = old.imu.clone();
                else
                        imu = null;
+               last_imu_time = old.last_imu_time;
+
+               if (old.rotation != null)
+                       rotation = new AltosRotation (old.rotation);
+
+               if (old.ground_rotation != null) {
+                       ground_rotation = new AltosRotation(old.ground_rotation);
+               }
+
+               accel_zero_along = old.accel_zero_along;
+               accel_zero_across = old.accel_zero_across;
+               accel_zero_through = old.accel_zero_through;
+
+               accel_ground_along = old.accel_ground_along;
+               accel_ground_across = old.accel_ground_across;
+               accel_ground_through = old.accel_ground_through;
+               pad_orientation = old.pad_orientation;
+
+               gyro_zero_roll = old.gyro_zero_roll;
+               gyro_zero_pitch = old.gyro_zero_pitch;
+               gyro_zero_yaw = old.gyro_zero_yaw;
 
                if (old.mag != null)
                        mag = old.mag.clone();
@@ -1112,16 +1163,170 @@ public class AltosState implements Cloneable {
                }
        }
 
+
+       public double   accel_zero_along;
+       public double   accel_zero_across;
+       public double   accel_zero_through;
+
+       public AltosRotation    rotation;
+       public AltosRotation    ground_rotation;
+
+       public void set_accel_zero(double zero_along, double zero_across, double zero_through) {
+               if (zero_along != AltosLib.MISSING) {
+                       accel_zero_along = zero_along;
+                       accel_zero_across = zero_across;
+                       accel_zero_through = zero_through;
+               }
+       }
+
+       public int pad_orientation;
+
+       public double   accel_ground_along, accel_ground_across, accel_ground_through;
+
+       void update_pad_rotation() {
+               if (pad_orientation != AltosLib.MISSING && accel_ground_along != AltosLib.MISSING) {
+                       rotation = new AltosRotation(AltosIMU.convert_accel(accel_ground_across - accel_zero_across),
+                                                    AltosIMU.convert_accel(accel_ground_through - accel_zero_through),
+                                                    AltosIMU.convert_accel(accel_ground_along - accel_zero_along),
+                                                    pad_orientation);
+                       ground_rotation = rotation;
+                       orient.set_computed(rotation.tilt(), time);
+               }
+       }
+
+       public void set_accel_ground(double ground_along, double ground_across, double ground_through) {
+               accel_ground_along = ground_along;
+               accel_ground_across = ground_across;
+               accel_ground_through = ground_through;
+               update_pad_rotation();
+       }
+
+       public void set_pad_orientation(int pad_orientation) {
+               this.pad_orientation = pad_orientation;
+               update_pad_rotation();
+       }
+
+       public double   gyro_zero_roll;
+       public double   gyro_zero_pitch;
+       public double   gyro_zero_yaw;
+
+       public void set_gyro_zero(double roll, double pitch, double yaw) {
+               if (roll != AltosLib.MISSING) {
+                       gyro_zero_roll = roll;
+                       gyro_zero_pitch = pitch;
+                       gyro_zero_yaw = yaw;
+               }
+       }
+
+       public double   last_imu_time;
+
+       private double radians(double degrees) {
+               if (degrees == AltosLib.MISSING)
+                       return AltosLib.MISSING;
+               return degrees * Math.PI / 180.0;
+       }
+
+       private void update_orient() {
+               if (last_imu_time != AltosLib.MISSING) {
+                       double  t = time - last_imu_time;
+
+                       double  pitch = radians(gyro_pitch());
+                       double  yaw = radians(gyro_yaw());
+                       double  roll = radians(gyro_roll());
+
+                       if (t > 0 & pitch != AltosLib.MISSING && rotation != null) {
+                               rotation.rotate(t, pitch, yaw, roll);
+                               orient.set_computed(rotation.tilt(), time);
+                       }
+               }
+               last_imu_time = time;
+       }
+
        public void set_imu(AltosIMU imu) {
                if (imu != null)
                        imu = imu.clone();
                this.imu = imu;
+               update_orient();
+       }
+
+       private double gyro_zero_overflow(double first) {
+               double v = first / 128.0;
+               if (v < 0)
+                       v = Math.ceil(v);
+               else
+                       v = Math.floor(v);
+               return v * 128.0;
+       }
+
+       public void check_imu_wrap(AltosIMU imu) {
+               if (this.imu == null) {
+                       gyro_zero_roll += gyro_zero_overflow(imu.gyro_roll);
+                       gyro_zero_pitch += gyro_zero_overflow(imu.gyro_pitch);
+                       gyro_zero_yaw += gyro_zero_overflow(imu.gyro_yaw);
+               }
+       }
+
+       public double accel_along() {
+               if (imu != null && accel_zero_along != AltosLib.MISSING)
+                       return AltosIMU.convert_accel(imu.accel_along - accel_zero_along);
+               return AltosLib.MISSING;
+       }
+
+       public double accel_across() {
+               if (imu != null && accel_zero_across != AltosLib.MISSING)
+                       return AltosIMU.convert_accel(imu.accel_across - accel_zero_across);
+               return AltosLib.MISSING;
+       }
+
+       public double accel_through() {
+               if (imu != null && accel_zero_through != AltosLib.MISSING)
+                       return AltosIMU.convert_accel(imu.accel_through - accel_zero_through);
+               return AltosLib.MISSING;
+       }
+
+       public double gyro_roll() {
+               if (imu != null && gyro_zero_roll != AltosLib.MISSING) {
+                       return AltosIMU.convert_gyro(imu.gyro_roll - gyro_zero_roll);
+               }
+               return AltosLib.MISSING;
+       }
+
+       public double gyro_pitch() {
+               if (imu != null && gyro_zero_pitch != AltosLib.MISSING) {
+                       return AltosIMU.convert_gyro(imu.gyro_pitch - gyro_zero_pitch);
+               }
+               return AltosLib.MISSING;
+       }
+
+       public double gyro_yaw() {
+               if (imu != null && gyro_zero_yaw != AltosLib.MISSING) {
+                       return AltosIMU.convert_gyro(imu.gyro_yaw - gyro_zero_yaw);
+               }
+               return AltosLib.MISSING;
        }
 
        public void set_mag(AltosMag mag) {
                this.mag = mag.clone();
        }
 
+       public double mag_along() {
+               if (mag != null)
+                       return AltosMag.convert_gauss(mag.along);
+               return AltosLib.MISSING;
+       }
+
+       public double mag_across() {
+               if (mag != null)
+                       return AltosMag.convert_gauss(mag.across);
+               return AltosLib.MISSING;
+       }
+
+       public double mag_through() {
+               if (mag != null)
+                       return AltosMag.convert_gauss(mag.through);
+               return AltosLib.MISSING;
+       }
+
        public AltosMs5607 make_baro() {
                if (baro == null)
                        baro = new AltosMs5607();
index 4154b71ceec90a8d77473e0432977b0c47ae6f32..3b58fc32e8485ce430a0fe8894e983d83039607d 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.*;
 import java.util.*;
index 70530f756623e201c46dfe0bd4dcd3a6ba455bed..93b9f1c03f4c96fba2552df7f84353ce955e0413 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 public interface AltosStateUpdate {
        public void     update_state(AltosState state) throws InterruptedException;
index a123d7528145471a9944b1fa95fd6c9f7a611bc3..449384d528ef5c8ed66dc7fcce3ec2b78942a28b 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.text.*;
 
index f578e6adc5404f8e5ce2f99a0ae363a174b6fd9e..8c922b03fa24b1340870e865ce176ba7be9a12eb 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 
 public class AltosTelemetryConfiguration extends AltosTelemetryStandard {
index 15344b8dba5f06464f482b13aee3817fc3125990..738e4dd7e4a636215703f957a617bcae1002d96c 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.*;
 import java.util.*;
index ac42597d5935e7a7da957b95a7ef68883828d8ae..131389d58ece005a1ec8c6d2626dd7031e3510d3 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.io.*;
 import java.util.*;
index 72a8bc4a0750b6faeb0c95b12f11f1045f4e49ac..923d139e911290187aeb65b594eb2223ae09d34b 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.text.*;
 
index 427ae16ebed3552459ebf5487854201320a568c2..85da27d5b8642aec301eef9fc895d2ed96432f59 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 
 public class AltosTelemetryLocation extends AltosTelemetryStandard {
index 758311eb21560e0c3affd41416c52d0bb6177139..e8c02e9be8533da4ac8bc762acff31008171c263 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 import java.text.*;
 import java.util.HashMap;
 
index d949c02f3bc233fcc937e17150841f5184daf495..2b80df4a91f673b26d2e83b0efa2dc32d09ba0a2 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 public class AltosTelemetryMegaData extends AltosTelemetryStandard {
        int     state;
index 1b568c88cea80b47ca45bc6edc5d63559b32514d..a01c0826ab27a11d73f62d236a97696285cec49e 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 public class AltosTelemetryMegaSensor extends AltosTelemetryStandard {
        int     accel;
@@ -66,24 +66,13 @@ public class AltosTelemetryMegaSensor extends AltosTelemetryStandard {
 
                state.set_orient(orient);
 
-               AltosIMU imu = new AltosIMU();
+               state.set_imu(new AltosIMU(accel_y,     /* along */
+                                          accel_x,     /* across */
+                                          accel_z,     /* through */
+                                          gyro_y,      /* along */
+                                          gyro_x,      /* across */
+                                          gyro_z));    /* through */
 
-               imu.accel_x = AltosIMU.convert_accel(accel_x);
-               imu.accel_y = AltosIMU.convert_accel(accel_y);
-               imu.accel_z = AltosIMU.convert_accel(accel_z);
-
-               imu.gyro_x = AltosIMU.convert_gyro(gyro_x);
-               imu.gyro_y = AltosIMU.convert_gyro(gyro_y);
-               imu.gyro_z = AltosIMU.convert_gyro(gyro_z);
-
-               state.imu = imu;
-
-               AltosMag mag = new AltosMag();
-
-               mag.x = AltosMag.convert_gauss(mag_x);
-               mag.y = AltosMag.convert_gauss(mag_y);
-               mag.z = AltosMag.convert_gauss(mag_z);
-
-               state.mag = mag;
+               state.set_mag(new AltosMag(mag_x, mag_y, mag_z));
        }
 }
index 3377d969b972034fc6e4390cb3544b14cf27ade8..e53f12838836148a604dffe6d4616b204ec671a0 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 
 public class AltosTelemetryMetrumData extends AltosTelemetryStandard {
index beab6da99f18e9a3180b321e735be57f1c7d2620..415b00a6e56e22d73decb024ececcb54810a123a 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 
 public class AltosTelemetryMetrumSensor extends AltosTelemetryStandard {
index 221bb67c5fea9535c1808a881f2d888a4dfa0f16..02537c9c0843fcb80c8268507e16c2d1e9344cda 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 
 public class AltosTelemetryMini extends AltosTelemetryStandard {
index 2a535e84e1de290655e3364f8128f4a1dcdc10d4..4254fc8391655d01d7f539d39df4f3c90146a9ab 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 public class AltosTelemetryRaw extends AltosTelemetryStandard {
        public AltosTelemetryRaw(int[] bytes) {
index 20526a2c584b95d4780a54cfae4a5ef73fa2718f..908fb5c7480c451f6c7692cd4f3300c6bc638511 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 import java.text.*;
 import java.io.*;
@@ -28,20 +28,16 @@ public class AltosTelemetryReader extends AltosFlightReader {
        int             telemetry;
        int             telemetry_rate;
        AltosState      state = null;
-       AltosFlightReader       stacked;
 
        LinkedBlockingQueue<AltosLine> telem;
 
        public AltosState read() throws InterruptedException, ParseException, AltosCRCException, IOException {
-               if (stacked != null) {
-                       state = stacked.read();
-                       if (state != null)
-                               return state;
-                       stacked = null;
-               }
-               AltosLine l = telem.take();
-               if (l.line == null)
-                       throw new IOException("IO error");
+               AltosLine l;
+               do {
+                       l = telem.take();
+                       if (l.line == null)
+                               throw new IOException("IO error");
+               } while (!link.get_monitor());
                AltosTelemetry  telem = AltosTelemetry.parse(l.line);
                if (state == null)
                        state = new AltosState();
@@ -57,15 +53,11 @@ public class AltosTelemetryReader extends AltosFlightReader {
 
        public void reset() {
                flush();
+               state = null;
        }
 
        public void close(boolean interrupted) {
 
-               if (stacked != null) {
-                       stacked.close(interrupted);
-                       stacked = null;
-               }
-
                link.remove_monitor(telem);
                log.close();
                try {
@@ -161,10 +153,9 @@ public class AltosTelemetryReader extends AltosFlightReader {
                return link.monitor_battery();
        }
 
-       public AltosTelemetryReader (AltosLink in_link, AltosFlightReader in_stacked)
+       public AltosTelemetryReader (AltosLink in_link)
                throws IOException, InterruptedException, TimeoutException {
                link = in_link;
-               stacked = in_stacked;
                boolean success = false;
                try {
                        log = new AltosLog(link);
@@ -183,22 +174,4 @@ public class AltosTelemetryReader extends AltosFlightReader {
                                close(true);
                }
        }
-
-       private static AltosFlightReader existing_data(AltosLink link) {
-               if (link == null)
-                       return null;
-
-               File    file = AltosPreferences.logfile(link.serial);
-               if (file != null) {
-                       AltosStateIterable      iterable = AltosStateIterable.iterable(file);
-                       if (iterable != null)
-                               return new AltosReplayReader(iterable.iterator(), file, false);
-               }
-               return null;
-       }
-
-       public AltosTelemetryReader(AltosLink link)
-               throws IOException, InterruptedException, TimeoutException {
-               this(link, null);
-       }
 }
index d1cdaf6de12a54755be85e283c97b2b18d11bd64..474789ba6bcd97f3e99f9f56531959de6d250723 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 public class AltosTelemetrySatellite extends AltosTelemetryStandard {
        int             channels;
index fc3fe8589040c6af8d25a02b3495b451ef3b8061..b0c84fd358b80fe9c2cbc7ce05b37ddef269e542 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 
 public class AltosTelemetrySensor extends AltosTelemetryStandard {
index f4dfd8e9665953dc58987c972022e313bc176e27..fb8a162e6a00f6e1fae1de2aae17ef4829a2c39f 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 public abstract class AltosTelemetryStandard extends AltosTelemetry {
        int[]   bytes;
index e654fada4c2b235f51ae49388838fb5b0c4c4115..494f4e3e5c73d6f75ff7fb0b0d08dffa0e66fc9e 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 public class AltosTemperature extends AltosUnits {
 
index dbdb788248ee150826ea272732e72ddb4d693da3..f6e34e773ed36e153d46dd8e6d8be2a0972d4624 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 public abstract class AltosUnits {
 
index 664aed67cf77a571c65fc310f53bf5472826f838..1b66eb45a349d2021ef82a6d8b6e15c59058a9a6 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 public interface AltosUnitsListener {
        public void units_changed(boolean imperial_units);
index 22bd1aeec201a235353448302e3f47209dba29a1..986d74b40f7694208df071f1b6cc4fb486bf3747 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 public class AltosVoltage extends AltosUnits {
 
index fb208b02989bc77590d09a10ef5fd224aff6f3f7..b125bd872c681707dc0b26943c912550c49b15b1 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
 
 public interface AltosWriter {
 
index 0ad9b7dad226236c8d8b1212bb9794c92fa60f65..c640c69cadf1fffda78cecad47ed7dac9ca0529d 100644 (file)
@@ -82,6 +82,7 @@ altoslib_JAVA = \
        AltosProgrammer.java \
        AltosReplayReader.java \
        AltosRomconfig.java \
+       AltosSavedState.java \
        AltosSelfFlash.java \
        AltosSensorMM.java \
        AltosSensorEMini.java \
@@ -89,6 +90,7 @@ altoslib_JAVA = \
        AltosSensorTMini.java \
        AltosSensorMega.java \
        AltosSensorMetrum.java \
+       AltosSensorTGPS.java \
        AltosState.java \
        AltosStateIterable.java \
        AltosStateUpdate.java \
@@ -124,7 +126,9 @@ altoslib_JAVA = \
        AltosLatitude.java \
        AltosLongitude.java \
        AltosPyro.java \
-       AltosWriter.java
+       AltosWriter.java \
+       AltosQuaternion.java \
+       AltosRotation.java
 
 JAR=altoslib_$(ALTOSLIB_VERSION).jar
 
index a9b80aa4dbcbaaf12bf0a44bb286737fbaefb112..556973a62f84877b5efa85c6c25f26922b28a735 100644 (file)
@@ -17,7 +17,7 @@ Altos-Linux-*.tar.bz2
 Altos-Linux-*.sh
 Altos-Mac-*.zip
 Altos-Windows-*.exe
-.desktop
+*.desktop
 *.dll
 *.dylib
 *.so
index 74b45f1c97027ac32e1263cb1311798856750303..e82931b23499c809d0fe89d4d506779d5514779d 100644 (file)
@@ -20,8 +20,8 @@ package altosui;
 import java.awt.*;
 import libaltosJNI.*;
 
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class Altos extends AltosUILib {
 
index 24fc362fb424e2abd6d0d91ba388930a84928b7e..10080efd47896b8bfd05a2b52f55b38636951331 100644 (file)
@@ -21,8 +21,8 @@ import java.util.*;
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class AltosAscent extends AltosUIFlightTab {
        JLabel  cur, max;
index 7ac53dd8ca9418ceb56cb184ffff4cbdca4e4c59..68dab227481e0f75d126464f31821e6942f37064 100644 (file)
@@ -19,8 +19,8 @@ package altosui;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class AltosCompanionInfo extends JTable implements AltosFlightDisplay {
        private AltosFlightInfoTableModel model;
index 40f7ebecb4c4635809dfdec7ebc9d068edca3af5..3c5415d2a4be95769c7a35ab9c760474334ca4f6 100644 (file)
@@ -22,8 +22,8 @@ import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
 import java.text.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class AltosConfig implements ActionListener {
 
index 64336c8e06daa1ac0b5d72fedab5960ddd383762..61208dfe91676a81acfdc1b0f317d9e48d53a6a6 100644 (file)
@@ -21,8 +21,8 @@ import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
 import javax.swing.event.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class AltosConfigPyroUI
        extends AltosUIDialog
index 9020ed9ddc874f0d652c39aa491a74b641c2ceb2..cd20a174300c822d70362f541fbdd09d2eed800c 100644 (file)
@@ -21,8 +21,8 @@ import java.awt.event.*;
 import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class AltosConfigTD implements ActionListener {
 
index b677ad2388de472cbe0d4bae76279d7cccb8e435..52225108fbf135cd5a45b290289a02902bd5e5ca 100644 (file)
@@ -21,8 +21,8 @@ import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
 import javax.swing.event.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class AltosConfigTDUI
        extends AltosUIDialog
index 9fcace610a7212c604bbe7785fcf13779838aaa8..54f06065af4da4df28c43880eb066b8f83a7a0c5 100644 (file)
@@ -21,8 +21,8 @@ import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
 import javax.swing.event.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class AltosConfigUI
        extends AltosUIDialog
index 85a3f6c0d455954253486536e4abddf7b37a1f90..7bc50570eaca77c329a90dcf372b33e0e6f125ee 100644 (file)
@@ -22,7 +22,7 @@ import java.awt.event.*;
 import java.beans.*;
 import javax.swing.*;
 import javax.swing.event.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class AltosConfigureUI
        extends AltosUIConfigure
index e38b35edf305b60d79e1e996238774a2c55fb80d..0db1a4c2f27b8c4405a2a346a75ad32eee3e1032 100644 (file)
@@ -21,8 +21,8 @@ import java.util.*;
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class AltosDescent extends AltosUIFlightTab {
 
index 7e7efa64d91a96621b7256c6905e6c676eb00085..c0d3312b8b71cf4d81c9f15541ce32a2153af55b 100644 (file)
@@ -19,8 +19,8 @@ package altosui;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class AltosFlightStatus extends JComponent implements AltosFlightDisplay {
        GridBagLayout   layout;
@@ -229,10 +229,14 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay
                long    last_secs = -1;
 
                void show(AltosState state, AltosListenerState listener_state) {
-                       long secs = (System.currentTimeMillis() - state.received_time + 500) / 1000;
-                       if (secs != last_secs) {
-                               value.setText(String.format("%d", secs));
-                               last_secs = secs;
+                       if (listener_state.running) {
+                               long secs = (System.currentTimeMillis() - state.received_time + 500) / 1000;
+                               if (secs != last_secs) {
+                                       value.setText(String.format("%d", secs));
+                                       last_secs = secs;
+                               }
+                       } else {
+                               value.setText("done");
                        }
                }
 
@@ -276,6 +280,8 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay
                flight_state.show(state, listener_state);
                rssi.show(state, listener_state);
                last_packet.show(state, listener_state);
+               if (!listener_state.running)
+                       stop();
        }
 
        public int height() {
@@ -285,6 +291,22 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay
 
        public String getName() { return "Flight Status"; }
 
+       AltosFlightStatusUpdate status_update;
+       javax.swing.Timer       timer;
+
+       public void start(AltosFlightStatusUpdate status_update) {
+               this.status_update = status_update;
+               timer = new javax.swing.Timer(100, status_update);
+               timer.start();
+       }
+
+       public void stop() {
+               if (timer != null) {
+                       timer.stop();
+                       timer = null;
+               }
+       }
+
        public AltosFlightStatus() {
                layout = new GridBagLayout();
 
index 336b44aa691737ef1eb6e9060212624aa5bde3fd..f2031698c377afd2d2df94bc77a13a915ebebb50 100644 (file)
@@ -27,7 +27,7 @@ import java.util.*;
 import java.text.*;
 import java.util.prefs.*;
 import java.util.concurrent.LinkedBlockingQueue;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosFlightStatusTableModel extends AbstractTableModel {
        private String[] columnNames = {
index 3ba78c19f8e18460e35abca368002a07118b54ed..3f6494b8055655e71fc00814e2be1b3ae0dd2b91 100644 (file)
@@ -18,7 +18,7 @@
 package altosui;
 
 import java.awt.event.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosFlightStatusUpdate implements ActionListener {
 
index 6af345ea909068c09fdf1cb887badd0e7532b540..424c57da91db18c36e972044a501610e932c27e4 100644 (file)
@@ -22,8 +22,8 @@ import java.awt.event.*;
 import javax.swing.*;
 import java.util.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay {
        AltosVoice              voice;
@@ -97,6 +97,7 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay {
 
        public void show(AltosState state, AltosListenerState listener_state) {
                status_update.saved_state = state;
+               status_update.saved_listener_state = listener_state;
 
                if (state == null)
                        state = new AltosState();
@@ -335,9 +336,14 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay {
                AltosUIPreferences.register_font_listener(this);
                AltosPreferences.register_units_listener(this);
 
+               status_update = new AltosFlightStatusUpdate(flightStatus);
+
+               flightStatus.start(status_update);
+
                addWindowListener(new WindowAdapter() {
                                @Override
                                public void windowClosing(WindowEvent e) {
+                                       flightStatus.stop();
                                        disconnect();
                                        setVisible(false);
                                        dispose();
@@ -353,10 +359,6 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay {
 
                thread = new AltosDisplayThread(this, voice, this, reader);
 
-               status_update = new AltosFlightStatusUpdate(flightStatus);
-
-               new javax.swing.Timer(100, status_update).start();
-
                thread.start();
        }
 
index ddd281a6d41813453cedb2a932211eb99d7d88c9..f5e339a59a2d26b3968b54d39174a1291c57510f 100644 (file)
@@ -23,8 +23,8 @@ import java.util.ArrayList;
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 import org.jfree.chart.ChartPanel;
 import org.jfree.chart.JFreeChart;
@@ -55,12 +55,17 @@ public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, Alt
        }
 
        public void font_size_changed(int font_size) {
-               map.font_size_changed(font_size);
-               statsTable.font_size_changed(font_size);
+               if (map != null)
+                       map.font_size_changed(font_size);
+               if (statsTable != null)
+                       statsTable.font_size_changed(font_size);
        }
 
        public void units_changed(boolean imperial_units) {
-               map.units_changed(imperial_units);
+               if (map != null)
+                       map.units_changed(imperial_units);
+               if (enable != null)
+                       enable.units_changed(imperial_units);
        }
 
        AltosGraphUI(AltosStateIterable states, File file) throws InterruptedException, IOException {
index 67b7a9897717a2aea529ae383916babb946ffdda..204d81ed2c26c6d53df13d390e567c97393cd690 100644 (file)
@@ -24,8 +24,8 @@ import javax.swing.event.*;
 import java.io.*;
 import java.util.concurrent.*;
 import java.util.Arrays;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDisplay, AltosIdleMonitorListener, DocumentListener {
        AltosDevice             device;
@@ -102,6 +102,15 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl
                SwingUtilities.invokeLater(r);
        }
 
+       public void failed() {
+               Runnable r = new Runnable() {
+                               public void run() {
+                                       close();
+                               }
+                       };
+               SwingUtilities.invokeLater(r);
+       }
+
        Container       bag;
        AltosUIFreqList frequencies;
        JTextField      callsign_value;
@@ -174,6 +183,19 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl
                }
        }
 
+       private void close() {
+               try {
+                       disconnect();
+               } catch (Exception ex) {
+                       System.out.printf("Exception %s\n", ex.toString());
+                       for (StackTraceElement el : ex.getStackTrace())
+                               System.out.printf("%s\n", el.toString());
+               }
+               setVisible(false);
+               dispose();
+               AltosUIPreferences.unregister_font_listener(AltosIdleMonitorUI.this);
+       }
+
        public AltosIdleMonitorUI(JFrame in_owner)
                throws FileNotFoundException, TimeoutException, InterruptedException {
 
@@ -184,9 +206,10 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl
 
                serial = device.getSerial();
 
-               AltosLink link;
+               AltosSerial link;
                try {
                        link = new AltosSerial(device);
+                       link.set_frame(this);
                } catch (Exception ex) {
                        idle_exception(in_owner, ex);
                        return;
@@ -248,16 +271,7 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl
                addWindowListener(new WindowAdapter() {
                                @Override
                                public void windowClosing(WindowEvent e) {
-                                       try {
-                                               disconnect();
-                                       } catch (Exception ex) {
-                                               System.out.printf("Exception %s\n", ex.toString());
-                                               for (StackTraceElement el : ex.getStackTrace())
-                                                       System.out.printf("%s\n", el.toString());
-                                       }
-                                       setVisible(false);
-                                       dispose();
-                                       AltosUIPreferences.unregister_font_listener(AltosIdleMonitorUI.this);
+                                       close();
                                }
                        });
 
index 15a81e57e37a5fd604142123d776e378aed3c1f1..944c659bfd06bf5707fb323ec31eede94c19dbfa 100644 (file)
@@ -24,8 +24,8 @@ import java.io.*;
 import java.text.*;
 import java.util.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class AltosIgniteUI
        extends AltosUIDialog
index 117def093981154c6daaf35baddebafadffefbfd..82582a28d3bf70e404a6ae954e7a1892d04966f9 100644 (file)
@@ -20,8 +20,8 @@ package altosui;
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class AltosIgnitor extends AltosUIFlightTab {
 
index 7c50adacba874d053c892e913277dc71330083d0..2237df0c129d53afd9d091c884aeb1ed6080b905 100644 (file)
@@ -21,8 +21,8 @@ import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
 import java.io.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class AltosLanded extends AltosUIFlightTab implements ActionListener {
 
index 1717861698f4c1bbb36a28cb99787cd998e6c612..37077c42fb8553a95f84f59c64ed9e6c940fa173 100644 (file)
@@ -20,7 +20,7 @@ package altosui;
 import java.io.*;
 import java.util.concurrent.*;
 import java.awt.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class AltosLaunch {
        AltosDevice     device;
index 3320e6751c9207ed725575e460bdea80dbe31d9b..4c205d44db7448fe0f63f817fabe5af2add21d6a 100644 (file)
@@ -23,7 +23,7 @@ import javax.swing.*;
 import java.io.*;
 import java.text.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altosuilib_6.*;
 
 class FireButton extends JButton {
        protected void processMouseEvent(MouseEvent e) {
index eb0c56448eb5a2bbd6a9ade8598797c7781ac7bc..6214fa5a58965c82094d07789131c65f34ae5512 100644 (file)
@@ -18,8 +18,8 @@
 package altosui;
 
 import java.util.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class AltosPad extends AltosUIFlightTab {
 
index 0aa5d03ce142ef1a420b2c45d4d581b9654ac829..0af09651e304509dce7358d5e92f860f63effb63 100644 (file)
@@ -22,8 +22,8 @@ import java.awt.event.*;
 import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class AltosUI extends AltosUIFrame {
        public AltosVoice voice = new AltosVoice();
@@ -471,7 +471,6 @@ public class AltosUI extends AltosUIFrame {
                if (reader == null)
                        return false;
                AltosFlightUI flight_ui = new AltosFlightUI(new AltosVoice(), reader);
-               flight_ui.set_exit_on_close();
                return true;
        }
 
@@ -559,9 +558,9 @@ public class AltosUI extends AltosUIFrame {
        public static void help(int code) {
                System.out.printf("Usage: altosui [OPTION]... [FILE]...\n");
                System.out.printf("  Options:\n");
-               System.out.printf("    --fetchmaps <lat> <lon>\tpre-fetch maps for site map view\n");
                System.out.printf("    --replay <filename>\t\trelive the glory of past flights \n");
                System.out.printf("    --graph <filename>\t\tgraph a flight\n");
+               System.out.printf("    --summary <filename>\t\tText summary of a flight\n");
                System.out.printf("    --csv\tgenerate comma separated output for spreadsheets, etc\n");
                System.out.printf("    --kml\tgenerate KML output for use with Google Earth\n");
                System.exit(code);
@@ -574,10 +573,11 @@ public class AltosUI extends AltosUIFrame {
                        UIManager.setLookAndFeel(AltosUIPreferences.look_and_feel());
                } catch (Exception e) {
                }
+               AltosUI altosui = null;
+
                /* Handle batch-mode */
                if (args.length == 0) {
-                       AltosUI altosui = new AltosUI();
-
+                       altosui = new AltosUI();
                        java.util.List<AltosDevice> devices = AltosUSBDevice.list(Altos.product_basestation);
                        if (devices != null)
                                for (AltosDevice device : devices)
@@ -615,10 +615,14 @@ public class AltosUI extends AltosUIFrame {
                                        switch (process) {
                                        case process_none:
                                        case process_graph:
+                                               if (altosui == null)
+                                                       altosui = new AltosUI();
                                                if (!process_graph(file))
                                                        ++errors;
                                                break;
                                        case process_replay:
+                                               if (altosui == null)
+                                                       altosui = new AltosUI();
                                                if (!process_replay(file))
                                                        ++errors;
                                                break;
diff --git a/altosui/AltosUIPreferencesBackend.java b/altosui/AltosUIPreferencesBackend.java
deleted file mode 100644 (file)
index b229d7b..0000000
+++ /dev/null
@@ -1,101 +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; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package altosui;
-
-import java.io.File;
-import java.util.prefs.*;
-import org.altusmetrum.altoslib_5.*;
-import javax.swing.filechooser.FileSystemView;
-
-public class AltosUIPreferencesBackend implements AltosPreferencesBackend {
-
-       private Preferences _preferences = null;
-
-       public AltosUIPreferencesBackend() {
-               _preferences = Preferences.userRoot().node("/org/altusmetrum/altosui");
-       }
-
-       public AltosUIPreferencesBackend(Preferences in_preferences) {
-               _preferences = in_preferences;
-       }
-
-       public String  getString(String key, String def) {
-               return _preferences.get(key, def);
-       }
-       public void    putString(String key, String value) {
-               _preferences.put(key, value);
-       }
-
-       public int     getInt(String key, int def) {
-               return _preferences.getInt(key, def);
-       }
-       public void    putInt(String key, int value) {
-               _preferences.putInt(key, value);
-       }
-
-       public double  getDouble(String key, double def) {
-               return _preferences.getDouble(key, def);
-       }
-       public void    putDouble(String key, double value) {
-               _preferences.putDouble(key, value);
-       }
-
-       public boolean getBoolean(String key, boolean def) {
-               return _preferences.getBoolean(key, def);
-       }
-       public void    putBoolean(String key, boolean value) {
-               _preferences.putBoolean(key, value);
-       }
-
-       public boolean nodeExists(String key) {
-               try {
-                       return _preferences.nodeExists(key);
-               } catch (BackingStoreException be) {
-                       return false;
-               }
-       }
-
-       public AltosPreferencesBackend node(String key) {
-               return new AltosUIPreferencesBackend(_preferences.node(key));
-       }
-
-       public String[] keys() {
-               try {
-                       return _preferences.keys();
-               } catch (BackingStoreException be) {
-                       return null;
-               }
-       }
-
-       public void remove(String key) {
-               _preferences.remove(key);
-       }
-
-       public void    flush() {
-               try {
-                       _preferences.flush();
-               } catch (BackingStoreException ee) {
-                       System.err.printf("Cannot save preferences\n");
-               }
-       }
-
-       public File homeDirectory() {
-               /* Use the file system view default directory */
-               return FileSystemView.getFileSystemView().getDefaultDirectory();
-       }
-}
index cd47c1b53337ff5205256dae4d05c872d7f12f7f..d989ddd6693726b5e035d16f813541323ebbac62 100644 (file)
@@ -42,7 +42,7 @@ Function DoDetectJRE
   ReadRegStr $2 HKCU "SOFTWARE\JavaSoft\Java Runtime Environment" \
              "CurrentVersion"
 
-  IfErrors hklm_version
+  IfErrors hkcuwow_version
 
   DetailPrint "HKEY_CURRENT_USER Java version $2"
 
@@ -50,6 +50,22 @@ Function DoDetectJRE
 
   IntCmp $3 1 yes yes no
 
+hkcuwow_version:
+
+  ; Check in HKCU Wow6432Node for CurrentVersion
+
+  ClearErrors
+  ReadRegStr $2 HKCU "SOFTWARE\Wow6432Node\JavaSoft\Java Runtime Environment" \
+            "CurrentVersion"
+
+  Iferrors hklm_version
+
+  DetailPrint "HKEY_CURRENT_USER Wow6432Node Java version $2"
+
+  ${VersionCompare} $2 ${JRE_VERSION} $3
+
+  IntCmp $3 1 yes yes no
+
 hklm_version:
 
   ; Check in HKLM for CurrentVersion
@@ -58,7 +74,7 @@ hklm_version:
   ReadRegStr $2 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment" \
              "CurrentVersion"
   
-  IfErrors hkcu_any
+  IfErrors hklmwow_version
 
   DetailPrint "HKEY_LOCAL_MACHINE Java version $2"
 
@@ -66,6 +82,22 @@ hklm_version:
 
   IntCmp $3 1 yes yes no
 
+hklmwow_version:
+
+  ; Check in HKLM Wow6432Node for CurrentVersion
+
+  ClearErrors
+  ReadRegStr $2 HKLM "SOFTWARE\Wow6432Node\JavaSoft\Java Runtime Environment" \
+            "CurrentVersion"
+
+  Iferrors hkcu_any
+
+  DetailPrint "HKEY_LOCAL_MACHINE Wow6432Node Java version $2"
+
+  ${VersionCompare} $2 ${JRE_VERSION} $3
+
+  IntCmp $3 1 yes yes no
+
 hkcu_any:
 
   ; Check in HKCU for any Java install
index 48f58933ec0900e52483b077c0c919bebd767a87..e6de1d97345ddb66b7945f88b140b3fc20c72c42 100644 (file)
@@ -32,7 +32,6 @@ altosui_JAVA = \
        AltosLaunchUI.java \
        AltosLanded.java \
        AltosPad.java \
-       AltosUIPreferencesBackend.java \
        AltosUI.java \
        AltosGraphUI.java
 
@@ -114,7 +113,8 @@ LINUX_MIMETYPE      =\
 
 # Firmware
 FIRMWARE_TD_0_2=$(top_srcdir)/src/teledongle-v0.2/teledongle-v0.2-$(VERSION).ihx
-FIRMWARE_TD=$(FIRMWARE_TD_0_2)
+FIRMWARE_TD_3_0=$(top_srcdir)/src/teledongle-v3.0/teledongle-v3.0-$(VERSION).ihx
+FIRMWARE_TD=$(FIRMWARE_TD_0_2) $(FIRMWARE_TD_3_0)
 
 FIRMWARE_TM_1_0=$(top_srcdir)/src/telemetrum-v1.0/telemetrum-v1.0-$(VERSION).ihx
 FIRMWARE_TM_1_1=$(top_srcdir)/src/telemetrum-v1.1/telemetrum-v1.1-$(VERSION).ihx
index 11c1dc0700d0682dae16f1833258c8287ed667b1..6d4dabfa86ba8338c7514bfcf8032ef145e5d8d4 100644 (file)
@@ -108,7 +108,7 @@ Section "${REG_NAME} Application"
 
        File "../icon/${WIN_APP_ICON}"
 
-       CreateShortCut "$SMPROGRAMS\${REG_NAME}.lnk" "$SYSDIR\javaw.exe" "-jar ${FAT_NAME}" "$INSTDIR\${WIN_APP_ICON}"
+       CreateShortCut "$SMPROGRAMS\${REG_NAME}.lnk" "$INSTDIR\${FAT_NAME}" "" "$INSTDIR\${WIN_APP_ICON}"
 SectionEnd
 
 Section "${REG_NAME} Desktop Shortcut"
@@ -126,6 +126,7 @@ Section "Firmware"
        File "../src/telemini-v1.0/telemini-v1.0-${VERSION}.ihx"
        File "../src/telegps-v1.0/telegps-v1.0-${VERSION}.ihx"
        File "../src/teledongle-v0.2/teledongle-v0.2-${VERSION}.ihx"
+       File "../src/teledongle-v3.0/teledongle-v3.0-${VERSION}.ihx"
        File "../src/telebt-v1.0/telebt-v1.0-${VERSION}.ihx"
        File "../src/telemega-v1.0/telemega-v1.0-${VERSION}.ihx"
        File "../src/easymini-v1.0/easymini-v1.0-${VERSION}.ihx"
@@ -164,13 +165,15 @@ Section "File Associations"
        DeleteRegKey   HKCR ".telem\${PROG_ID_EEPROM}"
        DeleteRegValue HKCR ".telem\OpenWithProgids" "${PROG_ID_EEPROM}"
 
+       SearchPath $1 "javaw.exe"
+
        ; .eeprom elements
 
        WriteRegStr HKCR "${PROG_ID_EEPROM}"            ""                              "Altus Metrum Log File"
        WriteRegStr HKCR "${PROG_ID_EEPROM}"            "FriendlyTypeName"              "Altus Metrum Log File"
        WriteRegStr HKCR "${PROG_ID_EEPROM}\CurVer"     ""                              "${PROG_ID_EEPROM}"
        WriteRegStr HKCR "${PROG_ID_EEPROM}\DefaultIcon" ""                             '"$INSTDIR\${WIN_EEPROM_EXE}",-101'
-  WriteRegExpandStr HKCR "${PROG_ID_EEPROM}\shell\open\command" ""                     '"%SYSTEMROOT%\System32\javaw.exe" -Djava.library.path="$INSTDIR" -jar "$INSTDIR\${FAT_NAME}" "%1"'
+  WriteRegExpandStr HKCR "${PROG_ID_EEPROM}\shell\open\command" ""                     '"$1" -Djava.library.path="$INSTDIR" -jar "$INSTDIR\${FAT_NAME}" "%1"'
 
        WriteRegStr HKCR ".eeprom"                      ""                              "${PROG_ID_EEPROM}"
        WriteRegStr HKCR ".eeprom"                      "PerceivedType"                 "Altus Metrum Log File"
@@ -185,7 +188,7 @@ Section "File Associations"
        WriteRegStr HKCR "${PROG_ID_TELEM}"             "FriendlyTypeName"              "Altus Metrum Telemetry File"
        WriteRegStr HKCR "${PROG_ID_TELEM}\CurVer"      ""                              "${PROG_ID_TELEM}"
        WriteRegStr HKCR "${PROG_ID_TELEM}\DefaultIcon" ""                              '"$INSTDIR\${WIN_TELEM_EXE}",-101'
-  WriteRegExpandStr HKCR "${PROG_ID_TELEM}\shell\open\command" ""                      '"%SYSTEMROOT%\System32\javaw.exe" -Djava.library.path="$INSTDIR" -jar "$INSTDIR\${FAT_NAME}" "%1"'
+  WriteRegExpandStr HKCR "${PROG_ID_TELEM}\shell\open\command" ""                      '"$1" -Djava.library.path="$INSTDIR" -jar "$INSTDIR\${FAT_NAME}" "%1"'
 
        WriteRegStr HKCR ".telem"                       ""                              "${PROG_ID_TELEM}"
        WriteRegStr HKCR ".telem"                       "PerceivedType"                 "Altus Metrum Telemetry File"
index 2c0850213627a6083751d984e493ec807d2c68c1..0dd1cab231b3ed32db9fe0211591115a4d6cf4dc 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import libaltosJNI.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosBTDevice extends altos_bt_device implements AltosDevice {
 
index c99b27f94e8d0c3b0d309c994960e7405408cbd7..eebad36b5865eebf17c2b96d3d47d5449acec1f5 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.util.*;
 import libaltosJNI.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosBTDeviceIterator implements Iterator<AltosBTDevice> {
        AltosBTDevice   current;
index c526269d12ef871b4549b46d14669b285e48e3c1..73ee473fa6e833a1c1dbfbf2abdd770e934bfc9b 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.util.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosBTKnown implements Iterable<AltosBTDevice> {
        LinkedList<AltosBTDevice>       devices = new LinkedList<AltosBTDevice>();
index b953ca923d484f1f6ba4b72b88510443121457ab..c4ac363f5267974e6c838666cad81b664be60e10 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -23,7 +23,7 @@ import javax.swing.*;
 import javax.swing.plaf.basic.*;
 import java.util.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosBTManage extends AltosUIDialog implements ActionListener, Iterable<AltosBTDevice> {
        LinkedBlockingQueue<AltosBTDevice> found_devices;
index 6328d37dea1bd67d0934dea8941fdc755840b471..94d523fe20b3e433704a9cee1672ec7e69293d95 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
 import java.io.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosCSVUI
        extends AltosUIDialog
index a0525a00886eb7697575680a57032b752c956e56..6253e3e4c254f1e51e73a0a8d437c7b281642576 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
 import java.util.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 class AltosEditFreqUI extends AltosUIDialog implements ActionListener {
        Frame           frame;
index 1990faf1f4d73c2e2af315fcded7691d733a1a73..3fe76687e8df39e4c49c1f61efe71a03d79ad04e 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import javax.swing.*;
 import javax.swing.filechooser.FileNameExtensionFilter;
 import java.io.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosDataChooser extends JFileChooser {
        JFrame  frame;
index 1f5536ffe4fea88a324494ae1043aec05a83ac00..401387a46b9e6afa0f8853a55d5e48d482fca975 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import libaltosJNI.*;
 
index d2ccd5e76f15e388daf1d9bae3314ea1b847eea9..5fb1331ee210a5cf40618e5b58a7e91c69a0974f 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import javax.swing.*;
 import java.awt.*;
index 80a76d6d6c2d532abb061cdd0d17b8cb215eb77a..9618895ee04acf12f20a25aa8edc18007497c97d 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import javax.swing.*;
 import java.awt.*;
index 6b6e03e7372baa86c778f52e7946ee54ef914dca..ccf8b3ef22fb90329cdbd4b654a3be95cd65c37d 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.*;
 import javax.swing.*;
 import java.io.*;
 import java.text.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosDisplayThread extends Thread {
 
@@ -224,8 +224,10 @@ public class AltosDisplayThread extends Thread {
                        for (;;) {
                                try {
                                        state = reader.read();
-                                       if (state == null)
+                                       if (state == null) {
+                                               listener_state.running = false;
                                                break;
+                                       }
                                        reader.update(state);
                                        show_safely();
                                        told = tell();
index 39585dad3793aef24bdc01c7fb56e09f8fc5c06f..9fb21cf443f2b76a0d22275c6b1796e2ba4803a9 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.event.*;
 import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosEepromDelete implements Runnable {
        AltosEepromList         flights;
index 81dd3d13e4eb50a01bb50a6d0408f91f741cc1fc..47a62ef7e97b1aaa029fd4680ba24ed7f7ad09fa 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.event.*;
 import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosEepromManage implements ActionListener {
 
index 060d0474f888b872b64c3eceb185d921a67621f0..83c5c1d0c73c48dbdc3f321a665c67906901188f 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.*;
 import java.awt.event.*;
index 11dd4adb3f51c062f000a6d9ff8fbb3328eb9d15..ac39fb1dedd443886583d5ab99cdacebd45edcbe 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMonitor {
        JFrame          owner;
@@ -37,6 +37,8 @@ public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMo
        int             min_state, max_state;
        ActionListener  listener;
 
+       static final int        progress_max = 10000;
+
        public AltosEepromMonitorUI(JFrame owner) {
                super (owner, "Download Flight Data", false);
 
@@ -102,7 +104,7 @@ public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMo
 
                pbar = new JProgressBar();
                pbar.setMinimum(0);
-               pbar.setMaximum(1000);
+               pbar.setMaximum(progress_max);
                pbar.setValue(0);
                pbar.setString("startup");
                pbar.setStringPainted(true);
@@ -155,16 +157,40 @@ public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMo
        }
 
        private void set_value_internal(String state_name, int state, int state_block, int block) {
-               if (state_block > 100)
-                       state_block = 100;
-               if (state < min_state) state = min_state;
-               if (state >= max_state) state = max_state - 1;
-               state -= min_state;
+               double  pos;
+               String  s;
+
+               if (min_state == AltosLib.ao_flight_invalid) {
+                       int     lblock = block;
+                       if (lblock > 1000)
+                               lblock = 1000;
+                       pos = lblock / 1000.0;
+                       s = String.format("block %d", block);
+               } else {
+                       if (state == AltosLib.ao_flight_invalid)
+                               state = 0;
+                       if (state_block > 100)
+                               state_block = 100;
+                       if (state < min_state) state = min_state;
+                       if (state > max_state) state = max_state;
+
+                       if (state == max_state)
+                               state_block = 0;
+
+                       state -= min_state;
 
-               int pos = state * 100 + state_block;
+                       int     nstate = max_state - min_state;
+
+                       double  spos = (double) state / (double) nstate;
+                       double  bpos = state_block / 100.0;
+
+                       pos = spos + bpos / nstate;
+
+                       s = String.format("block %d state %s", block, state_name);
+               }
 
-               pbar.setString(String.format("block %d state %s", block, state_name));
-               pbar.setValue(pos);
+               pbar.setString(s);
+               pbar.setValue((int) (pos * progress_max));
        }
 
        public void set_value(String in_state_name, int in_state, int in_state_block, int in_block) {
index 1adfdab57256df407ff6fbc9e9ec93e22332a888..b291c35a08197d75b68c0f7c7dbff8fe7197352c 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import javax.swing.*;
 import javax.swing.border.*;
 import java.awt.*;
 import java.awt.event.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 class AltosEepromItem implements ActionListener {
        AltosEepromLog  log;
index 44be2a9064f6183396b073d208979340fdfc9128..6e497c429be6bb9cbdc93674e29537e13c3b7e03 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -23,7 +23,7 @@ import javax.swing.*;
 import javax.swing.filechooser.FileNameExtensionFilter;
 import java.io.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosFlashUI
        extends AltosUIDialog
@@ -56,8 +56,8 @@ public class AltosFlashUI
 
        private static String[] pair_programmed = {
                "teleballoon",
-               "telebt",
-               "teledongle",
+               "telebt-v1",
+               "teledongle-v0",
                "telefire",
                "telemetrum-v0",
                "telemetrum-v1",
index d0f20bb49d2dd08c86f9499dd7aec473609f41e2..ac65c49e0587fcd1aaa76fce418349a284dc2315 100644 (file)
@@ -15,9 +15,9 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public interface AltosFlightDisplay extends AltosUnitsListener, AltosFontListener {
        void reset();
index 0bc4f847ca1fef7a2c403bf4980dfa744750ecd4..f9d7d180bcf00df1544959862d94e914d7361344 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import javax.swing.table.*;
 
index 1ec4a03e5030615a42a2652ef4112b1505b02af3..8a686646f615fede8d74d01dcede37a7be34fec6 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.*;
 import javax.swing.*;
 import java.util.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosFlightStatsTable extends JComponent implements AltosFontListener {
        GridBagLayout   layout;
index a1b2170bff2561d3057830ebd5014f32cfcd4d24..936252785efd6b24b20599323f8ddd1530d8d012 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 public interface AltosFontListener {
        void font_size_changed(int font_size);
index 522eea1ef65ed1d463a9d84a303e213ef65f1c96..d7739228585997b8cfe11aab5230e438b5949c77 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.io.*;
 import java.util.ArrayList;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 import org.jfree.ui.*;
 import org.jfree.chart.*;
@@ -329,48 +329,54 @@ public class AltosGraph extends AltosUIGraph {
                                  gps_nsat_solution_color,
                                  false,
                                  nsat_axis);
-                       addSeries("GPS Satellites in View",
-                                 AltosGraphDataPoint.data_gps_nsat_view,
-                                 nsat_units,
-                                 gps_nsat_view_color,
-                                 false,
-                                 nsat_axis);
-                       addSeries("GPS Course",
-                                 AltosGraphDataPoint.data_gps_course,
-                                 orient_units,
-                                 gps_course_color,
-                                 false,
-                                 course_axis);
-                       addSeries("GPS Ground Speed",
-                                 AltosGraphDataPoint.data_gps_ground_speed,
-                                 AltosConvert.speed,
-                                 gps_ground_speed_color,
-                                 enable_gps,
-                                 speed_axis);
-                       addSeries("GPS Climb Rate",
-                                 AltosGraphDataPoint.data_gps_climb_rate,
-                                 AltosConvert.speed,
-                                 gps_climb_rate_color,
-                                 enable_gps,
-                                 speed_axis);
+                       if (stats.has_gps_sats) {
+                               addSeries("GPS Satellites in View",
+                                         AltosGraphDataPoint.data_gps_nsat_view,
+                                         nsat_units,
+                                         gps_nsat_view_color,
+                                         false,
+                                         nsat_axis);
+                       }
+                       if (stats.has_gps_detail) {
+                               addSeries("GPS Course",
+                                         AltosGraphDataPoint.data_gps_course,
+                                         orient_units,
+                                         gps_course_color,
+                                         false,
+                                         course_axis);
+                               addSeries("GPS Ground Speed",
+                                         AltosGraphDataPoint.data_gps_ground_speed,
+                                         AltosConvert.speed,
+                                         gps_ground_speed_color,
+                                         enable_gps,
+                                         speed_axis);
+                               addSeries("GPS Climb Rate",
+                                         AltosGraphDataPoint.data_gps_climb_rate,
+                                         AltosConvert.speed,
+                                         gps_climb_rate_color,
+                                         enable_gps,
+                                         speed_axis);
+                       }
                        addSeries("GPS Position DOP",
                                  AltosGraphDataPoint.data_gps_pdop,
                                  dop_units,
                                  gps_pdop_color,
                                  false,
                                  dop_axis);
-                       addSeries("GPS Horizontal DOP",
-                                 AltosGraphDataPoint.data_gps_hdop,
-                                 dop_units,
-                                 gps_hdop_color,
-                                 false,
-                                 dop_axis);
-                       addSeries("GPS Vertical DOP",
-                                 AltosGraphDataPoint.data_gps_vdop,
-                                 dop_units,
-                                 gps_vdop_color,
-                                 false,
-                                 dop_axis);
+                       if (stats.has_gps_detail) {
+                               addSeries("GPS Horizontal DOP",
+                                         AltosGraphDataPoint.data_gps_hdop,
+                                         dop_units,
+                                         gps_hdop_color,
+                                         false,
+                                         dop_axis);
+                               addSeries("GPS Vertical DOP",
+                                         AltosGraphDataPoint.data_gps_vdop,
+                                         dop_units,
+                                         gps_vdop_color,
+                                         false,
+                                         dop_axis);
+                       }
                }
                if (stats.has_rssi)
                        addSeries("Received Signal Strength",
@@ -410,58 +416,58 @@ public class AltosGraph extends AltosUIGraph {
                }
 
                if (stats.has_imu) {
-                       addSeries("Acceleration X",
-                                 AltosGraphDataPoint.data_accel_x,
+                       addSeries("Acceleration Along",
+                                 AltosGraphDataPoint.data_accel_along,
                                  AltosConvert.accel,
                                  accel_x_color,
                                  false,
                                  accel_axis);
-                       addSeries("Acceleration Y",
-                                 AltosGraphDataPoint.data_accel_y,
+                       addSeries("Acceleration Across",
+                                 AltosGraphDataPoint.data_accel_across,
                                  AltosConvert.accel,
                                  accel_y_color,
                                  false,
                                  accel_axis);
-                       addSeries("Acceleration Z",
-                                 AltosGraphDataPoint.data_accel_z,
+                       addSeries("Acceleration Through",
+                                 AltosGraphDataPoint.data_accel_through,
                                  AltosConvert.accel,
                                  accel_z_color,
                                  false,
                                  accel_axis);
-                       addSeries("Rotation Rate X",
-                                 AltosGraphDataPoint.data_gyro_x,
+                       addSeries("Roll Rate",
+                                 AltosGraphDataPoint.data_gyro_roll,
                                  gyro_units,
                                  gyro_x_color,
                                  false,
                                  gyro_axis);
-                       addSeries("Rotation Rate Y",
-                                 AltosGraphDataPoint.data_gyro_y,
+                       addSeries("Pitch Rate",
+                                 AltosGraphDataPoint.data_gyro_pitch,
                                  gyro_units,
                                  gyro_y_color,
                                  false,
                                  gyro_axis);
-                       addSeries("Rotation Rate Z",
-                                 AltosGraphDataPoint.data_gyro_z,
+                       addSeries("Yaw Rate",
+                                 AltosGraphDataPoint.data_gyro_yaw,
                                  gyro_units,
                                  gyro_z_color,
                                  false,
                                  gyro_axis);
                }
                if (stats.has_mag) {
-                       addSeries("Magnetometer X",
-                                 AltosGraphDataPoint.data_mag_x,
+                       addSeries("Magnetometer Along",
+                                 AltosGraphDataPoint.data_mag_along,
                                  mag_units,
                                  mag_x_color,
                                  false,
                                  mag_axis);
-                       addSeries("Magnetometer Y",
-                                 AltosGraphDataPoint.data_mag_y,
+                       addSeries("Magnetometer Across",
+                                 AltosGraphDataPoint.data_mag_across,
                                  mag_units,
                                  mag_y_color,
                                  false,
                                  mag_axis);
-                       addSeries("Magnetometer Z",
-                                 AltosGraphDataPoint.data_mag_z,
+                       addSeries("Magnetometer Through",
+                                 AltosGraphDataPoint.data_mag_through,
                                  mag_units,
                                  mag_z_color,
                                  false,
index 56dadb8b49170389975d6063c77ce4cccd2e3539..47989d0e9549d10b3e2490a3d81e4599c9992d40 100644 (file)
@@ -15,9 +15,9 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosGraphDataPoint implements AltosUIDataPoint {
 
@@ -40,15 +40,15 @@ public class AltosGraphDataPoint implements AltosUIDataPoint {
        public static final int data_range = 14;
        public static final int data_distance = 15;
        public static final int data_pressure = 16;
-       public static final int data_accel_x = 17;
-       public static final int data_accel_y = 18;
-       public static final int data_accel_z = 19;
-       public static final int data_gyro_x = 20;
-       public static final int data_gyro_y = 21;
-       public static final int data_gyro_z = 22;
-       public static final int data_mag_x = 23;
-       public static final int data_mag_y = 24;
-       public static final int data_mag_z = 25;
+       public static final int data_accel_along = 17;
+       public static final int data_accel_across = 18;
+       public static final int data_accel_through = 19;
+       public static final int data_gyro_roll = 20;
+       public static final int data_gyro_pitch = 21;
+       public static final int data_gyro_yaw = 22;
+       public static final int data_mag_along = 23;
+       public static final int data_mag_across = 24;
+       public static final int data_mag_through = 25;
        public static final int data_orient = 26;
        public static final int data_gps_course = 27;
        public static final int data_gps_ground_speed = 28;
@@ -128,53 +128,32 @@ public class AltosGraphDataPoint implements AltosUIDataPoint {
                        y = state.pressure();
                        break;
 
-               case data_accel_x:
-               case data_accel_y:
-               case data_accel_z:
-               case data_gyro_x:
-               case data_gyro_y:
-               case data_gyro_z:
-                       AltosIMU        imu = state.imu;
-                       if (imu == null)
-                               break;
-                       switch (index) {
-                       case data_accel_x:
-                               y = imu.accel_x;
-                               break;
-                       case data_accel_y:
-                               y = imu.accel_y;
-                               break;
-                       case data_accel_z:
-                               y = imu.accel_z;
-                               break;
-                       case data_gyro_x:
-                               y = imu.gyro_x;
-                               break;
-                       case data_gyro_y:
-                               y = imu.gyro_y;
-                               break;
-                       case data_gyro_z:
-                               y = imu.gyro_z;
-                               break;
-                       }
+               case data_accel_along:
+                       y = state.accel_along();
                        break;
-               case data_mag_x:
-               case data_mag_y:
-               case data_mag_z:
-                       AltosMag        mag = state.mag;
-                       if (mag == null)
-                               break;
-                       switch (index) {
-                       case data_mag_x:
-                               y = mag.x;
-                               break;
-                       case data_mag_y:
-                               y = mag.y;
-                               break;
-                       case data_mag_z:
-                               y = mag.z;
-                               break;
-                       }
+               case data_accel_across:
+                       y = state.accel_across();
+                       break;
+               case data_accel_through:
+                       y = state.accel_through();
+                       break;
+               case data_gyro_roll:
+                       y = state.gyro_roll();
+                       break;
+               case data_gyro_pitch:
+                       y = state.gyro_pitch();
+                       break;
+               case data_gyro_yaw:
+                       y = state.gyro_yaw();
+                       break;
+               case data_mag_along:
+                       y = state.mag_along();
+                       break;
+               case data_mag_across:
+                       y = state.mag_across();
+                       break;
+               case data_mag_through:
+                       y = state.mag_through();
                        break;
                case data_orient:
                        y = state.orient();
index 0845f20ecbf87fcc59a8de6d0f83e8fff0efc555..b9c9d2a8855c65b32fe88adc6c5fd24bc28e34d6 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.lang.*;
 import java.io.*;
 import java.util.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 class AltosGraphIterator implements Iterator<AltosUIDataPoint> {
        AltosGraphDataSet       dataSet;
index 625fe76f6ff33f09416490b057f3fc99a97e4be6..89a656c9004d1af67d59abb6c7973365a2136600 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
 import javax.swing.table.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosInfoTable extends JTable implements AltosFlightDisplay, HierarchyListener {
        private AltosFlightInfoTableModel model;
@@ -207,7 +207,7 @@ public class AltosInfoTable extends JTable implements AltosFlightDisplay, Hierar
                                                     state.gps.climb_rate);
 
                                if (state.gps.h_error != AltosLib.MISSING && state.gps.v_error != AltosLib.MISSING)
-                                       info_add_row(1, "GPS error", "%6d m(h)%3d m(v)",
+                                       info_add_row(1, "GPS error", "%6.0f m(h)%6.0f m(v)",
                                                     state.gps.h_error, state.gps.v_error);
                                if (state.gps.pdop != AltosLib.MISSING &&
                                    state.gps.hdop != AltosLib.MISSING &&
index 0dd5740cae3e5ad2e080d0ee4afb58ac98d2e8f6..fa33c4b678d1a30d81dd910b872c44999bdfbaa2 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import javax.swing.*;
 
index 30934d96ad84104977c156c574b691ad4776ffac..05d06ac46ec7421f0e2dc6a2eb3e5f63a1e52557 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.*;
 import javax.swing.*;
index dfc3c649c2adf4defc07572b33bb42e11ed239ae..1274a64a237092304e103d4e3d54f21055508d8b 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 public interface AltosPositionListener {
        public void position_changed(int position);
index 481ce6565087d8b018d70ab8db062b81c499cd53..99e4d00428273b364f272f043b8546f7e3a6472f 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosRomconfigUI
        extends AltosUIDialog
index 7e51a55a757d174d8dce0a1ac6566cefbbaf5d8d..5a7e21b18867ea02c6e1b3e64033b5e77bed077f 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -25,7 +25,7 @@ import java.io.*;
 import java.util.*;
 import java.text.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 class AltosScanResult {
        String          callsign;
@@ -159,6 +159,8 @@ public class AltosScanUI
        Thread                          thread;
        AltosFrequency[]                frequencies;
        int                             frequency_index;
+       int                             packet_count;
+       int                             tick_count;
 
        void scan_exception(Exception e) {
                if (e instanceof FileNotFoundException) {
@@ -200,6 +202,7 @@ public class AltosScanUI
                                                AltosState      state = reader.read();
                                                if (state == null)
                                                        continue;
+                                               packet_count++;
                                                if (state.flight != AltosLib.MISSING) {
                                                        final AltosScanResult   result = new AltosScanResult(state.callsign,
                                                                                                             state.serial,
@@ -251,9 +254,6 @@ public class AltosScanUI
        void next() throws InterruptedException, TimeoutException {
                reader.set_monitor(false);
 
-               /* Let any pending input from the last configuration drain out */
-               Thread.sleep(100);
-
                if (select_rate) {
                        boolean wrapped = false;
                        do {
@@ -284,6 +284,8 @@ public class AltosScanUI
                                return;
                        }
                }
+               packet_count = 0;
+               tick_count = 0;
                ++frequency_index;
                if (frequency_index >= frequencies.length)
                        frequency_index = 0;
@@ -308,7 +310,9 @@ public class AltosScanUI
        }
 
        void tick_timer() throws InterruptedException, TimeoutException {
-               next();
+               ++tick_count;
+               if (packet_count == 0 || tick_count > 5)
+                       next();
        }
 
        public void actionPerformed(ActionEvent e) {
@@ -356,7 +360,6 @@ public class AltosScanUI
                                if (r != null) {
                                        if (device != null) {
                                                if (reader != null) {
-                                                       System.out.printf("frequency %g rate %d\n", r.frequency.frequency, r.rate);
                                                        reader.set_telemetry(r.telemetry);
                                                        reader.set_telemetry_rate(r.rate);
                                                        reader.set_frequency(r.frequency.frequency);
@@ -441,6 +444,7 @@ public class AltosScanUI
        }
 
        public AltosScanUI(AltosUIFrame in_owner, boolean in_select_telemetry) {
+               super(in_owner, "Scan Telemetry", false);
 
                owner = in_owner;
                select_telemetry = in_select_telemetry;
index 0eba55fd36f7078d763ef7e7ae9ada1c96686a94..95815a7b28553e40e29f67962a909a8bcb934d50 100644 (file)
  * Deal with TeleDongle on a serial port
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.io.*;
 import java.util.*;
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 import libaltosJNI.*;
 
 /*
index cd19b101105ce3dccdb61a6022356a8c004e07b1..0487e14677b078cfcefa06d3254e297ce63eafa2 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 public class AltosSerialInUseException extends Exception {
        public AltosDevice      device;
index 9e98ddb77bb7cade58e5132d27352eecbe17387f..89f5493bd38910d55126262291390f82537cd124 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.io.*;
 import java.util.ArrayList;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 import org.jfree.ui.*;
 import org.jfree.chart.*;
index 9c0f3bc7af933ff9dff2f1241d5c65aadfc31d24..b022aeec8c40efbfeeae955dd484d182ff942b3c 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.*;
 import java.awt.event.*;
index 9a810a41de670e849af16af74d858c70eed13d2b..a0e41fef947bf5a74367915f0dcfed0987aa81d7 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 public class AltosUIDataMissing extends Exception {
        public int      id;
index f72bbcd5e92da902a6f6f3e9677e6ad320e3034b..82ce862faf1cd902aec88713a9674037d20b0972 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 public interface AltosUIDataPoint {
        public abstract double x() throws AltosUIDataMissing;
index 9e048587c3861799f472dd37d052e03b1827c02a..6293911d0a4393780943ab2bf0a704d1157bddd8 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 public interface AltosUIDataSet {
        public abstract String name();
index 9fc5283efebeca4a1c8c5b2ebf6b57ca38aa5a63..77e549c4457ec137c04a8e0d0580605f2aa2424f 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.*;
 import java.awt.event.*;
index e227d2b774e283d6a9690f7b7ef614e0437f3672..481e5b87240d46941fd6fa2d0ec1045233303a0e 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -23,7 +23,7 @@ import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
 import java.util.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 import org.jfree.ui.*;
 import org.jfree.chart.*;
@@ -37,12 +37,19 @@ import org.jfree.data.*;
 
 public class AltosUIEnable extends Container {
 
-       Insets  il, ir;
-       int     y;
-       int     x;
+       Insets          il, ir;
+       int             y;
+       int             x;
+       JCheckBox       imperial_units;
 
        static final int max_rows = 14;
 
+       public void units_changed(boolean imperial_units) {
+               if (this.imperial_units != null) {
+                       this.imperial_units.setSelected(imperial_units);
+               }
+       }
+
        class GraphElement implements ActionListener {
                AltosUIGrapher  grapher;
                JCheckBox       enable;
@@ -86,7 +93,7 @@ public class AltosUIEnable extends Container {
                /* Imperial units setting */
 
                /* Add label */
-               JCheckBox imperial_units = new JCheckBox("Imperial Units", AltosUIPreferences.imperial_units());
+               imperial_units = new JCheckBox("Imperial Units", AltosUIPreferences.imperial_units());
                imperial_units.addActionListener(new ActionListener() {
                                public void actionPerformed(ActionEvent e) {
                                        JCheckBox item = (JCheckBox) e.getSource();
index 74161634193d58b509e11675fa411f28b80d67bd..ea4f0cb0608487a6bfe852e824376488d96de123 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.util.*;
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public abstract class AltosUIFlightTab extends JComponent implements AltosFlightDisplay, HierarchyListener {
        public GridBagLayout    layout;
index 2e886932b8f4ba168622a2280eac52f854d651a2..39b1eb7348aa1d0ba1cc321720eb4d300d6a03da 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.*;
 import java.awt.event.*;
index 84e6dce402601a8c07abd14b84bcf0e93ec489a0..430069f57874f3f9fe76e09820ff3eb6b1214a8f 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosUIFreqList extends JComboBox<AltosFrequency> {
 
index 870c4e9356de5fd82d468ba2b0e6b4f200900424..d20aa54b8a9311455e3d6781e8ce15a17a8ecd80 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.io.*;
 import java.util.ArrayList;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 import org.jfree.ui.*;
 import org.jfree.chart.*;
index 39accab44405b208da65268d651e936665204c3e..fcd3546f89896a6ab2b6b5ed3c90a5300c7d806e 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.io.*;
 import java.util.ArrayList;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 import org.jfree.ui.*;
 import org.jfree.chart.*;
index d17078e781b17c1d3f55119796d4311d660d33b2..f2e772184d07045f0ba9e50a002ab6ea56b6c803 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public abstract class AltosUIIndicator implements AltosFontListener, AltosUnitsListener {
        JLabel          label;
index a15bf19fec5c59f0f9437eb0829e8172c337327b..72ff74d8284de907249443a1fdb6a459fdf27a13 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -25,7 +25,7 @@ import java.lang.Math;
 import java.awt.geom.*;
 import java.util.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosUILatLon {
        public double   lat;
index 8fa7dfe69d937b1833c0452282d112aeeefeb875..2fa6cbd621fc16df3ceef1a65f3079fb681a28c9 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.*;
 import libaltosJNI.*;
 
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosUILib extends AltosLib {
 
@@ -82,11 +82,23 @@ public class AltosUILib extends AltosLib {
        static public boolean loaded_library = false;
        static public boolean has_bluetooth = false;
 
-       static final String[] library_names = { "altos", "altos32", "altos64" };
+       static final String[] library_names_32 = { "altos", "altos32", "altos64" };
+       static final String[] library_names_64 = { "altos", "altos64", "altos32" };
 
        public static boolean load_library() {
                if (!initialized) {
-                       for (String name : library_names) {
+                       String model = System.getProperty("sun.arch.data.model", "missing");
+                       boolean is_64 = false;
+                       if (model.equals("64")) {
+                               is_64 = true;
+                       } else if (model.equals("32")) {
+                               ;
+                       } else {
+                               String arch = System.getProperty("os.arch", "missing");
+                               if (arch.endsWith("64"))
+                                       is_64 = true;
+                       }
+                       for (String name : is_64 ? library_names_64 : library_names_32) {
                                try {
                                        System.loadLibrary(name);
                                        libaltos.altos_init();
index a32d310c4b9c0ec2726009f01776d652c916d423..9eec0b24b5e9595e9fd711270a119d2d02301e1b 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 public interface AltosUIListener {
        public void ui_changed(String look_and_feel);
index c22801f8bea098bc022a504c8a9d67022b264c95..5c6d5bdf7938fb8bb84437d504cc675013c77ab6 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -25,7 +25,7 @@ import java.lang.Math;
 import java.awt.geom.*;
 import java.util.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosUIMapZoomListener {
 
index b9064cf435860fc4b812c6e93c566845f8ed14bc..73401e3cf7041773e7c10f7edf17fca55c2141ff 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import javax.swing.*;
 import javax.imageio.ImageIO;
index 680d123e3b153a02bbbd921a10ac519eeb66965f..1eec7b0acf271359ecfd4fe930beb192b9ac6ec5 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 public interface AltosUIMapCacheListener {
        public void map_cache_changed(int map_cache);
index 77cd4299b3c5fdc0bf60d08c693f6ae1ae15f4ca..97220a401565e6ec7f73a2d620c77075dd9da98c 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import javax.swing.*;
 import javax.imageio.ImageIO;
index 32437d4ec513ad7c301784dfeed72ee782e64699..2634f8439d7ef9a65feacb103d987411091d51b9 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -25,7 +25,7 @@ import java.lang.Math;
 import java.awt.geom.*;
 import java.util.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosUIMapLine {
        AltosUILatLon   start, end;
index 47fc4d5e28ab54e6f5be959a7b277eb794f3fe43..b4b98efafe7a0ccf91af58d32fbf30531ac68a5a 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -25,7 +25,7 @@ import java.lang.Math;
 import java.awt.geom.*;
 import java.util.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosUIMapMark {
 
index 705f4b6a8b2c6f2e95c632a1084461f4cf3338d0..e77af5802e99f608862f0250b5089450011f6fb8 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -25,7 +25,7 @@ import java.lang.Math;
 import java.awt.geom.*;
 import java.util.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 class PathPoint {
        AltosUILatLon   lat_lon;
index 1c088a497cf202bbcd031687ed59c0093c2d9359..e82b6c60880c1d0b1dcde0d4f4a7cc749fb2d977 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -26,7 +26,7 @@ import java.text.*;
 import java.lang.Math;
 import java.net.URL;
 import java.net.URLConnection;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 class AltosUIMapPos extends Box {
        AltosUIFrame    owner;
index 463ef3f21de7c6d05950b0db4a5ef1ddedbba306..dc0e4cc1ce43934db39eff6e3890563440b9f51f 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 public class AltosUIMapRectangle {
        AltosUILatLon   ul, lr;
index dd8ace32c7c0800768a19becbb0ebcde4c072b65..70bb6fedcdf5b9fd4d68f879d4be8e37e45fb929 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.io.*;
 import java.net.*;
index 0bbd2bc93c6bebfac7fb1d048c2850be45a7fa28..ccda8983c2c634bcc1c51bc5c57157ee650abd7d 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 public interface AltosUIMapStoreListener {
        abstract void notify_store(AltosUIMapStore store, int status);
index 8b6a8f0a3862a3f49f0946fc6382fe0daae1822e..afd1bbc6be814e18c4410e6d9349d304c5ebf50c 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.*;
 import java.awt.image.*;
@@ -25,7 +25,7 @@ import java.awt.geom.*;
 import java.io.*;
 import java.util.*;
 import java.awt.RenderingHints.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosUIMapTile {
        AltosUIMapTileListener  listener;
index f58f55e0defb8662803e5778503118aeb5e071fe..dace5b769df0abf12f4fa06f89778298e64137f6 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 public interface AltosUIMapTileListener {
        abstract public void notify_tile(AltosUIMapTile tile, int status);
index 89a3e9f682b95f6ba88e7848795b92fdbc3e40fe..25497403d3def7ba2c67b78aa8dbc123d5d35c42 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -25,7 +25,7 @@ import java.lang.Math;
 import java.awt.geom.*;
 import java.util.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosUIMapTransform {
 
index 70b8e2e92c8fb7772e387ce9d209df809a472145..c8632b9962682c32c64b1c27f648cccc45213062 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -26,7 +26,7 @@ import java.lang.*;
 import java.awt.geom.*;
 import java.util.*;
 import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosUIMapView extends Component implements MouseMotionListener, MouseListener, MouseWheelListener, ComponentListener, AltosUIMapTileListener, AltosUIMapStoreListener {
 
index 23498c89c7d41a781f880bad4f6e30917edde7d6..9f74baca180c044808f663609203713c035519f7 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 public interface AltosUIMapZoomListener {
        abstract public void zoom_changed(int zoom);
index 5e9809ee07660149c6e58fb02e7dcc574cbd8fb6..843ee939b9843e8e5021df1b91adbe00901479de 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.io.*;
 import java.util.ArrayList;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 import org.jfree.ui.*;
 import org.jfree.chart.*;
index ecab20d4ee7e54846660002fe4a5775dad110b5d..9760494c74f7bea6193611f8a70d7c650493d526 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.io.*;
 import java.util.*;
 import java.awt.Component;
 import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosUIPreferences extends AltosPreferences {
 
index 4048fd83b99f4a52b0018c829cb69e8df48d0140..91fe42ec8e3b6f08959b1d60c7abba86fba88274 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.io.File;
 import java.util.prefs.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 import javax.swing.filechooser.FileSystemView;
 
 public class AltosUIPreferencesBackend implements AltosPreferencesBackend {
@@ -62,6 +62,14 @@ public class AltosUIPreferencesBackend implements AltosPreferencesBackend {
                _preferences.putBoolean(key, value);
        }
 
+       public byte[] getBytes(String key, byte[] def) {
+               return _preferences.getByteArray(key, def);
+       }
+
+       public void putBytes(String key, byte[] value) {
+               _preferences.putByteArray(key, value);
+       }
+
        public boolean nodeExists(String key) {
                try {
                        return _preferences.nodeExists(key);
index ee35ce6d1585a07f5a45bebedf7c9207658ca2cf..0c783a89d46a6ad3b4089101296b0f2cc68a36db 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class AltosUIRateList extends JComboBox<String> {
 
index 809020c49e79c25d31dc2394dadfdee610490915..4cd5ccd12ad77a6ef973a65ac457e926cab4f0a0 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.io.*;
 import java.util.ArrayList;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 import org.jfree.ui.*;
 import org.jfree.chart.*;
index facfdcde04e348a1be6fa2a2503e9a11b33e21a7..77eef56754f3661315f521dc2e3634b4a53f0ce8 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.util.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 
 public class AltosUITelemetryList extends JComboBox<String> {
index 50c30851fea62ac52e895b403407e7e6a68b51f1..f86e274f271ec3757d42901909318b8003e0cc18 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public abstract class AltosUIUnitsIndicator extends AltosUIIndicator {
 
index 9fd5757b76753d021e2875d699f937844843c183..beb62cbfe03c6929d85edec9998cafc85ff9ed91 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 public class AltosUIVersion {
        public final static String version = "@VERSION@";
index 8e99185678e971860c53ed831b48c5f0605eb833..44ad2ea2d175bea91013dd44242045776eab98c7 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public abstract class AltosUIVoltageIndicator extends AltosUIUnitsIndicator {
 
index f4906a73662c4f8f0140c0152ad5e4935f726f78..e940493fd5183da19ac0186aa64d825f387625f2 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.util.*;
 import libaltosJNI.*;
index e02730bac7399a357ed662a7479168fac53e0d63..867f661900cbd74a7968bc08441320d82666a160 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import com.sun.speech.freetts.Voice;
 import com.sun.speech.freetts.VoiceManager;
index 9bccb808d8e9743222f677a1046b885483bd6072..5d9ce2d9c3230fb49c0a67141d079d6142c613ca 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.awt.*;
 import java.awt.event.*;
index 23aacd78829c7274ebf3075908413c0f48f8a1a1..28b00ce1f7d5a88834cdc888fafd5e213bc53348 100755 (executable)
@@ -55,7 +55,7 @@ Copyright © 2003-2007 Apple, Inc., All Rights Reserved
 
 */
 
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
 
 import java.lang.reflect.*;
 import java.util.HashMap;
index 68a8ebf2f56928924d70839535bf28799e4c35fc..5d876e21e9e2ead8179ff20d23a0d98a74ecacd1 100755 (executable)
@@ -19,16 +19,17 @@ while true; do
 
        echo 'C 0' > $dev
 
+       calline=`./get-radio-cal $dev`
+       CURRENT_CAL=`echo $calline | awk '{print $2}'`
+       CURRENT_FREQ=`echo $calline | awk '{print $4}'`
+       CAL_VALUE=$CURRENT_CAL
+
        case "$FREQ" in
        "")
                echo $SERIAL","$CAL_VALUE >> cal_values
                exit 0
                ;;
        *)
-               calline=`./get-radio-cal $dev`
-               CURRENT_CAL=`echo $calline | awk '{print $2}'`
-               CURRENT_FREQ=`echo $calline | awk '{print $4}'`
-
                echo "Current radio calibration "$CURRENT_CAL
                echo "Current radio frequency "$CURRENT_FREQ
 
@@ -36,6 +37,8 @@ while true; do
 
                echo "Programming flash with cal value " $CAL_VALUE
 
+               dd if=$dev iflag=nonblock
+
                cat << EOF > $dev
 c f $CAL_VALUE
 c w
diff --git a/ao-bringup/cal-freq-file b/ao-bringup/cal-freq-file
new file mode 100755 (executable)
index 0000000..fb48907
--- /dev/null
@@ -0,0 +1,54 @@
+#!/bin/sh
+
+case $# in
+2)
+    dev="$1"
+    serial="$2"
+       ;;
+*)
+       echo "Usage: $0 <device> <serial>"
+       exit 1;
+       ;;
+esac
+
+echo 'E 0' > $dev
+
+while true; do
+
+        dd if=$dev iflag=nonblock of=/dev/null > /dev/null 2>&1
+
+       echo 'C 1' > $dev
+
+       echo -n "Generating RF carrier. Please enter measured frequency [enter for done]: "
+
+       read FREQ
+
+       echo 'C 0' > $dev
+
+       calline=`./get-radio-cal $dev`
+       CURRENT_CAL=`echo $calline | awk '{print $2}'`
+       CURRENT_FREQ=`echo $calline | awk '{print $4}'`
+       CAL_VALUE=$CURRENT_CAL
+
+       case "$FREQ" in
+       "")
+               echo $serial","$CAL_VALUE >> cal_values
+               exit 0
+               ;;
+       *)
+               echo "Current radio calibration "$CURRENT_CAL
+               echo "Current radio frequency "$CURRENT_FREQ
+
+               CAL_VALUE=`nickle -e "floor($CURRENT_FREQ / $FREQ * $CURRENT_CAL + 0.5)"`
+
+               echo "Setting cal value" $CAL_VALUE
+
+               dd if=$dev iflag=nonblock of=/dev/null > /dev/null 2>&1
+
+               cat << EOF > $dev
+c f $CAL_VALUE
+EOF
+               ;;
+       esac
+done
+
index eabe1ee5f975aa6e2b29dc43997e385ef9296d9e..76f3effb63ae69e4a36dff927b3d1a8826162a14 100755 (executable)
@@ -17,22 +17,10 @@ ao-list | while read product serial dev; do
        "$PRODUCT-v$VERSION")
 
            echo "Testing $product $serial $dev"
+           echo ""
 
-           for igniter in drogue main 0 1 2 3; do
-               echo "Testing $igniter igniter."
-               echo -n "Press enter to continue..."
-               read foo < /dev/tty
-               ../ao-tools/ao-test-igniter/ao-test-igniter --tty="$dev" $igniter
-
-               case $? in
-                   0)
-                       ;;
-                   *)
-                       echo "failed"
-                       exit 1
-                       ;;
-               esac
-           done
+           ./test-igniters $dev drogue main 0 1 2 3
+           echo""
 
            echo "Testing baro sensor"
            ../ao-tools/ao-test-baro/ao-test-baro --tty="$dev"
@@ -44,6 +32,7 @@ ao-list | while read product serial dev; do
                    echo "failed"
                    exit 1
            esac
+           echo""
 
            FLASHSIZE=8388608
 
@@ -57,12 +46,10 @@ ao-list | while read product serial dev; do
                    echo "failed"
                    exit 1
            esac
+           echo""
 
            echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
            ret=0
            ;;
-       *)
-           echo "Skipping $product $serial $dev"
-           ;;
     esac
 done
index 17e0095526e3270e735eaccfc28f3445e42ac8aa..e11244d2372eced9700fe10b5be103d574617c4d 100755 (executable)
@@ -17,17 +17,10 @@ ao-list | while read product serial dev; do
        "$PRODUCT-v$VERSION")
 
            echo "Testing $product $serial $dev"
-
-           echo "Testing igniters. Both should flash"
-           ../ao-tools/ao-test-igniter/ao-test-igniter --tty="$dev" drogue main
-
-           case $? in
-               0)
-                   ;;
-               *)
-                   echo "failed"
-                   exit 1
-           esac
+           echo ""
+           
+           ./test-igniters "$dev" drogue main
+           echo ""
 
            echo "Testing baro sensor"
            ../ao-tools/ao-test-baro/ao-test-baro --tty="$dev"
@@ -39,6 +32,7 @@ ao-list | while read product serial dev; do
                    echo "failed"
                    exit 1
            esac
+           echo""
 
            FLASHSIZE=1048576
 
@@ -52,12 +46,10 @@ ao-list | while read product serial dev; do
                    echo "failed"
                    exit 1
            esac
+           echo""
 
            echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
            ret=0
            ;;
-       *)
-           echo "Skipping $product $serial $dev"
-           ;;
     esac
 done
diff --git a/ao-bringup/test-igniters b/ao-bringup/test-igniters
new file mode 100755 (executable)
index 0000000..763f42a
--- /dev/null
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+dev="$1"
+shift
+
+for igniter in "$@"; do
+       pass="n"
+       while [ $pass != "y" ]; do
+               echo -n "Testing $igniter igniter. Press enter to continue..."
+               read foo < /dev/tty
+               ../ao-tools/ao-test-igniter/ao-test-igniter --tty="$dev" $igniter
+
+               case $? in
+                   0)
+                       echo "pass"
+                       pass="y"
+                       ;;
+                   *)
+                       echo "Failed. Try again."
+                       ;;
+               esac
+       done
+done
+
+exit 0
index 9295dd062db03c698308eb4198530c9e27f79afc..0b27580205e4794c05f2d59139a80b951e86d09b 100755 (executable)
@@ -21,7 +21,7 @@ ao-list | while read product serial dev; do
            FLASHSIZE=2097152
 
            echo "Testing flash"
-           ./test-flash "$dev" "$FLASHSIZE"
+           ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE"
 
            case $? in
                0)
@@ -32,7 +32,7 @@ ao-list | while read product serial dev; do
            esac
 
            echo "Testing GPS"
-           ./test-gps "$dev"
+           ../ao-tools/ao-test-gps/ao-test-gps --tty="$dev"
 
            case $? in
                0)
diff --git a/ao-bringup/test-telemega b/ao-bringup/test-telemega
new file mode 100755 (executable)
index 0000000..2e49788
--- /dev/null
@@ -0,0 +1,66 @@
+#!/bin/sh
+
+VERSION=1.0
+PRODUCT=TeleMega
+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"
+
+           ./test-igniters $dev main drogue 3 0 1 2
+           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
+           ret=0
+           ;;
+    esac
+done
diff --git a/ao-bringup/test-telemetrum b/ao-bringup/test-telemetrum
new file mode 100755 (executable)
index 0000000..57a4d90
--- /dev/null
@@ -0,0 +1,67 @@
+#!/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
+           ret=0
+           ;;
+    esac
+done
index ddee5ee81e6fc89091c838554c6b6b5371b421b6..058e72cec590936c7073bae6755cf17c5fb27e5f 100755 (executable)
@@ -31,18 +31,27 @@ read SERIAL
 
 echo $RAWLOAD
 
-$RAWLOAD -D 100 -r ao_led_blink.ihx
+case $USER in
+    bdale)
+       programmer=100
+       ;;
+    keithp)
+       programmer=186
+       ;;
+esac
+
+$RAWLOAD -D $programmer -r ao_led_blink.ihx
 echo "LEDs should be blinking"
 sleep 5
 
-$RAWLOAD -D 100 -r ao_radio_xmit.ihx
+$RAWLOAD -D $programmer -r ao_radio_xmit.ihx
 echo -n "Generating RF carrier.  Please enter measured frequency: "
 read FREQ
 
 CAL_VALUE=`nickle -e "floor(434.55 / $FREQ * 1186611 + 0.5)"`
 
 echo "Programming flash with cal value " $CAL_VALUE
-$AOLOAD -D 100 --cal $CAL_VALUE /usr/share/altos/teledongle-v0.2*.ihx $SERIAL
+$AOLOAD -D $programmer --cal $CAL_VALUE /usr/share/altos/teledongle-v0.2*.ihx $SERIAL
 
 echo "Serial number "$SERIAL" programmed with RF cal value "$CAL_VALUE
 echo $SERIAL","$CAL_VALUE >> cal_values
diff --git a/ao-bringup/turnon_teledonglev3 b/ao-bringup/turnon_teledonglev3
new file mode 100755 (executable)
index 0000000..e6750c4
--- /dev/null
@@ -0,0 +1,89 @@
+#!/bin/sh
+
+if [ -x ../ao-tools/ao-flash/ao-flash-lpc ]; then
+       FLASH_LPC=../ao-tools/ao-flash/ao-flash-lpc
+elif [ -x /usr/bin/ao-flash-lpc ]; then
+       FLASH_LPC=/usr/bin/ao-flash-lpc
+else
+       echo "Can't find ao-flash-lpc!  Aborting."
+       exit 1
+fi
+
+if [ -x /usr/bin/ao-usbload ]; then
+       USBLOAD=/usr/bin/ao-usbload
+else
+       echo "Can't find ao-usbload!  Aborting."
+       exit 1
+fi
+
+PRODUCT=teledongle
+PRODUCT_NAME=TeleDongle
+VERSION=3.0
+
+echo "$PRODUCT_NAME v$VERSION Turn-On and Calibration Program"
+echo "Copyright © 2015 by Bdale Garbee.  Released under GPL v2"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT_NAME 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_NAME-$VERSION serial number: "
+read SERIAL
+
+BINARIES=$HOME/altusmetrumllc/Binaries
+
+LOADER="$BINARIES/loaders/$PRODUCT-v$VERSION-"*.elf
+ALTOS="$BINARIES/$PRODUCT-v$VERSION"*.elf
+
+$FLASH_LPC $LOADER || exit 1
+
+sleep 2
+
+$USBLOAD --serial=$SERIAL $ALTOS || exit 1
+
+sleep 5
+
+dev=`ao-list | awk '/TeleDongle-v'"$VERSION"'/ { print $3; exit(0); }'`
+
+case "$dev" in
+/dev/tty*)
+       echo "TeleDongle found on $dev"
+       ;;
+*)
+       echo 'No TeleDongle-v'"$VERSION"' found'
+       exit 1
+       ;;
+esac
+
+echo 'E 0' > $dev
+
+./cal-freq-file $dev $SERIAL
+
+case $? in
+    0)
+       ;;
+    *)
+       echo "Frequency calibration failed"
+       exit 1
+       ;;
+esac
+
+CAL_VALUE=`grep "^$SERIAL," cal_values | tail -1 | sed 's/^[^,]*,//'`
+
+case "$CAL_VALUE" in
+    [1-9]*)
+    ;;
+    *)
+       echo "Invalid calibration value: $CAL_VALUE"
+       exit 1
+       ;;
+esac
+
+echo "Reflashing with calibration: $CAL_VALUE"
+
+$USBLOAD --cal=$CAL_VALUE --tty=$dev $ALTOS || exit 1
+
+echo "$PRODUCT_NAME-v$VERSION $SERIAL is ready to ship"
+
+exit $?
index 7745a8e560abcddf71bddf50fc8281c0db75965d..7b95bf20fb9eb4ea756564b439061a8f4517b6fb 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 if [ -x /usr/bin/ao-flash-stm ]; then
-       STMLOAD=/usr/bin/ao-flash-stm
+       FLASH_STM=/usr/bin/ao-flash-stm
 else
        echo "Can't find ao-flash-stm!  Aborting."
        exit 1
@@ -21,22 +21,22 @@ echo "TeleMega v$VERSION Turn-On and Calibration Program"
 echo "Copyright 2014 by Bdale Garbee.  Released under GPL v2"
 echo
 echo "Expectations:"
-echo "\tTeleMega v$VERSIOn powered from USB"
+echo "\tTeleMega 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 "TeleMega-$VERSION serial number: "
 read SERIAL
 
-echo $STMLOAD
+echo $FLASH_STM
 
-$STMLOAD $REPO/loaders/telemega-v$VERSION*.elf || exit 1
+$FLASH_STM $REPO/loaders/telemega-v$VERSION*.elf || exit 1
 
-sleep 2
+sleep 5
 
 $USBLOAD --serial=$SERIAL $REPO/telemega-v$VERSION*.elf || exit 1
 
-sleep 2
+sleep 5
 
 dev=`ao-list | awk '/TeleMega-v'"$VERSION"'/ { print $3; exit(0); }'`
 
@@ -57,3 +57,7 @@ SERIAL=$SERIAL ./cal-freq $dev
 ../ao-tools/ao-cal-accel/ao-cal-accel $dev
 
 echo 'E 1' > $dev
+
+./test-telemega
+
+exit $?
index 48ff1e276cb6083aeed292821b6e8469b186675f..ba40a08a363b763f38ef95555ebf48a3b8196a82 100755 (executable)
@@ -56,3 +56,7 @@ SERIAL=$SERIAL ./cal-freq $dev
 ../ao-tools/ao-cal-accel/ao-cal-accel $dev
 
 echo 'E 1' > $dev
+
+./test-telemetrum
+
+exit $?
index 2d873e5049f97c469b1a977991a7d0fb95d98f1a..6a170cbdc7e1c4e6861a85facac6a66c8cf70cf5 100644 (file)
@@ -2,7 +2,7 @@ SUBDIRS=lib ao-rawload ao-dbg ao-bitbang ao-eeprom ao-list \
        ao-load ao-telem ao-send-telem ao-sky-flash \
        ao-dumpflash ao-edit-telem ao-dump-up ao-elftohex \
        ao-flash ao-usbload ao-test-igniter ao-test-baro \
-       ao-test-flash ao-cal-accel
+       ao-test-flash ao-cal-accel ao-test-gps ao-usbtrng
 if LIBSTLINK
 SUBDIRS += ao-stmload
 endif
index 26c3263e72a193886a248067adb83746c869ba0f..ef6f892c1387f4a00b7e4fe75da2dbf220bbadb4 100644 (file)
@@ -29,12 +29,14 @@ static const struct option options[] = {
        { .name = "device", .has_arg = 1, .val = 'D' },
        { .name = "frequency", .has_arg = 1, .val = 'F' },
        { .name = "realtime", .has_arg = 0, .val = 'R' },
+       { .name = "verbose", .has_arg = 0, .val = 'v' },
+       { .name = "fake", .has_arg = 0, .val = 'f' },
        { 0, 0, 0, 0},
 };
 
 static void usage(char *program)
 {
-       fprintf(stderr, "usage: %s [--tty <tty-name>] [--device <device-name>] [--frequency <kHz>] [--realtime] file.telem ...\n", program);
+       fprintf(stderr, "usage: %s [--tty <tty-name>] [--device <device-name>] [--frequency <kHz>] [--realtime] [--verbose] [--fake] file.telem ...\n", program);
        exit(1);
 }
 
@@ -126,7 +128,7 @@ send_telem(struct cc_usb *cc, union ao_telemetry_all *telem)
        for (i = 0; i < 0x20; i++)
                cc_usb_printf(cc, "%02x", b[i]);
        cc_usb_sync(cc);
-}      
+}
 
 static void
 do_delay(uint16_t now, uint16_t then)
@@ -173,9 +175,11 @@ main (int argc, char **argv)
        uint16_t        last_tick;
        int             started;
        int             realtime = 0;
-      
+       int             verbose = 0;
+       int             fake = 0;
+       int             rate = 0;
 
-       while ((c = getopt_long(argc, argv, "RT:D:F:", options, NULL)) != -1) {
+       while ((c = getopt_long(argc, argv, "vRfT:D:F:r:", options, NULL)) != -1) {
                switch (c) {
                case 'T':
                        tty = optarg;
@@ -189,6 +193,30 @@ main (int argc, char **argv)
                case 'R':
                        realtime = 1;
                        break;
+               case 'v':
+                       verbose++;
+                       break;
+               case 'f':
+                       fake++;
+                       break;
+               case 'r':
+                       rate = atoi(optarg);
+                       switch (rate) {
+                       case 38400:
+                               rate = 0;
+                               break;
+                       case 9600:
+                               rate = 1;
+                               break;
+                       case 2400:
+                               rate = 2;
+                               break;
+                       default:
+                               fprintf(stderr, "Rate %d isn't 38400, 9600 or 2400\n", rate);
+                               usage(argv[0]);
+                               break;
+                       }
+                       break;
                default:
                        usage(argv[0]);
                        break;
@@ -206,42 +234,65 @@ main (int argc, char **argv)
 
        cc_usb_printf(cc, "m 0\n");
        cc_usb_printf(cc, "c F %d\n", freq);
-       for (i = optind; i < argc; i++) {
-               file = fopen(argv[i], "r");
-               if (!file) {
-                       perror(argv[i]);
-                       ret++;
-                       continue;
+       cc_usb_printf(cc, "c T %d\n", rate);
+
+       if (fake) {
+               union ao_telemetry_all  telem;
+               uint16_t                tick;
+               int                     i;
+
+               memset(&telem, '\0', sizeof (telem));
+               telem.generic.serial = 1;
+               telem.generic.type = 0;
+               for (i = 0; i < sizeof (telem.generic.payload); i++)
+                       telem.generic.payload[i] = i & 7;
+               for (;;) {
+                       telem.generic.tick += 50;
+                       send_telem(cc, &telem);
+                       do_delay(50, 0);
                }
-               started = 0;
-               last_tick = 0;
-               while (fgets(line, sizeof (line), file)) {
-                       union ao_telemetry_all telem;
-
-                       if (cc_telemetry_parse(line, &telem)) {
-                               /*
-                                * Skip packets with CRC errors.
-                                */
-                               if ((telem.generic.status & (1 << 7)) == 0)
-                                       continue;
-
-                               if (started) {
-                                       do_delay(telem.generic.tick, last_tick);
-                                       last_tick = telem.generic.tick;
-                                       send_telem(cc, &telem);
-                               } else {
-                                       enum ao_flight_state state = packet_state(&telem);
-                                       add_telem(&telem);
-                                       if (ao_flight_pad < state && state < ao_flight_landed) {
-                                               printf ("started\n");
-                                               started = 1;
-                                               last_tick = send_queued(cc, realtime);
+       } else {
+               for (i = optind; i < argc; i++) {
+                       file = fopen(argv[i], "r");
+                       if (!file) {
+                               perror(argv[i]);
+                               ret++;
+                               continue;
+                       }
+                       started = 0;
+                       last_tick = 0;
+                       while (fgets(line, sizeof (line), file)) {
+                               union ao_telemetry_all telem;
+
+                               if (cc_telemetry_parse(line, &telem)) {
+                                       /*
+                                        * Skip packets with CRC errors.
+                                        */
+                                       if ((telem.generic.status & (1 << 7)) == 0)
+                                               continue;
+
+                                       if (verbose)
+                                               printf ("type %4d\n", telem.generic.type);
+
+                                       if (started || realtime) {
+                                               do_delay(telem.generic.tick, last_tick);
+                                               last_tick = telem.generic.tick;
+                                               send_telem(cc, &telem);
+                                       } else {
+                                               enum ao_flight_state state = packet_state(&telem);
+                                               printf ("\tstate %4d\n", state);
+                                               add_telem(&telem);
+                                               if (ao_flight_pad < state && state < ao_flight_landed) {
+                                                       printf ("started\n");
+                                                       started = 1;
+                                                       last_tick = send_queued(cc, realtime);
+                                               }
                                        }
                                }
                        }
-               }
-               fclose (file);
+                       fclose (file);
 
+               }
        }
        return ret;
 }
diff --git a/ao-tools/ao-test-gps/.gitignore b/ao-tools/ao-test-gps/.gitignore
new file mode 100644 (file)
index 0000000..ac203bc
--- /dev/null
@@ -0,0 +1 @@
+ao-test-gps
diff --git a/ao-tools/ao-test-gps/Makefile.am b/ao-tools/ao-test-gps/Makefile.am
new file mode 100644 (file)
index 0000000..d89dddd
--- /dev/null
@@ -0,0 +1,11 @@
+bin_PROGRAMS=ao-test-gps
+
+AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+
+ao_test_gps_DEPENDENCIES = $(top_builddir)/ao-tools/lib/libao-tools.a
+
+ao_test_gps_LDADD=$(top_builddir)/ao-tools/lib/libao-tools.a $(LIBUSB_LIBS)
+
+ao_test_gps_SOURCES=ao-test-gps.c
+
+man_MANS = ao-test-gps.1
diff --git a/ao-tools/ao-test-gps/ao-test-gps.1 b/ao-tools/ao-test-gps/ao-test-gps.1
new file mode 100644 (file)
index 0000000..3d99c24
--- /dev/null
@@ -0,0 +1,55 @@
+.\"
+.\" Copyright © 2009 Keith Packard <keithp@keithp.com>
+.\"
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful, but
+.\" WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+.\" General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License along
+.\" with this program; if not, write to the Free Software Foundation, Inc.,
+.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+.\"
+.\"
+.TH AO-LOAD 1 "ao-test-gps" ""
+.SH NAME
+ao-test-baro \- test AltOS tracker GPS receiver
+.SH SYNOPSIS
+.B "ao-test-gps"
+[\-T \fItty-device\fP]
+[\--tty \fItty-device\fP]
+[\-D \fIaltos-device\fP]
+[\--device \fIaltos-device\fP]
+\fIgps-name...\fP
+.SH DESCRIPTION
+.I ao-test-gps
+Waits for the GPS receiver to report lock.
+.SH OPTIONS
+.TP
+\-T tty-device | --tty tty-device
+This selects which tty device the debugger uses to communicate with
+the target device.
+.TP
+\-D AltOS-device | --device AltOS-device
+Search for a connected device. This requires an argument of one of the
+following forms:
+.IP
+TeleMega:2
+.br
+TeleMega
+.br
+2
+.IP
+Leaving out the product name will cause the tool to select a suitable
+product, leaving out the serial number will cause the tool to match
+one of the available devices.
+.SH USAGE
+.I ao-test-gps
+opens the target device and waits for it to report GPS lock.
+.SH AUTHOR
+Keith Packard
diff --git a/ao-tools/ao-test-gps/ao-test-gps.c b/ao-tools/ao-test-gps/ao-test-gps.c
new file mode 100644 (file)
index 0000000..84ed713
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * Copyright © 2014 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <err.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <string.h>
+#include <stdbool.h>
+#include "ao-elf.h"
+#include "ccdbg.h"
+#include "cc-usb.h"
+#include "cc.h"
+#include "ao-verbose.h"
+
+static const struct option options[] = {
+       { .name = "tty", .has_arg = 1, .val = 'T' },
+       { .name = "device", .has_arg = 1, .val = 'D' },
+       { .name = "raw", .has_arg = 0, .val = 'r' },
+       { .name = "verbose", .has_arg = 1, .val = 'v' },
+       { 0, 0, 0, 0},
+};
+
+static void usage(char *program)
+{
+       fprintf(stderr, "usage: %s [--verbose=<verbose>] [--device=<device>] [-tty=<tty>] main|drogue\n", program);
+       exit(1);
+}
+
+void
+done(struct cc_usb *cc, int code)
+{
+/*     cc_usb_printf(cc, "a\n"); */
+       cc_usb_close(cc);
+       exit (code);
+}
+
+static int
+ends_with(char *whole, char *suffix)
+{
+       int whole_len = strlen(whole);
+       int suffix_len = strlen(suffix);
+
+       if (suffix_len > whole_len)
+               return 0;
+       return strcmp(whole + whole_len - suffix_len, suffix) == 0;
+}
+
+static int
+starts_with(char *whole, char *prefix)
+{
+       int whole_len = strlen(whole);
+       int prefix_len = strlen(prefix);
+
+       if (prefix_len > whole_len)
+               return 0;
+       return strncmp(whole, prefix, prefix_len) == 0;
+}
+
+static char **
+tok(char *line) {
+       char    **strs = malloc (sizeof (char *)), *str;
+       int     n = 0;
+
+       while ((str = strtok(line, " \t"))) {
+               line = NULL;
+               strs = realloc(strs, (n + 2) * sizeof (char *));
+               strs[n] = strdup(str);
+               n++;
+       }
+       strs[n] = '\0';
+       return strs;
+}
+
+static void
+free_strs(char **strs) {
+       char    *str;
+       int     i;
+
+       for (i = 0; (str = strs[i]) != NULL; i++)
+               free(str);
+       free(strs);
+}
+
+struct gps {
+       struct gps      *next;
+       char            **strs;
+};
+
+static struct gps *
+gps(struct cc_usb *usb)
+{
+       struct gps      *head = NULL, **tail = &head;
+       cc_usb_printf(usb, "g\nv\n");
+       for (;;) {
+               char    line[512];
+               struct gps      *b;
+
+               cc_usb_getline(usb, line, sizeof (line));
+               b = malloc (sizeof (struct gps));
+               b->strs = tok(line);
+               b->next = NULL;
+               *tail = b;
+               tail = &b->next;
+               if (strstr(line, "software-version"))
+                       break;
+       }
+       return head;
+}
+
+static void
+free_gps(struct gps *b) {
+       struct gps *n;
+
+       while (b) {
+               n = b->next;
+               free_strs(b->strs);
+               free(b);
+               b = n;
+       }
+}
+
+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
+do_gps(struct cc_usb *usb) {
+       int     count = 0;
+
+       for (;;) {
+               struct gps *b = gps(usb);
+               char **flags = find_gps(b, "Flags:");
+               char **sats = find_gps(b, "Sats:");
+               int actual_flags = strtol(flags[1], NULL, 0);
+               int actual_sats = strtol(sats[1], NULL, 0);
+
+               if (actual_flags & (1 << 4)) {
+                       printf("\n");
+                       printf("Flags: %s (0x%x)\n", flags[1], actual_flags);
+                       printf("Sats: %s (%d)\n", sats[1], actual_sats);
+                       break;
+               }
+
+               free_gps(b);
+               printf("%d", actual_sats);
+               ++count;
+               if (count >= 50) {
+                       putchar('\n');
+                       count = 0;
+               }
+               else if (count % 10 == 0)
+                       putchar(' ');
+               fflush(stdout);
+               sleep(1);
+       }
+       return 1;
+}
+
+int
+main (int argc, char **argv)
+{
+       char                    *device = NULL;
+       char                    *filename;
+       Elf                     *e;
+       unsigned int            s;
+       int                     i;
+       int                     c;
+       int                     tries;
+       struct cc_usb           *cc = NULL;
+       char                    *tty = NULL;
+       int                     success;
+       int                     verbose = 0;
+       int                     ret = 0;
+
+       while ((c = getopt_long(argc, argv, "rT:D:c:s:v:", options, NULL)) != -1) {
+               switch (c) {
+               case 'T':
+                       tty = optarg;
+                       break;
+               case 'D':
+                       device = optarg;
+                       break;
+               case 'v':
+                       verbose++;
+                       break;
+               default:
+                       usage(argv[0]);
+                       break;
+               }
+       }
+
+       ao_verbose = verbose;
+
+       if (verbose > 1)
+               ccdbg_add_debug(CC_DEBUG_BITBANG);
+
+       if (!tty)
+               tty = cc_usbdevs_find_by_arg(device, "TeleGPS");
+       if (!tty)
+               tty = cc_usbdevs_find_by_arg(device, "TeleMega");
+       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);
+
+       if (!do_gps(cc))
+               ret = 1;
+       done(cc, ret);
+}
index 6a699fe8586d0a60ec19cac6ad9d865a05ae9a43..419c89482c84d721af51bf6e26f91d3a7652312a 100644 (file)
@@ -190,7 +190,6 @@ main (int argc, char **argv)
        if (verbose > 1)
                ccdbg_add_debug(CC_DEBUG_BITBANG);
 
-       printf ("device %s\n", device);
        if (!tty)
                tty = cc_usbdevs_find_by_arg(device, "TeleMega-v1.0");
        if (!tty)
index fd34fbdcfad8f21f7c0443a89fe312f4c500527e..1b217e55aae6d4fa11346379b78a551d159f18b5 100644 (file)
@@ -86,12 +86,13 @@ static const struct option options[] = {
        { .name = "cal", .has_arg = 1, .val = 'c' },
        { .name = "serial", .has_arg = 1, .val = 's' },
        { .name = "verbose", .has_arg = 1, .val = 'v' },
+       { .name = "wait", .has_arg = 0, .val = 'w' },
        { 0, 0, 0, 0},
 };
 
 static void usage(char *program)
 {
-       fprintf(stderr, "usage: %s [--raw] [--verbose=<verbose>] [--device=<device>] [-tty=<tty>] [--cal=<radio-cal>] [--serial=<serial>] file.{elf,ihx}\n", program);
+       fprintf(stderr, "usage: %s [--raw] [--verbose=<verbose>] [--device=<device>] [-tty=<tty>] [--cal=<radio-cal>] [--serial=<serial>] [--wait] file.{elf,ihx}\n", program);
        exit(1);
 }
 
@@ -145,7 +146,7 @@ main (int argc, char **argv)
        uint32_t                flash_base, flash_bound;
        int                     has_flash_size = 0;
 
-       while ((c = getopt_long(argc, argv, "rT:D:c:s:v:", options, NULL)) != -1) {
+       while ((c = getopt_long(argc, argv, "wrT:D:c:s:v:", options, NULL)) != -1) {
                switch (c) {
                case 'T':
                        tty = optarg;
@@ -156,6 +157,9 @@ main (int argc, char **argv)
                case 'r':
                        raw = 1;
                        break;
+               case 'w':
+                       cc_default_timeout = -1;
+                       break;
                case 'c':
                        cal = strtoul(optarg, &cal_end, 10);
                        if (cal_end == optarg || *cal_end != '\0')
@@ -208,6 +212,10 @@ main (int argc, char **argv)
                                this_tty = cc_usbdevs_find_by_arg(device, "AltosFlash");
                        if (!this_tty)
                                this_tty = cc_usbdevs_find_by_arg(device, "TeleMega");
+                       if (!this_tty)
+                               this_tty = cc_usbdevs_find_by_arg(device, "TeleMetrum");
+                       if (!this_tty)
+                               this_tty = cc_usbdevs_find_by_arg(device, "TeleGPS");
                        if (!this_tty)
                                this_tty = getenv("ALTOS_TTY");
                        if (!this_tty)
diff --git a/ao-tools/ao-usbtrng/.gitignore b/ao-tools/ao-usbtrng/.gitignore
new file mode 100644 (file)
index 0000000..54833a2
--- /dev/null
@@ -0,0 +1 @@
+ao-usbtrng
diff --git a/ao-tools/ao-usbtrng/Makefile.am b/ao-tools/ao-usbtrng/Makefile.am
new file mode 100644 (file)
index 0000000..5cbab5c
--- /dev/null
@@ -0,0 +1,11 @@
+bin_PROGRAMS=ao-usbtrng
+
+AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+
+ao_usbtrng_DEPENDENCIES = $(top_builddir)/ao-tools/lib/libao-tools.a
+
+ao_usbtrng_LDADD=$(top_builddir)/ao-tools/lib/libao-tools.a $(LIBUSB_LIBS)
+
+ao_usbtrng_SOURCES=ao-usbtrng.c
+
+man_MANS = ao-usbtrng.1
diff --git a/ao-tools/ao-usbtrng/ao-usbtrng.1 b/ao-tools/ao-usbtrng/ao-usbtrng.1
new file mode 100644 (file)
index 0000000..7a1311b
--- /dev/null
@@ -0,0 +1,58 @@
+.\"
+.\" Copyright © 2009 Keith Packard <keithp@keithp.com>
+.\"
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful, but
+.\" WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+.\" General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License along
+.\" with this program; if not, write to the Free Software Foundation, Inc.,
+.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+.\"
+.\"
+.TH AO-LOAD 1 "ao-usbtrng" ""
+.SH NAME
+ao-usbtrng \- dump random numbers from USBtrng
+.SH SYNOPSIS
+.B "ao-usbtrng"
+[\-T \fItty-device\fP]
+[\--tty \fItty-device\fP]
+[\-D \fIaltos-device\fP]
+[\--device \fIaltos-device\fP]
+\fIkbytes\fP
+.SH DESCRIPTION
+.I ao-usbtrng
+dumps random numbers from a USBtrng device
+.SH OPTIONS
+.TP
+\-T tty-device | --tty tty-device
+This selects which tty device the debugger uses to communicate with
+the target device. The special name 'BITBANG' directs ao-dbg to use
+the cp2103 connection, otherwise this should be a usb serial port
+connected to a suitable cc1111 debug node.
+.TP
+\-D AltOS-device | --device AltOS-device
+Search for a connected device. This requires an argument of one of the
+following forms:
+.IP
+usbtrng:2
+.br
+usbtrng
+.br
+2
+.IP
+Leaving out the product name will cause the tool to select a suitable
+product, leaving out the serial number will cause the tool to match
+one of the available devices.
+.SH USAGE
+.I ao-usbtrng
+opens the target device and reads the specified number of kbytes of
+random data.
+.SH AUTHOR
+Keith Packard
diff --git a/ao-tools/ao-usbtrng/ao-usbtrng.c b/ao-tools/ao-usbtrng/ao-usbtrng.c
new file mode 100644 (file)
index 0000000..232f4e3
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright © 2014 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <err.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <string.h>
+#include <stdbool.h>
+#include "ao-elf.h"
+#include "ccdbg.h"
+#include "cc-usb.h"
+#include "cc.h"
+#include "ao-verbose.h"
+
+static const struct option options[] = {
+       { .name = "tty", .has_arg = 1, .val = 'T' },
+       { .name = "device", .has_arg = 1, .val = 'D' },
+       { .name = "raw", .has_arg = 0, .val = 'r' },
+       { .name = "verbose", .has_arg = 1, .val = 'v' },
+       { 0, 0, 0, 0},
+};
+
+static void usage(char *program)
+{
+       fprintf(stderr, "usage: %s [--verbose=<verbose>] [--device=<device>] [-tty=<tty>] <kbytes>\n", program);
+       exit(1);
+}
+
+void
+done(struct cc_usb *cc, int code)
+{
+       cc_usb_close(cc);
+       exit (code);
+}
+
+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;
+       int                     kbytes;
+       uint8_t                 bits[1024];
+
+       while ((c = getopt_long(argc, argv, "rT:D:c:s:v:", options, NULL)) != -1) {
+               switch (c) {
+               case 'T':
+                       tty = optarg;
+                       break;
+               case 'D':
+                       device = optarg;
+                       break;
+               case 'v':
+                       verbose++;
+                       break;
+               default:
+                       usage(argv[0]);
+                       break;
+               }
+       }
+
+       if (!argv[optind])
+               usage(argv[0]);
+
+       kbytes = atoi(argv[optind]);
+       if (kbytes < 1)
+               kbytes = 1;
+
+       ao_verbose = verbose;
+
+       if (verbose > 1)
+               ccdbg_add_debug(CC_DEBUG_BITBANG);
+
+       if (!tty)
+               tty = cc_usbdevs_find_by_arg(device, "usbtrng");
+       if (!tty)
+               tty = getenv("ALTOS_TTY");
+       if (!tty)
+               tty="/dev/ttyACM0";
+
+       cc = cc_usb_open(tty);
+
+       if (!cc)
+               exit(1);
+
+       cc_usb_printf(cc, "f %d\n", kbytes);
+
+       while (kbytes--) {
+               int     i;
+               for (i = 0; i < 1024; i++)
+                       bits[i] = cc_usb_getchar(cc);
+               write(1, bits, 1024);
+       }
+
+       done(cc, ret);
+}
index 38dfff04936c87e6fbed2b8df73b5286edd92987..1a4dc7a1163f7460bdf139422be70d72ed44d35c 100644 (file)
@@ -152,6 +152,8 @@ cc_usb_dbg(int indent, uint8_t *bytes, int len)
        }
 }
 
+int    cc_default_timeout = 5000;
+
 /*
  * Flush pending writes, fill pending reads
  */
@@ -227,7 +229,7 @@ _cc_usb_sync(struct cc_usb *cc, int wait_for_input, int write_timeout)
 void
 cc_usb_sync(struct cc_usb *cc)
 {
-       if (_cc_usb_sync(cc, 0, 5000) < 0) {
+       if (_cc_usb_sync(cc, 0, cc_default_timeout) < 0) {
                fprintf(stderr, "USB link timeout\n");
                exit(1);
        }
@@ -268,7 +270,7 @@ int
 cc_usb_getchar_timeout(struct cc_usb *cc, int timeout)
 {
        while (cc->in_pos == cc->in_count) {
-               if (_cc_usb_sync(cc, timeout, 5000) < 0) {
+               if (_cc_usb_sync(cc, timeout, cc_default_timeout) < 0) {
                        fprintf(stderr, "USB link timeout\n");
                        exit(1);
                }
@@ -279,7 +281,7 @@ cc_usb_getchar_timeout(struct cc_usb *cc, int timeout)
 int
 cc_usb_getchar(struct cc_usb *cc)
 {
-       return cc_usb_getchar_timeout(cc, 5000);
+       return cc_usb_getchar_timeout(cc, cc_default_timeout);
 }
 
 void
@@ -400,7 +402,7 @@ cc_usb_open_remote(struct cc_usb *cc, int freq, char *call)
                cc_usb_printf(cc, "\nc F %d\nc c %s\np\nE 0\n", freq, call);
                do {
                        cc->in_count = cc->in_pos = 0;
-                       _cc_usb_sync(cc, 100, 5000);
+                       _cc_usb_sync(cc, 100, cc_default_timeout);
                } while (cc->in_count > 0);
                cc->remote = 1;
        }
@@ -459,7 +461,7 @@ cc_usb_open(char *tty)
        cc_usb_printf(cc, "\nE 0\nm 0\n");
        do {
                cc->in_count = cc->in_pos = 0;
-               _cc_usb_sync(cc, 100, 5000);
+               _cc_usb_sync(cc, 100, cc_default_timeout);
        } while (cc->in_count > 0);
        return cc;
 }
index e08a956b25868747861597bb185ee16c0b066841..9ed198cd290c9ecad29fa2b15717fdae042bd9d4 100644 (file)
@@ -23,6 +23,8 @@
 
 struct cc_usb;
 
+extern int cc_default_timeout;
+
 struct cc_usb *
 cc_usb_open(char *tty);
 
index 3062b13b8c080ad3a871e81b169c020ce069276f..b09daa823ed1528c5509bd8454f95d653c532678 100644 (file)
@@ -18,7 +18,7 @@ dnl
 dnl Process this file with autoconf to create configure.
 
 AC_PREREQ(2.57)
-AC_INIT([altos], 1.5)
+AC_INIT([altos], 1.6)
 AC_CONFIG_SRCDIR([src/kernel/ao.h])
 AM_INIT_AUTOMAKE([foreign dist-bzip2])
 AM_MAINTAINER_MODE
@@ -29,8 +29,8 @@ AC_SUBST(VERSION_DASH)
 dnl ==========================================================================
 dnl Java library versions
 
-ALTOSUILIB_VERSION=3
-ALTOSLIB_VERSION=5
+ALTOSUILIB_VERSION=6
+ALTOSLIB_VERSION=6
 
 AC_SUBST(ALTOSLIB_VERSION)
 AC_DEFINE(ALTOSLIB_VERSION,$ALTOSLIB_VERSION,[Version of the AltosLib package])
@@ -144,13 +144,18 @@ if test "x$ANDROID_SDK" != "xno"; then
        fi
 fi
 
+ANDROID_RELEASE=no
 if test "x$ANDROID_SDK" != "xno"; then
        HAVE_ANDROID_SDK="yes"
+       if test -f "$HOME/altusmetrumllc/release.keystore" -a -f "$HOME/altusmetrumllc/Passphrase"; then
+               ANDROID_RELEASE=yes
+       fi
 else
        HAVE_ANDROID_SDK="no"
 fi
 
 AM_CONDITIONAL([ANDROID], [test x$ANDROID_SDK != xno])
+AM_CONDITIONAL([ANDROID_RELEASE], [test x$ANDROID_RELEASE = xyes])
 
 AC_SUBST(ANDROID_SDK)
 
@@ -546,6 +551,8 @@ ao-tools/ao-test-igniter/Makefile
 ao-tools/ao-test-baro/Makefile
 ao-tools/ao-test-flash/Makefile
 ao-tools/ao-cal-accel/Makefile
+ao-tools/ao-test-gps/Makefile
+ao-tools/ao-usbtrng/Makefile
 ao-utils/Makefile
 src/Version
 ])
@@ -562,6 +569,7 @@ echo "    CC1111 support..............: ${HAVE_SDCC}"
 echo "    AVR compiler................: ${AVR_CC} ${AVR_OBJCOPY}"
 echo "    AVR support.................: ${HAVE_AVR_CC}"
 echo "    Android support.............: ${HAVE_ANDROID_SDK}"
+echo "    Android release support.....: ${ANDROID_RELEASE}"
 echo "    STlink support..............: ${HAVE_STLINK}"
 echo "    Local pdclib................: ${HAVE_PDCLIB}"
 echo "    i386 and amd64 libaltos.....: ${MULTI_ARCH}"
index 60c63f63524d156f08c2f927ac06493ff202bf17..2887a229465242fa1ccd094f9499ec66e2c6fc61 100644 (file)
@@ -17,7 +17,8 @@ RELNOTES=\
        release-notes-1.3.2.html \
        release-notes-1.4.html \
        release-notes-1.4.1.html \
-       release-notes-1.5.html
+       release-notes-1.5.html \
+       release-notes-1.6.html
 
 PICTURES=\
        altosui.png \
index 0785f65a9a8219ebaae8d4e3ffe553a7234cbd3c..1631983a93a6caa9edf8fe0b4cd8e8d80e2a7d03 100644 (file)
@@ -22,7 +22,7 @@
       <surname>Towns</surname>
     </author>
     <copyright>
-      <year>2014</year>
+      <year>2015</year>
       <holder>Bdale Garbee and Keith Packard</holder>
     </copyright>
     <mediaobject>
       </para>
     </legalnotice>
     <revhistory>
+      <revision>
+       <revnumber>1.6</revnumber>
+       <date>8 January 2015</date>
+       <revremark>
+         Major release adding TeleDongle v3.0 support.
+       </revremark>
+      </revision>
       <revision>
        <revnumber>1.5</revnumber>
        <date>6 September 2014</date>
@@ -215,13 +222,15 @@ NAR #88757, TRA #12200
       channels and integrated gyroscopes for staging/air-start inhibit.
     </para>
     <para>
-      TeleDongle was our first ground station, providing a USB to RF
+      TeleDongle v0.2 was our first ground station, providing a USB to RF
       interfaces for communicating with the altimeters. Combined with
       your choice of antenna and notebook computer, TeleDongle and our
       associated user interface software form a complete ground
       station capable of logging and displaying in-flight telemetry,
       aiding rocket recovery, then processing and archiving flight
-      data for analysis and review.
+      data for analysis and review. The latest version, TeleDongle
+      v3, has all new electronics with a higher performance radio
+      for improved range.
     </para>
     <para>
       For a slightly more portable ground station experience that also
@@ -2760,9 +2769,12 @@ NAR #88757, TRA #12200
         <listitem>
           <para>
             The Received Signal Strength Indicator value. This lets
-            you know how strong a signal TeleDongle is receiving. The
-            radio inside TeleDongle operates down to about -99dBm;
-            weaker signals may not be receivable. The packet link uses
+            you know how strong a signal TeleDongle is receiving. At
+            the default data rate, 38400 bps, in bench testing, the
+            radio inside TeleDongle v0.2 operates down to about
+            -106dBm, while the v3 radio works down to about -111dBm.
+            Weaker signals, or an environment with radio noise may
+            cause the data to not be received. The packet link uses
             error detection and correction techniques which prevent
             incorrect data from being reported.
           </para>
@@ -3768,12 +3780,13 @@ NAR #88757, TRA #12200
       <title>Flash Image</title>
       <para>
         This reprograms Altus Metrum devices with new
-        firmware. TeleMetrum v1.x, TeleDongle, TeleMini and TeleBT are
-        all reprogrammed by using another similar unit as a
-        programming dongle (pair programming). TeleMega, EasyMega, TeleMetrum v2
-        and EasyMini are all programmed directly over their USB ports
-        (self programming).  Please read the directions for flashing
-        devices in the Updating Device Firmware chapter below.
+        firmware. TeleMetrum v1.x, TeleDongle v0.2, TeleMini and
+        TeleBT are all reprogrammed by using another similar unit as a
+        programming dongle (pair programming). TeleMega, EasyMega,
+        TeleMetrum v2, EasyMini and TeleDongle v3 are all programmed
+        directly over their USB ports (self programming).  Please read
+        the directions for flashing devices in the Updating Device
+        Firmware chapter below.
       </para>
     </section>
     <section>
@@ -4496,11 +4509,12 @@ NAR #88757, TRA #12200
   <chapter>
     <title>Updating Device Firmware</title>
     <para>
-      TeleMega, TeleMetrum v2, EasyMega and EasyMini are all programmed directly
-      over their USB connectors (self programming). TeleMetrum v1, TeleMini and
-      TeleDongle are all programmed by using another device as a
-      programmer (pair programming). It's important to recognize which
-      kind of devices you have before trying to reprogram them.
+      TeleMega, TeleMetrum v2, EasyMega, EasyMini and TeleDongle v3
+      are all programmed directly over their USB connectors (self
+      programming). TeleMetrum v1, TeleMini and TeleDongle v0.2 are
+      all programmed by using another device as a programmer (pair
+      programming). It's important to recognize which kind of devices
+      you have before trying to reprogram them.
     </para>
     <para>
       You may wish to begin by ensuring you have current firmware images.
@@ -4512,7 +4526,7 @@ NAR #88757, TRA #12200
       version from <ulink url="http://www.altusmetrum.org/AltOS/"/>.
     </para>
     <para>
-      If you need to update the firmware on a TeleDongle, we recommend 
+      If you need to update the firmware on a TeleDongle v0.2, we recommend 
       updating the altimeter first, before updating TeleDongle.  However,
       note that TeleDongle rarely need to be updated.  Any firmware version
       1.0.1 or later will work, version 1.2.1 may have improved receiver
@@ -4524,12 +4538,13 @@ NAR #88757, TRA #12200
     </para>
     <section>
       <title>
-       Updating TeleMega, TeleMetrum v2, EasyMega or EasyMini Firmware
+       Updating TeleMega, TeleMetrum v2, EasyMega, EasyMini or
+       TeleDongle v3 Firmware
       </title>
       <orderedlist inheritnum='inherit' numeration='arabic'>
        <listitem>
          <para>
-           Attach a battery and power switch to the target
+           Attach a battery if necessary and power switch to the target
            device. Power up the device.
          </para>
        </listitem>
@@ -4573,7 +4588,8 @@ NAR #88757, TRA #12200
        <listitem>
          <para>
            Verify that the device is working by using the 'Configure
-           Altimeter' item to check over the configuration.
+           Altimeter' or 'Configure Groundstation' item to check over
+           the configuration.
          </para>
        </listitem>
       </orderedlist>
@@ -4645,6 +4661,17 @@ NAR #88757, TRA #12200
              </para>
            </listitem>
          </varlistentry>
+         <varlistentry>
+           <term>TeleDongle v3</term>
+           <listitem>
+             <para>
+               Connect pin 32 on the CPU to ground. Pin 32 is closest
+               to the USB wires on the row of pins towards the center
+               of the board. Ground is available on the capacitor
+               next to it, on the end towards the USB wires.
+             </para>
+           </listitem>
+         </varlistentry>
        </variablelist>
        <para>
          Once you've located the right pins:
@@ -4696,10 +4723,10 @@ NAR #88757, TRA #12200
       <title>Pair Programming</title>
       <para>
        The big concept to understand is that you have to use a
-       TeleMega, TeleMetrum or TeleDongle as a programmer to update a
-       pair programmed device. Due to limited memory resources in the
-       cc1111, we don't support programming directly over USB for these
-       devices.
+       TeleMetrum v1.0, TeleBT v1.0 or TeleDongle v0.2 as a
+       programmer to update a pair programmed device. Due to limited
+       memory resources in the cc1111, we don't support programming
+       directly over USB for these devices.
       </para>
     </section>
     <section>
@@ -4714,14 +4741,14 @@ NAR #88757, TRA #12200
         </listitem>
         <listitem>
          <para>
-          Take the 2 screws out of the TeleDongle case to get access
-          to the circuit board.
+          Take the 2 screws out of the TeleDongle v0.2 or TeleBT v1.0
+          case to get access to the circuit board.
          </para>
         </listitem>
         <listitem>
          <para>
           Plug the 8-pin end of the programming cable to the
-          matching connector on the TeleDongle, and the 4-pin end to the
+          matching connector on the TeleDongle v0.2 or TeleBT v1.0, and the 4-pin end to the
           matching connector on the TeleMetrum.
          Note that each MicroMaTch connector has an alignment pin that
          goes through a hole in the PC board when you have the cable
@@ -4735,7 +4762,7 @@ NAR #88757, TRA #12200
         </listitem>
         <listitem>
          <para>
-          Plug the TeleDongle into your computer's USB port, and power
+          Plug the TeleDongle v0.2 or TeleBT v1.0 into your computer's USB port, and power
           up the TeleMetrum.
          </para>
         </listitem>
@@ -4746,7 +4773,7 @@ NAR #88757, TRA #12200
         </listitem>
         <listitem>
          <para>
-          Pick the TeleDongle device from the list, identifying it as the
+          Pick the TeleDongle v0.2 or TeleBT v1.0 device from the list, identifying it as the
           programming device.
          </para>
         </listitem>
@@ -4798,14 +4825,14 @@ NAR #88757, TRA #12200
 </listitem>
         <listitem>
 <para>
-          Take the 2 screws out of the TeleDongle case to get access
+          Take the 2 screws out of the TeleDongle v0.2 or TeleBT v1.0 case to get access
           to the circuit board.
         </para>
 </listitem>
         <listitem>
 <para>
           Plug the 8-pin end of the programming cable to the matching
-          connector on the TeleDongle, and the 4-pins into the holes
+          connector on the TeleDongle v0.2 or TeleBT v1.0, and the 4-pins into the holes
           in the TeleMini circuit board.  Note that the MicroMaTch
           connector has an alignment pin that goes through a hole in
           the PC board when you have the cable oriented correctly, and
@@ -4820,7 +4847,7 @@ NAR #88757, TRA #12200
 </listitem>
         <listitem>
 <para>
-          Plug the TeleDongle into your computer's USB port, and power
+          Plug the TeleDongle v0.2 or TeleBT v1.0 into your computer's USB port, and power
           up the TeleMini
         </para>
 </listitem>
@@ -4831,7 +4858,7 @@ NAR #88757, TRA #12200
 </listitem>
         <listitem>
 <para>
-          Pick the TeleDongle device from the list, identifying it as the
+          Pick the TeleDongle v0.2 or TeleBT v1.0 device from the list, identifying it as the
           programming device.
         </para>
 </listitem>
@@ -4871,10 +4898,12 @@ NAR #88757, TRA #12200
       </orderedlist>
     </section>
     <section>
-      <title>Updating TeleDongle Firmware</title>
+      <title>Updating TeleDongle v0.2 Firmware</title>
       <para>
-        Updating TeleDongle's firmware is just like updating TeleMetrum or TeleMini
-       firmware, but you use either a TeleMetrum or another TeleDongle as the programmer.
+        Updating TeleDongle v0.2 firmware is just like updating
+       TeleMetrum v1.x or TeleMini
+       firmware, but you use either a TeleMetrum v1.x, TeleDongle
+       v0.2 or TeleBT v1.0 as the programmer.
        </para>
       <orderedlist inheritnum='inherit' numeration='arabic'>
         <listitem>
@@ -4887,12 +4916,13 @@ NAR #88757, TRA #12200
         <listitem>
 <para>
          Find the USB cable that you got as part of the starter kit, and
-         plug the “mini” end in to the mating connector on TeleMetrum or TeleDongle.
+         plug the “mini” end in to the mating connector on TeleMetrum
+         v1.x, TeleDongle v0.2 or TeleBT v1.0.
         </para>
 </listitem>
         <listitem>
 <para>
-          Take the 2 screws out of the TeleDongle case to get access
+          Take the 2 screws out of the TeleDongle v0.2 or TeleBT v1.0 case to get access
           to the circuit board.
         </para>
 </listitem>
@@ -4900,7 +4930,7 @@ NAR #88757, TRA #12200
 <para>
           Plug the 8-pin end of the programming cable to the
           matching connector on the programmer, and the 4-pin end to the
-          matching connector on the TeleDongle.
+          matching connector on the TeleDongle v0.2.
          Note that each MicroMaTch connector has an alignment pin that
          goes through a hole in the PC board when you have the cable
          oriented correctly.
@@ -4908,7 +4938,7 @@ NAR #88757, TRA #12200
 </listitem>
         <listitem>
 <para>
-          Attach a battery to the TeleMetrum board if you're using one.
+          Attach a battery to the TeleMetrum v1.x board if you're using one.
         </para>
 </listitem>
         <listitem>
@@ -4930,7 +4960,7 @@ NAR #88757, TRA #12200
 </listitem>
         <listitem>
 <para>
-          Select the image you want put on the TeleDongle, which should have a
+          Select the image you want put on the TeleDongle v0.2, which should have a
           name in the form teledongle-v0.2-1.0.0.ihx.  It should be visible
        in the default directory, if not you may have to poke around
        your system to find it.
@@ -4940,7 +4970,8 @@ NAR #88757, TRA #12200
 <para>
           Make sure the configuration parameters are reasonable
           looking. If the serial number and/or RF configuration
-          values aren't right, you'll need to change them.  The TeleDongle
+          values aren't right, you'll need to change them.  The
+         TeleDongle v0.2
          serial number is on the “bottom” of the circuit board, and can
          usually be read through the translucent blue plastic case without
          needing to remove the board from the case.
@@ -4949,16 +4980,16 @@ NAR #88757, TRA #12200
         <listitem>
 <para>
           Hit the 'OK' button and the software should proceed to flash
-          the TeleDongle with new firmware, showing a progress bar.
+          the TeleDongle v0.2 with new firmware, showing a progress bar.
         </para>
 </listitem>
         <listitem>
 <para>
-          Confirm that the TeleDongle board seems to have updated OK, which you
+          Confirm that the TeleDongle v0.2 board seems to have updated OK, which you
           can do by plugging in to it over USB and using a terminal program
           to connect to the board and issue the 'v' command to check
           the version, etc.  Once you're happy, remove the programming cable
-         and put the cover back on the TeleDongle.
+         and put the cover back on the TeleDongle v0.2.
         </para>
 </listitem>
         <listitem>
@@ -5830,13 +5861,65 @@ NAR #88757, TRA #12200
         </para>
       </section>
   </appendix>
+  <appendix>
+    <title>Igniter Current</title>
+      <para>
+       The question "how much igniter current can Altus Metrum products 
+       handle?" comes up fairly frequently.  The short answer is "more than
+       you're likely to need", the remainder of this appendix provides a
+       longer answer.
+      </para>
+      <section>
+        <title>Current Products</title>
+        <para>
+         The FET switches we're using on all of our current products that 
+         have pyro channels are the Vishay Siliconix Si7232DN.  These parts 
+         have exceptionally low Rds(on) values, better than 0.02 ohms!  That 
+         means they aren't making a lot of heat... and the limit on current 
+         is "package limited", meaning it's all about how much you can heat 
+         the die before something breaks.
+       </para>
+       <para>
+         Cutting to the chase, the Si7232DN specs are 25 amps <emphasis>continuous</emphasis> at
+         20V at a temperature of 25C.  In pulsed mode, they're rated for 40A.
+         However, those specs are a little mis-leading because it really is 
+         all about the heat generated... you can get something like 85A 
+         through one briefly.  Note that a typical commercial e-match only 
+         needed about 13 microseconds to fire in tests on my bench a couple 
+         years ago!
+       </para>
+       <para>
+         So a great plan is to use something like an e-match as the initiator 
+         and build up pyrogen(s) as required to actually light what you're 
+         trying to light...  But if you want to use a high-current igniter, 
+         we can probably handle it!
+       </para>
+      </section>
+      <section>
+        <title>Version 1 Products</title>
+        <para>
+         The FET switches used on TeleMetrum v1 and TeleMini v1 products
+         were Fairchild FDS9926A.  The Rds(on) values under our operating
+         conditions are on the order of 0.04 ohms.  These parts were rated
+         for a continuous current-carrying capacity of 6.5A, and a pulsed 
+         current capacity of 20A.
+       </para>
+       <para>
+         As with the more modern parts, the real limit is based on the heat
+         generated in the part during the firing interval.  So, while the 
+         specs on these parts aren't as good as the ones we use on current
+         products, they were still great, and we never had a complaint about
+         current carrying capacity with any of our v1 boards.
+       </para>
+      </section>
+  </appendix>
   <appendix>
     <title>Release Notes</title>
     <simplesect>
-      <title>Version 1.4.1</title>
+      <title>Version 1.6</title>
       <xi:include
          xmlns:xi="http://www.w3.org/2001/XInclude"
-         href="release-notes-1.4.1.xsl"
+         href="release-notes-1.6.xsl"
          xpointer="xpointer(/article/*)"/>
     </simplesect>
     <simplesect>
@@ -5846,6 +5929,13 @@ NAR #88757, TRA #12200
          href="release-notes-1.5.xsl"
          xpointer="xpointer(/article/*)"/>
     </simplesect>
+    <simplesect>
+      <title>Version 1.4.1</title>
+      <xi:include
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         href="release-notes-1.4.1.xsl"
+         xpointer="xpointer(/article/*)"/>
+    </simplesect>
     <simplesect>
       <title>Version 1.4</title>
       <xi:include
diff --git a/doc/release-notes-1.6.xsl b/doc/release-notes-1.6.xsl
new file mode 100644 (file)
index 0000000..604fe09
--- /dev/null
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"/usr/share/xml/docbook/schema/dtd/4.5/docbookx.dtd">
+
+<article>
+  <para>
+    Version 1.6 includes support for our updated TeleDongle v3.0
+    product and bug fixes in in the flight software for all our boards
+    and ground station interfaces.
+  </para>
+  <para>
+    AltOS New Features
+    <itemizedlist>
+      <listitem>
+       <para>
+         Add support for TeleDongle v3.0 boards.
+       </para>
+      </listitem>
+    </itemizedlist>
+  </para>
+  <para>
+    AltOS Fixes
+    <itemizedlist>
+      <listitem>
+       <para>
+         Don't beep out the continuity twice by accident in idle mode.
+         If the battery voltage report takes longer than the initialiation
+         sequence, the igniter continuity would get reported twice.
+       </para>
+      </listitem>
+      <listitem>
+       <para>
+         Record all 32 bits of gyro calibration data in TeleMega and
+         EasyMega log files. This fixes computation of the gyro rates
+         in AltosUI.
+       </para>
+      </listitem>
+      <listitem>
+       <para>
+         Change TeleDongle LED usage. Green LED flashes when valid
+         packet is received. Red LED flashes when invalid packet is
+         received.
+       </para>
+      </listitem>
+      <listitem>
+       <para>
+         Replace LPC11U14 SPI driver with non-interrupt version. The
+         interrupt code would occasionally wedge on long transfers
+         if interrupts were blocked for too long. This affects all
+         released TeleGPS products; if you have a TeleGPS device,
+         you'll want to reflash the firmware.
+       </para>
+      </listitem>
+    </itemizedlist>
+  </para>
+  <para>
+    AltosUI and TeleGPS New Features
+    <itemizedlist>
+      <listitem>
+       <para>
+         Compute tilt angle from TeleMega and EasyMega log
+         files. This duplicates the quaternion-based angle tracking
+         code from the flight firmware inside the ground station
+         software so that post-flight analysis can include evaluation
+         of the tilt angle.
+       </para>
+      </listitem>
+      <listitem>
+       <para>
+         Shows the tool button window when starting with a data file
+         specified. This means that opening a data file from the file
+         manager will now bring up the main window to let you operate
+         the whole application.
+       </para>
+      </listitem>
+    </itemizedlist>
+  </para>
+  <para>
+    AltosUI Fixes
+    <itemizedlist>
+      <listitem>
+       <para>
+         Show the 'Connecting' dialog when using Monitor Idle. Lets
+         you cancel the Monitor Idle startup when connecting over the
+         radio link.
+       </para>
+      </listitem>
+      <listitem>
+       <para>
+         Make 'Monitor Idle' work for TeleGPS devices when connected
+         over USB. It's nice for testing without needing to broadcast
+         over the radio.
+       </para>
+      </listitem>
+      <listitem>
+       <para>
+         Use different Windows API to discover USB devices. This
+         works better on my Windows 7 box, and will be used if the
+         older API fails to provide the necessary information.
+       </para>
+      </listitem>
+      <listitem>
+       <para>
+         Look in more places in the registry to try and identify the
+         installed Java version on Windows. If you install the
+         default 32-bit version of Windows on a 64-bit OS, the Java
+         registry information is hiding \SOFTWARE\Wow6432Node for
+         some reason.
+       </para>
+      </listitem>
+      <listitem>
+       <para>
+         Fix file association on Windows by searching for the
+         javaw.exe program instead of assuming it is in
+         %SYSTEMROOT%. This makes double-clicking on Altus Metrum
+         data files in the file manager work correctly.
+       </para>
+      </listitem>
+      <listitem>
+       <para>
+         When replaying a file, put 'done' in the Age field when we
+         reach the end of the file, instead of continuing to count forever.
+       </para>
+      </listitem>
+      <listitem>
+       <para>
+         In the Scan Channels code, wait for five seconds if we see
+         any packet. This is needed because AltOS now sends the
+         callsign, serial number and flight number only once every
+         five seconds these days.
+       </para>
+      </listitem>
+      <listitem>
+       <para>
+         In the Scan Channels code, reset pending flight state
+         information each time we change channels. This avoids having
+         flight computers appear on multiple frequencies by accident.
+       </para>
+      </listitem>
+    </itemizedlist>
+  </para>
+</article>
index bf7eec5ae7d74c64e997e2c1fef7c6e2b7392814..8de5c56d3c319734739cee9babbbdc4d73e07dfa 100644 (file)
@@ -10,7 +10,7 @@
       <surname>Packard</surname>
     </author>
     <copyright>
-      <year>2014</year>
+      <year>2015</year>
       <holder>Bdale Garbee and Keith Packard</holder>
     </copyright>
     <mediaobject>
       </para>
     </legalnotice>
     <revhistory>
+      <revision>
+       <revnumber>1.6</revnumber>
+       <date>8 January 2015</date>
+       <revremark>
+         Major release adding TeleDongle v3.0 support.
+       </revremark>
+      </revision>
       <revision>
        <revnumber>1.4.1</revnumber>
        <date>20 June 2014</date>
@@ -1305,7 +1312,14 @@ NAR #88757, TRA #12200
   <appendix>
     <title>Release Notes</title>
     <simplesect>
-      <title>Version 1.41</title>
+      <title>Version 1.6</title>
+      <xi:include
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         href="release-notes-1.6.xsl"
+         xpointer="xpointer(/article/*)"/>
+    </simplesect>
+    <simplesect>
+      <title>Version 1.4.1</title>
       <xi:include
          xmlns:xi="http://www.w3.org/2001/XInclude"
          href="release-notes-1.4.1.xsl"
index 4e3bc2c51b2d5b1f7fcd2eb9c8d090118657a13a..97b7b3f9bba44037206e409362824131c833bec9 100644 (file)
@@ -1121,6 +1121,8 @@ altos_list_next(struct altos_list *list, struct altos_device *device)
        HRESULT         result;
        DWORD           friendlyname_type;
        DWORD           friendlyname_len;
+       char            instanceid[1024];
+       DWORD           instanceid_len;
 
        dev_info_data.cbSize = sizeof (SP_DEVINFO_DATA);
        while(SetupDiEnumDeviceInfo(list->dev_info, list->index,
@@ -1141,6 +1143,7 @@ altos_list_next(struct altos_list *list, struct altos_device *device)
                        pid = 0x6015;
                        serial = 0;
                } else {
+                       vid = pid = serial = 0;
                        /* Fetch symbolic name for this device and parse out
                         * the vid/pid/serial info */
                        symbolic_len = sizeof(symbolic);
@@ -1148,16 +1151,34 @@ altos_list_next(struct altos_list *list, struct altos_device *device)
                                                 symbolic, &symbolic_len);
                        if (result != 0) {
                                altos_set_last_windows_error();
+                       } else {
+                               sscanf((char *) symbolic + sizeof("\\??\\USB#VID_") - 1,
+                                      "%04X", &vid);
+                               sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_") - 1,
+                                      "%04X", &pid);
+                               sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_XXXX#") - 1,
+                                      "%d", &serial);
+                       }
+                       if (vid == 0 || pid == 0 || serial == 0) {
+                               if (SetupDiGetDeviceInstanceId(list->dev_info,
+                                                              &dev_info_data,
+                                                              instanceid,
+                                                              sizeof (instanceid),
+                                                              &instanceid_len)) {
+                                       sscanf((char *) instanceid + sizeof("USB\\VID_") - 1,
+                                              "%04X", &vid);
+                                       sscanf((char *) instanceid + sizeof("USB\\VID_XXXX&PID_") - 1,
+                                              "%04X", &pid);
+                                       sscanf((char *) instanceid + sizeof("USB\\VID_XXXX&PID_XXXX\\") - 1,
+                                              "%d", &serial);
+                               } else {
+                                       altos_set_last_windows_error();
+                               }
+                       }
+                       if (vid == 0 || pid == 0 || serial == 0) {
                                RegCloseKey(dev_key);
                                continue;
                        }
-                       vid = pid = serial = 0;
-                       sscanf((char *) symbolic + sizeof("\\??\\USB#VID_") - 1,
-                              "%04X", &vid);
-                       sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_") - 1,
-                              "%04X", &pid);
-                       sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_XXXX#") - 1,
-                              "%d", &serial);
                }
 
                /* Fetch the com port name */
index c38ada9151868a8e69e704cec6d6f42f01dabe1f..857dbe584b0c157a14f7bd322f288eb7e1848bb9 100644 (file)
@@ -20,8 +20,8 @@ package org.altusmetrum.micropeak;
 import java.lang.*;
 import java.io.*;
 import java.util.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 class MicroIterator implements Iterator<MicroDataPoint> {
        int             i;
index 849ae5365abca7cedcda0b5c41c58ef4603a7da6..45d5ba273fba13bfa45850ecbdfe41eb5c117b20 100644 (file)
@@ -17,7 +17,7 @@
 
 package org.altusmetrum.micropeak;
 
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class MicroDataPoint implements AltosUIDataPoint {
        public double           time;
index 304eac7df05318e4c6c3cb68b7a19c43f907020a..5532848261fc6802de7d7e927c35dc78dbe247f9 100644 (file)
@@ -21,7 +21,7 @@ import javax.swing.*;
 import java.awt.*;
 import java.awt.event.*;
 import java.util.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class MicroDeviceDialog extends AltosDeviceDialog {
 
index 32dd04508d20e50c0e8cbdc1d7c02eb3b47d29c4..a03d7b3ac4a9d98b494e91a149681e4dbae538fd 100644 (file)
@@ -23,8 +23,8 @@ import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
 import java.util.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class MicroDownload extends AltosUIDialog implements Runnable, ActionListener, MicroSerialLog, WindowListener {
        MicroPeak       owner;
index 8d62ace680d3c4899ae6e277437b49f134b08af3..93c8cae8d34284be02835c0ae84fad995a1705e5 100644 (file)
@@ -23,8 +23,8 @@ import java.util.ArrayList;
 import java.awt.*;
 import javax.swing.*;
 import javax.swing.filechooser.FileNameExtensionFilter;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class MicroExport extends JFileChooser {
 
index d6abfcb717869ee3ec7421f4b37aab24fc4d421d..78f7dac2175fba3f42b71cd90209cf56f8e477e1 100644 (file)
@@ -19,8 +19,8 @@ package org.altusmetrum.micropeak;
 
 import java.io.*;
 import java.util.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class MicroFile {
 
index 371c22d0eb9a9a68a0d4e18eedb9faf99181b8b6..5ac22e3049306900aa16fb691e6df43349df0ed0 100644 (file)
@@ -20,8 +20,8 @@ package org.altusmetrum.micropeak;
 import javax.swing.*;
 import javax.swing.filechooser.FileNameExtensionFilter;
 import java.io.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class MicroFileChooser extends JFileChooser {
        JFrame  frame;
index 8b3d49b561629501e6d426d4ce7a80862e014b28..47b03a12cb97799bfb4b15a033828a9c6e820cc2 100644 (file)
@@ -21,7 +21,7 @@ import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
 import java.util.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class MicroFrame extends AltosUIFrame {
        static String[] micro_icon_names = {
index 811b1e7c14984c6511e46611285371f9c6a4538a..a6d511c3c8d428fa8bde5fd4d3b7edacbfe39c1a 100644 (file)
@@ -22,8 +22,8 @@ import java.util.ArrayList;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 import org.jfree.ui.*;
 import org.jfree.chart.*;
index 1744e8033cc6dd08842b9e1eee36c72d11e749e2..9f7095f36248ebd85105cd00dd389c65d9041ad0 100644 (file)
@@ -23,8 +23,8 @@ import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
 import java.util.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class MicroPeak extends MicroFrame implements ActionListener, ItemListener {
 
index 7a225dcbcc39933c7e557a292516753548889a9c..587fe927cf3a5849f184145fa4520a5aa790f590 100644 (file)
@@ -20,8 +20,8 @@ package org.altusmetrum.micropeak;
 import java.awt.*;
 import java.io.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class MicroRaw extends JTextArea {
 
index 9497fb33544c8a02c38292c808431e1180074a1e..65026bdaacf09084c21f72d9de7aa47f8e4149d9 100644 (file)
@@ -24,8 +24,8 @@ import javax.swing.filechooser.FileNameExtensionFilter;
 import java.io.*;
 import java.util.concurrent.*;
 import java.util.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class MicroSave extends JFileChooser {
 
index f5108c22dee8e5a9a53903b288754d06e426d502..4282aba170c67db33a8117a1badbb1c9d5dd9098 100644 (file)
@@ -20,7 +20,7 @@ package org.altusmetrum.micropeak;
 import java.util.*;
 import java.io.*;
 import libaltosJNI.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class MicroSerial extends InputStream {
        SWIGTYPE_p_altos_file   file;
index c49b69ab8130f2b87e58e3cb608c60f3dc58acc3..3ee44649e8a4a54e8ab4fec9ae5a82e24c91edf6 100644 (file)
@@ -20,7 +20,7 @@ package org.altusmetrum.micropeak;
 import java.util.*;
 import java.io.*;
 import libaltosJNI.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public interface MicroSerialLog {
 
index 3fc05bd6cc85aa2c5c388627dfd779afdca021fb..47ef2a799547d3fbc4d10d8cfa4adbb6024d6027 100644 (file)
@@ -18,8 +18,8 @@
 package org.altusmetrum.micropeak;
 
 import java.io.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class MicroStats {
        double          coast_height;
index d6265fe8c70a7873361e8d8fcf29bfc7de9eece6..139c4416280ce958011baead0a1370d1732c21a3 100644 (file)
@@ -19,8 +19,8 @@ package org.altusmetrum.micropeak;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class MicroStatsTable extends JComponent implements AltosFontListener {
        GridBagLayout   layout;
index 24f6722b79a9b69d9e47a2d6ebe9fe210fd17395..fa20488d9c77d4ed357803d1f408a4d91b48029d 100644 (file)
@@ -19,7 +19,8 @@ package org.altusmetrum.micropeak;
 
 import java.util.*;
 import libaltosJNI.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class MicroUSB extends altos_device implements AltosDevice {
 
@@ -74,25 +75,50 @@ public class MicroUSB extends altos_device implements AltosDevice {
                return libaltos.altos_open(this);
        }
 
+       private boolean isFTDI() {
+               int vid = getVendor();
+               int pid = getProduct();
+               if (vid == 0x0403 && pid == 0x6015)
+                       return true;
+               return false;
+       }
+
        private boolean isMicro() {
-               if (getVendor() != 0x0403)
-                       return false;
-               if (getProduct() != 0x6015)
-                       return false;
-               return true;
+               int vid = getVendor();
+               int pid = getProduct();
+               if (vid == AltosLib.vendor_altusmetrum &&
+                   pid == AltosLib.product_mpusb)
+                       return true;
+               return false;
        }
 
        public boolean matchProduct(int product) {
-               return isMicro();
+               return isFTDI() || isMicro();
        }
 
        static java.util.List<MicroUSB> list() {
                if (!load_library())
                        return null;
 
-               SWIGTYPE_p_altos_list list = libaltos.altos_ftdi_list_start();
-
                ArrayList<MicroUSB> device_list = new ArrayList<MicroUSB>();
+
+               SWIGTYPE_p_altos_list list;
+
+               list = libaltos.altos_ftdi_list_start();
+
+               if (list != null) {
+                       for (;;) {
+                               MicroUSB device = new MicroUSB();
+                               if (libaltos.altos_list_next(list, device) == 0)
+                                       break;
+                               if (device.isFTDI())
+                                       device_list.add(device);
+                       }
+                       libaltos.altos_list_finish(list);
+               }
+
+               list = libaltos.altos_list_start();
+
                if (list != null) {
                        for (;;) {
                                MicroUSB device = new MicroUSB();
@@ -106,4 +132,4 @@ public class MicroUSB extends altos_device implements AltosDevice {
 
                return device_list;
        }
-}
\ No newline at end of file
+}
index 848523b03d79fc34d6b9f5e58a0c202be43235c5..a3779630630b40ded1c6b3b8756b6e491f957f23 100644 (file)
@@ -71,6 +71,29 @@ Section "FTDI USB Driver"
        ExecWait $2
 SectionEnd
 
+Section "Install Driver" InstDriver
+
+       InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} AltusMetrumSerial
+       Pop $0
+       DetailPrint "InitDriverSetup: $0"
+       InstDrv::DeleteOemInfFiles /NOUNLOAD
+       InstDrv::CreateDevice /NOUNLOAD
+
+       SetOutPath $INSTDIR
+       File "../altusmetrum.inf"
+       File "../altusmetrum.cat"
+
+       ${DisableX64FSRedirection}
+       IfFileExists $WINDIR\System32\PnPutil.exe 0 nopnp
+               ${DisableX64FSRedirection}
+               nsExec::ExecToLog '"$WINDIR\System32\PnPutil.exe" -i -a "$INSTDIR\altusmetrum.inf"'
+               Goto done
+nopnp:
+               InstDrv::InstallDriver /NOUNLOAD "$INSTDIR\altusmetrum.inf"
+done:
+
+SectionEnd
+
 Section "${REG_NAME} Application"
        Call DetectJRE
 
@@ -86,7 +109,7 @@ Section "${REG_NAME} Application"
 
        File "../icon/${WIN_APP_ICON}"
 
-       CreateShortCut "$SMPROGRAMS\${REG_NAME}.lnk" "$SYSDIR\javaw.exe" "-jar ${FAT_NAME}" "$INSTDIR\${WIN_APP_ICON}"
+       CreateShortCut "$SMPROGRAMS\${REG_NAME}.lnk" "$INSTDIR\${FAT_NAME}" "" "$INSTDIR\${WIN_APP_ICON}"
 SectionEnd
 
 Section "${REG_NAME} Desktop Shortcut"
@@ -102,11 +125,15 @@ SectionEnd
 
 Section "File Associations"
 
+       ${DisableX64FSRedirection}
+
        SetOutPath $INSTDIR
 
        File "../icon/${WIN_APP_EXE}"
        File "../icon/${WIN_MPD_EXE}"
 
+       SearchPath $1 "javaw.exe"
+
        ; application elements
        
        DeleteRegKey HKCR "${PROG_ID}"
@@ -116,7 +143,7 @@ Section "File Associations"
        WriteRegStr HKCR "${PROG_ID_MPD}"               "FriendlyTypeName"              "MicroPeak Data File"
        WriteRegStr HKCR "${PROG_ID_MPD}\CurVer"        ""                              "${PROG_ID_MPD}"
        WriteRegStr HKCR "${PROG_ID_MPD}\DefaultIcon"   ""                              '"$INSTDIR\${WIN_MPD_EXE}",-101'
-  WriteRegExpandStr HKCR "${PROG_ID_MPD}\shell\play\command" ""                                '"%SYSTEMROOT%\System32\javaw.exe" -Djava.library.path="$INSTDIR" -jar "$INSTDIR\${FAT_NAME}" "%1"'
+  WriteRegExpandStr HKCR "${PROG_ID_MPD}\shell\play\command" ""                                '"$1" -Djava.library.path="$INSTDIR" -jar "$INSTDIR\${FAT_NAME}" "%1"'
 
        ; .mpd elements
 
index a8628fae726e31eccd5582b53550fb976f524261..aad18d4cfe10ca70efafbb7d43edc1baea9df8d4 100644 (file)
@@ -1,4 +1,5 @@
 Makedefs
 altitude.h
 altitude-pa.h
+altitude-pa-small.h
 ao_whiten.h
index 20126de6771b336f1e54b631496e7a7ab07952c2..05e99c7fbfd77405ecabb89694cff4aa2662de00 100644 (file)
@@ -35,7 +35,9 @@ ARMM3DIRS=\
        telegps-v1.0 telegps-v1.0/flash-loader \
        telelco-v0.2 telelco-v0.2/flash-loader \
        telescience-v0.2 telescience-v0.2/flash-loader \
-       teleballoon-v2.0
+       teledongle-v3.0 teledongle-v3.0/flash-loader \
+       teleballoon-v2.0 \
+       telebt-v3.0 telebt-v3.0/flash-loader
 
 ARMM0DIRS=\
        easymini-v1.0 easymini-v1.0/flash-loader
index 8140dd30b2541da6a885b39e6b3e64e0d7a41855..6ca12af65836904ccbc9a05c1937e1347c054715 100644 (file)
@@ -31,6 +31,8 @@
 
 #define AO_STACK_SIZE  116
 
+#define AO_PORT_TYPE   uint8_t
+
 /* Various definitions to make GCC look more like SDCC */
 
 #define ao_arch_naked_declare  __attribute__((naked))
index d626e830ee97bf4bdb7bf760ef2832fff698853a..f8c7f042a1954ebc7287adacc531fe9be7b0ab74 100644 (file)
@@ -41,6 +41,8 @@
 #define AO_STACK_SIZE  116
 #endif
 
+#define AO_PORT_TYPE   uint8_t
+
 /* Various definitions to make GCC look more like SDCC */
 
 #define ao_arch_naked_declare  __attribute__((naked))
index fcac331be55363d3d9a6a4fffb17432acc546283..b3c6b5dcce6fd29ffa7710ec47c1ecb5293a950d 100644 (file)
@@ -40,6 +40,8 @@
 #define AO_STACK_END   0xfe
 #define AO_STACK_SIZE  (AO_STACK_END - AO_STACK_START + 1)
 
+#define AO_PORT_TYPE   uint8_t
+
 #define ao_arch_reboot() do {                                  \
        WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_64;  \
        ao_delay(AO_SEC_TO_TICKS(2));                           \
index 3b6028a030f49abc5ef9cae9133b6bdc72659ae2..e6b286881e778a13e54049c849f91f4f0f714e61 100644 (file)
  */
 
 #include "ao.h"
+#ifdef AO_BTM_INT_PORT
+#include <ao_exti.h>
+#endif
 
 #ifndef ao_serial_btm_getchar
 #define ao_serial_btm_putchar  ao_serial1_putchar
 #define _ao_serial_btm_pollchar        _ao_serial1_pollchar
+#define _ao_serial_btm_sleep() ao_sleep((void *) &ao_serial1_rx_fifo)
 #define ao_serial_btm_set_speed ao_serial1_set_speed
 #define ao_serial_btm_drain    ao_serial1_drain
-#define ao_serial_btm_rx_fifo  ao_serial1_rx_fifo
 #endif
 
 int8_t                 ao_btm_stdio;
@@ -32,7 +35,7 @@ __xdata uint8_t               ao_btm_connected;
 
 #if BT_DEBUG
 __xdata char           ao_btm_buffer[256];
-int                    ao_btm_ptr;
+uint16_t               ao_btm_ptr;
 char                   ao_btm_dir;
 
 static void
@@ -81,6 +84,10 @@ ao_btm_dump(void)
                        putchar(ao_btm_buffer[i]);
        }
        putchar('\n');
+       ao_cmd_decimal();
+       if (ao_cmd_status == ao_cmd_success && ao_cmd_lex_i)
+               ao_btm_ptr = 0;
+       ao_cmd_status = ao_cmd_success;
 }
 
 static void
@@ -95,9 +102,44 @@ ao_btm_speed(void)
                ao_cmd_status = ao_cmd_syntax_error;
 }
 
+static uint8_t ao_btm_enable;
+
+static void
+ao_btm_do_echo(void)
+{
+       int     c;
+       while (ao_btm_enable) {
+               ao_arch_block_interrupts();
+               while ((c = _ao_serial_btm_pollchar()) == AO_READ_AGAIN && ao_btm_enable)
+                       _ao_serial_btm_sleep();
+               ao_arch_release_interrupts();
+               if (c != AO_READ_AGAIN) {
+                       putchar(c);
+                       flush();
+               }
+       }
+       ao_exit();
+}
+
+static struct ao_task ao_btm_echo_task;
+
+static void
+ao_btm_send(void)
+{
+       int c;
+       ao_btm_enable = 1;
+       ao_add_task(&ao_btm_echo_task, ao_btm_do_echo, "btm-echo");
+       while ((c = getchar()) != '~') {
+               ao_serial_btm_putchar(c);
+       }
+       ao_btm_enable = 0;
+       ao_wakeup((void *) &ao_serial_btm_rx_fifo);
+}
+
 __code struct ao_cmds ao_btm_cmds[] = {
        { ao_btm_dump,          "d\0Dump btm buffer." },
        { ao_btm_speed,         "s <19200,57600>\0Set btm serial speed." },
+       { ao_btm_send,          "S\0BTM interactive mode. ~ to exit." },
        { 0, NULL },
 };
 
@@ -125,7 +167,7 @@ ao_btm_getchar(void)
        ao_arch_block_interrupts();
        while ((c = _ao_serial_btm_pollchar()) == AO_READ_AGAIN) {
                ao_alarm(AO_MS_TO_TICKS(10));
-               c = ao_sleep(&ao_serial_btm_rx_fifo);
+               c = _ao_serial_btm_sleep();
                ao_clear_alarm();
                if (c) {
                        c = AO_READ_AGAIN;
@@ -146,6 +188,7 @@ ao_btm_get_line(void)
 {
        uint8_t ao_btm_reply_len = 0;
        int c;
+       uint8_t l;
 
        while ((c = ao_btm_getchar()) != AO_READ_AGAIN) {
                ao_btm_log_in_char(c);
@@ -154,8 +197,8 @@ ao_btm_get_line(void)
                if (c == '\r' || c == '\n')
                        break;
        }
-       for (c = ao_btm_reply_len; c < sizeof (ao_btm_reply);)
-               ao_btm_reply[c++] = '\0';
+       for (l = ao_btm_reply_len; l < sizeof (ao_btm_reply);)
+               ao_btm_reply[l++] = '\0';
        return ao_btm_reply_len;
 }
 
@@ -214,7 +257,7 @@ ao_btm_string(__code char *cmd)
 {
        char    c;
 
-       while (c = *cmd++)
+       while ((c = *cmd++) != '\0')
                ao_btm_putchar(c);
 }
 
@@ -256,6 +299,52 @@ ao_btm_try_speed(uint8_t speed)
        return 0;
 }
 
+#if BT_LINK_ON_P2
+#define BT_PICTL_ICON  PICTL_P2ICON
+#define BT_PIFG                P2IFG
+#define BT_PDIR                P2DIR
+#define BT_PINP                P2INP
+#define BT_IEN2_PIE    IEN2_P2IE
+#define BT_CC1111      1
+#endif
+#if BT_LINK_ON_P1
+#define BT_PICTL_ICON  PICTL_P1ICON
+#define BT_PIFG                P1IFG
+#define BT_PDIR                P1DIR
+#define BT_PINP                P1INP
+#define BT_IEN2_PIE    IEN2_P1IE
+#define BT_CC1111      1
+#endif
+
+void
+ao_btm_check_link()
+{
+#if BT_CC1111
+       ao_arch_critical(
+               /* Check the pin and configure the interrupt detector to wait for the
+                * pin to flip the other way
+                */
+               if (BT_LINK_PIN) {
+                       ao_btm_connected = 0;
+                       PICTL |= BT_PICTL_ICON;
+               } else {
+                       ao_btm_connected = 1;
+                       PICTL &= ~BT_PICTL_ICON;
+               }
+               );
+#else
+       ao_arch_block_interrupts();
+       if (ao_gpio_get(AO_BTM_INT_PORT, AO_BTM_INT_PIN, AO_BTM_INT) == 0) {
+               ao_btm_connected = 1;
+       } else {
+               ao_btm_connected = 0;
+       }
+       ao_arch_release_interrupts();
+#endif
+}
+
+__xdata struct ao_task ao_btm_task;
+
 /*
  * A thread to initialize the bluetooth device and
  * hang around to blink the LED when connected
@@ -298,6 +387,13 @@ ao_btm(void)
                                    NULL);
        ao_btm_echo(0);
 
+       /* Check current pin state */
+       ao_btm_check_link();
+
+#ifdef AO_BTM_INT_PORT
+       ao_exti_enable(AO_BTM_INT_PORT, AO_BTM_INT_PIN);
+#endif
+
        for (;;) {
                while (!ao_btm_connected)
                        ao_sleep(&ao_btm_connected);
@@ -308,40 +404,8 @@ ao_btm(void)
        }
 }
 
-__xdata struct ao_task ao_btm_task;
-
-#if BT_LINK_ON_P2
-#define BT_PICTL_ICON  PICTL_P2ICON
-#define BT_PIFG                P2IFG
-#define BT_PDIR                P2DIR
-#define BT_PINP                P2INP
-#define BT_IEN2_PIE    IEN2_P2IE
-#endif
-#if BT_LINK_ON_P1
-#define BT_PICTL_ICON  PICTL_P1ICON
-#define BT_PIFG                P1IFG
-#define BT_PDIR                P1DIR
-#define BT_PINP                P1INP
-#define BT_IEN2_PIE    IEN2_P1IE
-#endif
-
-void
-ao_btm_check_link()
-{
-       ao_arch_critical(
-               /* Check the pin and configure the interrupt detector to wait for the
-                * pin to flip the other way
-                */
-               if (BT_LINK_PIN) {
-                       ao_btm_connected = 0;
-                       PICTL |= BT_PICTL_ICON;
-               } else {
-                       ao_btm_connected = 1;
-                       PICTL &= ~BT_PICTL_ICON;
-               }
-               );
-}
 
+#if BT_CC1111
 void
 ao_btm_isr(void)
 #if BT_LINK_ON_P1
@@ -357,6 +421,16 @@ ao_btm_isr(void)
        }
        BT_PIFG = 0;
 }
+#endif
+
+#ifdef AO_BTM_INT_PORT
+void
+ao_btm_isr(void)
+{
+       ao_btm_check_link();
+       ao_wakeup(&ao_btm_connected);
+}
+#endif
 
 void
 ao_btm_init (void)
@@ -365,6 +439,18 @@ ao_btm_init (void)
 
        ao_serial_btm_set_speed(AO_SERIAL_SPEED_19200);
 
+#ifdef AO_BTM_RESET_PORT
+       ao_enable_output(AO_BTM_RESET_PORT,AO_BTM_RESET_PIN,AO_BTM_RESET,0);
+#endif
+
+#ifdef AO_BTM_INT_PORT
+       ao_enable_port(AO_BTM_INT_PORT);
+       ao_exti_setup(AO_BTM_INT_PORT, AO_BTM_INT_PIN,
+                     AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_LOW,
+                     ao_btm_isr);
+#endif
+
+#if BT_CC1111
 #if BT_LINK_ON_P1
        /*
         * Configure ser reset line
@@ -386,9 +472,7 @@ ao_btm_init (void)
 
        /* Enable interrupts */
        IEN2 |= BT_IEN2_PIE;
-
-       /* Check current pin state */
-       ao_btm_check_link();
+#endif
 
 #if BT_LINK_ON_P2
        /* Eable the pin interrupt */
index 3ea8b7044b4cecb25f1880f5be5a3b1bbfb066cd..90d6cc75ab5f76eb5677a052203a44e85eb6b94d 100644 (file)
@@ -1125,12 +1125,12 @@ ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout)
        ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
                         AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
 
-       ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);
-       ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
-
        rx_starting = 1;
        rx_task_id = ao_cur_task->task_id;
 
+       ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);
+       ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
+
        ao_radio_strobe(CC1120_SRX);
 
        if (timeout)
@@ -1148,8 +1148,9 @@ ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout)
                ao_clear_alarm();
 
        if (ao_radio_abort) {
+               if (rx_task_id_save == 0)
+                       ao_radio_burst_read_stop();
                ret = 0;
-               rx_task_id = 0;
                goto abort;
        }
 
index cf61acfe9c4ae45a6def0d88caf05c8d3d0dac96..0246ba02ddfce5a4f5925a2ac080fbbcb9bad563 100644 (file)
@@ -38,7 +38,7 @@ static uint8_t ao_radio_abort;                /* radio operation should abort */
 
 #define FOSC   26000000
 
-#define ao_radio_select()      ao_spi_get_mask(AO_CC115L_SPI_CS_PORT,(1 << AO_CC115L_SPI_CS_PIN),AO_CC115L_SPI_BUS,AO_SPI_SPEED_1MHz)
+#define ao_radio_select()      ao_spi_get_mask(AO_CC115L_SPI_CS_PORT,(1 << AO_CC115L_SPI_CS_PIN),AO_CC115L_SPI_BUS,AO_SPI_SPEED_6MHz)
 #define ao_radio_deselect()    ao_spi_put_mask(AO_CC115L_SPI_CS_PORT,(1 << AO_CC115L_SPI_CS_PIN),AO_CC115L_SPI_BUS)
 #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC115L_SPI_BUS)
 #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC115L_SPI_BUS)
@@ -246,6 +246,8 @@ ao_radio_idle(void)
        }
        /* Flush any pending TX bytes */
        ao_radio_strobe(CC115L_SFTX);
+       /* Make sure the RF calibration is current */
+       ao_radio_strobe(CC115L_SCAL);
 }
 
 /*
@@ -325,23 +327,22 @@ static const struct {
 
 static const uint16_t packet_setup[] = {
        CC115L_MDMCFG3,         (PACKET_DRATE_M),
-       CC115L_MDMCFG2,         (0x00 |
-                                (CC115L_MDMCFG2_MOD_FORMAT_GFSK << CC115L_MDMCFG2_MOD_FORMAT) |
+       CC115L_MDMCFG2,         ((CC115L_MDMCFG2_MOD_FORMAT_GFSK << CC115L_MDMCFG2_MOD_FORMAT) |
                                 (0 << CC115L_MDMCFG2_MANCHESTER_EN) |
                                 (CC115L_MDMCFG2_SYNC_MODE_16BITS << CC115L_MDMCFG2_SYNC_MODE)),
 };
 
 
 /*
- * RDF deviation is 5kHz
+ * RDF deviation is 3kHz
  *
  *     fdev = fosc >> 17 * (8 + dev_m) << dev_e
  *
- *             26e6 / (2 ** 17) * (8 + 4) * (2 ** 1) = 4761Hz
+ *             26e6 / (2 ** 17) * (8 + 7) * (2 ** 0) = 2975
  */
 
-#define RDF_DEV_E      1
-#define RDF_DEV_M      4
+#define RDF_DEV_E      0
+#define RDF_DEV_M      7
 
 /*
  * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
@@ -364,8 +365,7 @@ static const uint16_t rdf_setup[] = {
        CC115L_MDMCFG4,         ((0xf << 4) |
                                 (RDF_DRATE_E << CC115L_MDMCFG4_DRATE_E)),
        CC115L_MDMCFG3,         (RDF_DRATE_M),
-       CC115L_MDMCFG2,         (0x00 |
-                                (CC115L_MDMCFG2_MOD_FORMAT_GFSK << CC115L_MDMCFG2_MOD_FORMAT) |
+       CC115L_MDMCFG2,         ((CC115L_MDMCFG2_MOD_FORMAT_GFSK << CC115L_MDMCFG2_MOD_FORMAT) |
                                 (0 << CC115L_MDMCFG2_MANCHESTER_EN) |
                                 (CC115L_MDMCFG2_SYNC_MODE_NONE << CC115L_MDMCFG2_SYNC_MODE)),
 };
@@ -401,8 +401,7 @@ static const uint16_t aprs_setup[] = {
        CC115L_MDMCFG4,         ((0xf << 4) |
                                 (APRS_DRATE_E << CC115L_MDMCFG4_DRATE_E)),
        CC115L_MDMCFG3,         (APRS_DRATE_M),
-       CC115L_MDMCFG2,         (0x00 |
-                                (CC115L_MDMCFG2_MOD_FORMAT_GFSK << CC115L_MDMCFG2_MOD_FORMAT) |
+       CC115L_MDMCFG2,         ((CC115L_MDMCFG2_MOD_FORMAT_GFSK << CC115L_MDMCFG2_MOD_FORMAT) |
                                 (0 << CC115L_MDMCFG2_MANCHESTER_EN) |
                                 (CC115L_MDMCFG2_SYNC_MODE_NONE << CC115L_MDMCFG2_SYNC_MODE)),
 };
@@ -491,16 +490,21 @@ static const uint16_t radio_setup[] = {
        AO_CC115L_DONE_INT_GPIO_IOCFG,      CC115L_IOCFG_GPIO_CFG_PA_PD | (1 << CC115L_IOCFG_GPIO_INV),
 
         CC115L_FIFOTHR,                     0x47,       /* TX FIFO Thresholds */
-       CC115L_MDMCFG1,                     (0x00 |
-                                            (CC115L_MDMCFG1_NUM_PREAMBLE_4 << CC115L_MDMCFG1_NUM_PREAMBLE) |
-                                            (1 << CC115L_MDMCFG1_CHANSPC_E)),
+       CC115L_MDMCFG1,                                 /* Modem Configuration */
+               ((CC115L_MDMCFG1_NUM_PREAMBLE_4 << CC115L_MDMCFG1_NUM_PREAMBLE) |
+                (1 << CC115L_MDMCFG1_CHANSPC_E)),
        CC115L_MDMCFG0,                     248,        /* Channel spacing M value (100kHz channels) */
+       CC115L_MCSM1,                       0x30,       /* Main Radio Control State Machine Configuration */
         CC115L_MCSM0,                       0x38,       /* Main Radio Control State Machine Configuration */
         CC115L_RESERVED_0X20,               0xfb,       /* Use setting from SmartRF Studio */
+       CC115L_FREND0,                      0x10,       /* Front End TX Configuration */
         CC115L_FSCAL3,                      0xe9,       /* Frequency Synthesizer Calibration */
         CC115L_FSCAL2,                      0x2a,       /* Frequency Synthesizer Calibration */
         CC115L_FSCAL1,                      0x00,       /* Frequency Synthesizer Calibration */
         CC115L_FSCAL0,                      0x1f,       /* Frequency Synthesizer Calibration */
+       CC115L_RESERVED_0X29,               0x59,       /* RESERVED */
+       CC115L_RESERVED_0X2A,               0x7f,       /* RESERVED */
+       CC115L_RESERVED_0X2B,               0x3f,       /* RESERVED */
         CC115L_TEST2,                       0x81,       /* Various Test Settings */
         CC115L_TEST1,                       0x35,       /* Various Test Settings */
         CC115L_TEST0,                       0x09,       /* Various Test Settings */
@@ -508,6 +512,18 @@ static const uint16_t radio_setup[] = {
 
 static uint8_t ao_radio_configured = 0;
 
+#if HAS_RADIO_POWER
+#define RADIO_POWER    ao_config.radio_power
+#else
+
+#if 0
+#define RADIO_POWER    0x03    /* -31.75dBm on the test board */
+#endif
+
+#define RADIO_POWER    0xc0    /* full power */
+
+#endif
+
 static void
 ao_radio_setup(void)
 {
@@ -523,6 +539,8 @@ ao_radio_setup(void)
 
        ao_config_get();
 
+       ao_radio_reg_write(CC115L_PA, RADIO_POWER);
+
        ao_radio_strobe(CC115L_SCAL);
 
        ao_radio_configured = 1;
@@ -553,6 +571,8 @@ ao_radio_get(void)
                ao_radio_reg_write(CC115L_FREQ1, ao_config.radio_setting >> 8);
                ao_radio_reg_write(CC115L_FREQ0, ao_config.radio_setting);
                last_radio_setting = ao_config.radio_setting;
+               /* Make sure the RF calibration is current */
+               ao_radio_strobe(CC115L_SCAL);
        }
        if (ao_config.radio_rate != last_radio_rate) {
                ao_radio_mode &= ~AO_RADIO_MODE_BITS_PACKET_TX;
@@ -666,23 +686,11 @@ ao_radio_rdf_abort(void)
 
 #define POWER_STEP     0x08
 
-#if HAS_RADIO_POWER
-#define RADIO_POWER    ao_config.radio_power
-#else
-#define RADIO_POWER    0xc0
-#endif
-
 static void
 ao_radio_stx(void)
 {
-       uint8_t power;
        ao_radio_pa_on();
-       ao_radio_reg_write(CC115L_PA, 0);
        ao_radio_strobe(CC115L_STX);
-       for (power = POWER_STEP; power < RADIO_POWER; power += POWER_STEP)
-               ao_radio_reg_write(CC115L_PA, power);
-       if (power != RADIO_POWER)
-               ao_radio_reg_write(CC115L_PA, RADIO_POWER);
 }
 
 static void
diff --git a/src/drivers/ao_cc1200.c b/src/drivers/ao_cc1200.c
new file mode 100644 (file)
index 0000000..8546900
--- /dev/null
@@ -0,0 +1,1462 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_cc1200.h>
+#include <ao_exti.h>
+#include <ao_fec.h>
+#include <ao_packet.h>
+
+static uint8_t ao_radio_mutex;
+
+static uint8_t ao_radio_wake;          /* radio ready. Also used as sleep address */
+static uint8_t ao_radio_abort;         /* radio operation should abort */
+
+int8_t ao_radio_rssi;                  /* Last received RSSI value */
+
+#ifndef CC1200_DEBUG
+#define CC1200_DEBUG           0
+#endif
+
+#ifndef CC1200_LOW_LEVEL_DEBUG
+#define CC1200_LOW_LEVEL_DEBUG 0
+#endif
+
+#define CC1200_TRACE           0
+#define CC1200_APRS_TRACE      0
+
+extern const uint32_t  ao_radio_cal;
+
+#define FOSC   40000000
+
+#define ao_radio_select()      ao_spi_get_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS,AO_SPI_SPEED_FAST)
+#define ao_radio_deselect()    ao_spi_put_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS)
+#define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1200_SPI_BUS)
+#define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1200_SPI_BUS)
+#define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC1200_SPI_BUS)
+#define ao_radio_duplex(o,i,l) ao_spi_duplex((o), (i), (l), AO_CC1200_SPI_BUS)
+
+static uint8_t
+ao_radio_reg_read(uint16_t addr)
+{
+       uint8_t data[2];
+       uint8_t d;
+
+#if CC1200_TRACE
+       printf("\t\tao_radio_reg_read (%04x): ", addr); flush();
+#endif
+       if (CC1200_IS_EXTENDED(addr)) {
+               data[0] = ((1 << CC1200_READ)  |
+                          (0 << CC1200_BURST) |
+                          CC1200_EXTENDED);
+               data[1] = addr;
+               d = 2;
+       } else {
+               data[0] = ((1 << CC1200_READ)  |
+                          (0 << CC1200_BURST) |
+                          addr);
+               d = 1;
+       }
+       ao_radio_select();
+       ao_radio_spi_send(data, d);
+       ao_radio_spi_recv(data, 1);
+       ao_radio_deselect();
+#if CC1200_TRACE
+       printf (" %02x\n", data[0]);
+#endif
+       return data[0];
+}
+
+static void
+ao_radio_reg_write(uint16_t addr, uint8_t value)
+{
+       uint8_t data[3];
+       uint8_t d;
+
+#if CC1200_TRACE
+       printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value);
+#endif
+       if (CC1200_IS_EXTENDED(addr)) {
+               data[0] = ((0 << CC1200_READ)  |
+                          (0 << CC1200_BURST) |
+                          CC1200_EXTENDED);
+               data[1] = addr;
+               d = 2;
+       } else {
+               data[0] = ((0 << CC1200_READ)  |
+                          (0 << CC1200_BURST) |
+                          addr);
+               d = 1;
+       }
+       data[d] = value;
+       ao_radio_select();
+       ao_radio_spi_send(data, d+1);
+       ao_radio_deselect();
+#if CC1200_TRACE
+       (void) ao_radio_reg_read(addr);
+#endif
+}
+
+static uint8_t
+ao_radio_strobe(uint8_t addr)
+{
+       uint8_t in;
+
+#if CC1200_TRACE
+       printf("\t\tao_radio_strobe (%02x): ", addr); flush();
+#endif
+       ao_radio_select();
+       ao_radio_duplex(&addr, &in, 1);
+       ao_radio_deselect();
+#if CC1200_TRACE
+       printf("%02x\n", in); flush();
+#endif
+       return in;
+}
+
+static uint8_t
+ao_radio_fifo_read(uint8_t *data, uint8_t len)
+{
+       uint8_t addr = ((1 << CC1200_READ)  |
+                       (1 << CC1200_BURST) |
+                       CC1200_FIFO);
+       uint8_t status;
+
+       ao_radio_select();
+       ao_radio_duplex(&addr, &status, 1);
+       ao_radio_spi_recv(data, len);
+       ao_radio_deselect();
+       return status;
+}
+
+static uint8_t
+ao_radio_fifo_write_start(void)
+{
+       uint8_t addr = ((0 << CC1200_READ)  |
+                       (1 << CC1200_BURST) |
+                       CC1200_FIFO);
+       uint8_t status;
+
+       ao_radio_select();
+       ao_radio_duplex(&addr, &status, 1);
+       return status;
+}
+
+static inline uint8_t ao_radio_fifo_write_stop(uint8_t status) {
+       ao_radio_deselect();
+       return status;
+}
+
+static uint8_t
+ao_radio_fifo_write(const uint8_t *data, uint8_t len)
+{
+       uint8_t status = ao_radio_fifo_write_start();
+       ao_radio_spi_send(data, len);
+       return ao_radio_fifo_write_stop(status);
+}
+
+static uint8_t
+ao_radio_fifo_write_fixed(uint8_t data, uint8_t len)
+{
+       uint8_t status = ao_radio_fifo_write_start();
+       ao_radio_spi_send_fixed(data, len);
+       return ao_radio_fifo_write_stop(status);
+}
+
+static uint8_t
+ao_radio_tx_fifo_space(void)
+{
+       return CC1200_FIFO_SIZE - ao_radio_reg_read(CC1200_NUM_TXBYTES);
+}
+
+static uint8_t
+ao_radio_status(void)
+{
+       return ao_radio_strobe (CC1200_SNOP);
+}
+
+void
+ao_radio_recv_abort(void)
+{
+       ao_radio_abort = 1;
+       ao_wakeup(&ao_radio_wake);
+}
+
+#define ao_radio_rdf_value 0x55
+
+static void
+ao_radio_isr(void)
+{
+       ao_exti_disable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
+       ao_radio_wake = 1;
+       ao_wakeup(&ao_radio_wake);
+}
+
+static void
+ao_radio_start_tx(void)
+{
+       ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
+       ao_radio_strobe(CC1200_STX);
+}
+
+static void
+ao_radio_start_rx(void)
+{
+       ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
+       ao_radio_strobe(CC1200_SRX);
+}
+
+static void
+ao_radio_idle(void)
+{
+       for (;;) {
+               uint8_t state = (ao_radio_strobe(CC1200_SIDLE) >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK;
+               if (state == CC1200_STATUS_STATE_IDLE)
+                       break;
+               if (state == CC1200_STATUS_STATE_TX_FIFO_ERROR)
+                       ao_radio_strobe(CC1200_SFTX);
+               if (state == CC1200_STATUS_STATE_RX_FIFO_ERROR)
+                       ao_radio_strobe(CC1200_SFRX);
+       }
+       /* Flush any pending data in the fifos */
+       ao_radio_strobe(CC1200_SFTX);
+       ao_radio_strobe(CC1200_SFRX);
+       /* Make sure the RF calibration is current */
+       ao_radio_strobe(CC1200_SCAL);
+}
+
+/*
+ * Packet deviation
+ *
+ *     fdev = fosc >> 22 * (256 + dev_m) << dev_e
+ *
+ * Deviation for 38400 baud should be 20.5kHz:
+ *
+ *             40e6 / (2 ** 22) * (256 + 13) * (2 ** 3) = 20523Hz
+ *
+ * Deviation for 9600 baud should be 5.125kHz:
+ *
+ *             40e6 / (2 ** 22) * (256 + 13) * (2 ** 1) = 5131Hz
+ *
+ * Deviation for 2400 baud should be 1.28125kHz, but cc1111 and
+ * cc115l can't do that, so we'll use 1.5kHz instead:
+ *
+ *             40e6 / (2 ** 21) * (79) = 1506Hz
+ */
+
+#define PACKET_DEV_M_384       13
+#define PACKET_DEV_E_384       3
+
+#define PACKET_DEV_M_96                13
+#define PACKET_DEV_E_96                1
+
+#define PACKET_DEV_M_24                79
+#define PACKET_DEV_E_24                0
+
+/*
+ * For our packet data
+ *
+ *              (2**20 + DATARATE_M) * 2 ** DATARATE_E
+ *     Rdata = -------------------------------------- * fosc
+ *                          2 ** 39
+ *
+ * Given the bit period of the baseband, T, the bandwidth of the
+ * baseband signal is B = 1/(2T).  The overall bandwidth of the
+ * modulated signal is then Channel bandwidth = 2Δf + 2B.
+ *
+ * 38400 -- 2 * 20500 + 38400 = 79.4 kHz
+ *  9600 -- 2 * 5.125 +  9600 = 19.9 kHz
+ *  2400 -- 2 * 1.5   +  2400 =  5.4 khz
+ *
+ * Symbol rate 38400 Baud:
+ *
+ *     DATARATE_M = 1013008
+ *     DATARATE_E = 8
+ *     CHANBW = 104.16667
+ *
+ * Symbol rate 9600 Baud:
+ *
+ *     DATARATE_M = 1013008
+ *     DATARATE_E = 6
+ *     CHANBW = 26.042 (round to 19.8)
+ *
+ * Symbol rate 2400 Baud:
+ *
+ *     DATARATE_M = 1013008
+ *     DATARATE_E = 4
+ *     CHANBW = 5.0 (round to 9.5)
+ */
+
+#define PACKET_SYMBOL_RATE_M           1013008
+
+#define PACKET_SYMBOL_RATE_E_384       8
+
+/* 200 / 2 = 100 */
+#define PACKET_CHAN_BW_384     ((CC1200_CHAN_BW_ADC_CIC_DECFACT_12 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
+                                (16 << CC1200_CHAN_BW_BB_CIC_DECFACT))
+
+#define PACKET_SYMBOL_RATE_E_96                6
+/* 200 / 10 = 20 */
+#define PACKET_CHAN_BW_96      ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
+                                (16 << CC1200_CHAN_BW_BB_CIC_DECFACT))
+
+#define PACKET_SYMBOL_RATE_E_24                4
+/* 200 / 25 = 8 */
+#define PACKET_CHAN_BW_24      ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
+                                (44 << CC1200_CHAN_BW_BB_CIC_DECFACT))
+
+static const uint16_t packet_setup[] = {
+       CC1200_SYMBOL_RATE1,            ((PACKET_SYMBOL_RATE_M >> 8) & 0xff),
+       CC1200_SYMBOL_RATE0,            ((PACKET_SYMBOL_RATE_M >> 0) & 0xff),
+        CC1200_PKT_CFG2,                                /* Packet Configuration Reg. 2 */
+               ((0 << CC1200_PKT_CFG2_FG_MODE_EN) |
+                (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
+                (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
+        CC1200_PKT_CFG1,                                 /* Packet Configuration Reg. 1 */
+               ((1 << CC1200_PKT_CFG1_FEC_EN) |
+                (1 << CC1200_PKT_CFG1_WHITE_DATA) |
+                (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) |
+                (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
+                (CC1200_PKT_CFG1_CRC_CFG_CRC16_INIT_ONES << CC1200_PKT_CFG1_CRC_CFG) |
+                (1 << CC1200_PKT_CFG1_APPEND_STATUS)),
+        CC1200_PREAMBLE_CFG1,  ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
+                                (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
+};
+
+static const uint16_t packet_setup_384[] = {
+       CC1200_DEVIATION_M,     PACKET_DEV_M_384,
+       CC1200_MODCFG_DEV_E,    ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
+                                (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
+                                (PACKET_DEV_E_384 << CC1200_MODCFG_DEV_E_DEV_E)),
+       CC1200_SYMBOL_RATE2,    ((PACKET_SYMBOL_RATE_E_384 << CC1200_SYMBOL_RATE2_DATARATE_E) |
+                                (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
+       CC1200_CHAN_BW,         PACKET_CHAN_BW_384,
+        CC1200_MDMCFG2,                                  /* General Modem Parameter Configuration Reg. 2 */
+               ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
+                (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
+                (CC1200_MDMCFG2_UPSAMPLER_P_8 << CC1200_MDMCFG2_UPSAMPLER_P) |
+                (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
+};
+
+static const uint16_t packet_setup_96[] = {
+       CC1200_DEVIATION_M,     PACKET_DEV_M_96,
+       CC1200_MODCFG_DEV_E,    ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
+                                (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
+                                (PACKET_DEV_E_96 << CC1200_MODCFG_DEV_E_DEV_E)),
+       CC1200_SYMBOL_RATE2,    ((PACKET_SYMBOL_RATE_E_96 << CC1200_SYMBOL_RATE2_DATARATE_E) |
+                                (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
+       CC1200_CHAN_BW,         PACKET_CHAN_BW_96,
+        CC1200_MDMCFG2,                                  /* General Modem Parameter Configuration Reg. 2 */
+               ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
+                (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
+                (CC1200_MDMCFG2_UPSAMPLER_P_32 << CC1200_MDMCFG2_UPSAMPLER_P) |
+                (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
+};
+
+static const uint16_t packet_setup_24[] = {
+       CC1200_DEVIATION_M,     PACKET_DEV_M_24,
+       CC1200_MODCFG_DEV_E,    ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
+                                (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
+                                (PACKET_DEV_E_24 << CC1200_MODCFG_DEV_E_DEV_E)),
+       CC1200_SYMBOL_RATE2,    ((PACKET_SYMBOL_RATE_E_24 << CC1200_SYMBOL_RATE2_DATARATE_E) |
+                                (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
+       CC1200_CHAN_BW,         PACKET_CHAN_BW_24,
+        CC1200_MDMCFG2,                                  /* General Modem Parameter Configuration Reg. 2 */
+               ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
+                (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
+                (CC1200_MDMCFG2_UPSAMPLER_P_64 << CC1200_MDMCFG2_UPSAMPLER_P) |
+                (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
+};
+
+/*
+ * RDF deviation is 3kHz
+ *
+ *     fdev = fosc >> 22 * (256 + dev_m) << dev_e      dev_e != 0
+ *     fdev = fosc >> 21 * dev_m                       dev_e == 0
+ *
+ *             40e6 / (2 ** 21) * 157 = 2995Hz
+ */
+
+#define RDF_DEV_E      0
+#define RDF_DEV_M      157
+
+/*
+ * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
+ *
+ *              (2**20 + DATARATE_M) * 2 ** DATARATE_E
+ *     Rdata = -------------------------------------- * fosc
+ *                          2 ** 39
+ *
+ *     DATARATE_M = 669411
+ *     DATARATE_E = 4
+ *
+ * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
+ */
+#define RDF_SYMBOL_RATE_E      4
+#define RDF_SYMBOL_RATE_M      669411
+#define RDF_PACKET_LEN 50
+
+static const uint16_t rdf_setup[] = {
+       CC1200_DEVIATION_M,     RDF_DEV_M,
+       CC1200_MODCFG_DEV_E,    ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
+                                (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
+                                (RDF_DEV_E << CC1200_MODCFG_DEV_E_DEV_E)),
+       CC1200_SYMBOL_RATE2,    ((RDF_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) |
+                                (((RDF_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
+       CC1200_SYMBOL_RATE1,    ((RDF_SYMBOL_RATE_M >> 8) & 0xff),
+       CC1200_SYMBOL_RATE0,    ((RDF_SYMBOL_RATE_M >> 0) & 0xff),
+        CC1200_PKT_CFG2,                                /* Packet Configuration Reg. 2 */
+               ((0 << CC1200_PKT_CFG2_FG_MODE_EN) |
+                (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
+                (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
+        CC1200_PKT_CFG1,                                 /* Packet Configuration Reg. 1 */
+               ((0 << CC1200_PKT_CFG1_FEC_EN) |
+                (0 << CC1200_PKT_CFG1_WHITE_DATA) |
+                (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) |
+                (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
+                (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) |
+                (0 << CC1200_PKT_CFG1_APPEND_STATUS)),
+        CC1200_PREAMBLE_CFG1,
+               ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
+                (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
+        CC1200_MDMCFG2,                                  /* General Modem Parameter Configuration Reg. 2 */
+               ((0 << CC1200_MDMCFG2_ASK_SHAPE) |
+                (0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
+                (12 << CC1200_MDMCFG2_UPSAMPLER_P) |
+                (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
+};
+
+/*
+ * APRS deviation is 3kHz
+ *
+ *     fdev = fosc >> 22 * (256 + dev_m) << dev_e      dev_e != 0
+ *     fdev = fosc >> 21 * dev_m                       dev_e == 0
+ *
+ *             40e6 / (2 ** 21) * 157 = 2995Hz
+ */
+
+#define APRS_DEV_E     0
+#define APRS_DEV_M     157
+
+/*
+ * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate)
+ *
+ *              (2**20 + DATARATE_M) * 2 ** DATARATE_E
+ *     Rdata = -------------------------------------- * fosc
+ *                          2 ** 39
+ *
+ *     DATARATE_M = 1013008
+ *     DATARATE_E = 6
+ *
+ *     Rdata = 9599.998593330383301
+ *
+ */
+#define APRS_SYMBOL_RATE_E     6
+#define APRS_SYMBOL_RATE_M     1013008
+
+static const uint16_t aprs_setup[] = {
+       CC1200_DEVIATION_M,     APRS_DEV_M,
+       CC1200_MODCFG_DEV_E,    ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
+                                (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
+                                (APRS_DEV_E << CC1200_MODCFG_DEV_E_DEV_E)),
+       CC1200_SYMBOL_RATE2,    ((APRS_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) |
+                                (((APRS_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
+       CC1200_SYMBOL_RATE1,    ((APRS_SYMBOL_RATE_M >> 8) & 0xff),
+       CC1200_SYMBOL_RATE0,    ((APRS_SYMBOL_RATE_M >> 0) & 0xff),
+        CC1200_PKT_CFG2,                                /* Packet Configuration Reg. 2 */
+               ((0 << CC1200_PKT_CFG2_FG_MODE_EN) |
+                (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
+                (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
+        CC1200_PKT_CFG1,                                 /* Packet Configuration Reg. 1 */
+               ((0 << CC1200_PKT_CFG1_FEC_EN) |
+                (0 << CC1200_PKT_CFG1_WHITE_DATA) |
+                (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) |
+                (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
+                (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) |
+                (0 << CC1200_PKT_CFG1_APPEND_STATUS)),
+        CC1200_PKT_CFG0,                                 /* Packet Configuration Reg. 0 */
+               ((CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) |
+                (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) |
+                (0 << CC1200_PKT_CFG0_UART_MODE_EN) |
+                (0 << CC1200_PKT_CFG0_UART_SWAP_EN)),
+        CC1200_PREAMBLE_CFG1,
+               ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
+                (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
+        CC1200_MDMCFG2,                                  /* General Modem Parameter Configuration Reg. 2 */
+               ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
+                (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
+                (CC1200_MDMCFG2_UPSAMPLER_P_8 << CC1200_MDMCFG2_UPSAMPLER_P) |
+                (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
+};
+
+/*
+ * For Test mode, we want an unmodulated carrier. To do that, we
+ * set the deviation to zero and enable a preamble so that the radio
+ * turns on before we send any data
+ */
+
+static const uint16_t test_setup[] = {
+       CC1200_DEVIATION_M,     0,
+       CC1200_MODCFG_DEV_E,    ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
+                                (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
+                                (0 << CC1200_MODCFG_DEV_E_DEV_E)),
+       CC1200_SYMBOL_RATE2,            ((APRS_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) |
+                                (((APRS_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
+       CC1200_SYMBOL_RATE1,            ((APRS_SYMBOL_RATE_M >> 8) & 0xff),
+       CC1200_SYMBOL_RATE0,            ((APRS_SYMBOL_RATE_M >> 0) & 0xff),
+       CC1200_PKT_CFG2,        ((CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
+                                (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
+       CC1200_PKT_CFG1,        ((0 << CC1200_PKT_CFG1_WHITE_DATA) |
+                                (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
+                                (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) |
+                                (0 << CC1200_PKT_CFG1_APPEND_STATUS)),
+        CC1200_PREAMBLE_CFG1,  ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
+                                (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
+};
+
+#define AO_PKT_CFG0_INFINITE ((CC1200_PKT_CFG0_LENGTH_CONFIG_INFINITE << CC1200_PKT_CFG0_LENGTH_CONFIG) | \
+                             (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) |      \
+                             (0 << CC1200_PKT_CFG0_UART_MODE_EN) |     \
+                             (0 << CC1200_PKT_CFG0_UART_SWAP_EN))
+
+#define AO_PKT_CFG0_FIXED ((CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) | \
+                          (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) |         \
+                          (0 << CC1200_PKT_CFG0_UART_MODE_EN) |        \
+                          (0 << CC1200_PKT_CFG0_UART_SWAP_EN))
+
+static uint16_t ao_radio_mode;
+
+#define AO_RADIO_MODE_BITS_PACKET      1
+#define AO_RADIO_MODE_BITS_TX_BUF      4
+#define AO_RADIO_MODE_BITS_TX_FINISH   8
+#define AO_RADIO_MODE_BITS_RX          16
+#define AO_RADIO_MODE_BITS_RDF         32
+#define AO_RADIO_MODE_BITS_APRS                64
+#define AO_RADIO_MODE_BITS_TEST                128
+#define AO_RADIO_MODE_BITS_INFINITE    256
+#define AO_RADIO_MODE_BITS_FIXED       512
+
+#define AO_RADIO_MODE_NONE             0
+#define AO_RADIO_MODE_PACKET_TX                (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_FIXED    | AO_RADIO_MODE_BITS_TX_FINISH)
+#define AO_RADIO_MODE_PACKET_RX                (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_FIXED    | AO_RADIO_MODE_BITS_RX)
+#define AO_RADIO_MODE_RDF              (AO_RADIO_MODE_BITS_RDF    | AO_RADIO_MODE_BITS_FIXED    | AO_RADIO_MODE_BITS_TX_FINISH)
+#define AO_RADIO_MODE_APRS_BUF         (AO_RADIO_MODE_BITS_APRS   | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
+#define AO_RADIO_MODE_APRS_LAST_BUF    (AO_RADIO_MODE_BITS_APRS   | AO_RADIO_MODE_BITS_FIXED    | AO_RADIO_MODE_BITS_TX_BUF)
+#define AO_RADIO_MODE_APRS_FINISH      (AO_RADIO_MODE_BITS_APRS   | AO_RADIO_MODE_BITS_FIXED    | AO_RADIO_MODE_BITS_TX_FINISH)
+#define AO_RADIO_MODE_TEST             (AO_RADIO_MODE_BITS_TEST   | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
+
+static void
+_ao_radio_set_regs(const uint16_t *regs, int nreg)
+{
+       int i;
+
+       for (i = 0; i < nreg; i++) {
+               ao_radio_reg_write(regs[0], regs[1]);
+               regs += 2;
+       }
+}
+
+#define ao_radio_set_regs(setup) _ao_radio_set_regs(setup, (sizeof (setup) / sizeof(setup[0])) >> 1)
+
+static void
+ao_radio_set_mode(uint16_t new_mode)
+{
+       uint16_t changes;
+
+       if (new_mode == ao_radio_mode)
+               return;
+
+       changes = new_mode & (~ao_radio_mode);
+
+       if (changes & AO_RADIO_MODE_BITS_PACKET) {
+               ao_radio_set_regs(packet_setup);
+
+               switch (ao_config.radio_rate) {
+               default:
+               case AO_RADIO_RATE_38400:
+                       ao_radio_set_regs(packet_setup_384);
+                       break;
+               case AO_RADIO_RATE_9600:
+                       ao_radio_set_regs(packet_setup_96);
+                       break;
+               case AO_RADIO_RATE_2400:
+                       ao_radio_set_regs(packet_setup_24);
+                       break;
+               }
+       }
+
+       if (changes & AO_RADIO_MODE_BITS_TX_BUF) {
+               ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_TXFIFO_THR);
+               ao_exti_set_mode(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
+       }
+
+       if (changes & AO_RADIO_MODE_BITS_TX_FINISH) {
+               ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_PKT_SYNC_RXTX);
+               ao_exti_set_mode(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
+       }
+
+       if (changes & AO_RADIO_MODE_BITS_RX) {
+               ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP);
+               ao_exti_set_mode(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_HIGH);
+       }
+
+       if (changes & AO_RADIO_MODE_BITS_RDF)
+               ao_radio_set_regs(rdf_setup);
+
+       if (changes & AO_RADIO_MODE_BITS_APRS)
+               ao_radio_set_regs(aprs_setup);
+
+       if (changes & AO_RADIO_MODE_BITS_TEST)
+               ao_radio_set_regs(test_setup);
+
+       if (changes & AO_RADIO_MODE_BITS_INFINITE)
+               ao_radio_reg_write(CC1200_PKT_CFG0, AO_PKT_CFG0_INFINITE);
+
+       if (changes & AO_RADIO_MODE_BITS_FIXED)
+               ao_radio_reg_write(CC1200_PKT_CFG0, AO_PKT_CFG0_FIXED);
+
+       ao_radio_mode = new_mode;
+}
+
+static const uint16_t radio_setup[] = {
+#include "ao_cc1200_CC1200.h"
+};
+
+static uint8_t ao_radio_configured = 0;
+
+static void
+ao_radio_setup(void)
+{
+       ao_radio_strobe(CC1200_SRES);
+
+       ao_radio_set_regs(radio_setup);
+
+       ao_radio_mode = 0;
+
+       ao_radio_idle();
+
+       ao_config_get();
+
+       ao_radio_configured = 1;
+}
+
+static void
+ao_radio_set_len(uint8_t len)
+{
+       static uint8_t  last_len;
+
+       if (len != last_len) {
+               ao_radio_reg_write(CC1200_PKT_LEN, len);
+               last_len = len;
+       }
+}
+
+static void
+ao_radio_get(uint8_t len)
+{
+       static uint32_t last_radio_setting;
+       static uint8_t  last_radio_rate;
+
+       ao_mutex_get(&ao_radio_mutex);
+
+       if (!ao_radio_configured)
+               ao_radio_setup();
+       if (ao_config.radio_setting != last_radio_setting) {
+               ao_radio_reg_write(CC1200_FREQ2, ao_config.radio_setting >> 16);
+               ao_radio_reg_write(CC1200_FREQ1, ao_config.radio_setting >> 8);
+               ao_radio_reg_write(CC1200_FREQ0, ao_config.radio_setting);
+               last_radio_setting = ao_config.radio_setting;
+               ao_radio_strobe(CC1200_SCAL);
+       }
+       if (ao_config.radio_rate != last_radio_rate) {
+               ao_radio_mode &= ~AO_RADIO_MODE_BITS_PACKET;
+               last_radio_rate = ao_config.radio_rate;
+       }
+       ao_radio_set_len(len);
+}
+
+#define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
+
+static inline uint8_t
+ao_radio_state(void)
+{
+       return (ao_radio_status() >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK;
+}
+
+#if CC1200_DEBUG
+void
+ao_radio_show_state(char *where)
+{
+       printf("%s: state %d len %d rxbytes %d\n",
+              where, ao_radio_state(),
+              ao_radio_reg_read(CC1200_PKT_LEN),
+              ao_radio_reg_read(CC1200_NUM_RXBYTES));
+}
+#else
+#define ao_radio_show_state(where)
+#endif
+
+/* Wait for the radio to signal an interrupt
+ */
+static void
+ao_radio_wait_isr(uint16_t timeout)
+{
+       if (timeout)
+               ao_alarm(timeout);
+
+       ao_arch_block_interrupts();
+       while (!ao_radio_wake && !ao_radio_abort)
+               if (ao_sleep(&ao_radio_wake))
+                       ao_radio_abort = 1;
+       ao_arch_release_interrupts();
+
+       if (timeout)
+               ao_clear_alarm();
+}
+
+static void
+ao_rdf_start(uint8_t len)
+{
+       ao_radio_abort = 0;
+       ao_radio_get(len);
+
+       ao_radio_set_mode(AO_RADIO_MODE_RDF);
+       ao_radio_wake = 0;
+}
+
+static void
+ao_radio_run(void)
+{
+       ao_radio_wake = 0;
+       ao_radio_abort = 0;
+       ao_radio_start_tx();
+       ao_radio_wait_isr(0);
+       if (!ao_radio_wake)
+               ao_radio_idle();
+       ao_radio_put();
+}
+
+void
+ao_radio_rdf(void)
+{
+       ao_rdf_start(AO_RADIO_RDF_LEN);
+
+       ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN);
+
+       ao_radio_run();
+}
+
+void
+ao_radio_continuity(uint8_t c)
+{
+       uint8_t i;
+       uint8_t status;
+
+       ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN);
+
+       status = ao_radio_fifo_write_start();
+       for (i = 0; i < 3; i++) {
+               ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
+               if (i < c)
+                       ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN);
+               else
+                       ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN);
+       }
+       ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
+       status = ao_radio_fifo_write_stop(status);
+       (void) status;
+       ao_radio_run();
+}
+
+void
+ao_radio_rdf_abort(void)
+{
+       ao_radio_abort = 1;
+       ao_wakeup(&ao_radio_wake);
+}
+
+static void
+ao_radio_test_cmd(void)
+{
+       uint8_t mode = 2;
+       static uint8_t radio_on;
+       ao_cmd_white();
+       if (ao_cmd_lex_c != '\n') {
+               ao_cmd_decimal();
+               mode = (uint8_t) ao_cmd_lex_u32;
+       }
+       mode++;
+       if ((mode & 2) && !radio_on) {
+#if HAS_MONITOR
+               ao_monitor_disable();
+#endif
+#if PACKET_HAS_SLAVE
+               ao_packet_slave_stop();
+#endif
+               ao_radio_get(0xff);
+               ao_radio_set_mode(AO_RADIO_MODE_TEST);
+               ao_radio_strobe(CC1200_STX);
+#if CC1200_TRACE
+               { int t;
+                       for (t = 0; t < 10; t++) {
+                               printf ("status: %02x\n", ao_radio_status());
+                               ao_delay(AO_MS_TO_TICKS(100));
+                       }
+               }
+#endif
+               radio_on = 1;
+       }
+       if (mode == 3) {
+               printf ("Hit a character to stop..."); flush();
+               getchar();
+               putchar('\n');
+       }
+       if ((mode & 1) && radio_on) {
+               ao_radio_idle();
+               ao_radio_put();
+               radio_on = 0;
+#if HAS_MONITOR
+               ao_monitor_enable();
+#endif
+       }
+}
+
+void
+ao_radio_send(const void *d, uint8_t size)
+{
+       ao_radio_get(size);
+       ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX);
+
+       ao_radio_fifo_write(d, size);
+
+       ao_radio_run();
+}
+
+
+#define AO_RADIO_LOTS  64
+
+void
+ao_radio_send_aprs(ao_radio_fill_func fill)
+{
+       uint8_t buf[AO_RADIO_LOTS], *b;
+       int     cnt;
+       int     total = 0;
+       uint8_t done = 0;
+       uint8_t started = 0;
+       uint8_t fifo_space;
+
+       ao_radio_abort = 0;
+       ao_radio_get(0xff);
+       fifo_space = CC1200_FIFO_SIZE;
+       while (!done) {
+               cnt = (*fill)(buf, sizeof(buf));
+               if (cnt < 0) {
+                       done = 1;
+                       cnt = -cnt;
+               }
+#if CC1200_APRS_TRACE
+               printf("APRS fill %d bytes done %d\n", cnt, done);
+#endif
+               total += cnt;
+
+               /* At the last buffer, set the total length */
+               if (done)
+                       ao_radio_set_len(total & 0xff);
+
+               b = buf;
+               while (cnt) {
+                       uint8_t this_len = cnt;
+
+                       /* Wait for some space in the fifo */
+                       while (!ao_radio_abort && (fifo_space = ao_radio_tx_fifo_space()) == 0) {
+#if CC1200_APRS_TRACE
+                               printf("APRS space %d cnt %d\n", fifo_space, cnt); flush();
+#endif
+                               ao_radio_wake = 0;
+                               ao_radio_wait_isr(AO_MS_TO_TICKS(1000));
+                       }
+                       if (ao_radio_abort)
+                               break;
+                       if (this_len > fifo_space)
+                               this_len = fifo_space;
+
+                       cnt -= this_len;
+
+                       if (done) {
+                               if (cnt)
+                                       ao_radio_set_mode(AO_RADIO_MODE_APRS_LAST_BUF);
+                               else
+                                       ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH);
+                       } else
+                               ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF);
+
+                       ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
+
+                       ao_radio_fifo_write(b, this_len);
+                       b += this_len;
+#if CC1200_APRS_TRACE
+                       printf("APRS write fifo %d space now %d\n", this_len, ao_radio_tx_fifo_space());
+#endif
+                       if (!started) {
+#if CC1200_APRS_TRACE
+                               printf("APRS start\n");
+#endif
+                               ao_radio_strobe(CC1200_STX);
+#if CC1200_APRS_TRACE
+                               { int t;
+                                       for (t = 0; t < 20; t++) {
+                                               uint8_t status = ao_radio_status();
+                                               uint8_t space = ao_radio_tx_fifo_space();
+                                               printf ("status: %02x fifo %d\n", status, space);
+                                               if ((status >> 4) == 2)
+                                                       break;
+                                               ao_delay(AO_MS_TO_TICKS(0));
+                                       }
+                               }
+#endif
+                               started = 1;
+                       }
+               }
+               if (ao_radio_abort) {
+                       ao_radio_idle();
+                       break;
+               }
+       }
+       /* Wait for the transmitter to go idle */
+       ao_radio_wake = 0;
+#if CC1200_APRS_TRACE
+       printf("APRS wait idle\n"); flush();
+#endif
+       ao_radio_wait_isr(AO_MS_TO_TICKS(1000));
+#if CC1200_APRS_TRACE
+       printf("APRS abort %d\n", ao_radio_abort);
+#endif
+       ao_radio_put();
+}
+
+#if 0
+static uint8_t
+ao_radio_marc_state(void)
+{
+       return ao_radio_reg_read(CC1200_MARCSTATE);
+}
+
+static uint8_t
+ao_radio_modem_status1(void)
+{
+       return ao_radio_reg_read(CC1200_MODEM_STATUS1);
+}
+
+static uint8_t
+ao_radio_modem_status0(void)
+{
+       return ao_radio_reg_read(CC1200_MODEM_STATUS0);
+}
+
+struct ao_radio_state {
+       char    where[4];
+       uint8_t marc_state;
+       uint8_t marc_status1;
+       uint8_t marc_status0;
+       uint8_t modem_status1;
+       uint8_t modem_status0;
+};
+
+static void
+ao_radio_fill_state(char *where, struct ao_radio_state *s)
+{
+       strcpy(s->where, where);
+       s->marc_state = ao_radio_marc_state();
+       s->marc_status1 = ao_radio_reg_read(CC1200_MARC_STATUS1);
+       s->marc_status0 = ao_radio_reg_read(CC1200_MARC_STATUS0);
+       s->modem_status1 = ao_radio_modem_status1();
+       s->modem_status0 = ao_radio_modem_status0();
+}
+
+static void
+ao_radio_dump_state(struct ao_radio_state *s)
+{
+       printf ("%s: marc %2x marc1 %2x marc0 %2x modem1 %2x modem0 %2x\n",
+               s->where, s->marc_state, s->marc_status1, s->marc_status0, s->modem_status1, s->modem_status0);
+}
+#endif
+
+uint8_t
+ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout)
+{
+       uint8_t success = 0;
+
+       ao_radio_abort = 0;
+       ao_radio_get(size - 2);
+       ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
+       ao_radio_wake = 0;
+       ao_radio_start_rx();
+
+       while (!ao_radio_abort) {
+               ao_radio_wait_isr(timeout);
+               if (ao_radio_wake) {
+                       uint8_t         marc_status1 = ao_radio_reg_read(CC1200_MARC_STATUS1);
+
+                       /* Check the receiver status to see what happened
+                        */
+                       switch (marc_status1) {
+                       case CC1200_MARC_STATUS1_RX_FINISHED:
+                       case CC1200_MARC_STATUS1_ADDRESS:
+                       case CC1200_MARC_STATUS1_CRC:
+                               /* Normal return, go fetch the bytes from the FIFO
+                                * and give them back to the caller
+                                */
+                               success = 1;
+                               break;
+                       case CC1200_MARC_STATUS1_RX_TIMEOUT:
+                       case CC1200_MARC_STATUS1_RX_TERMINATION:
+                       case CC1200_MARC_STATUS1_EWOR_SYNC_LOST:
+                       case CC1200_MARC_STATUS1_MAXIMUM_LENGTH:
+                       case CC1200_MARC_STATUS1_RX_FIFO_OVERFLOW:
+                       case CC1200_MARC_STATUS1_RX_FIFO_UNDERFLOW:
+                               /* Something weird happened; reset the radio and
+                                * return failure
+                                */
+                               success = 0;
+                               break;
+                       default:
+                               /* some other status; go wait for the radio to do something useful
+                                */
+                               continue;
+                       }
+                       break;
+               } else {
+                       uint8_t modem_status1 = ao_radio_reg_read(CC1200_MODEM_STATUS1);
+
+                       /* Check to see if the packet header has been seen, in which case we'll
+                        * want to keep waiting for the rest of the packet to appear
+                        */
+                       if (modem_status1 & (1 << CC1200_MODEM_STATUS1_SYNC_FOUND))
+                       {
+                               ao_radio_abort = 0;
+
+                               /* Set a timeout based on the packet length so that we make sure to
+                                * wait long enough to receive the whole thing.
+                                *
+                                * timeout = bits * FEC expansion / rate
+                                */
+                               switch (ao_config.radio_rate) {
+                               default:
+                               case AO_RADIO_RATE_38400:
+                                       timeout = AO_MS_TO_TICKS(size * (8 * 2 * 10) / 384) + 1;
+                                       break;
+                               case AO_RADIO_RATE_9600:
+                                       timeout = AO_MS_TO_TICKS(size * (8 * 2 * 10) / 96) + 1;
+                                       break;
+                               case AO_RADIO_RATE_2400:
+                                       timeout = AO_MS_TO_TICKS(size * (8 * 2 * 10) / 24) + 1;
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       if (success) {
+               int8_t  rssi;
+               uint8_t status;
+
+               status = ao_radio_fifo_read(d, size);
+               (void) status;
+               rssi = ((int8_t *) d)[size - 2];
+               ao_radio_rssi = rssi;
+
+               /* Bound it to the representable range */
+               if (rssi > -11)
+                       rssi = -11;
+
+               /* Write it back to the packet */
+               ((int8_t *) d)[size-2] = AO_RADIO_FROM_RSSI(rssi);
+       } else {
+               ao_radio_idle();
+               ao_radio_rssi = 0;
+       }
+
+       ao_radio_put();
+       return success;
+}
+
+
+#if CC1200_DEBUG
+static char *cc1200_state_name[] = {
+       [CC1200_STATUS_STATE_IDLE] = "IDLE",
+       [CC1200_STATUS_STATE_RX] = "RX",
+       [CC1200_STATUS_STATE_TX] = "TX",
+       [CC1200_STATUS_STATE_FSTXON] = "FSTXON",
+       [CC1200_STATUS_STATE_CALIBRATE] = "CALIBRATE",
+       [CC1200_STATUS_STATE_SETTLING] = "SETTLING",
+       [CC1200_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
+       [CC1200_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
+};
+
+struct ao_cc1200_reg {
+       uint16_t        addr;
+       char            *name;
+};
+
+static const struct ao_cc1200_reg ao_cc1200_reg[] = {
+       { .addr = CC1200_IOCFG3,        .name = "IOCFG3" },
+       { .addr = CC1200_IOCFG2,        .name = "IOCFG2" },
+       { .addr = CC1200_IOCFG1,        .name = "IOCFG1" },
+       { .addr = CC1200_IOCFG0,        .name = "IOCFG0" },
+       { .addr = CC1200_SYNC3, .name = "SYNC3" },
+       { .addr = CC1200_SYNC2, .name = "SYNC2" },
+       { .addr = CC1200_SYNC1, .name = "SYNC1" },
+       { .addr = CC1200_SYNC0, .name = "SYNC0" },
+       { .addr = CC1200_SYNC_CFG1,     .name = "SYNC_CFG1" },
+       { .addr = CC1200_SYNC_CFG0,     .name = "SYNC_CFG0" },
+       { .addr = CC1200_DEVIATION_M,   .name = "DEVIATION_M" },
+       { .addr = CC1200_MODCFG_DEV_E,  .name = "MODCFG_DEV_E" },
+       { .addr = CC1200_DCFILT_CFG,    .name = "DCFILT_CFG" },
+       { .addr = CC1200_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
+       { .addr = CC1200_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
+       { .addr = CC1200_IQIC,  .name = "IQIC" },
+       { .addr = CC1200_CHAN_BW,       .name = "CHAN_BW" },
+       { .addr = CC1200_MDMCFG2,       .name = "MDMCFG2" },
+       { .addr = CC1200_MDMCFG1,       .name = "MDMCFG1" },
+       { .addr = CC1200_MDMCFG0,       .name = "MDMCFG0" },
+       { .addr = CC1200_SYMBOL_RATE2,  .name = "SYMBOL_RATE2" },
+       { .addr = CC1200_SYMBOL_RATE1,  .name = "SYMBOL_RATE1" },
+       { .addr = CC1200_SYMBOL_RATE0,  .name = "SYMBOL_RATE0" },
+       { .addr = CC1200_AGC_REF,       .name = "AGC_REF" },
+       { .addr = CC1200_AGC_CS_THR,    .name = "AGC_CS_THR" },
+       { .addr = CC1200_AGC_GAIN_ADJUST,       .name = "AGC_GAIN_ADJUST" },
+       { .addr = CC1200_AGC_CFG3,      .name = "AGC_CFG3" },
+       { .addr = CC1200_AGC_CFG2,      .name = "AGC_CFG2" },
+       { .addr = CC1200_AGC_CFG1,      .name = "AGC_CFG1" },
+       { .addr = CC1200_AGC_CFG0,      .name = "AGC_CFG0" },
+       { .addr = CC1200_FIFO_CFG,      .name = "FIFO_CFG" },
+       { .addr = CC1200_DEV_ADDR,      .name = "DEV_ADDR" },
+       { .addr = CC1200_SETTLING_CFG,  .name = "SETTLING_CFG" },
+       { .addr = CC1200_FS_CFG,        .name = "FS_CFG" },
+       { .addr = CC1200_WOR_CFG1,      .name = "WOR_CFG1" },
+       { .addr = CC1200_WOR_CFG0,      .name = "WOR_CFG0" },
+       { .addr = CC1200_WOR_EVENT0_MSB,        .name = "WOR_EVENT0_MSB" },
+       { .addr = CC1200_WOR_EVENT0_LSB,        .name = "WOR_EVENT0_LSB" },
+       { .addr = CC1200_RXDCM_TIME,            .name = "RXDCM_TIME" },
+       { .addr = CC1200_PKT_CFG2,      .name = "PKT_CFG2" },
+       { .addr = CC1200_PKT_CFG1,      .name = "PKT_CFG1" },
+       { .addr = CC1200_PKT_CFG0,      .name = "PKT_CFG0" },
+       { .addr = CC1200_RFEND_CFG1,    .name = "RFEND_CFG1" },
+       { .addr = CC1200_RFEND_CFG0,    .name = "RFEND_CFG0" },
+       { .addr = CC1200_PA_CFG1,       .name = "PA_CFG1" },
+       { .addr = CC1200_PA_CFG0,       .name = "PA_CFG0" },
+       { .addr = CC1200_PKT_LEN,       .name = "PKT_LEN" },
+       { .addr = CC1200_IF_MIX_CFG,    .name = "IF_MIX_CFG" },
+       { .addr = CC1200_FREQOFF_CFG,   .name = "FREQOFF_CFG" },
+       { .addr = CC1200_TOC_CFG,       .name = "TOC_CFG" },
+       { .addr = CC1200_MARC_SPARE,    .name = "MARC_SPARE" },
+       { .addr = CC1200_ECG_CFG,       .name = "ECG_CFG" },
+       { .addr = CC1200_EXT_CTRL,      .name = "EXT_CTRL" },
+       { .addr = CC1200_RCCAL_FINE,    .name = "RCCAL_FINE" },
+       { .addr = CC1200_RCCAL_COARSE,  .name = "RCCAL_COARSE" },
+       { .addr = CC1200_RCCAL_OFFSET,  .name = "RCCAL_OFFSET" },
+       { .addr = CC1200_FREQOFF1,      .name = "FREQOFF1" },
+       { .addr = CC1200_FREQOFF0,      .name = "FREQOFF0" },
+       { .addr = CC1200_FREQ2, .name = "FREQ2" },
+       { .addr = CC1200_FREQ1, .name = "FREQ1" },
+       { .addr = CC1200_FREQ0, .name = "FREQ0" },
+       { .addr = CC1200_IF_ADC2,       .name = "IF_ADC2" },
+       { .addr = CC1200_IF_ADC1,       .name = "IF_ADC1" },
+       { .addr = CC1200_IF_ADC0,       .name = "IF_ADC0" },
+       { .addr = CC1200_FS_DIG1,       .name = "FS_DIG1" },
+       { .addr = CC1200_FS_DIG0,       .name = "FS_DIG0" },
+       { .addr = CC1200_FS_CAL3,       .name = "FS_CAL3" },
+       { .addr = CC1200_FS_CAL2,       .name = "FS_CAL2" },
+       { .addr = CC1200_FS_CAL1,       .name = "FS_CAL1" },
+       { .addr = CC1200_FS_CAL0,       .name = "FS_CAL0" },
+       { .addr = CC1200_FS_CHP,        .name = "FS_CHP" },
+       { .addr = CC1200_FS_DIVTWO,     .name = "FS_DIVTWO" },
+       { .addr = CC1200_FS_DSM1,       .name = "FS_DSM1" },
+       { .addr = CC1200_FS_DSM0,       .name = "FS_DSM0" },
+       { .addr = CC1200_FS_DVC1,       .name = "FS_DVC1" },
+       { .addr = CC1200_FS_DVC0,       .name = "FS_DVC0" },
+       { .addr = CC1200_FS_LBI,        .name = "FS_LBI" },
+       { .addr = CC1200_FS_PFD,        .name = "FS_PFD" },
+       { .addr = CC1200_FS_PRE,        .name = "FS_PRE" },
+       { .addr = CC1200_FS_REG_DIV_CML,        .name = "FS_REG_DIV_CML" },
+       { .addr = CC1200_FS_SPARE,      .name = "FS_SPARE" },
+       { .addr = CC1200_FS_VCO4,       .name = "FS_VCO4" },
+       { .addr = CC1200_FS_VCO3,       .name = "FS_VCO3" },
+       { .addr = CC1200_FS_VCO2,       .name = "FS_VCO2" },
+       { .addr = CC1200_FS_VCO1,       .name = "FS_VCO1" },
+       { .addr = CC1200_FS_VCO0,       .name = "FS_VCO0" },
+       { .addr = CC1200_GBIAS6,        .name = "GBIAS6" },
+       { .addr = CC1200_GBIAS5,        .name = "GBIAS5" },
+       { .addr = CC1200_GBIAS4,        .name = "GBIAS4" },
+       { .addr = CC1200_GBIAS3,        .name = "GBIAS3" },
+       { .addr = CC1200_GBIAS2,        .name = "GBIAS2" },
+       { .addr = CC1200_GBIAS1,        .name = "GBIAS1" },
+       { .addr = CC1200_GBIAS0,        .name = "GBIAS0" },
+       { .addr = CC1200_IFAMP, .name = "IFAMP" },
+       { .addr = CC1200_LNA,   .name = "LNA" },
+       { .addr = CC1200_RXMIX, .name = "RXMIX" },
+       { .addr = CC1200_XOSC5, .name = "XOSC5" },
+       { .addr = CC1200_XOSC4, .name = "XOSC4" },
+       { .addr = CC1200_XOSC3, .name = "XOSC3" },
+       { .addr = CC1200_XOSC2, .name = "XOSC2" },
+       { .addr = CC1200_XOSC1, .name = "XOSC1" },
+       { .addr = CC1200_XOSC0, .name = "XOSC0" },
+       { .addr = CC1200_ANALOG_SPARE,  .name = "ANALOG_SPARE" },
+       { .addr = CC1200_PA_CFG3,       .name = "PA_CFG3" },
+       { .addr = CC1200_WOR_TIME1,     .name = "WOR_TIME1" },
+       { .addr = CC1200_WOR_TIME0,     .name = "WOR_TIME0" },
+       { .addr = CC1200_WOR_CAPTURE1,  .name = "WOR_CAPTURE1" },
+       { .addr = CC1200_WOR_CAPTURE0,  .name = "WOR_CAPTURE0" },
+       { .addr = CC1200_BIST,  .name = "BIST" },
+       { .addr = CC1200_DCFILTOFFSET_I1,       .name = "DCFILTOFFSET_I1" },
+       { .addr = CC1200_DCFILTOFFSET_I0,       .name = "DCFILTOFFSET_I0" },
+       { .addr = CC1200_DCFILTOFFSET_Q1,       .name = "DCFILTOFFSET_Q1" },
+       { .addr = CC1200_DCFILTOFFSET_Q0,       .name = "DCFILTOFFSET_Q0" },
+       { .addr = CC1200_IQIE_I1,       .name = "IQIE_I1" },
+       { .addr = CC1200_IQIE_I0,       .name = "IQIE_I0" },
+       { .addr = CC1200_IQIE_Q1,       .name = "IQIE_Q1" },
+       { .addr = CC1200_IQIE_Q0,       .name = "IQIE_Q0" },
+       { .addr = CC1200_RSSI1, .name = "RSSI1" },
+       { .addr = CC1200_RSSI0, .name = "RSSI0" },
+       { .addr = CC1200_MARCSTATE,     .name = "MARCSTATE" },
+       { .addr = CC1200_LQI_VAL,       .name = "LQI_VAL" },
+       { .addr = CC1200_PQT_SYNC_ERR,  .name = "PQT_SYNC_ERR" },
+       { .addr = CC1200_DEM_STATUS,    .name = "DEM_STATUS" },
+       { .addr = CC1200_FREQOFF_EST1,  .name = "FREQOFF_EST1" },
+       { .addr = CC1200_FREQOFF_EST0,  .name = "FREQOFF_EST0" },
+       { .addr = CC1200_AGC_GAIN3,     .name = "AGC_GAIN3" },
+       { .addr = CC1200_AGC_GAIN2,     .name = "AGC_GAIN2" },
+       { .addr = CC1200_AGC_GAIN1,     .name = "AGC_GAIN1" },
+       { .addr = CC1200_AGC_GAIN0,     .name = "AGC_GAIN0" },
+       { .addr = CC1200_SOFT_RX_DATA_OUT,      .name = "SOFT_RX_DATA_OUT" },
+       { .addr = CC1200_SOFT_TX_DATA_IN,       .name = "SOFT_TX_DATA_IN" },
+       { .addr = CC1200_ASK_SOFT_RX_DATA,      .name = "ASK_SOFT_RX_DATA" },
+       { .addr = CC1200_RNDGEN,        .name = "RNDGEN" },
+       { .addr = CC1200_MAGN2, .name = "MAGN2" },
+       { .addr = CC1200_MAGN1, .name = "MAGN1" },
+       { .addr = CC1200_MAGN0, .name = "MAGN0" },
+       { .addr = CC1200_ANG1,  .name = "ANG1" },
+       { .addr = CC1200_ANG0,  .name = "ANG0" },
+       { .addr = CC1200_CHFILT_I2,     .name = "CHFILT_I2" },
+       { .addr = CC1200_CHFILT_I1,     .name = "CHFILT_I1" },
+       { .addr = CC1200_CHFILT_I0,     .name = "CHFILT_I0" },
+       { .addr = CC1200_CHFILT_Q2,     .name = "CHFILT_Q2" },
+       { .addr = CC1200_CHFILT_Q1,     .name = "CHFILT_Q1" },
+       { .addr = CC1200_CHFILT_Q0,     .name = "CHFILT_Q0" },
+       { .addr = CC1200_GPIO_STATUS,   .name = "GPIO_STATUS" },
+       { .addr = CC1200_FSCAL_CTRL,    .name = "FSCAL_CTRL" },
+       { .addr = CC1200_PHASE_ADJUST,  .name = "PHASE_ADJUST" },
+       { .addr = CC1200_PARTNUMBER,    .name = "PARTNUMBER" },
+       { .addr = CC1200_PARTVERSION,   .name = "PARTVERSION" },
+       { .addr = CC1200_SERIAL_STATUS, .name = "SERIAL_STATUS" },
+       { .addr = CC1200_MODEM_STATUS1, .name = "MODEM_STATUS1" },
+       { .addr = CC1200_MODEM_STATUS0, .name = "MODEM_STATUS0" },
+       { .addr = CC1200_MARC_STATUS1,  .name = "MARC_STATUS1" },
+       { .addr = CC1200_MARC_STATUS0,  .name = "MARC_STATUS0" },
+       { .addr = CC1200_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
+       { .addr = CC1200_FSRF_TEST,     .name = "FSRF_TEST" },
+       { .addr = CC1200_PRE_TEST,      .name = "PRE_TEST" },
+       { .addr = CC1200_PRE_OVR,       .name = "PRE_OVR" },
+       { .addr = CC1200_ADC_TEST,      .name = "ADC_TEST" },
+       { .addr = CC1200_DVC_TEST,      .name = "DVC_TEST" },
+       { .addr = CC1200_ATEST, .name = "ATEST" },
+       { .addr = CC1200_ATEST_LVDS,    .name = "ATEST_LVDS" },
+       { .addr = CC1200_ATEST_MODE,    .name = "ATEST_MODE" },
+       { .addr = CC1200_XOSC_TEST1,    .name = "XOSC_TEST1" },
+       { .addr = CC1200_XOSC_TEST0,    .name = "XOSC_TEST0" },
+       { .addr = CC1200_RXFIRST,       .name = "RXFIRST" },
+       { .addr = CC1200_TXFIRST,       .name = "TXFIRST" },
+       { .addr = CC1200_RXLAST,        .name = "RXLAST" },
+       { .addr = CC1200_TXLAST,        .name = "TXLAST" },
+       { .addr = CC1200_NUM_TXBYTES,   .name = "NUM_TXBYTES" },
+       { .addr = CC1200_NUM_RXBYTES,   .name = "NUM_RXBYTES" },
+       { .addr = CC1200_FIFO_NUM_TXBYTES,      .name = "FIFO_NUM_TXBYTES" },
+       { .addr = CC1200_FIFO_NUM_RXBYTES,      .name = "FIFO_NUM_RXBYTES" },
+};
+
+#define AO_NUM_CC1200_REG      (sizeof ao_cc1200_reg / sizeof ao_cc1200_reg[0])
+
+static uint8_t
+ao_radio_get_marc_status(void)
+{
+       return ao_radio_reg_read(CC1200_MARC_STATUS1);
+}
+
+static void ao_radio_show(void) {
+       uint8_t status;
+       unsigned int    i;
+
+       ao_mutex_get(&ao_radio_mutex);
+       status = ao_radio_status();
+       printf ("Status:   %02x\n", status);
+       printf ("CHIP_RDY: %d\n", (status >> CC1200_STATUS_CHIP_RDY) & 1);
+       printf ("STATE:    %s\n", cc1200_state_name[(status >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK]);
+       printf ("MARC:     %02x\n", ao_radio_get_marc_status());
+
+       for (i = 0; i < AO_NUM_CC1200_REG; i++)
+               printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1200_reg[i].addr), ao_cc1200_reg[i].name);
+
+       ao_radio_put();
+}
+
+static void ao_radio_beep(void) {
+       ao_radio_rdf();
+}
+
+static void ao_radio_packet(void) {
+       static const uint8_t packet[] = {
+#if 1
+               0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+               0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+               0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+               0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+#else
+               3, 1, 2, 3
+#endif
+       };
+
+       ao_radio_send(packet, sizeof (packet));
+}
+
+void
+ao_radio_test_recv(void)
+{
+       uint8_t bytes[34];
+       uint8_t b;
+
+       if (ao_radio_recv(bytes, 34, 0)) {
+               if (bytes[33] & 0x80)
+                       printf ("CRC OK");
+               else
+                       printf ("CRC BAD");
+               printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32]));
+               for (b = 0; b < 32; b++)
+                       printf (" %02x", bytes[b]);
+
+               printf (" RSSI %02x LQI %02x", bytes[32], bytes[33]);
+               printf ("\n");
+       }
+}
+
+#if HAS_APRS
+#include <ao_aprs.h>
+
+static void
+ao_radio_aprs(void)
+{
+#if PACKET_HAS_SLAVE
+       ao_packet_slave_stop();
+#endif
+       ao_aprs_send();
+}
+#endif
+#endif
+
+#if CC1200_LOW_LEVEL_DEBUG
+static void
+ao_radio_strobe_test(void)
+{
+       uint8_t r;
+
+       ao_cmd_hex();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       r = ao_radio_strobe(ao_cmd_lex_i);
+       printf ("Strobe %02x -> %02x (rdy %d state %d)\n",
+               ao_cmd_lex_i,
+               r,
+               r >> 7,
+               (r >> 4) & 0x7);
+}
+
+static void
+ao_radio_write_test(void)
+{
+       uint16_t        addr;
+       uint8_t         data;
+
+       ao_cmd_hex();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       addr = ao_cmd_lex_i;
+       ao_cmd_hex();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       data = ao_cmd_lex_i;
+       printf ("Write %04x = %02x\n", addr, data);
+       ao_radio_reg_write(addr, data);
+}
+
+static void
+ao_radio_read_test(void)
+{
+       uint16_t        addr;
+       uint8_t         data;
+
+       ao_cmd_hex();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       addr = ao_cmd_lex_i;
+       data = ao_radio_reg_read(addr);
+       printf ("Read %04x = %02x\n", addr, data);
+}
+#endif
+
+static const struct ao_cmds ao_radio_cmds[] = {
+       { ao_radio_test_cmd,    "C <1 start, 0 stop, none both>\0Radio carrier test" },
+#if CC1200_DEBUG
+#if HAS_APRS
+       { ao_radio_aprs,        "G\0Send APRS packet" },
+#endif
+       { ao_radio_show,        "R\0Show CC1200 status" },
+       { ao_radio_beep,        "b\0Emit an RDF beacon" },
+       { ao_radio_packet,      "p\0Send a test packet" },
+       { ao_radio_test_recv,   "q\0Recv a test packet" },
+#endif
+#if CC1200_LOW_LEVEL_DEBUG
+       { ao_radio_strobe_test, "A <value>\0Strobe radio" },
+       { ao_radio_write_test,  "W <addr> <value>\0Write radio reg" },
+       { ao_radio_read_test,   "B <addr>\0Read radio reg" },
+#endif
+       { 0, NULL }
+};
+
+void
+ao_radio_init(void)
+{
+       ao_radio_configured = 0;
+       ao_spi_init_cs (AO_CC1200_SPI_CS_PORT, (1 << AO_CC1200_SPI_CS_PIN));
+
+#if 0
+       AO_CC1200_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1200_SPI_CS_PIN));
+       for (i = 0; i < 10000; i++) {
+               if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0)
+                       break;
+       }
+       AO_CC1200_SPI_CS_PORT->bsrr = (1 << AO_CC1200_SPI_CS_PIN);
+       if (i == 10000)
+               ao_panic(AO_PANIC_SELF_TEST_CC1200);
+#endif
+
+       /* Enable the EXTI interrupt for the appropriate pin */
+       ao_enable_port(AO_CC1200_INT_PORT);
+       ao_exti_setup(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN,
+                     AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
+                     ao_radio_isr);
+
+       ao_cmd_register(&ao_radio_cmds[0]);
+}
diff --git a/src/drivers/ao_cc1200.h b/src/drivers/ao_cc1200.h
new file mode 100644 (file)
index 0000000..b04775f
--- /dev/null
@@ -0,0 +1,632 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_CC1200_H_
+#define _AO_CC1200_H_
+
+#define CC1200_READ    (7)
+#define CC1200_BURST   (6)
+
+/* Register space */
+#define CC1200_IOCFG3          0x00
+#define  CC1200_IOCFG_GPIO_ATRAN       7
+#define  CC1200_IOCFG_GPIO_INV         6
+#define  CC1200_IOCFG_GPIO_CFG         0
+#define  CC1200_IOCFG_GPIO_CFG_RXFIFO_THR      0
+#define  CC1200_IOCFG_GPIO_CFG_RXFIFO_THR_PKT  1
+#define  CC1200_IOCFG_GPIO_CFG_TXFIFO_THR      2
+#define  CC1200_IOCFG_GPIO_CFG_TXFIFO_THR_PKT  3
+#define  CC1200_IOCFG_GPIO_CFG_RXFIFO_OVERFLOW 4
+#define  CC1200_IOCFG_GPIO_CFG_TXFIFO_UNDERFLOW        5
+#define  CC1200_IOCFG_GPIO_CFG_PKT_SYNC_RXTX   6
+#define  CC1200_IOCFG_GPIO_CFG_CRC_OK          7
+#define  CC1200_IOCFG_GPIO_CFG_SERIAL_CLK      8
+#define  CC1200_IOCFG_GPIO_CFG_SERIAL_RX       9
+#define  CC1200_IOCFG_GPIO_CFG_PQT_REACHED     11
+#define  CC1200_IOCFG_GPIO_CFG_PQT_VALID       12
+#define  CC1200_IOCFG_GPIO_CFG_RSSI_VALID      13
+#define  CC1200_IOCFG_GPIO3_CFG_RSSI_UPDATE    14
+#define  CC1200_IOCFG_GPIO2_CFG_RSSI_UPDATE    14
+#define  CC1200_IOCFG_GPIO1_CFG_AGC_HOLD       14
+#define  CC1200_IOCFG_GPIO0_CFG_AGC_UPDATE     14
+#define  CC1200_IOCFG_GPIO3_CFG_CGA_STATUS     15
+#define  CC1200_IOCFG_GPIO2_CFG_TXONCCA_DONE   15
+#define  CC1200_IOCFG_GPIO1_CFG_CCA_STATUS     15
+#define  CC1200_IOCFG_GPIO0_CFG_TXONCCA_FAILED 15
+#define  CC1200_IOCFG_GPIO_CFG_CARRIER_SENSE_VALID     16
+#define  CC1200_IOCFG_GPIO_CFG_CARRIER_SENSE   17
+#define  CC1200_IOCFG_GPIO3_CFG_DSSS_CLK       18
+#define  CC1200_IOCFG_GPIO2_CFG_DSSS_DATA0     18
+#define  CC1200_IOCFG_GPIO1_CFG_DSSS_CLK       18
+#define  CC1200_IOCFG_GPIO0_CFG_DSSS_DATA1     18
+#define  CC1200_IOCFG_GPIO_CFG_PKT_CRC_OK      19
+#define  CC1200_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP 20
+#define  CC1200_IOCFG_GPIO_CFG_SYNC_LOW0_HIGH1 21
+#define  CC1200_IOCFG_GPIO_CFG_LNA_PA_REG_PD   23
+#define  CC1200_IOCFG_GPIO_CFG_LNA_PD          24
+#define  CC1200_IOCFG_GPIO_CFG_PA_RD           25
+#define  CC1200_IOCFG_GPIO_CFG_RX0TX1_CFG      26
+#define  CC1200_IOCFG_GPIO_CFG_IMAGE_FOUND     28
+#define  CC1200_IOCFG_GPIO_CFG_CLKEN_SOFT      29
+#define  CC1200_IOCFG_GPIO_CFG_SOFT_TX_DATA_CLK        30
+#define  CC1200_IOCFG_GPIO_CFG_RSSI_STEP_FOUND 33
+#define  CC1200_IOCFG_GPIO_CFG_RSSI_STEP_EVENT 34
+#define  CC1200_IOCFG_GPIO_CFG_ANTENNA_SELECT  36
+#define  CC1200_IOCFG_GPIO_CFG_MARC_2PIN_STATUS1       37
+#define  CC1200_IOCFG_GPIO_CFG_MARC_2PIN_STATUS0       38
+#define  CC1200_IOCFG_GPIO2_CFG_TXFIFO_OVERFLOW                39
+#define  CC1200_IOCFG_GPIO0_CFG_RXFIFO_UNDERFLOW       39
+#define  CC1200_IOCFG_GPIO3_CFG_MAGN_VALID     40
+#define  CC1200_IOCFG_GPIO2_CFG_CHFILT_VALID   40
+#define  CC1200_IOCFG_GPIO1_CFG_RCC_CAL_VALID  40
+#define  CC1200_IOCFG_GPIO0_CFG_CHFILTER_STARTUP_VALID 40
+#define  CC1200_IOCFG_GPIO3_CFG_COLLISION_FOUND                41
+#define  CC1200_IOCFG_GPIO2_CFG_SYNC_EVENT             41
+#define  CC1200_IOCFG_GPIO1_CFG_COLLISION_FOUND                41
+#define  CC1200_IOCFG_GPIO0_CFG_COLLISION_EVENT                41
+#define  CC1200_IOCFG_GPIO_CFG_PA_RAMP_UP              42
+#define  CC1200_IOCFG_GPIO3_CFG_CRC_FAILED             43
+#define  CC1200_IOCFG_GPIO2_CFG_LENGTH_FAILED          43
+#define  CC1200_IOCFG_GPIO1_CFG_ADDR_FAILED            43
+#define  CC1200_IOCFG_GPIO0_CFG_UART_FRAMING_ERROR     43
+#define  CC1200_IOCFG_GPIO_CFG_AGC_STABLE_GAIN         44
+#define  CC1200_IOCFG_GPIO_CFG_AGC_UPDATE              45
+#define  CC1200_IOCFG_GPIO3_CFG_ADC_CLOCK              46
+#define  CC1200_IOCFG_GPIO2_CFG_ADC_Q_DATA_SAMPLE      46
+#define  CC1200_IOCFG_GPIO1_CFG_ADC_CLOCK              46
+#define  CC1200_IOCFG_GPIO0_CFG_ADC_I_DATA_SAMPLE      46
+#define  CC1200_IOCFG_GPIO_CFG_HIGHZ                   48
+#define  CC1200_IOCFG_GPIO_CFG_EXT_CLOCK               49
+#define  CC1200_IOCFG_GPIO_CFG_CHIP_RDY                        50
+#define  CC1200_IOCFG_GPIO_CFG_HW0                     51
+#define  CC1200_IOCFG_GPIO_CFG_CLOCK_32K               54
+#define  CC1200_IOCFG_GPIO_CFG_WOR_EVENT0              55
+#define  CC1200_IOCFG_GPIO_CFG_WOR_EVENT1              56
+#define  CC1200_IOCFG_GPIO_CFG_WOR_EVENT2              57
+#define  CC1200_IOCFG_GPIO_CFG_XOSC_STABLE             59
+#define  CC1200_IOCFG_GPIO_CFG_EXT_OSC_EN              60
+#define  CC1200_IOCFG_GPIO_CFG_MASK    0x3f
+
+#define CC1200_IOCFG2          0x01
+#define CC1200_IOCFG1          0x02
+#define CC1200_IOCFG0          0x03
+#define CC1200_SYNC3           0x04
+#define CC1200_SYNC2           0x05
+#define CC1200_SYNC1           0x06
+#define CC1200_SYNC0           0x07
+
+#define CC1200_SYNC_CFG1       0x08
+
+#define  CC1200_SYNC_CFG1_SYNC_MODE    5
+#define  CC1200_SYNC_CFG1_SYNC_MODE_NONE               0
+#define  CC1200_SYNC_CFG1_SYNC_MODE_11_BITS            1
+#define  CC1200_SYNC_CFG1_SYNC_MODE_16_BITS            2
+#define  CC1200_SYNC_CFG1_SYNC_MODE_18_BITS            3
+#define  CC1200_SYNC_CFG1_SYNC_MODE_24_BITS            4
+#define  CC1200_SYNC_CFG1_SYNC_MODE_32_BITS            5
+#define  CC1200_SYNC_CFG1_SYNC_MODE_16H_BITS           6
+#define  CC1200_SYNC_CFG1_SYNC_MODE_16D_BITS           7
+#define  CC1200_SYNC_CFG1_SYNC_MODE_MASK               7
+
+#define  CC1200_SYNC_CFG1_SYNC_THR     0
+#define  CC1200_SYNC_CFG1_SYNC_MASK                    0x1f
+
+#define CC1200_SYNC_CFG0       0x09
+#define  CC1200_SYNC_CFG0_AUTO_CLEAR           5
+#define  CC1200_SYNC_CFG0_RX_CONFIG_LIMITATION 4
+#define  CC1200_SYNC_CFG0_PQT_GATING_EN                3
+#define  CC1200_SYNC_CFG0_EXT_SYNC_DETECT      2
+
+#define  CC1200_SYNC_CFG0_SYNC_STRICT_SYNC_CHECK       0
+#define  CC1200_SYNC_CFG0_SYNC_STRICT_SYNC_CHECK_LEVEL_1       0
+#define  CC1200_SYNC_CFG0_SYNC_STRICT_SYNC_CHECK_LEVEL_2       1
+#define  CC1200_SYNC_CFG0_SYNC_STRICT_SYNC_CHECK_LEVEL_3       2
+#define  CC1200_SYNC_CFG0_SYNC_STRICT_SYNC_CHECK_DISABLED      3
+#define  CC1200_SYNC_CFG0_SYNC_STRICT_SYNC_CHECK_MASK          3
+
+#define CC1200_DEVIATION_M     0x0a
+#define CC1200_MODCFG_DEV_E    0x0b
+#define  CC1200_MODCFG_DEV_E_MODEM_MODE                6
+#define  CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL         0
+#define  CC1200_MODCFG_DEV_E_MODEM_MODE_DSSS_REPEAT    1
+#define  CC1200_MODCFG_DEV_E_MODEM_MODE_DSSS_PN                2
+#define  CC1200_MODCFG_DEV_E_MODEM_MODE_CARRIER_SENSE  3
+#define  CC1200_MODCFG_DEV_E_MODEM_MODE_MASK           3
+#define  CC1200_MODCFG_DEV_E_MOD_FORMAT                3
+#define  CC1200_MODCFG_DEV_E_MOD_FORMAT_2_FSK          0
+#define  CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK         1
+#define  CC1200_MODCFG_DEV_E_MOD_FORMAT_ASK_OOK                3
+#define  CC1200_MODCFG_DEV_E_MOD_FORMAT_4_FSK          4
+#define  CC1200_MODCFG_DEV_E_MOD_FORMAT_4_GFSK         5
+#define  CC1200_MODCFG_DEV_E_MOD_FORMAT_MASK           7
+#define  CC1200_MODCFG_DEV_E_DEV_E             0
+#define  CC1200_MODCFG_DEV_E_DEV_E_MASK                7
+
+#define CC1200_DCFILT_CFG      0x0c
+#define CC1200_PREAMBLE_CFG1   0x0d
+#define  CC1200_PREAMBLE_CFG1_NUM_PREAMBLE     2
+#define  CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE                0
+#define  CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_0_5_BYTE    1
+#define  CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_1_BYTE      2
+#define  CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_1_5_BYTE    3
+#define  CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_2_BYTES     4
+#define  CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_3_BYTES     5
+#define  CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES     6
+#define  CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_5_BYTES     7
+#define  CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_6_BYTES     8
+#define  CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_7_BYTES     9
+#define  CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_8_BYTES     10
+#define  CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_12_BYTES    11
+#define  CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_24_BYTES    12
+#define  CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_30_BYTES    13
+#define  CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_MASK                0xf
+
+#define  CC1200_PREAMBLE_CFG1_PREAMBLE_WORD    0
+#define  CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA         0
+#define  CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_55         1
+#define  CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_33         2
+#define  CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_CC         3
+#define  CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_MASK       3
+
+#define CC1200_PREAMBLE_CFG0   0x0e
+#define  CC1200_PREAMBLE_CFG0_PQT_EN           7
+#define  CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT        4
+#define  CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_11     0
+#define  CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_12     1
+#define  CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_13     2
+#define  CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_15     3
+#define  CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_16     4
+#define  CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_17     5
+#define  CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_24     6
+#define  CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_32     7
+#define  CC1200_PREAMBLE_CFG0_PQT              0
+#define  CC1200_PREAMBLE_CFG0_PQT_MASK                 0xf
+
+#define CC1200_IQIC            0x0f
+#define CC1200_CHAN_BW         0x10
+#define  CC1200_CHAN_BW_ADC_CIC_DECFACT                6
+#define  CC1200_CHAN_BW_ADC_CIC_DECFACT_12             0
+#define  CC1200_CHAN_BW_ADC_CIC_DECFACT_24             1
+#define  CC1200_CHAN_BW_ADC_CIC_DECFACT_48             2
+#define  CC1200_CHAN_BW_BB_CIC_DECFACT         0
+
+#define CC1200_MDMCFG1         0x11
+#define  CC1200_MDMCFG1_CARRIER_SENSE_GATE     7
+#define  CC1200_MDMCFG1_FIFO_EN                        6
+#define  CC1200_MDMCFG1_MANCHESTER_EN          5
+#define  CC1200_MDMCFG1_INVERT_DATA_EN         4
+#define  CC1200_MDMCFG1_COLLISION_DETECT_EN    3
+#define  CC1200_MDMCFG1_DVGA_GAIN              1
+#define  CC1200_MDMCFG1_DVGA_GAIN_0                    0
+#define  CC1200_MDMCFG1_DVGA_GAIN_3                    1
+#define  CC1200_MDMCFG1_DVGA_GAIN_6                    2
+#define  CC1200_MDMCFG1_DVGA_GAIN_9                    3
+#define  CC1200_MDMCFG1_DVGA_GAIN_MASK                 3
+#define  CC1200_MDMCFG1_SINGLE_ADC_EN          0
+
+#define CC1200_MDMCFG0         0x12
+#define  CC1200_MDMCFG0_TRANSPARENT_MODE_EN    6
+#define  CC1200_MDMCFG0_TRANSPARENT_INTFACT    4
+#define  CC1200_MDMCFG0_DATA_FILTER_EN         3
+#define  CC1200_MDMCFG0_VITERBI_EN             2
+
+#define CC1200_SYMBOL_RATE2    0x13
+#define  CC1200_SYMBOL_RATE2_DATARATE_E                        4
+#define  CC1200_SYMBOL_RATE2_DATARATE_E_MASK           0xf
+#define  CC1200_SYMBOL_RATE2_DATARATE_M_19_16          0
+#define  CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK     0xf
+
+#define CC1200_SYMBOL_RATE1    0x14
+#define CC1200_SYMBOL_RATE0    0x15
+#define CC1200_AGC_REF         0x16
+#define CC1200_AGC_CS_THR      0x17
+#define CC1200_AGC_GAIN_ADJUST 0x18
+
+#define CC1200_AGC_CFG3                0x19
+#define  CC1200_AGC_CFG3_RSSI_STEP_THR         7
+#define  CC1200_AGC_CFG3_AGC_MIN_GAIN          0
+#define  CC1200_AGC_CFG3_AGC_MIN_GAIN_MASK     0x1f
+
+#define CC1200_AGC_CFG2                0x1a
+#define  CC1200_AGC_CFG2_START_PREVIOUS_GAIN_EN        7
+#define  CC1200_AGC_CFG2_FE_PERFORMANCE_MODE   5
+#define  CC1200_AGC_CFG2_FE_PERFORMANCE_MODE_OPTIMIZE_LINEARITY        0
+#define  CC1200_AGC_CFG2_FE_PERFORMANCE_MODE_NORMAL            1
+#define  CC1200_AGC_CFG2_FE_PERFORMANCE_MODE_LOW_POWER         2
+#define  CC1200_AGC_CFG2_FE_PERFORMANCE_MODE_MASK              3
+#define  CC1200_AGC_CFG2_AGC_MAX_GAIN          0
+#define  CC1200_AGC_CFG2_AGC_MAX_MASK          0x1f
+
+#define CC1200_AGC_CFG1                0x1b
+#define  CC1200_AGC_CFG1_RSSI_STEP_THR         6
+#define  CC1200_AGC_CFG1_AGC_WIN_SIZE          3
+#define  CC1200_AGC_CFG1_AGC_WIN_SIZE_8                        0
+#define  CC1200_AGC_CFG1_AGC_WIN_SIZE_16               1
+#define  CC1200_AGC_CFG1_AGC_WIN_SIZE_32               2
+#define  CC1200_AGC_CFG1_AGC_WIN_SIZE_64               3
+#define  CC1200_AGC_CFG1_AGC_WIN_SIZE_128              4
+#define  CC1200_AGC_CFG1_AGC_WIN_SIZE_256              5
+#define  CC1200_AGC_CFG1_AGC_WIN_SIZE_MASK             7
+#define  CC1200_AGC_CFG1_AGC_SETTLE_WAIT       0
+#define  CC1200_AGC_CFG1_AGC_SETTLE_WAIT_24            0
+#define  CC1200_AGC_CFG1_AGC_SETTLE_WAIT_32            1
+#define  CC1200_AGC_CFG1_AGC_SETTLE_WAIT_40            2
+#define  CC1200_AGC_CFG1_AGC_SETTLE_WAIT_48            3
+#define  CC1200_AGC_CFG1_AGC_SETTLE_WAIT_64            4
+#define  CC1200_AGC_CFG1_AGC_SETTLE_WAIT_80            5
+#define  CC1200_AGC_CFG1_AGC_SETTLE_WAIT_96            6
+#define  CC1200_AGC_CFG1_AGC_SETTLE_WAIT_127           7
+
+#define CC1200_AGC_CFG0                0x1c
+
+#define  CC1200_AGC_CFG0_AGC_HYST_LEVEL                6
+#define   CC1200_AGC_CFG0_AGC_HYST_LEVEL_2             0
+#define   CC1200_AGC_CFG0_AGC_HYST_LEVEL_4             1
+#define   CC1200_AGC_CFG0_AGC_HYST_LEVEL_7             2
+#define   CC1200_AGC_CFG0_AGC_HYST_LEVEL_10            3
+
+#define  CC1200_AGC_CFG0_AGC_SLEWRATE_LIMIT    4
+#define   CC1200_AGC_CFG0_AGC_SLEWRATE_LIMIT_60                0
+#define   CC1200_AGC_CFG0_AGC_SLEWRATE_LIMIT_30                1
+#define   CC1200_AGC_CFG0_AGC_SLEWRATE_LIMIT_18                2
+#define   CC1200_AGC_CFG0_AGC_SLEWRATE_LIMIT_9         3
+
+#define  CC1200_AGC_CFG0_RSSI_VALID_CNT                2
+#define   CC1200_AGC_CFG0_RSSI_VALID_CNT_2             0
+#define   CC1200_AGC_CFG0_RSSI_VALID_CNT_3             1
+#define   CC1200_AGC_CFG0_RSSI_VALID_CNT_5             2
+#define   CC1200_AGC_CFG0_RSSI_VALID_CNT_9             3
+
+#define  CC1200_AGC_CFG0_AGC_ASK_DECAY         0
+#define   CC1200_AGC_CFG0_AGC_ASK_DECAY_1200           0
+#define   CC1200_AGC_CFG0_AGC_ASK_DECAY_2400           1
+#define   CC1200_AGC_CFG0_AGC_ASK_DECAY_4700           2
+#define   CC1200_AGC_CFG0_AGC_ASK_DECAY_9500           3
+
+#define CC1200_FIFO_CFG                0x1d
+#define  CC1200_FIFO_CFG_CRC_AUTOFLUSH         7
+#define  CC1200_FIFO_CFG_FIFO_THR              0
+
+#define CC1200_DEV_ADDR                0x1e
+#define CC1200_SETTLING_CFG    0x1f
+#define  CC1200_SETTLING_CFG_FS_AUTOCAL                3
+#define  CC1200_SETTLING_CFG_FS_AUTOCAL_NEVER          0
+#define  CC1200_SETTLING_CFG_FS_AUTOCAL_IDLE_TO_ON     1
+#define  CC1200_SETTLING_CFG_FS_AUTOCAL_ON_TO_IDLE     2
+#define  CC1200_SETTLING_CFG_FS_AUTOCAL_EVERY_4TH_TIME 3
+#define  CC1200_SETTLING_CFG_FS_AUTOCAL_MASK           3
+#define  CC1200_SETTLING_CFG_LOCK_TIME         1
+#define  CC1200_SETTLING_CFG_LOCK_TIME_50_20           0
+#define  CC1200_SETTLING_CFG_LOCK_TIME_75_30           1
+#define  CC1200_SETTLING_CFG_LOCK_TIME_100_40          2
+#define  CC1200_SETTLING_CFG_LOCK_TIME_150_60          3
+#define  CC1200_SETTLING_CFG_LOCK_TIME_MASK            3
+#define  CC1200_SETTLING_CFG_FSREG_TIME                0
+#define  CC1200_SETTLING_CFG_FSREG_TIME_30             0
+#define  CC1200_SETTLING_CFG_FSREG_TIME_60             1
+#define  CC1200_SETTLING_CFG_FSREG_TIME_MASK           1
+
+#define CC1200_FS_CFG          0x20
+#define  CC1200_FS_CFG_LOCK_EN                 4
+#define  CC1200_FS_CFG_FSD_BANDSELECT          0
+#define  CC1200_FS_CFG_FSD_BANDSELECT_820_960          2
+#define  CC1200_FS_CFG_FSD_BANDSELECT_410_480          4
+#define  CC1200_FS_CFG_FSD_BANDSELECT_273_320          6
+#define  CC1200_FS_CFG_FSD_BANDSELECT_205_240          8
+#define  CC1200_FS_CFG_FSD_BANDSELECT_164_192          10
+#define  CC1200_FS_CFG_FSD_BANDSELECT_136_160          11
+#define  CC1200_FS_CFG_FSD_BANDSELECT_MASK             0xf
+
+#define CC1200_WOR_CFG1                0x21
+#define CC1200_WOR_CFG0                0x22
+#define CC1200_WOR_EVENT0_MSB  0x23
+#define CC1200_WOR_EVENT0_LSB  0x24
+#define CC1200_RXDCM_TIME      0x25
+#define CC1200_PKT_CFG2                0x26
+#define  CC1200_PKT_CFG2_BYTE_SWAP_EN  6
+#define  CC1200_PKT_CFG2_FG_MODE_EN    5
+#define  CC1200_PKT_CFG2_CCA_MODE      2
+#define  CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR         0
+#define  CC1200_PKT_CFG2_CCA_MODE_RSSI_THRESHOLD       1
+#define  CC1200_PKT_CFG2_CCA_MODE_NOT_RECEIVING                2
+#define  CC1200_PKT_CFG2_CCA_MODE_RSSI_OR_NOT          3
+#define  CC1200_PKT_CFG2_CCA_MODE_RSSI_AND_ETSI_LBT    4
+#define  CC1200_PKT_CFG2_CCA_MODE_MASK                 7
+#define  CC1200_PKT_CFG2_PKT_FORMAT    0
+#define  CC1200_PKT_CFG2_PKT_FORMAT_NORMAL             0
+#define  CC1200_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL 1
+#define  CC1200_PKT_CFG2_PKT_FORMAT_RANDOM             2
+#define  CC1200_PKT_CFG2_PKT_FORMAT_TRANSPARENT_SERIAL 3
+#define  CC1200_PKT_CFG2_PKT_FORMAT_MASK               3
+
+#define CC1200_PKT_CFG1                0x27
+#define  CC1200_PKT_CFG1_FEC_EN                7
+#define  CC1200_PKT_CFG1_WHITE_DATA    6
+#define  CC1200_PKT_CFG1_PN9_SWAP_EN   5
+#define  CC1200_PKT_CFG1_ADDR_CHECK_CFG        3
+#define  CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE           0
+#define  CC1200_PKT_CFG1_ADDR_CHECK_CFG_CHECK          1
+#define  CC1200_PKT_CFG1_ADDR_CHECK_CFG_00_BROADCAST   2
+#define  CC1200_PKT_CFG1_ADDR_CHECK_CFG_00_FF_BROADCAST        3
+#define  CC1200_PKT_CFG1_ADDR_CHECK_CFG_MASK           3
+#define  CC1200_PKT_CFG1_CRC_CFG       1
+#define  CC1200_PKT_CFG1_CRC_CFG_DISABLED              0
+#define  CC1200_PKT_CFG1_CRC_CFG_CRC16_INIT_ONES       1
+#define  CC1200_PKT_CFG1_CRC_CFG_CRC16_INIT_ZEROS      2
+#define  CC1200_PKT_CFG1_CRC_CFG_MASK                  3
+#define  CC1200_PKT_CFG1_APPEND_STATUS 0
+
+#define CC1200_PKT_CFG0                0x28
+#define  CC1200_PKT_CFG0_RESERVED7     7
+#define  CC1200_PKT_CFG0_LENGTH_CONFIG 5
+#define  CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED           0
+#define  CC1200_PKT_CFG0_LENGTH_CONFIG_VARIABLE                1
+#define  CC1200_PKT_CFG0_LENGTH_CONFIG_INFINITE                2
+#define  CC1200_PKT_CFG0_LENGTH_CONFIG_VARIABLE_5LSB   3
+#define  CC1200_PKT_CFG0_LENGTH_CONFIG_MASK            3
+#define  CC1200_PKT_CFG0_PKG_BIT_LEN   2
+#define  CC1200_PKT_CFG0_PKG_BIT_LEN_MASK      7
+#define  CC1200_PKT_CFG0_UART_MODE_EN  1
+#define  CC1200_PKT_CFG0_UART_SWAP_EN  0
+
+#define CC1200_RFEND_CFG1      0x29
+#define  CC1200_RFEND_CFG1_RXOFF_MODE  4
+#define  CC1200_RFEND_CFG1_RXOFF_MODE_IDLE     0
+#define  CC1200_RFEND_CFG1_RXOFF_MODE_FSTXON   1
+#define  CC1200_RFEND_CFG1_RXOFF_MODE_TX       2
+#define  CC1200_RFEND_CFG1_RXOFF_MODE_RX       3
+#define  CC1200_RFEND_CFG1_RX_TIME     1
+#define  CC1200_RFEND_CFG1_RX_TIME_INFINITE    7
+#define  CC1200_RFEND_CFG1_RX_TIME_QUAL        0
+#define CC1200_RFEND_CFG0      0x2a
+#define  CC1200_RFEND_CFG0_CAL_END_WAKE_UP_EN  6
+#define  CC1200_RFEND_CFG0_TXOFF_MODE          4
+#define  CC1200_RFEND_CFG0_TXOFF_MODE_IDLE     0
+#define  CC1200_RFEND_CFG0_TXOFF_MODE_FSTXON   1
+#define  CC1200_RFEND_CFG0_TXOFF_MODE_TX       2
+#define  CC1200_RFEND_CFG0_TXOFF_MODE_RX       3
+#define  CC1200_RFEND_CFG0_TERM_ON_BAD_PACKET_EN 3
+#define  CC1200_RFEND_CFG0_ANT_DIV_RX_TERM_CFG 0
+#define CC1200_PA_CFG1         0x2b
+#define CC1200_PA_CFG0         0x2c
+#define CC1200_ASK_CFG         0x2d
+#define CC1200_PKT_LEN         0x2e
+
+#define CC1200_EXTENDED                0x2f
+
+/* Command strobes */
+#define CC1200_SRES            0x30
+#define CC1200_SFSTXON         0x31
+#define CC1200_SXOFF           0x32
+#define CC1200_SCAL            0x33
+#define CC1200_SRX             0x34
+#define CC1200_STX             0x35
+#define CC1200_SIDLE           0x36
+#define CC1200_SAFC            0x37
+#define CC1200_SWOR            0x38
+#define CC1200_SPWD            0x39
+#define CC1200_SFRX            0x3a
+#define CC1200_SFTX            0x3b
+#define CC1200_SWORRST         0x3c
+#define CC1200_SNOP            0x3d
+
+#define CC1200_DIRECT_FIFO     0x3e
+#define CC1200_FIFO            0x3f
+
+#define CC1200_FIFO_SIZE       128
+
+/* Extended register space */
+
+#define CC1200_EXTENDED_BIT    0x8000
+
+#define CC1200_IS_EXTENDED(r)  ((r) & CC1200_EXTENDED_BIT)
+
+#define CC1200_IF_MIX_CFG      (CC1200_EXTENDED_BIT | 0x00)
+#define CC1200_FREQOFF_CFG     (CC1200_EXTENDED_BIT | 0x01)
+#define CC1200_TOC_CFG         (CC1200_EXTENDED_BIT | 0x02)
+#define CC1200_MARC_SPARE      (CC1200_EXTENDED_BIT | 0x03)
+#define CC1200_ECG_CFG         (CC1200_EXTENDED_BIT | 0x04)
+#define CC1200_MDMCFG2         (CC1200_EXTENDED_BIT | 0x05)
+
+#define  CC1200_MDMCFG2_ASK_SHAPE      6
+#define  CC1200_MDMCFG2_ASK_SHAPE_8            0
+#define  CC1200_MDMCFG2_ASK_SHAPE_16           1
+#define  CC1200_MDMCFG2_ASK_SHAPE_32           2
+#define  CC1200_MDMCFG2_ASK_SHAPE_128          3
+#define  CC1200_MDMCFG2_SYMBOL_MAP_CFG 4
+#define  CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0  0
+#define  CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_1  1
+#define  CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_2  2
+#define  CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_3  3
+#define  CC1200_MDMCFG2_UPSAMPLER_P    1
+#define  CC1200_MDMCFG2_UPSAMPLER_P_1          0
+#define  CC1200_MDMCFG2_UPSAMPLER_P_2          1
+#define  CC1200_MDMCFG2_UPSAMPLER_P_4          2
+#define  CC1200_MDMCFG2_UPSAMPLER_P_8          3
+#define  CC1200_MDMCFG2_UPSAMPLER_P_16         4
+#define  CC1200_MDMCFG2_UPSAMPLER_P_32         5
+#define  CC1200_MDMCFG2_UPSAMPLER_P_64         6
+#define  CC1200_MDMCFG2_CFM_DATA_EN    0
+
+#define CC1200_EXT_CTRL                (CC1200_EXTENDED_BIT | 0x06)
+#define CC1200_RCCAL_FINE      (CC1200_EXTENDED_BIT | 0x07)
+#define CC1200_RCCAL_COARSE    (CC1200_EXTENDED_BIT | 0x08)
+#define CC1200_RCCAL_OFFSET    (CC1200_EXTENDED_BIT | 0x09)
+#define CC1200_FREQOFF1                (CC1200_EXTENDED_BIT | 0x0A)
+#define CC1200_FREQOFF0                (CC1200_EXTENDED_BIT | 0x0B)
+#define CC1200_FREQ2           (CC1200_EXTENDED_BIT | 0x0C)
+#define CC1200_FREQ1           (CC1200_EXTENDED_BIT | 0x0D)
+#define CC1200_FREQ0           (CC1200_EXTENDED_BIT | 0x0E)
+#define CC1200_IF_ADC2         (CC1200_EXTENDED_BIT | 0x0F)
+#define CC1200_IF_ADC1         (CC1200_EXTENDED_BIT | 0x10)
+#define CC1200_IF_ADC0         (CC1200_EXTENDED_BIT | 0x11)
+#define CC1200_FS_DIG1         (CC1200_EXTENDED_BIT | 0x12)
+#define CC1200_FS_DIG0         (CC1200_EXTENDED_BIT | 0x13)
+#define CC1200_FS_CAL3         (CC1200_EXTENDED_BIT | 0x14)
+#define CC1200_FS_CAL2         (CC1200_EXTENDED_BIT | 0x15)
+#define CC1200_FS_CAL1         (CC1200_EXTENDED_BIT | 0x16)
+#define CC1200_FS_CAL0         (CC1200_EXTENDED_BIT | 0x17)
+#define CC1200_FS_CHP          (CC1200_EXTENDED_BIT | 0x18)
+#define CC1200_FS_DIVTWO       (CC1200_EXTENDED_BIT | 0x19)
+#define CC1200_FS_DSM1         (CC1200_EXTENDED_BIT | 0x1A)
+#define CC1200_FS_DSM0         (CC1200_EXTENDED_BIT | 0x1B)
+#define CC1200_FS_DVC1         (CC1200_EXTENDED_BIT | 0x1C)
+#define CC1200_FS_DVC0         (CC1200_EXTENDED_BIT | 0x1D)
+#define CC1200_FS_LBI          (CC1200_EXTENDED_BIT | 0x1E)
+#define CC1200_FS_PFD          (CC1200_EXTENDED_BIT | 0x1F)
+#define CC1200_FS_PRE          (CC1200_EXTENDED_BIT | 0x20)
+#define CC1200_FS_REG_DIV_CML  (CC1200_EXTENDED_BIT | 0x21)
+#define CC1200_FS_SPARE                (CC1200_EXTENDED_BIT | 0x22)
+#define CC1200_FS_VCO4         (CC1200_EXTENDED_BIT | 0x23)
+#define CC1200_FS_VCO3         (CC1200_EXTENDED_BIT | 0x24)
+#define CC1200_FS_VCO2         (CC1200_EXTENDED_BIT | 0x25)
+#define CC1200_FS_VCO1         (CC1200_EXTENDED_BIT | 0x26)
+#define CC1200_FS_VCO0         (CC1200_EXTENDED_BIT | 0x27)
+#define CC1200_GBIAS6          (CC1200_EXTENDED_BIT | 0x28)
+#define CC1200_GBIAS5          (CC1200_EXTENDED_BIT | 0x29)
+#define CC1200_GBIAS4          (CC1200_EXTENDED_BIT | 0x2A)
+#define CC1200_GBIAS3          (CC1200_EXTENDED_BIT | 0x2B)
+#define CC1200_GBIAS2          (CC1200_EXTENDED_BIT | 0x2C)
+#define CC1200_GBIAS1          (CC1200_EXTENDED_BIT | 0x2D)
+#define CC1200_GBIAS0          (CC1200_EXTENDED_BIT | 0x2E)
+#define CC1200_IFAMP           (CC1200_EXTENDED_BIT | 0x2F)
+#define CC1200_LNA             (CC1200_EXTENDED_BIT | 0x30)
+#define CC1200_RXMIX           (CC1200_EXTENDED_BIT | 0x31)
+#define CC1200_XOSC5           (CC1200_EXTENDED_BIT | 0x32)
+#define CC1200_XOSC4           (CC1200_EXTENDED_BIT | 0x33)
+#define CC1200_XOSC3           (CC1200_EXTENDED_BIT | 0x34)
+#define CC1200_XOSC2           (CC1200_EXTENDED_BIT | 0x35)
+#define CC1200_XOSC1           (CC1200_EXTENDED_BIT | 0x36)
+#define CC1200_XOSC0           (CC1200_EXTENDED_BIT | 0x37)
+#define CC1200_ANALOG_SPARE    (CC1200_EXTENDED_BIT | 0x38)
+#define CC1200_PA_CFG3         (CC1200_EXTENDED_BIT | 0x39)
+#define CC1200_WOR_TIME1       (CC1200_EXTENDED_BIT | 0x64)
+#define CC1200_WOR_TIME0       (CC1200_EXTENDED_BIT | 0x65)
+#define CC1200_WOR_CAPTURE1    (CC1200_EXTENDED_BIT | 0x66)
+#define CC1200_WOR_CAPTURE0    (CC1200_EXTENDED_BIT | 0x67)
+#define CC1200_BIST            (CC1200_EXTENDED_BIT | 0x68)
+#define CC1200_DCFILTOFFSET_I1 (CC1200_EXTENDED_BIT | 0x69)
+#define CC1200_DCFILTOFFSET_I0 (CC1200_EXTENDED_BIT | 0x6A)
+#define CC1200_DCFILTOFFSET_Q1 (CC1200_EXTENDED_BIT | 0x6B)
+#define CC1200_DCFILTOFFSET_Q0 (CC1200_EXTENDED_BIT | 0x6C)
+#define CC1200_IQIE_I1         (CC1200_EXTENDED_BIT | 0x6D)
+#define CC1200_IQIE_I0         (CC1200_EXTENDED_BIT | 0x6E)
+#define CC1200_IQIE_Q1         (CC1200_EXTENDED_BIT | 0x6f)
+#define CC1200_IQIE_Q0         (CC1200_EXTENDED_BIT | 0x70)
+#define CC1200_RSSI1           (CC1200_EXTENDED_BIT | 0x71)
+#define CC1200_RSSI0           (CC1200_EXTENDED_BIT | 0x72)
+#define CC1200_MARCSTATE       (CC1200_EXTENDED_BIT | 0x73)
+#define CC1200_LQI_VAL         (CC1200_EXTENDED_BIT | 0x74)
+#define CC1200_PQT_SYNC_ERR    (CC1200_EXTENDED_BIT | 0x75)
+#define CC1200_DEM_STATUS      (CC1200_EXTENDED_BIT | 0x76)
+#define CC1200_FREQOFF_EST1    (CC1200_EXTENDED_BIT | 0x77)
+#define CC1200_FREQOFF_EST0    (CC1200_EXTENDED_BIT | 0x78)
+#define CC1200_AGC_GAIN3       (CC1200_EXTENDED_BIT | 0x79)
+#define CC1200_AGC_GAIN2       (CC1200_EXTENDED_BIT | 0x7a)
+#define CC1200_AGC_GAIN1       (CC1200_EXTENDED_BIT | 0x7b)
+#define CC1200_AGC_GAIN0       (CC1200_EXTENDED_BIT | 0x7c)
+#define CC1200_SOFT_RX_DATA_OUT        (CC1200_EXTENDED_BIT | 0x7d)
+#define CC1200_SOFT_TX_DATA_IN (CC1200_EXTENDED_BIT | 0x7e)
+#define CC1200_ASK_SOFT_RX_DATA        (CC1200_EXTENDED_BIT | 0x7f)
+#define CC1200_RNDGEN          (CC1200_EXTENDED_BIT | 0x80)
+#define CC1200_MAGN2           (CC1200_EXTENDED_BIT | 0x81)
+#define CC1200_MAGN1           (CC1200_EXTENDED_BIT | 0x82)
+#define CC1200_MAGN0           (CC1200_EXTENDED_BIT | 0x83)
+#define CC1200_ANG1            (CC1200_EXTENDED_BIT | 0x84)
+#define CC1200_ANG0            (CC1200_EXTENDED_BIT | 0x85)
+#define CC1200_CHFILT_I2       (CC1200_EXTENDED_BIT | 0x86)
+#define CC1200_CHFILT_I1       (CC1200_EXTENDED_BIT | 0x87)
+#define CC1200_CHFILT_I0       (CC1200_EXTENDED_BIT | 0x88)
+#define CC1200_CHFILT_Q2       (CC1200_EXTENDED_BIT | 0x89)
+#define CC1200_CHFILT_Q1       (CC1200_EXTENDED_BIT | 0x8a)
+#define CC1200_CHFILT_Q0       (CC1200_EXTENDED_BIT | 0x8b)
+#define CC1200_GPIO_STATUS     (CC1200_EXTENDED_BIT | 0x8c)
+#define CC1200_FSCAL_CTRL      (CC1200_EXTENDED_BIT | 0x8d)
+#define CC1200_PHASE_ADJUST    (CC1200_EXTENDED_BIT | 0x8e)
+#define CC1200_PARTNUMBER      (CC1200_EXTENDED_BIT | 0x8f)
+#define CC1200_PARTVERSION     (CC1200_EXTENDED_BIT | 0x90)
+#define CC1200_SERIAL_STATUS   (CC1200_EXTENDED_BIT | 0x91)
+#define CC1200_MODEM_STATUS1   (CC1200_EXTENDED_BIT | 0x92)
+#define  CC1200_MODEM_STATUS1_SYNC_FOUND       7
+#define  CC1200_MODEM_STATUS1_RXFIFO_FULL      6
+#define  CC1200_MODEM_STATUS1_RXFIFO_THR       5
+#define  CC1200_MODEM_STATUS1_RXFIFO_EMPTY     4
+#define  CC1200_MODEM_STATUS1_RXFIFO_OVERFLOW  3
+#define  CC1200_MODEM_STATUS1_RXFIFO_UNDERFLOW 2
+#define  CC1200_MODEM_STATUS1_PQT_REACHED      1
+#define  CC1200_MODEM_STATUS1_PQT_VALID                0
+
+#define CC1200_MODEM_STATUS0   (CC1200_EXTENDED_BIT | 0x93)
+#define  CC1200_MODEM_STATUS0_FEC_RX_OVERFLOW  6
+#define  CC1200_MODEM_STATUS0_SYNC_SENT                4
+#define  CC1200_MODEM_STATUS0_TXFIFO_FULL      3
+#define  CC1200_MODEM_STATUS0_TXFIFO_THR       2
+#define  CC1200_MODEM_STATUS0_TXFIFO_OVERFLOW  1
+#define  CC1200_MODEM_STATUS0_TXFIFO_UNDERFLOW 0
+
+#define CC1200_MARC_STATUS1    (CC1200_EXTENDED_BIT | 0x94)
+#define  CC1200_MARC_STATUS1_NO_FAILURE                0
+#define  CC1200_MARC_STATUS1_RX_TIMEOUT                1
+#define  CC1200_MARC_STATUS1_RX_TERMINATION    2
+#define  CC1200_MARC_STATUS1_EWOR_SYNC_LOST    3
+#define  CC1200_MARC_STATUS1_MAXIMUM_LENGTH    4
+#define  CC1200_MARC_STATUS1_ADDRESS           5
+#define  CC1200_MARC_STATUS1_CRC               6
+#define  CC1200_MARC_STATUS1_TX_FIFO_OVERFLOW  7
+#define  CC1200_MARC_STATUS1_TX_FIFO_UNDERFLOW 8
+#define  CC1200_MARC_STATUS1_RX_FIFO_OVERFLOW  9
+#define  CC1200_MARC_STATUS1_RX_FIFO_UNDERFLOW 10
+#define  CC1200_MARC_STATUS1_TX_ON_CCA_FAILED  11
+#define  CC1200_MARC_STATUS1_TX_FINISHED       0x40
+#define  CC1200_MARC_STATUS1_RX_FINISHED       0x80
+#define CC1200_MARC_STATUS0    (CC1200_EXTENDED_BIT | 0x95)
+#define CC1200_PA_IFAMP_TEST   (CC1200_EXTENDED_BIT | 0x96)
+#define CC1200_FSRF_TEST       (CC1200_EXTENDED_BIT | 0x97)
+#define CC1200_PRE_TEST                (CC1200_EXTENDED_BIT | 0x98)
+#define CC1200_PRE_OVR         (CC1200_EXTENDED_BIT | 0x99)
+#define CC1200_ADC_TEST                (CC1200_EXTENDED_BIT | 0x9a)
+#define CC1200_DVC_TEST                (CC1200_EXTENDED_BIT | 0x9b)
+#define CC1200_ATEST           (CC1200_EXTENDED_BIT | 0x9c)
+#define CC1200_ATEST_LVDS      (CC1200_EXTENDED_BIT | 0x9d)
+#define CC1200_ATEST_MODE      (CC1200_EXTENDED_BIT | 0x9e)
+#define CC1200_XOSC_TEST1      (CC1200_EXTENDED_BIT | 0x9f)
+#define CC1200_XOSC_TEST0      (CC1200_EXTENDED_BIT | 0xa0)
+#define CC1200_RXFIRST         (CC1200_EXTENDED_BIT | 0xd2)
+#define CC1200_TXFIRST         (CC1200_EXTENDED_BIT | 0xd3)
+#define CC1200_RXLAST          (CC1200_EXTENDED_BIT | 0xd4)
+#define CC1200_TXLAST          (CC1200_EXTENDED_BIT | 0xd5)
+#define CC1200_NUM_TXBYTES     (CC1200_EXTENDED_BIT | 0xd6)
+#define CC1200_NUM_RXBYTES     (CC1200_EXTENDED_BIT | 0xd7)
+#define CC1200_FIFO_NUM_TXBYTES        (CC1200_EXTENDED_BIT | 0xd8)
+#define CC1200_FIFO_NUM_RXBYTES        (CC1200_EXTENDED_BIT | 0xd9)
+#define CC1200_RXFIFO_PRE_BUF  (CC1200_EXTENDED_BIT | 0xda)
+#define CC1200_AES_WORKSPACE_0 (CC1200_EXTENDED_BIT | 0xe0)
+
+/* Status byte */
+#define CC1200_STATUS_CHIP_RDY 7
+#define CC1200_STATUS_STATE    4
+#define  CC1200_STATUS_STATE_IDLE              0
+#define  CC1200_STATUS_STATE_RX                        1
+#define  CC1200_STATUS_STATE_TX                        2
+#define  CC1200_STATUS_STATE_FSTXON            3
+#define  CC1200_STATUS_STATE_CALIBRATE         4
+#define  CC1200_STATUS_STATE_SETTLING          5
+#define  CC1200_STATUS_STATE_RX_FIFO_ERROR     6
+#define  CC1200_STATUS_STATE_TX_FIFO_ERROR     7
+#define  CC1200_STATUS_STATE_MASK              7
+
+#endif /* _AO_CC1200_H_ */
diff --git a/src/drivers/ao_cc1200_CC1200.h b/src/drivers/ao_cc1200_CC1200.h
new file mode 100644 (file)
index 0000000..3567312
--- /dev/null
@@ -0,0 +1,122 @@
+/***************************************************************
+ *  SmartRF Studio(tm) Export
+ *
+ *  Radio register settings specifed with address, value
+ *
+ *  RF device: CC1200
+ *
+ ***************************************************************/
+
+/*
+ * Values affecting receive sensitivity:
+ *
+ *
+ *     PQT             - sets how good the preamble needs to look before
+ *                       we start looking for a sync word
+ *     SYNC_THR        - sets how good the sync needs to be before we
+ *                       start decoding a packet
+ */
+
+/* Values depending on data rate
+ *
+ *     DCFILT_BW_SETTLE
+ *     DCFILT_BW
+ */
+
+#ifndef AO_CC1200_AGC_GAIN_ADJUST
+#define AO_CC1200_AGC_GAIN_ADJUST      -94
+#endif
+
+        CC1200_IOCFG2,                       0x06,       /* GPIO2 IO Pin Configuration */
+       CC1200_SYNC3,                        0xD3,       /* Sync Word Configuration [23:16] */
+       CC1200_SYNC2,                        0x91,       /* Sync Word Configuration [23:16] */
+        CC1200_SYNC1,                        0xD3,       /* Sync Word Configuration [15:8] */
+        CC1200_SYNC0,                        0x91,       /* Sync Word Configuration [7:0] */
+        CC1200_SYNC_CFG1,                                /* Sync Word Detection Configuration Reg. 1 */
+               ((CC1200_SYNC_CFG1_SYNC_MODE_16_BITS << CC1200_SYNC_CFG1_SYNC_MODE) |
+                (11 << CC1200_SYNC_CFG1_SYNC_THR)),
+        CC1200_SYNC_CFG0,                                /* Sync Word Detection Configuration Reg. 0 */
+               ((1 << CC1200_SYNC_CFG0_AUTO_CLEAR) |
+                (0 << CC1200_SYNC_CFG0_RX_CONFIG_LIMITATION) |
+                (1 << CC1200_SYNC_CFG0_PQT_GATING_EN) |
+                (0 << CC1200_SYNC_CFG0_EXT_SYNC_DETECT) |
+                (CC1200_SYNC_CFG0_SYNC_STRICT_SYNC_CHECK_DISABLED << CC1200_SYNC_CFG0_SYNC_STRICT_SYNC_CHECK)),
+        CC1200_DEVIATION_M,                  0x50,       /* Frequency Deviation Configuration */
+        CC1200_DCFILT_CFG,                   0x5d,       /* Digital DC Removal Configuration */
+        CC1200_PREAMBLE_CFG0,                           /* Preamble Detection Configuration Reg. 0 */
+               ((1 << CC1200_PREAMBLE_CFG0_PQT_EN) |
+                (CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_11 << CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT) |
+                (15 << CC1200_PREAMBLE_CFG0_PQT)),
+        CC1200_IQIC,                         0xcb,       /* Digital Image Channel Compensation Configuration */
+        CC1200_CHAN_BW,                      0x11,       /* Channel Filter Configuration */
+        CC1200_MDMCFG1,                      0x40,       /* General Modem Parameter Configuration Reg. 1 */
+        CC1200_MDMCFG0,                      0x05,       /* General Modem Parameter Configuration Reg. 0 */
+        CC1200_SYMBOL_RATE2,                 0x93,       /* Symbol Rate Configuration Exponent and Mantissa [1.. */
+        CC1200_AGC_REF,                      0x27,       /* AGC Reference Level Configuration */
+        CC1200_AGC_CS_THR,                   0xec,       /* Carrier Sense Threshold Configuration */
+       CC1200_AGC_GAIN_ADJUST,                          /* RSSI adjustment */
+               AO_CC1200_AGC_GAIN_ADJUST,
+        CC1200_AGC_CFG1,                     0x51,       /* Automatic Gain Control Configuration Reg. 1 */
+        CC1200_AGC_CFG0,                     0x87,       /* Automatic Gain Control Configuration Reg. 0 */
+        CC1200_FIFO_CFG,                     0x40,       /* FIFO Configuration */
+       CC1200_SETTLING_CFG,                             /* Frequency Synthesizer Calibration and Settling Configuration */
+               ((CC1200_SETTLING_CFG_FS_AUTOCAL_EVERY_4TH_TIME << CC1200_SETTLING_CFG_FS_AUTOCAL) |
+                (CC1200_SETTLING_CFG_LOCK_TIME_75_30 << CC1200_SETTLING_CFG_LOCK_TIME) |
+                (CC1200_SETTLING_CFG_FSREG_TIME_60 << CC1200_SETTLING_CFG_FSREG_TIME)),
+        CC1200_FS_CFG,                                   /* Frequency Synthesizer Configuration */
+               ((1 << CC1200_FS_CFG_LOCK_EN) |
+                (CC1200_FS_CFG_FSD_BANDSELECT_410_480 << CC1200_FS_CFG_FSD_BANDSELECT)),
+        CC1200_PKT_CFG2,                                /* Packet Configuration Reg. 2 */
+               ((0 << CC1200_PKT_CFG2_FG_MODE_EN) |
+                (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
+                (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
+        CC1200_PKT_CFG1,                                 /* Packet Configuration Reg. 1 */
+               ((1 << CC1200_PKT_CFG1_FEC_EN) |
+                (1 << CC1200_PKT_CFG1_WHITE_DATA) |
+                (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) |
+                (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
+                (CC1200_PKT_CFG1_CRC_CFG_CRC16_INIT_ONES << CC1200_PKT_CFG1_CRC_CFG) |
+                (1 << CC1200_PKT_CFG1_APPEND_STATUS)),
+        CC1200_PKT_CFG0,                                 /* Packet Configuration Reg. 0 */
+               ((CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) |
+                (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) |
+                (0 << CC1200_PKT_CFG0_UART_MODE_EN) |
+                (0 << CC1200_PKT_CFG0_UART_SWAP_EN)),
+       CC1200_RFEND_CFG1,                               /* RFEND Configuration Reg. 1 */
+               ((CC1200_RFEND_CFG1_RXOFF_MODE_IDLE << CC1200_RFEND_CFG1_RXOFF_MODE) |
+                (CC1200_RFEND_CFG1_RX_TIME_INFINITE << CC1200_RFEND_CFG1_RX_TIME) |
+                (0 << CC1200_RFEND_CFG1_RX_TIME_QUAL)),
+       CC1200_RFEND_CFG0,                               /* RFEND Configuration Reg. 0 */
+               ((0 << CC1200_RFEND_CFG0_CAL_END_WAKE_UP_EN) |
+                (CC1200_RFEND_CFG0_TXOFF_MODE_IDLE << CC1200_RFEND_CFG0_TXOFF_MODE) |
+                (1 << CC1200_RFEND_CFG0_TERM_ON_BAD_PACKET_EN) |
+                (0 << CC1200_RFEND_CFG0_ANT_DIV_RX_TERM_CFG)),
+        CC1200_PA_CFG1,                      0x3f,       /* Power Amplifier Configuration Reg. 1 */
+        CC1200_PA_CFG0,                      0x53,       /* Power Amplifier Configuration Reg. 0 */
+        CC1200_PKT_LEN,                      0xff,       /* Packet Length Configuration */
+        CC1200_IF_MIX_CFG,                   0x1c,       /* IF Mix Configuration */
+        CC1200_FREQOFF_CFG,                  0x22,       /* Frequency Offset Correction Configuration */
+        CC1200_MDMCFG2,                                  /* General Modem Parameter Configuration Reg. 2 */
+               ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
+                (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
+                (CC1200_MDMCFG2_UPSAMPLER_P_8 << CC1200_MDMCFG2_UPSAMPLER_P) |
+                (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
+        CC1200_FREQ2,                        0x6c,       /* Frequency Configuration [23:16] */
+        CC1200_FREQ1,                        0xa3,       /* Frequency Configuration [15:8] */
+        CC1200_FREQ0,                        0x33,       /* Frequency Configuration [7:0] */
+        CC1200_IF_ADC1,                      0xee,       /* Analog to Digital Converter Configuration Reg. 1 */
+        CC1200_IF_ADC0,                      0x10,       /* Analog to Digital Converter Configuration Reg. 0 */
+        CC1200_FS_DIG1,                      0x07,       /* Frequency Synthesizer Digital Reg. 1 */
+        CC1200_FS_DIG0,                      0xaf,       /* Frequency Synthesizer Digital Reg. 0 */
+        CC1200_FS_CAL1,                      0x40,       /* Frequency Synthesizer Calibration Reg. 1 */
+        CC1200_FS_CAL0,                      0x0e,       /* Frequency Synthesizer Calibration Reg. 0 */
+        CC1200_FS_DIVTWO,                    0x03,       /* Frequency Synthesizer Divide by 2 */
+        CC1200_FS_DSM0,                      0x33,       /* FS Digital Synthesizer Module Configuration Reg. 0 */
+        CC1200_FS_DVC0,                      0x17,       /* Frequency Synthesizer Divider Chain Configuration .. */
+        CC1200_FS_PFD,                       0x00,       /* Frequency Synthesizer Phase Frequency Detector Con.. */
+        CC1200_FS_PRE,                       0x6e,       /* Frequency Synthesizer Prescaler Configuration */
+        CC1200_FS_REG_DIV_CML,               0x1c,       /* Frequency Synthesizer Divider Regulator Configurat.. */
+        CC1200_FS_SPARE,                     0xac,       /* Frequency Synthesizer Spare */
+        CC1200_FS_VCO0,                      0xb5,       /* FS Voltage Controlled Oscillator Configuration Reg.. */
+        CC1200_XOSC5,                        0x0e,       /* Crystal Oscillator Configuration Reg. 5 */
+        CC1200_XOSC1,                        0x03,       /* Crystal Oscillator Configuration Reg. 1 */
index 2354504981d6f09d3b51046d02fab1e300bc6b3a..42a4f5bfd35f064f22aa9cd682aa5295a897fe3b 100644 (file)
@@ -17,7 +17,7 @@
 
 #include "ao.h"
 
-static char
+static int
 ao_packet_getchar(void)
 {
        int c;
index 0edde5a2315d755bd89176e599052c89b783889c..1d794497af0600dd2046dc765b97779a2628a413 100644 (file)
@@ -18,7 +18,7 @@
 #define HAS_BEEP               1
 #define HAS_BATTERY_REPORT     1
 
-#define AO_STACK_SIZE  384
+#define AO_STACK_SIZE  376
 
 #define IS_FLASH_LOADER        0
 
index ad5bbf8e76ae152fefaed06eed6758963b8ec0da..59a469ae4fc41742f779da7628b2d372b30b9bb3 100644 (file)
 #define HAS_TASK       1
 #endif
 
-#ifndef AO_PORT_TYPE
-#define AO_PORT_TYPE uint8_t
-#endif
-
 typedef AO_PORT_TYPE ao_port_t;
 
 #if HAS_TASK
@@ -76,6 +72,7 @@ typedef AO_PORT_TYPE ao_port_t;
 #define AO_PANIC_BUFIO         15      /* Mis-using bufio API */
 #define AO_PANIC_EXTI          16      /* Mis-using exti API */
 #define AO_PANIC_FAST_TIMER    17      /* Mis-using fast timer API */
+#define AO_PANIC_ADC           18      /* Mis-using ADC interface */
 #define AO_PANIC_SELF_TEST_CC1120      0x40 | 1        /* Self test failure */
 #define AO_PANIC_SELF_TEST_HMC5883     0x40 | 2        /* Self test failure */
 #define AO_PANIC_SELF_TEST_MPU6000     0x40 | 3        /* Self test failure */
@@ -518,15 +515,9 @@ struct ao_telemetry_raw_recv {
 
 /* Set delay between telemetry reports (0 to disable) */
 
-#ifdef AO_SEND_ALL_BARO
-#define AO_TELEMETRY_INTERVAL_PAD      AO_MS_TO_TICKS(100)
-#define AO_TELEMETRY_INTERVAL_FLIGHT   AO_MS_TO_TICKS(100)
-#define AO_TELEMETRY_INTERVAL_RECOVER  AO_MS_TO_TICKS(100)
-#else
 #define AO_TELEMETRY_INTERVAL_PAD      AO_MS_TO_TICKS(1000)
 #define AO_TELEMETRY_INTERVAL_FLIGHT   AO_MS_TO_TICKS(100)
 #define AO_TELEMETRY_INTERVAL_RECOVER  AO_MS_TO_TICKS(1000)
-#endif
 
 void
 ao_telemetry_reset_interval(void);
@@ -662,6 +653,7 @@ union ao_monitor {
 extern __xdata union ao_monitor ao_monitor_ring[AO_MONITOR_RING];
 
 #define ao_monitor_ring_next(n)        (((n) + 1) & (AO_MONITOR_RING - 1))
+#define ao_monitor_ring_prev(n)        (((n) - 1) & (AO_MONITOR_RING - 1))
 
 extern __data uint8_t ao_monitoring;
 extern __data uint8_t ao_monitor_head;
index 6b8a1813509e5bb5634cef96e0d6e7456bce22bb..8dab7c42ad4ae06366f1364d1e7013aca1fd75a2 100644 (file)
@@ -557,10 +557,10 @@ ao_config_radio_rate_set(void) __reentrant
        }
        _ao_config_edit_start();
        ao_config.radio_rate = ao_cmd_lex_i;
+       _ao_config_edit_finish();
 #if HAS_TELEMETRY
        ao_telemetry_reset_interval();
 #endif
-       _ao_config_edit_finish();
 #if HAS_RADIO_RECV
        ao_radio_recv_abort();
 #endif
@@ -684,6 +684,9 @@ ao_config_radio_enable_set(void) __reentrant
        _ao_config_edit_start();
        ao_config.radio_enable = ao_cmd_lex_i;
        _ao_config_edit_finish();
+#if HAS_TELEMETRY && HAS_RADIO_RATE
+       ao_telemetry_reset_interval();
+#endif
 }
 #endif /* HAS_RADIO */
 
@@ -735,6 +738,7 @@ ao_config_aprs_set(void)
        _ao_config_edit_start();
        ao_config.aprs_interval = ao_cmd_lex_i;
        _ao_config_edit_finish();
+       ao_telemetry_reset_interval();
 }
 
 #endif /* HAS_APRS */
@@ -825,6 +829,9 @@ ao_config_tracker_set(void)
        ao_config.tracker_motion = m;
        ao_config.tracker_interval = i;
        _ao_config_edit_finish();
+#if HAS_TELEMETRY
+       ao_telemetry_reset_interval();
+#endif
 }
 #endif /* HAS_TRACKER */
 
index d26021da86b9511f340d9fbd203b730b3436b99d..6d9ee346ae4268312bb6ba800f9823786ed05329 100644 (file)
@@ -20,8 +20,8 @@
 #endif
 #include "ao_telem.h"
 
-#ifndef AO_TELEMETRY_LOCATION_ALTITUDE
-#define AO_TELEMETRY_LOCATION_ALTITUDE(l)      ((l)->altitude)
+#ifndef AO_GPS_ORIG_ALTITUDE
+#define AO_GPS_ORIG_ALTITUDE(l)        ((l)->altitude)
 #endif
 
 void
@@ -46,7 +46,7 @@ ao_gps_print(__xdata struct ao_gps_orig *gps_data) __reentrant
               AO_TELEM_GPS_ALTITUDE " %d ",
               (long) gps_data->latitude,
               (long) gps_data->longitude,
-              AO_TELEMETRY_LOCATION_ALTITUDE(gps_data));
+              AO_GPS_ORIG_ALTITUDE(gps_data));
 
        if (gps_data->flags & AO_GPS_DATE_VALID)
                printf(AO_TELEM_GPS_YEAR " %d "
index c13a2580f71e3bdae2af7be7d978b71d6d921eff..f86fb35998f8cfcf58af6134589fcd5f08882e5c 100644 (file)
@@ -43,11 +43,12 @@ extern __pdata enum ao_flight_state ao_log_state;
 #define AO_LOG_FORMAT_TINY             2       /* two byte state/baro records */
 #define AO_LOG_FORMAT_TELEMETRY                3       /* 32 byte ao_telemetry records */
 #define AO_LOG_FORMAT_TELESCIENCE      4       /* 32 byte typed telescience records */
-#define AO_LOG_FORMAT_TELEMEGA         5       /* 32 byte typed telemega records */
+#define AO_LOG_FORMAT_TELEMEGA_OLD     5       /* 32 byte typed telemega records */
 #define AO_LOG_FORMAT_EASYMINI         6       /* 16-byte MS5607 baro only, 3.0V supply */
 #define AO_LOG_FORMAT_TELEMETRUM       7       /* 16-byte typed telemetrum records */
 #define AO_LOG_FORMAT_TELEMINI         8       /* 16-byte MS5607 baro only, 3.3V supply */
 #define AO_LOG_FORMAT_TELEGPS          9       /* 32 byte telegps records */
+#define AO_LOG_FORMAT_TELEMEGA         10      /* 32 byte typed telemega records with 32 bit gyro cal */
 #define AO_LOG_FORMAT_NONE             127     /* No log at all */
 
 extern __code uint8_t ao_log_format;
@@ -208,6 +209,18 @@ struct ao_log_mega {
        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 */
@@ -218,7 +231,7 @@ struct ao_log_mega {
                        int16_t         ground_roll;            /* 18 */
                        int16_t         ground_pitch;           /* 20 */
                        int16_t         ground_yaw;             /* 22 */
-               } flight;                                       /* 24 */
+               } flight_old;                                   /* 24 */
                /* AO_LOG_STATE */
                struct {
                        uint16_t        state;
index 2d75c41c2c786bf98d7c03c05e4a09f9a58b70a0..cba0d80af603a778c57a7e275b0db7ae72b3b0c6 100644 (file)
@@ -94,9 +94,18 @@ __xdata struct ao_task ao_monitor_blink_task;
 void
 ao_monitor_blink(void)
 {
+#ifdef AO_MONITOR_BAD
+       uint8_t         *recv;
+#endif
        for (;;) {
                ao_sleep(DATA_TO_XDATA(&ao_monitor_head));
-               ao_led_for(AO_MONITOR_LED, AO_MS_TO_TICKS(100));
+#ifdef AO_MONITOR_BAD
+               recv = (uint8_t *) &ao_monitor_ring[ao_monitor_ring_prev(ao_monitor_head)];
+               if (ao_monitoring && !(recv[ao_monitoring + 1] & AO_RADIO_STATUS_CRC_OK))
+                       ao_led_for(AO_MONITOR_BAD, AO_MS_TO_TICKS(100));
+               else
+#endif
+                       ao_led_for(AO_MONITOR_LED, AO_MS_TO_TICKS(100));
        }
 }
 #endif
index baf213c01ad510eee2d278439ef546df2d04b321..dbc9f8e4121c36ec0f4ed3c873b742f28b7122fd 100644 (file)
@@ -34,6 +34,9 @@ ao_serial0_getchar(void);
 int
 _ao_serial0_pollchar(void);
 
+uint8_t
+_ao_serial0_sleep(void);
+
 void
 ao_serial0_putchar(char c);
 
@@ -54,6 +57,9 @@ ao_serial1_getchar(void);
 int
 _ao_serial1_pollchar(void);
 
+uint8_t
+_ao_serial1_sleep(void);
+
 void
 ao_serial1_putchar(char c);
 
@@ -74,6 +80,9 @@ ao_serial2_getchar(void);
 int
 _ao_serial2_pollchar(void);
 
+uint8_t
+_ao_serial2_sleep(void);
+
 void
 ao_serial2_putchar(char c);
 
@@ -94,6 +103,9 @@ ao_serial3_getchar(void);
 int
 _ao_serial3_pollchar(void);
 
+uint8_t
+_ao_serial3_sleep(void);
+
 void
 ao_serial3_putchar(char c);
 
index 9911813778698fadb89b1e40ec69ee6f91676f89..1d65fcf5c16589270625bbf45a553c9e35f526b1 100644 (file)
@@ -142,10 +142,8 @@ ao_add_stdio(int (*_pollchar)(void),
             void (*putchar)(char),
             void (*flush)(void)) __reentrant
 {
-#if AO_NUM_STDIOS > 1
        if (ao_num_stdios == AO_NUM_STDIOS)
                ao_panic(AO_PANIC_STDIO);
-#endif
        ao_stdios[ao_num_stdios]._pollchar = _pollchar;
        ao_stdios[ao_num_stdios].putchar = putchar;
        ao_stdios[ao_num_stdios].flush = flush;
index 27306a344c27a0cdb27b7e2bf19789e1fef4c97f..e2197f7a24cb1f9ad735ed49ea0d3c7c99cfb3c3 100644 (file)
 #include "ao_log.h"
 #include "ao_product.h"
 
-#ifndef HAS_RDF
-#define HAS_RDF 1
-#endif
-
 static __pdata uint16_t ao_telemetry_interval;
 
 #if HAS_RADIO_RATE
 static __xdata uint16_t ao_telemetry_desired_interval;
 #endif
 
+/* TeleMetrum v1.0 just doesn't have enough space to
+ * manage the more complicated telemetry scheduling, so
+ * it loses the ability to disable telem/rdf separately
+ */
+
+#if defined(TELEMETRUM_V_1_0)
+#define SIMPLIFY
+#endif
+
+#ifdef SIMPLIFY
+#define ao_telemetry_time time
+#define RDF_SPACE      __pdata
+#else
+#define RDF_SPACE      __xdata
+static __pdata uint16_t ao_telemetry_time;
+#endif
+
 #if HAS_RDF
-static __pdata uint8_t ao_rdf = 0;
-static __pdata uint16_t ao_rdf_time;
+static RDF_SPACE uint8_t ao_rdf = 0;
+static RDF_SPACE uint16_t ao_rdf_time;
 #endif
 
 #if HAS_APRS
@@ -120,7 +133,9 @@ ao_send_mega_sensor(void)
        telemetry.generic.tick = packet->tick;
        telemetry.generic.type = AO_TELEMETRY_MEGA_SENSOR;
 
+#if HAS_MPU6000
        telemetry.mega_sensor.orient = ao_sample_orient;
+#endif
        telemetry.mega_sensor.accel = ao_data_accel(packet);
        telemetry.mega_sensor.pres = ao_data_pres(packet);
        telemetry.mega_sensor.temp = ao_data_temp(packet);
@@ -269,30 +284,6 @@ ao_send_mini(void)
 
 #endif /* AO_SEND_MINI */
 
-#ifdef AO_SEND_ALL_BARO
-static uint8_t         ao_baro_sample;
-
-static void
-ao_send_baro(void)
-{
-       uint8_t         sample = ao_sample_data;
-       uint8_t         samples = (sample - ao_baro_sample) & (AO_DATA_RING - 1);
-
-       if (samples > 12) {
-               ao_baro_sample = (ao_baro_sample + (samples - 12)) & (AO_DATA_RING - 1);
-               samples = 12;
-       }
-       telemetry.generic.tick = ao_data_ring[sample].tick;
-       telemetry.generic.type = AO_TELEMETRY_BARO;
-       telemetry.baro.samples = samples;
-       for (sample = 0; sample < samples; sample++) {
-               telemetry.baro.baro[sample] = ao_data_ring[ao_baro_sample].adc.pres;
-               ao_baro_sample = ao_data_ring_next(ao_baro_sample);
-       }
-       ao_radio_send(&telemetry, sizeof (telemetry));
-}
-#endif
-
 static __pdata int8_t ao_telemetry_config_max;
 static __pdata int8_t ao_telemetry_config_cur;
 
@@ -332,6 +323,7 @@ ao_send_configuration(void)
 
 #if HAS_GPS
 
+static __pdata int8_t ao_telemetry_gps_max;
 static __pdata int8_t ao_telemetry_loc_cur;
 static __pdata int8_t ao_telemetry_sat_cur;
 
@@ -348,7 +340,7 @@ ao_send_location(void)
                telemetry.location.tick = ao_gps_tick;
                ao_mutex_put(&ao_gps_mutex);
                ao_radio_send(&telemetry, sizeof (telemetry));
-               ao_telemetry_loc_cur = ao_telemetry_config_max;
+               ao_telemetry_loc_cur = ao_telemetry_gps_max;
        }
 }
 
@@ -365,7 +357,7 @@ ao_send_satellite(void)
                       AO_MAX_GPS_TRACKING * sizeof (struct ao_telemetry_satellite_info));
                ao_mutex_put(&ao_gps_mutex);
                ao_radio_send(&telemetry, sizeof (telemetry));
-               ao_telemetry_sat_cur = ao_telemetry_config_max;
+               ao_telemetry_sat_cur = ao_telemetry_gps_max;
        }
 }
 #endif
@@ -411,6 +403,7 @@ ao_telemetry(void)
                while (ao_telemetry_interval == 0)
                        ao_sleep(&telemetry);
                time = ao_time();
+               ao_telemetry_time = time;
 #if HAS_RDF
                ao_rdf_time = time;
 #endif
@@ -418,79 +411,85 @@ ao_telemetry(void)
                ao_aprs_time = time;
 #endif
                while (ao_telemetry_interval) {
-#if HAS_APRS
+                       time = ao_time() + AO_SEC_TO_TICKS(100);
+#ifndef SIMPLIFY
                        if (!(ao_config.radio_enable & AO_RADIO_DISABLE_TELEMETRY))
 #endif
                        {
-#ifdef AO_SEND_ALL_BARO
-                               ao_send_baro();
+#ifndef SIMPLIFY
+                               if ( (int16_t) (ao_time() - ao_telemetry_time) >= 0)
 #endif
-
-#if HAS_FLIGHT
+                               {
+                                       ao_telemetry_time = ao_time() + ao_telemetry_interval;
 # ifdef AO_SEND_MEGA
-                               ao_send_mega_sensor();
-                               ao_send_mega_data();
+                                       ao_send_mega_sensor();
+                                       ao_send_mega_data();
 # endif
 # ifdef AO_SEND_METRUM
-                               ao_send_metrum_sensor();
-                               ao_send_metrum_data();
+                                       ao_send_metrum_sensor();
+                                       ao_send_metrum_data();
 # endif
 # ifdef AO_SEND_MINI
-                               ao_send_mini();
+                                       ao_send_mini();
 # endif
 # ifdef AO_TELEMETRY_SENSOR
-                               ao_send_sensor();
+                                       ao_send_sensor();
 # endif
-#endif /* HAS_FLIGHT */
-
 #if HAS_COMPANION
-                               if (ao_companion_running)
-                                       ao_send_companion();
+                                       if (ao_companion_running)
+                                               ao_send_companion();
 #endif
-                               ao_send_configuration();
 #if HAS_GPS
-                               ao_send_location();
-                               ao_send_satellite();
+                                       ao_send_location();
+                                       ao_send_satellite();
+#endif
+                                       ao_send_configuration();
+                               }
+#ifndef SIMPLIFY
+                               time = ao_telemetry_time;
 #endif
                        }
-#ifndef AO_SEND_ALL_BARO
 #if HAS_RDF
-                       if (ao_rdf &&
-#if HAS_APRS
-                           !(ao_config.radio_enable & AO_RADIO_DISABLE_RDF) &&
-#endif /* HAS_APRS */
-                           (int16_t) (ao_time() - ao_rdf_time) >= 0)
+                       if (ao_rdf
+#ifndef SIMPLIFY
+                           && !(ao_config.radio_enable & AO_RADIO_DISABLE_RDF)
+#endif
+                               )
                        {
+                               if ((int16_t) (ao_time() - ao_rdf_time) >= 0) {
 #if HAS_IGNITE_REPORT
-                               uint8_t c;
-#endif /* HAS_IGNITE_REPORT */
-                               ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS;
+                                       uint8_t c;
+#endif
+                                       ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS;
 #if HAS_IGNITE_REPORT
-                               if (ao_flight_state == ao_flight_pad && (c = ao_report_igniter()))
-                                       ao_radio_continuity(c);
-                               else
-#endif /* HAS_IGNITE_REPORT*/
-                                       ao_radio_rdf();
+                                       if (ao_flight_state == ao_flight_pad && (c = ao_report_igniter()))
+                                               ao_radio_continuity(c);
+                                       else
+#endif
+                                               ao_radio_rdf();
+                               }
+#ifndef SIMPLIFY
+                               if ((int16_t) (time - ao_rdf_time) > 0)
+                                       time = ao_rdf_time;
+#endif
                        }
 #endif /* HAS_RDF */
 #if HAS_APRS
-                       if (ao_config.aprs_interval != 0 &&
-                           (int16_t) (ao_time() - ao_aprs_time) >= 0)
-                       {
-                               ao_aprs_time = ao_time() + AO_SEC_TO_TICKS(ao_config.aprs_interval);
-                               ao_aprs_send();
+                       if (ao_config.aprs_interval != 0) {
+                               if ((int16_t) (ao_time() - ao_aprs_time) >= 0) {
+                                       ao_aprs_time = ao_time() + AO_SEC_TO_TICKS(ao_config.aprs_interval);
+                                       ao_aprs_send();
+                               }
+                               if ((int16_t) (time - ao_aprs_time) > 0)
+                                       time = ao_aprs_time;
                        }
 #endif /* HAS_APRS */
-#endif /* !AO_SEND_ALL_BARO */
-                       time += ao_telemetry_interval;
                        delay = time - ao_time();
                        if (delay > 0) {
                                ao_alarm(delay);
                                ao_sleep(&telemetry);
                                ao_clear_alarm();
                        }
-                       else
-                               time = ao_time();
                }
        }
 }
@@ -547,21 +546,31 @@ ao_telemetry_set_interval(uint16_t interval)
        ao_telemetry_companion_cur = cur;
 #endif
 
-       ao_telemetry_config_max = AO_SEC_TO_TICKS(5) / interval;
-#if HAS_COMPANION
-       if (ao_telemetry_config_max > cur)
-               cur++;
-       ao_telemetry_config_cur = cur;
-#endif
-
 #if HAS_GPS
-       if (ao_telemetry_config_max > cur)
+       ao_telemetry_gps_max = AO_SEC_TO_TICKS(1) / interval;
+       if (ao_telemetry_gps_max > cur)
                cur++;
        ao_telemetry_loc_cur = cur;
-       if (ao_telemetry_config_max > cur)
+       if (ao_telemetry_gps_max > cur)
                cur++;
        ao_telemetry_sat_cur = cur;
 #endif
+
+       ao_telemetry_config_max = AO_SEC_TO_TICKS(5) / interval;
+       if (ao_telemetry_config_max > cur)
+               cur++;
+       ao_telemetry_config_cur = cur;
+
+#ifndef SIMPLIFY
+       ao_telemetry_time = 
+#if HAS_RDF
+               ao_rdf_time =
+#endif
+#if HAS_APRS
+               ao_aprs_time =
+#endif
+               ao_time();
+#endif
        ao_wakeup(&telemetry);
 }
 
index 83d432cf95f39db62dc9f602d8011c58a46f49ae..711e0d36cb57230bb012c79265295c7763886582 100644 (file)
@@ -116,12 +116,16 @@ struct ao_telemetry_location {
        /* 32 */
 };
 
-#if HAS_GPS
-
 #ifndef HAS_WIDE_GPS
 #define HAS_WIDE_GPS   1
 #endif
 
+#ifdef HAS_TELEMETRY
+#ifndef HAS_RDF
+#define HAS_RDF                1
+#endif
+#endif
+
 #if HAS_WIDE_GPS
 typedef int32_t                gps_alt_t;
 #define AO_TELEMETRY_LOCATION_ALTITUDE(l)      (((gps_alt_t) (l)->altitude_high << 16) | ((l)->altitude_low))
@@ -135,8 +139,6 @@ typedef int16_t             gps_alt_t;
                                                  (l)->altitude_low = (a)))
 #endif /* HAS_WIDE_GPS */
 
-#endif /* HAS_GPS */
-
 #define AO_TELEMETRY_SATELLITE         0x06
 
 struct ao_telemetry_satellite_info {
index 9b007af82109defdc752e56cfcd375a374c5b1e6..962f145d39a4b0e21ae6b27017fdc1348a6b92a7 100644 (file)
@@ -132,7 +132,7 @@ ao_tracker(void)
                                        if (height < 0)
                                                height = -height;
 
-                                       if (ao_tracker_force_telem)
+                                       if (ao_tracker_force_telem > 1)
                                                printf("head %d ring %d ground_distance %d height %d\n", gps_head, ring, ground_distance, height);
                                        if (ground_distance > ao_config.tracker_motion ||
                                            height > (ao_config.tracker_motion << 1))
@@ -141,7 +141,7 @@ ao_tracker(void)
                                                break;
                                        }
                                }
-                               if (ao_tracker_force_telem) {
+                               if (ao_tracker_force_telem > 1) {
                                        printf ("moving %d started %d\n", moving, log_started);
                                        flush();
                                }
@@ -191,11 +191,9 @@ static struct ao_task ao_tracker_task;
 static void
 ao_tracker_set_telem(void)
 {
-       uint8_t telem;
        ao_cmd_hex();
-       telem = ao_cmd_lex_i;
        if (ao_cmd_status == ao_cmd_success)
-               ao_tracker_force_telem = telem;
+               ao_tracker_force_telem = ao_cmd_lex_i;
        ao_cmd_status = ao_cmd_success;
        printf ("flight: %d\n", ao_flight_number);
        printf ("force_telem: %d\n", ao_tracker_force_telem);
@@ -211,7 +209,7 @@ ao_tracker_set_telem(void)
 }
 
 static const struct ao_cmds ao_tracker_cmds[] = {
-       { ao_tracker_set_telem, "t <d>\0Set telem on USB" },
+       { ao_tracker_set_telem, "t <d>\0Set telem on USB (0 off, 1 on, 2 dbg)" },
        { 0, NULL },
 };
 
index 5fbb8dfaa0f24183341d1d78dbbc49e80cdf16b3..42faf06fcaf3d8b1015ca9a0f8a9dcf0c48e8c8a 100644 (file)
@@ -130,12 +130,15 @@ ao_serial_init(void);
 /* SPI definitions */
 
 #define AO_SPI_SPEED_12MHz             4
+#define AO_SPI_SPEED_8MHz              6
 #define AO_SPI_SPEED_6MHz              8
 #define AO_SPI_SPEED_4MHz              12
 #define AO_SPI_SPEED_2MHz              24
 #define AO_SPI_SPEED_1MHz              48
 #define AO_SPI_SPEED_500kHz            96
 #define AO_SPI_SPEED_250kHz            192
+#define AO_SPI_SPEED_125kHz            384
+#define AO_SPI_SPEED_62500Hz           768
 
 #define AO_SPI_SPEED_FAST      AO_SPI_SPEED_12MHz
 
index 21a7a8e5702f779fd2ddce6e164e89a8bf77ab9e..fbe641d87b9ee7ca53c16934e70a8ce6b35bc660 100644 (file)
 
 #define ao_gpio_get(port, bit, pin)    (lpc_gpio.byte[lpc_all_bit(port,bit)])
 
+#define PORT0_JTAG_REGS        ((1 << 11) | (1 << 12) | (1 << 14))
+
+static inline void lpc_set_gpio(int port, int bit) {
+       if (port == 0 && (1 << bit) & (PORT0_JTAG_REGS)) {
+               vuint32_t *_ioconf = &lpc_ioconf.pio0_0 + ((port)*24+(bit));
+
+               *_ioconf = (*_ioconf & ~LPC_IOCONF_FUNC_MASK) | LPC_IOCONF_FUNC_PIO0_11;
+       }
+}
+
 #define ao_enable_output(port,bit,pin,v) do {                  \
                ao_enable_port(port);                           \
+               lpc_set_gpio(port,bit);                         \
                ao_gpio_set(port, bit, pin, v);                 \
                lpc_gpio.dir[port] |= (1 << bit);               \
        } while (0)
@@ -52,6 +63,7 @@
 
 #define ao_enable_input(port,bit,mode) do {                            \
                ao_enable_port(port);                                   \
+               lpc_set_gpio(port,bit);                                 \
                lpc_gpio.dir[port] &= ~(1 << bit);                      \
                ao_gpio_set_mode(port,bit,mode);                        \
        } while (0)
@@ -201,7 +213,7 @@ void
 ao_spi_put(uint8_t spi_index);
 
 void
-ao_spi_send(void *block, uint16_t len, uint8_t spi_index);
+ao_spi_send(const void *block, uint16_t len, uint8_t spi_index);
 
 void
 ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index);
@@ -210,9 +222,7 @@ void
 ao_spi_recv(void *block, uint16_t len, uint8_t spi_index);
 
 void
-ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index);
-
-extern uint16_t        ao_spi_speed[LPC_NUM_SPI];
+ao_spi_duplex(const void *out, void *in, uint16_t len, uint8_t spi_index);
 
 void
 ao_spi_init(void);
index d983437cd4c4549c0a64886b434d8e61f2aebe7b..a0b293b923a8a3b39a683f7566a49da0cb35fabd 100644 (file)
@@ -59,6 +59,15 @@ void
 ao_led_init(AO_PORT_TYPE enable)
 {
        ao_led_enable = enable;
-       lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_GPIO);
+       ao_enable_port(LED_PORT);
+       if (LED_PORT == 0) {
+               if (enable & (1 << 11))
+                       lpc_ioconf.pio0_11 = LPC_IOCONF_FUNC_PIO0_11 | (1 << LPC_IOCONF_ADMODE);
+               if (enable & (1 << 12))
+                       lpc_ioconf.pio0_12 = LPC_IOCONF_FUNC_PIO0_12 | (1 << LPC_IOCONF_ADMODE);
+               if (enable & (1 << 14))
+                       lpc_ioconf.pio0_14 = LPC_IOCONF_FUNC_PIO0_14 | (1 << LPC_IOCONF_ADMODE);
+       }
        lpc_gpio.dir[LED_PORT] |= enable;
+       ao_led_off(enable);
 }
index e72b8286634adfbb0fe3b8e3f97bcfbbf2c92d3e..f091c89c570963542f602c0e7f6d8957116895d4 100644 (file)
@@ -21,34 +21,27 @@ static uint8_t              ao_spi_mutex[LPC_NUM_SPI];
 
 static struct lpc_ssp * const ao_lpc_ssp[LPC_NUM_SPI] = { &lpc_ssp0, &lpc_ssp1 };
 
-#define tx_busy(lpc_ssp) (lpc_ssp->sr & ((1 << LPC_SSP_SR_BSY) | (1 << LPC_SSP_SR_TNF))) != (1 << LPC_SSP_SR_TNF)
-#define rx_busy(lpc_ssp) (lpc_ssp->sr & ((1 << LPC_SSP_SR_BSY) | (1 << LPC_SSP_SR_RNE))) != (1 << LPC_SSP_SR_RNE)
-
 #define spi_loop(len, put, get) do {                                   \
                while (len--) {                                         \
-                       /* Wait for space in the fifo */                \
-                       while (tx_busy(lpc_ssp))                        \
-                               ;                                       \
-                                                                       \
                        /* send a byte */                               \
                        lpc_ssp->dr = put;                              \
-                                                                       \
-                       /* Wait for byte to appear in the fifo */       \
-                       while (rx_busy(lpc_ssp))                        \
+                       /* wait for the received byte to appear */      \
+                       while ((lpc_ssp->sr & (1 << LPC_SSP_SR_RNE)) == 0) \
                                ;                                       \
-                                                                       \
-                       /* recv a byte */                               \
+                       /* receive a byte */                            \
                        get lpc_ssp->dr;                                \
                }                                                       \
+               /* Wait for the SSP to go idle (it already should be) */ \
+               while (lpc_ssp->sr & (1 << LPC_SSP_SR_BSY));            \
        } while (0)
 
 void
-ao_spi_send(void *block, uint16_t len, uint8_t id)
+ao_spi_send(const void *block, uint16_t len, uint8_t id)
 {
-       uint8_t *b = block;
        struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id];
+       const uint8_t   *o = block;
 
-       spi_loop(len, *b++, (void));
+       spi_loop(len, *o++, (void));
 }
 
 void
@@ -62,18 +55,18 @@ ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t id)
 void
 ao_spi_recv(void *block, uint16_t len, uint8_t id)
 {
-       uint8_t *b = block;
        struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id];
+       uint8_t *i = block;
 
-       spi_loop(len, 0xff, *b++ =);
+       spi_loop(len, 0xff, *i++ =);
 }
 
 void
-ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t id)
+ao_spi_duplex(const void *out, void *in, uint16_t len, uint8_t id)
 {
-       uint8_t *o = out;
-       uint8_t *i = in;
        struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id];
+       const uint8_t *o = out;
+       uint8_t *i = in;
 
        spi_loop(len, *o++, *i++ =);
 }
@@ -84,7 +77,7 @@ ao_spi_get(uint8_t id, uint32_t speed)
        struct lpc_ssp  *lpc_ssp = ao_lpc_ssp[id];
 
        ao_mutex_get(&ao_spi_mutex[id]);
-       
+
        /* Set the clock prescale */
        lpc_ssp->cpsr = speed;
 }
@@ -101,6 +94,11 @@ ao_spi_channel_init(uint8_t id)
        struct lpc_ssp  *lpc_ssp = ao_lpc_ssp[id];
        uint8_t d;
 
+       /* Clear interrupt registers */
+       lpc_ssp->imsc = 0;
+       lpc_ssp->ris = 0;
+       lpc_ssp->mis = 0;
+
        lpc_ssp->cr0 = ((LPC_SSP_CR0_DSS_8 << LPC_SSP_CR0_DSS) |
                        (LPC_SSP_CR0_FRF_SPI << LPC_SSP_CR0_FRF) |
                        (0 << LPC_SSP_CR0_CPOL) |
@@ -151,7 +149,7 @@ ao_spi_init(void)
        lpc_scb.presetctrl &= ~(1 << LPC_SCB_PRESETCTRL_SSP0_RST_N);
        lpc_scb.presetctrl |= (1 << LPC_SCB_PRESETCTRL_SSP0_RST_N);
        ao_spi_channel_init(0);
-#endif                    
+#endif
 
 #if HAS_SPI_1
 
@@ -190,7 +188,7 @@ ao_spi_init(void)
 #ifndef HAS_MOSI1
 #error "No pin specified for MOSI1"
 #endif
-               
+
        /* Enable the device */
        lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_SSP1);
 
index 12f5d8e6973013c5c5113bbe9d50a97d509d9fd3..0dfaece480dc0f60f0b2bcb245b1e3578395ccc2 100644 (file)
@@ -80,14 +80,12 @@ static uint8_t      *ao_usb_ep0_setup_buffer;
 static uint8_t *ao_usb_ep0_rx_buffer;
 
 /* Pointer to bulk data tx/rx buffers in USB memory */
-static uint8_t *ao_usb_in_tx_buffer;
-static uint8_t *ao_usb_out_rx_buffer;
-
-/* Our data buffers */
-static uint8_t ao_usb_tx_buffer[AO_USB_IN_SIZE];
+static uint8_t *ao_usb_in_tx_buffer[2];
+static uint8_t ao_usb_in_tx_cur;
 static uint8_t ao_usb_tx_count;
 
-static uint8_t ao_usb_rx_buffer[AO_USB_OUT_SIZE];
+static uint8_t *ao_usb_out_rx_buffer[2];
+static uint8_t ao_usb_out_rx_cur;
 static uint8_t ao_usb_rx_count, ao_usb_rx_pos;
 
 extern struct lpc_usb_endpoint lpc_usb_endpoint;
@@ -234,15 +232,15 @@ ao_usb_ep0_in(void)
 }
 
 static inline vuint32_t *
-ao_usb_epn_out(uint8_t n)
+ao_usb_epn_out(uint8_t n, uint8_t i)
 {
-       return &lpc_usb_endpoint.epn[n-1].out[0];
+       return &lpc_usb_endpoint.epn[n-1].out[i];
 }
 
 static inline vuint32_t *
-ao_usb_epn_in(uint8_t n)
+ao_usb_epn_in(uint8_t n, uint8_t i)
 {
-       return &lpc_usb_endpoint.epn[n-1].in[0];
+       return &lpc_usb_endpoint.epn[n-1].in[i];
 }
 
 #if UNUSED
@@ -256,26 +254,26 @@ ao_usb_set_epn_in(uint8_t n, uint8_t *addr, uint16_t nbytes)
 static void
 ao_usb_set_epn_out(uint8_t n, uint8_t *addr, uint16_t nbytes)
 {
-       ao_usb_set_ep(ao_usb_epn_out(n), addr, nbytes);
+       ao_usb_set_ep(ao_usb_epn_out(n, 0), addr, nbytes);
 }
 
 static inline uint16_t
 ao_usb_epn_out_count(uint8_t n)
 {
-       return ao_usb_ep_count(ao_usb_epn_out(n));
+       return ao_usb_ep_count(ao_usb_epn_out(n, 0));
 }
 
 static inline uint16_t
 ao_usb_epn_in_count(uint8_t n)
 {
-       return ao_usb_ep_count(ao_usb_epn_in(n));
+       return ao_usb_ep_count(ao_usb_epn_in(n, 0));
 }
 
 static uint8_t *
 ao_usb_enable_ep(vuint32_t *ep, uint16_t nbytes, uint16_t set_nbytes)
 {
        uint8_t *addr = ao_usb_alloc_sram(nbytes);
-       
+
        ao_usb_set_ep(ep, addr, set_nbytes);
        return addr;
 }
@@ -294,28 +292,34 @@ ao_usb_disable_ep(vuint32_t *ep)
 }
 
 static void
-ao_usb_enable_epn(uint8_t n, uint16_t out_bytes, uint8_t **out_addr, uint16_t in_bytes, uint8_t **in_addr)
+ao_usb_enable_epn(uint8_t n,
+                 uint16_t out_bytes, uint8_t *out_addrs[2],
+                 uint16_t in_bytes, uint8_t *in_addrs[2])
 {
        uint8_t *addr;
 
-       addr = ao_usb_enable_ep(ao_usb_epn_out(n), out_bytes, out_bytes);
-       if (out_addr)
-               *out_addr = addr;
-       ao_usb_disable_ep(&lpc_usb_endpoint.epn[n-1].out[1]);
+       addr = ao_usb_enable_ep(ao_usb_epn_out(n, 0), out_bytes * 2, out_bytes);
+       if (out_addrs) {
+               out_addrs[0] = addr;
+               out_addrs[1] = addr + out_bytes;
+       }
+       ao_usb_disable_ep(ao_usb_epn_out(n, 1));
 
-       addr = ao_usb_enable_ep(ao_usb_epn_in(n), in_bytes, 0);
-       if (in_addr)
-               *in_addr = addr;
-       ao_usb_disable_ep(&lpc_usb_endpoint.epn[n-1].in[1]);
+       addr = ao_usb_enable_ep(ao_usb_epn_in(n, 0), in_bytes * 2, 0);
+       if (in_addrs) {
+               in_addrs[0] = addr;
+               in_addrs[1] = addr + in_bytes;
+       }
+       ao_usb_disable_ep(ao_usb_epn_in(n, 1));
 }
 
 static void
 ao_usb_disable_epn(uint8_t n)
 {
-       ao_usb_disable_ep(ao_usb_epn_out(n));
-       ao_usb_disable_ep(&lpc_usb_endpoint.epn[n-1].out[1]);
-       ao_usb_disable_ep(ao_usb_epn_in(n));
-       ao_usb_disable_ep(&lpc_usb_endpoint.epn[n-1].in[1]);
+       ao_usb_disable_ep(ao_usb_epn_out(n, 0));
+       ao_usb_disable_ep(ao_usb_epn_out(n, 1));
+       ao_usb_disable_ep(ao_usb_epn_in(n, 0));
+       ao_usb_disable_ep(ao_usb_epn_in(n, 1));
 }
 
 static void
@@ -362,12 +366,18 @@ ao_usb_set_configuration(void)
 
        /* Set up the INT end point */
        ao_usb_enable_epn(AO_USB_INT_EP, 0, NULL, 0, NULL);
-       
+
        /* Set up the OUT end point */
-       ao_usb_enable_epn(AO_USB_OUT_EP, AO_USB_OUT_SIZE, &ao_usb_out_rx_buffer, 0, NULL);
+       ao_usb_enable_epn(AO_USB_OUT_EP, AO_USB_OUT_SIZE, ao_usb_out_rx_buffer, 0, NULL);
+
+       /* Set the current RX pointer to the *other* buffer so that when buffer 0 gets
+        * data, we'll switch to it and pull bytes from there
+        */
+       ao_usb_out_rx_cur = 1;
 
        /* Set up the IN end point */
-       ao_usb_enable_epn(AO_USB_IN_EP, 0, NULL, AO_USB_IN_SIZE, &ao_usb_in_tx_buffer);
+       ao_usb_enable_epn(AO_USB_IN_EP, 0, NULL, AO_USB_IN_SIZE, ao_usb_in_tx_buffer);
+       ao_usb_in_tx_cur = 0;
 
        ao_usb_running = 1;
 }
@@ -716,8 +726,8 @@ _ao_usb_in_send(void)
        ao_usb_in_pending = 1;
        if (ao_usb_tx_count != AO_USB_IN_SIZE)
                ao_usb_in_flushed = 1;
-       memcpy(ao_usb_in_tx_buffer, ao_usb_tx_buffer, ao_usb_tx_count);
-       ao_usb_set_ep(ao_usb_epn_in(AO_USB_IN_EP), ao_usb_in_tx_buffer, ao_usb_tx_count);
+       ao_usb_set_ep(ao_usb_epn_in(AO_USB_IN_EP, 0), ao_usb_in_tx_buffer[ao_usb_in_tx_cur], ao_usb_tx_count);
+       ao_usb_in_tx_cur = 1 - ao_usb_in_tx_cur;
        ao_usb_tx_count = 0;
        _tx_dbg0("in_send end");
 }
@@ -771,7 +781,7 @@ ao_usb_putchar(char c)
        _ao_usb_in_wait();
 
        ao_usb_in_flushed = 0;
-       ao_usb_tx_buffer[ao_usb_tx_count++] = (uint8_t) c;
+       ao_usb_in_tx_buffer[ao_usb_in_tx_cur][ao_usb_tx_count++] = (uint8_t) c;
 
        /* Send the packet when full */
        if (ao_usb_tx_count == AO_USB_IN_SIZE) {
@@ -792,13 +802,12 @@ _ao_usb_out_recv(void)
 
        _rx_dbg1("out_recv count", ao_usb_rx_count);
        debug ("recv %d\n", ao_usb_rx_count);
-       debug_data("Fill OUT len %d:", ao_usb_rx_count);
-       memcpy(ao_usb_rx_buffer, ao_usb_out_rx_buffer, ao_usb_rx_count);
-       debug_data("\n");
+       debug_data("Fill OUT len %d\n", ao_usb_rx_count);
        ao_usb_rx_pos = 0;
+       ao_usb_out_rx_cur = 1 - ao_usb_out_rx_cur;
 
        /* ACK the packet */
-       ao_usb_set_epn_out(AO_USB_OUT_EP, ao_usb_out_rx_buffer, AO_USB_OUT_SIZE);
+       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
@@ -823,7 +832,7 @@ _ao_usb_pollchar(void)
        }
 
        /* Pull a character out of the fifo */
-       c = ao_usb_rx_buffer[ao_usb_rx_pos++];
+       c = ao_usb_out_rx_buffer[ao_usb_out_rx_cur][ao_usb_rx_pos++];
        return c;
 }
 
@@ -897,7 +906,7 @@ ao_usb_enable(void)
 
        /* Enable USB PHY */
        lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_USBPAD_PD);
-       
+
        /* Turn on USB PLL */
        lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_USBPLL_PD);
 
@@ -1044,7 +1053,7 @@ static void _dbg(int line, char *msg, uint32_t value)
        dbg[dbg_i].primask = primask;
 #if TX_DBG
        dbg[dbg_i].in_count = in_count;
-       dbg[dbg_i].in_ep = *ao_usb_epn_in(AO_USB_IN_EP);
+       dbg[dbg_i].in_ep = *ao_usb_epn_in(AO_USB_IN_EP, 0);
        dbg[dbg_i].in_pending = ao_usb_in_pending;
        dbg[dbg_i].tx_count = ao_usb_tx_count;
        dbg[dbg_i].in_flushed = ao_usb_in_flushed;
@@ -1053,7 +1062,7 @@ static void _dbg(int line, char *msg, uint32_t value)
        dbg[dbg_i].rx_count = ao_usb_rx_count;
        dbg[dbg_i].rx_pos = ao_usb_rx_pos;
        dbg[dbg_i].out_avail = ao_usb_out_avail;
-       dbg[dbg_i].out_ep = *ao_usb_epn_out(AO_USB_OUT_EP);
+       dbg[dbg_i].out_ep = *ao_usb_epn_out(AO_USB_OUT_EP, 0);
 #endif
        if (++dbg_i == NUM_USB_DBG)
                dbg_i = 0;
diff --git a/src/microsplash/.gitignore b/src/microsplash/.gitignore
new file mode 100644 (file)
index 0000000..5f6fe3b
--- /dev/null
@@ -0,0 +1,2 @@
+ao_product.h
+microsplash-*
diff --git a/src/microsplash/Makefile b/src/microsplash/Makefile
new file mode 100644 (file)
index 0000000..10cb825
--- /dev/null
@@ -0,0 +1,121 @@
+#
+# Tiny AltOS build
+#
+#
+vpath % ../attiny:../drivers:../kernel:../product:..
+vpath ao-make-product.5c ../util
+vpath make-altitude-pa ../util
+
+include ../avr/Makefile.defs
+
+PUBLISH_DIR=$(HOME)/altusmetrumllc/Binaries
+PUBLISH_FILE=$(PUBLISH_DIR)/$(PROG)-$(VERSION).hex
+
+MCU=attiny85
+DUDECPUTYPE=t85
+#PROGRAMMER=stk500v2 -P usb
+LOADSLOW=-i 32 -B 32
+LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w:
+
+#LDFLAGS=-L$(LDSCRIPTS) -Tavr25.x
+
+ALTOS_SRC = \
+       ao_micropeak.c \
+       ao_spi_attiny.c \
+       ao_led.c \
+       ao_clock.c \
+       ao_ms5607.c \
+       ao_exti.c \
+       ao_convert_pa.c \
+       ao_report_micro.c \
+       ao_notask.c \
+       ao_eeprom_tiny.c \
+       ao_panic.c \
+       ao_log_micro.c \
+       ao_async.c \
+       ao_microflight.c \
+       ao_microkalman.c
+
+INC=\
+       ao.h \
+       ao_pins.h \
+       ao_arch.h \
+       ao_arch_funcs.h \
+       ao_exti.h \
+       ao_ms5607.h \
+       ao_log_micro.h \
+       ao_micropeak.h \
+       altitude-pa.h
+
+IDPRODUCT=0
+PRODUCT=MicroSplash-v0.1
+PRODUCT_DEF=-DMICROPEAK
+CFLAGS = $(PRODUCT_DEF) -I. -I../attiny -I../kernel -I.. -I../drivers -I../product
+CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O2 -mcall-prologues -DATTINY
+
+NICKLE=nickle
+
+PROG=microsplash-v1.0
+
+SRC=$(ALTOS_SRC)
+OBJ=$(SRC:.c=.o)
+
+V=0
+# The user has explicitly enabled quiet compilation.
+ifeq ($(V),0)
+quiet = @printf "  $1 $2 $@\n"; $($1)
+endif
+# Otherwise, print the full command line.
+quiet ?= $($1)
+
+all: $(PROG) $(PROG).hex
+
+CHECK=sh ../util/check-avr-mem
+
+$(PROG): Makefile $(OBJ)
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ)
+       $(call quiet,CHECK) $(PROG) || ($(RM) -f $(PROG); exit 1)
+
+$(PROG).hex: $(PROG)
+       avr-size $(PROG)
+       $(OBJCOPY) -R .eeprom -O ihex $(PROG) $@
+
+
+load: $(PROG).hex
+       $(LOADCMD) $(LOADARG)$(PROG).hex
+
+load-slow: $(PROG).hex
+       $(LOADCMD) $(LOADSLOW) $(LOADARG)$(PROG).hex
+
+ao_product.h: ao-make-product.5c ../Version
+       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+ao_product.o: ao_product.c ao_product.h
+
+%.o : %.c $(INC)
+       $(call quiet,CC) -c $(CFLAGS) $<
+
+distclean:     clean
+
+clean:
+       rm -f *.o $(PROG) $(PROG).hex
+       rm -f ao_product.h
+
+
+publish: $(PROG).hex
+       cp -a $(PROG).hex $(PUBLISH_FILE)
+
+load-product:
+       $(LOADCMD) $(LOADARG)$(PUBLISH_FILE)
+
+load-product-slow:
+       $(LOADCMD) $(LOADSLOW) $(LOADARG)$(PUBLISH_FILE)
+
+../altitude-pa.h: make-altitude-pa
+       nickle $< > $@
+
+install:
+
+uninstall:
+
+$(OBJ): ao_product.h $(INC)
diff --git a/src/microsplash/ao_pins.h b/src/microsplash/ao_pins.h
new file mode 100644 (file)
index 0000000..37885ec
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+#include <avr/pgmspace.h>
+
+#define AO_LED_ORANGE          (1<<4)
+#define AO_LED_SERIAL          4
+#define AO_LED_PANIC           AO_LED_ORANGE
+#define AO_LED_REPORT          AO_LED_ORANGE
+#define LEDS_AVAILABLE         (AO_LED_ORANGE)
+#define USE_SERIAL_1_STDIN     0
+#define HAS_USB                        0
+#define PACKET_HAS_SLAVE       0
+#define HAS_SERIAL_1           0
+#define HAS_TASK               0
+#define HAS_MS5607             1
+#define HAS_MS5611             0
+#define HAS_EEPROM             0
+#define HAS_BEEP               0
+#define AVR_CLOCK              250000UL
+
+/* SPI */
+#define SPI_PORT               PORTB
+#define SPI_PIN                        PINB
+#define SPI_DIR                        DDRB
+#define AO_MS5607_CS_PORT      PORTB
+#define AO_MS5607_CS_PIN       3
+
+/* MS5607 */
+#define AO_MS5607_SPI_INDEX    0
+#define AO_MS5607_MISO_PORT    PORTB
+#define AO_MS5607_MISO_PIN     0
+#define AO_MS5607_BARO_OVERSAMPLE      4096
+#define AO_MS5607_TEMP_OVERSAMPLE      1024
+
+/* I2C */
+#define I2C_PORT               PORTB
+#define I2C_PIN                        PINB
+#define I2C_DIR                        DDRB
+#define I2C_PIN_SCL            PINB2
+#define I2C_PIN_SDA            PINB0
+
+#define AO_CONST_ATTRIB                PROGMEM
+typedef int32_t alt_t;
+#define FETCH_ALT(o)           ((alt_t) pgm_read_dword(&altitude_table[o]))
+
+#define AO_ALT_VALUE(x)                ((x) * (alt_t) 10)
+
+/* Pressure change (in Pa) to detect boost */
+#ifndef BOOST_DETECT
+#define BOOST_DETECT           120     /* 10m at sea level, 12m at 2000m */
+#endif
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/microwater/.gitignore b/src/microwater/.gitignore
deleted file mode 100644 (file)
index 0573d98..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-ao_product.h
-microwater-*
diff --git a/src/microwater/Makefile b/src/microwater/Makefile
deleted file mode 100644 (file)
index a49cda4..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-#
-# Tiny AltOS build
-#
-#
-vpath % ../attiny:../drivers:../kernel:../product:..
-vpath ao-make-product.5c ../util
-vpath make-altitude-pa ../util
-
-include ../avr/Makefile.defs
-
-PUBLISH_DIR=$(HOME)/altusmetrumllc/Binaries
-PUBLISH_FILE=$(PUBLISH_DIR)/$(PROG)-$(VERSION).hex
-
-MCU=attiny85
-DUDECPUTYPE=t85
-#PROGRAMMER=stk500v2 -P usb
-LOADSLOW=-i 32 -B 32
-LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w:
-
-#LDFLAGS=-L$(LDSCRIPTS) -Tavr25.x
-
-ALTOS_SRC = \
-       ao_micropeak.c \
-       ao_spi_attiny.c \
-       ao_led.c \
-       ao_clock.c \
-       ao_ms5607.c \
-       ao_exti.c \
-       ao_convert_pa.c \
-       ao_report_micro.c \
-       ao_notask.c \
-       ao_eeprom_tiny.c \
-       ao_panic.c \
-       ao_log_micro.c \
-       ao_async.c \
-       ao_microflight.c \
-       ao_microkalman.c
-
-INC=\
-       ao.h \
-       ao_pins.h \
-       ao_arch.h \
-       ao_arch_funcs.h \
-       ao_exti.h \
-       ao_ms5607.h \
-       ao_log_micro.h \
-       ao_micropeak.h \
-       altitude-pa.h
-
-IDPRODUCT=0
-PRODUCT=MicroWater-v0.1
-PRODUCT_DEF=-DMICROPEAK
-CFLAGS = $(PRODUCT_DEF) -I. -I../attiny -I../kernel -I.. -I../drivers -I../product
-CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O2 -mcall-prologues -DATTINY
-
-NICKLE=nickle
-
-PROG=microwater-v0.1
-
-SRC=$(ALTOS_SRC)
-OBJ=$(SRC:.c=.o)
-
-V=0
-# The user has explicitly enabled quiet compilation.
-ifeq ($(V),0)
-quiet = @printf "  $1 $2 $@\n"; $($1)
-endif
-# Otherwise, print the full command line.
-quiet ?= $($1)
-
-all: $(PROG) $(PROG).hex
-
-CHECK=sh ../util/check-avr-mem
-
-$(PROG): Makefile $(OBJ)
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ)
-       $(call quiet,CHECK) $(PROG) || ($(RM) -f $(PROG); exit 1)
-
-$(PROG).hex: $(PROG)
-       avr-size $(PROG)
-       $(OBJCOPY) -R .eeprom -O ihex $(PROG) $@
-
-
-load: $(PROG).hex
-       $(LOADCMD) $(LOADARG)$(PROG).hex
-
-load-slow: $(PROG).hex
-       $(LOADCMD) $(LOADSLOW) $(LOADARG)$(PROG).hex
-
-ao_product.h: ao-make-product.5c ../Version
-       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
-
-ao_product.o: ao_product.c ao_product.h
-
-%.o : %.c $(INC)
-       $(call quiet,CC) -c $(CFLAGS) $<
-
-distclean:     clean
-
-clean:
-       rm -f *.o $(PROG) $(PROG).hex
-       rm -f ao_product.h
-
-
-publish: $(PROG).hex
-       cp -a $(PROG).hex $(PUBLISH_FILE)
-
-load-product:
-       $(LOADCMD) $(LOADARG)$(PUBLISH_FILE)
-
-load-product-slow:
-       $(LOADCMD) $(LOADSLOW) $(LOADARG)$(PUBLISH_FILE)
-
-../altitude-pa.h: make-altitude-pa
-       nickle $< > $@
-
-install:
-
-uninstall:
-
-$(OBJ): ao_product.h $(INC)
diff --git a/src/microwater/ao_pins.h b/src/microwater/ao_pins.h
deleted file mode 100644 (file)
index 37885ec..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef _AO_PINS_H_
-#define _AO_PINS_H_
-#include <avr/pgmspace.h>
-
-#define AO_LED_ORANGE          (1<<4)
-#define AO_LED_SERIAL          4
-#define AO_LED_PANIC           AO_LED_ORANGE
-#define AO_LED_REPORT          AO_LED_ORANGE
-#define LEDS_AVAILABLE         (AO_LED_ORANGE)
-#define USE_SERIAL_1_STDIN     0
-#define HAS_USB                        0
-#define PACKET_HAS_SLAVE       0
-#define HAS_SERIAL_1           0
-#define HAS_TASK               0
-#define HAS_MS5607             1
-#define HAS_MS5611             0
-#define HAS_EEPROM             0
-#define HAS_BEEP               0
-#define AVR_CLOCK              250000UL
-
-/* SPI */
-#define SPI_PORT               PORTB
-#define SPI_PIN                        PINB
-#define SPI_DIR                        DDRB
-#define AO_MS5607_CS_PORT      PORTB
-#define AO_MS5607_CS_PIN       3
-
-/* MS5607 */
-#define AO_MS5607_SPI_INDEX    0
-#define AO_MS5607_MISO_PORT    PORTB
-#define AO_MS5607_MISO_PIN     0
-#define AO_MS5607_BARO_OVERSAMPLE      4096
-#define AO_MS5607_TEMP_OVERSAMPLE      1024
-
-/* I2C */
-#define I2C_PORT               PORTB
-#define I2C_PIN                        PINB
-#define I2C_DIR                        DDRB
-#define I2C_PIN_SCL            PINB2
-#define I2C_PIN_SDA            PINB0
-
-#define AO_CONST_ATTRIB                PROGMEM
-typedef int32_t alt_t;
-#define FETCH_ALT(o)           ((alt_t) pgm_read_dword(&altitude_table[o]))
-
-#define AO_ALT_VALUE(x)                ((x) * (alt_t) 10)
-
-/* Pressure change (in Pa) to detect boost */
-#ifndef BOOST_DETECT
-#define BOOST_DETECT           120     /* 10m at sea level, 12m at 2000m */
-#endif
-
-#endif /* _AO_PINS_H_ */
index 7ad3b4b8d97cffd47bac2cf83484d9942cafb892..42f1a2e5d75c5aeb4680dbf12c7c9b0f039e9ebb 100644 (file)
@@ -74,7 +74,7 @@ void
 ao_spi_put(uint8_t spi_index);
 
 void
-ao_spi_send(void *block, uint16_t len, uint8_t spi_index);
+ao_spi_send(const void *block, uint16_t len, uint8_t spi_index);
 
 void
 ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index);
index 0acab1065b82cb9440c25e7e553e457fdf4db519..9b61cf622e6f7e1fef9a05e47b4663b49a3f9c8d 100644 (file)
@@ -86,7 +86,7 @@ ao_led_for(uint16_t colors, uint16_t ticks) __reentrant
                stm_moder_set(port, bit, STM_MODER_OUTPUT);             \
                stm_otyper_set(port, bit, STM_OTYPER_PUSH_PULL);        \
        } while (0)
-       
+
 void
 ao_led_init(uint16_t enable)
 {
index 2133c5845e0ca33233332ffc7717ad87ab49b6be..2568cf430fe5cb92eccc751ae463d2e8c8ccf796 100644 (file)
@@ -63,7 +63,7 @@ int
 _ao_usart_pollchar(struct ao_stm_usart *usart)
 {
        int     c;
-       
+
        if (ao_fifo_empty(usart->rx_fifo))
                c = AO_READ_AGAIN;
        else {
@@ -85,6 +85,12 @@ ao_usart_getchar(struct ao_stm_usart *usart)
        return (char) c;
 }
 
+static inline uint8_t
+_ao_usart_sleep(struct ao_stm_usart *usart)
+{
+       return ao_sleep(&usart->rx_fifo);
+}
+
 void
 ao_usart_putchar(struct ao_stm_usart *usart, char c)
 {
@@ -179,6 +185,13 @@ ao_usart_init(struct ao_stm_usart *usart)
        ao_usart_set_speed(usart, AO_SERIAL_SPEED_9600);
 }
 
+void
+ao_usart_set_flow(struct ao_stm_usart *usart)
+{
+       usart->reg->cr3 |= ((1 << STM_USART_CR3_CTSE) |
+                           (1 << STM_USART_CR3_RTSE));
+}
+
 #if HAS_SERIAL_1
 
 struct ao_stm_usart ao_stm_usart1;
@@ -203,6 +216,18 @@ _ao_serial1_pollchar(void)
        return _ao_usart_pollchar(&ao_stm_usart1);
 }
 
+uint8_t
+_ao_serial1_sleep(void)
+{
+       return _ao_usart_sleep(&ao_stm_usart1);
+}
+
+void
+ao_serial1_drain(void)
+{
+       ao_usart_drain(&ao_stm_usart1);
+}
+
 void
 ao_serial1_set_speed(uint8_t speed)
 {
@@ -234,6 +259,18 @@ _ao_serial2_pollchar(void)
        return _ao_usart_pollchar(&ao_stm_usart2);
 }
 
+uint8_t
+_ao_serial2_sleep(void)
+{
+       return _ao_usart_sleep(&ao_stm_usart2);
+}
+
+void
+ao_serial2_drain(void)
+{
+       ao_usart_drain(&ao_stm_usart2);
+}
+
 void
 ao_serial2_set_speed(uint8_t speed)
 {
@@ -265,6 +302,12 @@ _ao_serial3_pollchar(void)
        return _ao_usart_pollchar(&ao_stm_usart3);
 }
 
+uint8_t
+_ao_serial3_sleep(void)
+{
+       return _ao_usart_sleep(&ao_stm_usart3);
+}
+
 void
 ao_serial3_set_speed(uint8_t speed)
 {
@@ -305,7 +348,7 @@ ao_serial_init(void)
 
        stm_nvic_set_enable(STM_ISR_USART1_POS);
        stm_nvic_set_priority(STM_ISR_USART1_POS, 4);
-#if USE_SERIAL_1_STDIN
+#if USE_SERIAL_1_STDIN && !DELAY_SERIAL_1_STDIN
        ao_add_stdio(_ao_serial1_pollchar,
                     ao_serial1_putchar,
                     NULL);
@@ -324,25 +367,35 @@ ao_serial_init(void)
 
        stm_afr_set(&stm_gpioa, 2, STM_AFR_AF7);
        stm_afr_set(&stm_gpioa, 3, STM_AFR_AF7);
+#if USE_SERIAL_2_FLOW
+       stm_afr_set(&stm_gpioa, 0, STM_AFR_AF7);
+       stm_afr_set(&stm_gpioa, 1, STM_AFR_AF7);
+#endif
 #else
 #if SERIAL_2_PD5_PD6
        stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN);
 
        stm_afr_set(&stm_gpiod, 5, STM_AFR_AF7);
        stm_afr_set(&stm_gpiod, 6, STM_AFR_AF7);
+#if USE_SERIAL_2_FLOW
+#error "Don't know how to set flowcontrol for serial 2 on PD"
+#endif
 #else
 #error "No SERIAL_2 port configuration specified"
-#endif 
+#endif
 #endif
        /* Enable USART */
        stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USART2EN);
 
        ao_stm_usart2.reg = &stm_usart2;
        ao_usart_init(&ao_stm_usart2);
+#if USE_SERIAL_2_FLOW
+       ao_usart_set_flow(&ao_stm_usart2);
+#endif
 
        stm_nvic_set_enable(STM_ISR_USART2_POS);
        stm_nvic_set_priority(STM_ISR_USART2_POS, 4);
-#if USE_SERIAL_2_STDIN
+#if USE_SERIAL_2_STDIN && !DELAY_SERIAL_2_STDIN
        ao_add_stdio(_ao_serial2_pollchar,
                     ao_serial2_putchar,
                     NULL);
@@ -386,12 +439,10 @@ ao_serial_init(void)
 
        stm_nvic_set_enable(STM_ISR_USART3_POS);
        stm_nvic_set_priority(STM_ISR_USART3_POS, 4);
-#if USE_SERIAL_3_STDIN
+#if USE_SERIAL_3_STDIN && !DELAY_SERIAL_3_STDIN
        ao_add_stdio(_ao_serial3_pollchar,
                     ao_serial3_putchar,
                     NULL);
 #endif
 #endif
 }
-
-
index 885af54466a8f41567604f336fce8da0bcf03477..7eaa392418438ea56c9c7c4ae774ef6a52b0bed1 100644 (file)
@@ -42,7 +42,7 @@ static const struct ao_spi_stm_info ao_spi_stm_info[STM_NUM_SPI] = {
 static uint8_t spi_dev_null;
 
 void
-ao_spi_send(void *block, uint16_t len, uint8_t spi_index)
+ao_spi_send(const void *block, uint16_t len, uint8_t spi_index)
 {
        struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
        uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index;
@@ -51,7 +51,7 @@ ao_spi_send(void *block, uint16_t len, uint8_t spi_index)
        /* Set up the transmit DMA to deliver data */
        ao_dma_set_transfer(mosi_dma_index,
                            &stm_spi->dr,
-                           block,
+                           (void *) block,
                            len,
                            (0 << STM_DMA_CCR_MEM2MEM) |
                            (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
diff --git a/src/stmf0/Makefile-flash.defs b/src/stmf0/Makefile-flash.defs
new file mode 100644 (file)
index 0000000..706b93e
--- /dev/null
@@ -0,0 +1,61 @@
+include $(TOPDIR)/stmf0/Makefile-stmf0.defs
+
+INC = \
+       ao.h \
+       ao_arch.h \
+       ao_arch_funcs.h \
+       ao_flash_pins.h \
+       ao_flash_stm_pins.h \
+       ao_flash_task.h \
+       ao_pins.h \
+       ao_product.h \
+       Makefile
+
+#
+# Common AltOS sources
+#
+SRC = \
+       ao_interrupt.c \
+       ao_romconfig.c \
+       ao_boot_chain.c \
+       ao_boot_pin.c \
+       ao_product.c \
+       ao_notask.c \
+       ao_timer.c \
+       ao_usb_stm.c \
+       ao_flash_stm.c \
+       ao_flash_task.c \
+       ao_flash_loader_stm.c
+
+OBJ=$(SRC:.c=.o)
+
+PRODUCT=AltosFlash
+PRODUCT_DEF=-DALTOS_FLASH
+IDPRODUCT=0x000a
+
+CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -g -Os
+
+LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stmf0 -Wl,-Taltos-loader.ld
+
+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) > $@
+
+$(OBJ): $(INC)
+
+all: $(PROG)
+
+distclean:     clean
+
+clean:
+       rm -f *.o $(HARDWARE)-$(PROGNAME)-*.elf
+       rm -f ao_product.h
+
+install:
+
+uninstall:
diff --git a/src/stmf0/Makefile-stmf0.defs b/src/stmf0/Makefile-stmf0.defs
new file mode 100644 (file)
index 0000000..4862f46
--- /dev/null
@@ -0,0 +1,47 @@
+ifndef TOPDIR
+TOPDIR=..
+endif
+
+include $(TOPDIR)/Makedefs
+
+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
+
+.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
+
+AO_CFLAGS=-I. -I$(TOPDIR)/stmf0 -I$(TOPDIR)/kernel -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) -I$(TOPDIR)/math $(PDCLIB_INCLUDES) 
+STMF0_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m0 -mthumb\
+       -ffreestanding -nostdlib $(AO_CFLAGS) $(WARN_FLAGS)
+
+NICKLE=nickle
+
+LIBS=$(PDCLIB_LIBS_M0) -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 $@ $<
diff --git a/src/stmf0/Makefile.defs b/src/stmf0/Makefile.defs
new file mode 100644 (file)
index 0000000..a1d93eb
--- /dev/null
@@ -0,0 +1,9 @@
+ifndef TOPDIR
+TOPDIR=..
+endif
+
+include $(TOPDIR)/stmf0/Makefile-stmf0.defs
+
+LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stmf0 -Wl,-Taltos.ld
+
+.DEFAULT_GOAL=all
diff --git a/src/stmf0/altos-loader.ld b/src/stmf0/altos-loader.ld
new file mode 100644 (file)
index 0000000..86cf183
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+MEMORY {
+       rom : ORIGIN = 0x08000000, LENGTH = 4K
+       ram : ORIGIN = 0x20000000, LENGTH = 6K
+}
+
+INCLUDE registers.ld
+
+EXTERN (stm_interrupt_vector)
+
+SECTIONS {
+       /*
+        * Rom contents
+        */
+
+       .interrupt : {
+               __text_start__ = .;
+               *(.interrupt)   /* Interrupt vectors */
+       } > rom
+
+       .text ORIGIN(rom) + 0x100 : {
+               ao_romconfig.o(.romconfig*)
+               ao_product.o(.romconfig*)
+
+               *(.text*)       /* Executable code */
+               *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+               *(.rodata*)     /* Constants */
+       } > rom
+       __text_end__ = .;
+
+       /* Boot data which must live at the start of ram so that
+        * the application and bootloader share the same addresses.
+        * This must be all uninitialized data
+        */
+       .boot ORIGIN(ram) + SIZEOF(.interrupt) (NOLOAD) : {
+               __boot_start__ = .;
+               *(.boot)
+               __boot_end__ = .;
+       } >ram
+
+       /* Functions placed in RAM (required for flashing)
+        *
+        * Align to 8 bytes as that's what the ARM likes text
+        * segment alignments to be, and if we don't, then
+        * we end up with a mismatch between the location in
+        * ROM and the desired location in RAM. I don't
+        * entirely understand this, but at least this appears
+        * to work...
+        */
+
+       .textram BLOCK(8): {
+               __data_start__ = .;
+               __text_ram_start__ = .;
+               *(.ramtext)
+               __text_ram_end = .;
+       } >ram AT>rom
+
+       /* Data -- relocated to RAM, but written to ROM
+        */
+       .data : {
+               *(.data)        /* initialized data */
+               __data_end__ = .;
+       } >ram AT>rom
+
+
+       .bss : {
+               __bss_start__ = .;
+               *(.bss)
+               *(COMMON)
+               __bss_end__ = .;
+       } >ram
+
+       PROVIDE(__stack__ = ORIGIN(ram) + LENGTH(ram));
+       PROVIDE(end = .);
+}
+
+ENTRY(start);
+
+
diff --git a/src/stmf0/altos.ld b/src/stmf0/altos.ld
new file mode 100644 (file)
index 0000000..9dbc83d
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+MEMORY {
+       rom (rx) :   ORIGIN = 0x08001000, LENGTH = 28K
+       ram (!w) :   ORIGIN = 0x20000000, LENGTH = 6k - 128
+       stack (!w) : ORIGIN = 0x20000000 + 6k - 128, LENGTH = 128
+}
+
+INCLUDE registers.ld
+
+EXTERN (stm_interrupt_vector)
+
+SECTIONS {
+       /*
+        * Rom contents
+        */
+
+       .interrupt ORIGIN(ram) : AT (ORIGIN(rom)) {
+               __interrupt_start__ = .;
+               __interrupt_rom__ = ORIGIN(rom);
+               *(.interrupt)   /* Interrupt vectors */
+               __interrupt_end__ = .;
+       } > ram
+
+       .text ORIGIN(rom) + 0x100 : {
+               __text_start__ = .;
+
+               /* Ick. What I want is to specify the
+                * addresses of some global constants so
+                * that I can find them across versions
+                * of the application. I can't figure out
+                * how to make gnu ld do that, so instead
+                * we just load the two files that include
+                * these defines in the right order here and
+                * expect things to 'just work'. Don't change
+                * the contents of those files, ok?
+                */
+               ao_romconfig.o(.romconfig*)
+               ao_product.o(.romconfig*)
+
+               *(.text*)       /* Executable code */
+               *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+               *(.rodata*)     /* Constants */
+
+       } > rom
+       __text_end__ = .;
+
+       /* Boot data which must live at the start of ram so that
+        * the application and bootloader share the same addresses.
+        * This must be all uninitialized data
+        */
+       .boot (NOLOAD) : {
+               __boot_start__ = .;
+               *(.boot)
+               . = ALIGN(4);
+               __boot_end__ = .;
+       } >ram
+
+       /* Data -- relocated to RAM, but written to ROM
+        */
+       .data : {
+               __data_start__ = .;
+               *(.data)        /* initialized data */
+               . = ALIGN(4);
+               __data_end__ = .;
+       } >ram AT>rom
+
+       .bss : {
+               __bss_start__ = .;
+               *(.bss)
+               *(COMMON)
+               . = ALIGN(4);
+               __bss_end__ = .;
+       } >ram
+
+       PROVIDE(end = .);
+
+       PROVIDE(__stack__ = ORIGIN(stack) + LENGTH(stack));
+}
+
+ENTRY(start);
+
+
diff --git a/src/stmf0/ao_adc_fast.c b/src/stmf0/ao_adc_fast.c
new file mode 100644 (file)
index 0000000..be9b598
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Copyright © 2015 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_adc_fast.h>
+
+uint16_t ao_adc_ring[AO_ADC_RING_SIZE];
+
+uint16_t ao_adc_ring_head, ao_adc_ring_tail;
+uint8_t ao_adc_running;
+
+/*
+ * Callback from DMA ISR
+ *
+ * Mark time in ring, shut down DMA engine
+ */
+static void ao_adc_dma_done(int index)
+{
+       (void) index;
+       ao_adc_ring_head += AO_ADC_RING_CHUNK;
+       if (ao_adc_ring_head == AO_ADC_RING_SIZE)
+               ao_adc_ring_head = 0;
+       ao_adc_running = 0;
+       ao_wakeup(&ao_adc_ring_head);
+       ao_dma_done_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1));
+}
+
+void
+_ao_adc_start(void)
+{
+       uint16_t        *buf;
+
+       if (ao_adc_running)
+               return;
+       if (_ao_adc_space() < AO_ADC_RING_CHUNK)
+               return;
+       ao_adc_running = 1;
+       buf = ao_adc_ring + ao_adc_ring_head;
+       stm_adc.isr = 0;
+       ao_dma_set_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1),
+                           &stm_adc.dr,
+                           buf,
+                           AO_ADC_RING_CHUNK,
+                           (0 << STM_DMA_CCR_MEM2MEM) |
+                           (STM_DMA_CCR_PL_HIGH << 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_set_isr(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1), ao_adc_dma_done);
+       ao_dma_start(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1));
+
+       stm_adc.cr |= (1 << STM_ADC_CR_ADSTART);
+}
+
+void
+ao_adc_init(void)
+{
+       uint32_t        chselr;
+       int             i;
+
+       /* Reset ADC */
+       stm_rcc.apb2rstr |= (1 << STM_RCC_APB2RSTR_ADCRST);
+       stm_rcc.apb2rstr &= ~(1 << STM_RCC_APB2RSTR_ADCRST);
+
+       /* Turn on ADC pins */
+       stm_rcc.ahbenr |= AO_ADC_RCC_AHBENR;
+
+#ifdef AO_ADC_PIN0_PORT
+       stm_moder_set(AO_ADC_PIN0_PORT, AO_ADC_PIN0_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN1_PORT
+       stm_moder_set(AO_ADC_PIN1_PORT, AO_ADC_PIN1_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN2_PORT
+       stm_moder_set(AO_ADC_PIN2_PORT, AO_ADC_PIN2_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN3_PORT
+       stm_moder_set(AO_ADC_PIN3_PORT, AO_ADC_PIN3_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN4_PORT
+       stm_moder_set(AO_ADC_PIN4_PORT, AO_ADC_PIN4_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN5_PORT
+       stm_moder_set(AO_ADC_PIN5_PORT, AO_ADC_PIN5_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN6_PORT
+       stm_moder_set(AO_ADC_PIN6_PORT, AO_ADC_PIN6_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN7_PORT
+       stm_moder_set(AO_ADC_PIN7_PORT, AO_ADC_PIN7_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN24_PORT
+       #error "Too many ADC ports"
+#endif
+
+       stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_ADCEN);
+
+       chselr = 0;
+#if AO_NUM_ADC > 0
+       chselr |= (1 << AO_ADC_PIN0_CH);
+#endif
+#if AO_NUM_ADC > 1
+       chselr |= (1 << AO_ADC_PIN1_CH);
+#endif
+#if AO_NUM_ADC > 2
+       chselr |= (1 << AO_ADC_PIN2_CH);
+#endif
+#if AO_NUM_ADC > 3
+       chselr |= (1 << AO_ADC_PIN3_CH);
+#endif
+#if AO_NUM_ADC > 4
+       chselr |= (1 << AO_ADC_PIN4_CH);
+#endif
+#if AO_NUM_ADC > 5
+       chselr |= (1 << AO_ADC_PIN5_CH);
+#endif
+#if AO_NUM_ADC > 6
+       chselr |= (1 << AO_ADC_PIN6_CH);
+#endif
+#if AO_NUM_ADC > 7
+       chselr |= (1 << AO_ADC_PIN7_CH);
+#endif
+#if AO_NUM_ADC > 8
+#error Need more ADC defines
+#endif
+       stm_adc.chselr = chselr;
+
+       /* Set the clock */
+       stm_adc.cfgr2 = STM_ADC_CFGR2_CKMODE_PCLK_2 << STM_ADC_CFGR2_CKMODE;
+
+       /* Shortest sample time */
+       stm_adc.smpr = STM_ADC_SMPR_SMP_1_5 << STM_ADC_SMPR_SMP;
+
+       /* Calibrate */
+       stm_adc.cr |= (1 << STM_ADC_CR_ADCAL);
+       for (i = 0; i < 0xf000; i++) {
+               if ((stm_adc.cr & (1 << STM_ADC_CR_ADCAL)) == 0)
+                       break;
+       }
+
+       /* Enable */
+       stm_adc.cr |= (1 << STM_ADC_CR_ADEN);
+       while ((stm_adc.isr & (1 << STM_ADC_ISR_ADRDY)) == 0)
+               ;
+
+       stm_adc.cfgr1 = ((0 << STM_ADC_CFGR1_AWDCH) |
+                        (0 << STM_ADC_CFGR1_AWDEN) |
+                        (0 << STM_ADC_CFGR1_AWDSGL) |
+                        (0 << STM_ADC_CFGR1_DISCEN) |
+                        (0 << STM_ADC_CFGR1_AUTOOFF) |
+                        (1 << STM_ADC_CFGR1_WAIT) |
+                        (1 << STM_ADC_CFGR1_CONT) |
+                        (0 << STM_ADC_CFGR1_OVRMOD) |
+                        (STM_ADC_CFGR1_EXTEN_DISABLE << STM_ADC_CFGR1_EXTEN) |
+                        (0 << STM_ADC_CFGR1_ALIGN) |
+                        (STM_ADC_CFGR1_RES_12 << STM_ADC_CFGR1_RES) |
+                        (STM_ADC_CFGR1_SCANDIR_UP << STM_ADC_CFGR1_SCANDIR) |
+                        (STM_ADC_CFGR1_DMACFG_ONESHOT << STM_ADC_CFGR1_DMACFG) |
+                        (1 << STM_ADC_CFGR1_DMAEN));
+       stm_adc.ccr = 0;
+
+       /* Clear any stale status bits */
+       stm_adc.isr = 0;
+
+       /* Turn on syscfg */
+       stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SYSCFGCOMPEN);
+
+       /* Set ADC to use DMA channel 1 (option 1) */
+       stm_syscfg.cfgr1 &= ~(1 << STM_SYSCFG_CFGR1_ADC_DMA_RMP);
+
+       ao_dma_alloc(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1));
+       ao_dma_set_isr(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1), ao_adc_dma_done);
+}
diff --git a/src/stmf0/ao_adc_fast.h b/src/stmf0/ao_adc_fast.h
new file mode 100644 (file)
index 0000000..eec4550
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright © 2015 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_ADC_FAST_H_
+#define _AO_ADC_FAST_H_
+
+void
+ao_adc_read(uint16_t *dest, int len);
+
+void
+ao_adc_init(void);
+
+/* Total ring size in samples */
+#define AO_ADC_RING_SIZE       256
+/* Number of samples fetched per ao_adc_start call */
+#define AO_ADC_RING_CHUNK      (AO_ADC_RING_SIZE >> 1)
+
+extern uint16_t        ao_adc_ring[AO_ADC_RING_SIZE];
+
+#define ao_adc_ring_step(pos,inc)      (((pos) + (inc)) & (AO_ADC_RING_SIZE - 1))
+
+extern uint16_t        ao_adc_ring_head, ao_adc_ring_tail;
+extern uint8_t ao_adc_running;
+
+void
+_ao_adc_start(void);
+
+static inline uint16_t
+_ao_adc_remain(void)
+{
+       if (ao_adc_ring_tail > ao_adc_ring_head)
+               return AO_ADC_RING_SIZE - ao_adc_ring_tail;
+       return ao_adc_ring_head - ao_adc_ring_tail;
+}
+
+static inline uint16_t
+_ao_adc_space(void)
+{
+       if (ao_adc_ring_head == ao_adc_ring_tail)
+               return AO_ADC_RING_SIZE;
+       if (ao_adc_ring_head > ao_adc_ring_tail)
+               return AO_ADC_RING_SIZE - ao_adc_ring_head;
+       return ao_adc_ring_tail - ao_adc_ring_head;
+}
+
+static inline uint16_t *
+ao_adc_get(uint16_t n)
+{
+       if (ao_adc_ring_tail + n > AO_ADC_RING_SIZE)
+               ao_panic(AO_PANIC_ADC);
+       ao_arch_block_interrupts();
+       while (_ao_adc_remain() < n) {
+               if (!ao_adc_running)
+                       _ao_adc_start();
+               ao_sleep(&ao_adc_ring_head);
+       }
+       ao_arch_release_interrupts();
+       return &ao_adc_ring[ao_adc_ring_tail];
+}
+
+static inline void
+ao_adc_ack(uint16_t n)
+{
+       if (ao_adc_ring_tail + n > AO_ADC_RING_SIZE)
+               ao_panic(AO_PANIC_ADC);
+       ao_arch_block_interrupts();
+       ao_adc_ring_tail += n;
+       if (ao_adc_ring_tail == AO_ADC_RING_SIZE)
+               ao_adc_ring_tail = 0;
+       if (!ao_adc_running && _ao_adc_space() >= AO_ADC_RING_CHUNK)
+               _ao_adc_start();
+       ao_arch_release_interrupts();
+}
+
+#endif /* _AO_ADC_FAST_H_ */
diff --git a/src/stmf0/ao_arch.h b/src/stmf0/ao_arch.h
new file mode 100644 (file)
index 0000000..6ee71ef
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_ARCH_H_
+#define _AO_ARCH_H_
+
+#include <stdio.h>
+#include <stm32f0.h>
+
+/*
+ * STM32F0 definitions and code fragments for AltOS
+ */
+
+#define AO_STACK_SIZE  512
+
+#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 */
+
+#define ao_arch_naked_declare  __attribute__((naked))
+#define ao_arch_naked_define
+#define __pdata
+#define __data
+#define __xdata
+#define __code const
+#define __reentrant
+#define __interrupt(n)
+#define __at(n)
+
+#define ao_arch_reboot() \
+       (stm_scb.aircr = ((STM_SCB_AIRCR_VECTKEY_KEY << STM_SCB_AIRCR_VECTKEY) | \
+                         (1 << STM_SCB_AIRCR_SYSRESETREQ)))
+
+#define ao_arch_nop()          asm("nop")
+
+#define ao_arch_interrupt(n)   /* nothing */
+
+#undef putchar
+#undef getchar
+#define putchar(c)     ao_putchar(c)
+#define getchar                ao_getchar
+
+extern void putchar(char c);
+extern char getchar(void);
+extern void ao_avr_stdio_init(void);
+
+
+/*
+ * ao_romconfig.c
+ */
+
+#define AO_ROMCONFIG_VERSION   2
+
+#define AO_ROMCONFIG_SYMBOL(a) __attribute__((section(".romconfig"))) const
+
+extern const uint16_t ao_romconfig_version;
+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")
+
+/*
+ * ao_timer.c
+ *
+ * For the stm32f042, we want to use the USB-based HSI48 clock
+ */
+
+#if AO_HSI48
+
+#define AO_SYSCLK      48000000
+#define AO_HCLK                (AO_SYSCLK / AO_AHB_PRESCALER)
+
+#endif
+
+#if AO_HSE || AO_HSI
+
+#if AO_HSE
+#define AO_PLLSRC      AO_HSE
+#else
+#define AO_PLLSRC      STM_HSI_FREQ
+#endif
+
+#define AO_PLLVCO      (AO_PLLSRC * AO_PLLMUL)
+#define AO_SYSCLK      (AO_PLLVCO / AO_PLLDIV)
+
+#endif
+
+#define AO_HCLK                (AO_SYSCLK / AO_AHB_PRESCALER)
+#define AO_PCLK1       (AO_HCLK / AO_APB1_PRESCALER)
+#define AO_PCLK2       (AO_HCLK / AO_APB2_PRESCALER)
+#define AO_SYSTICK     (AO_HCLK)
+
+#if AO_APB1_PRESCALER == 1
+#define AO_TIM23467_CLK                AO_PCLK1
+#else
+#define AO_TIM23467_CLK                (2 * AO_PCLK1)
+#endif
+
+#if AO_APB2_PRESCALER == 1
+#define AO_TIM91011_CLK                AO_PCLK2
+#else
+#define AO_TIM91011_CLK                (2 * AO_PCLK2)
+#endif
+
+#define AO_STM_NVIC_HIGH_PRIORITY      4
+#define AO_STM_NVIC_CLOCK_PRIORITY     6
+#define AO_STM_NVIC_MED_PRIORITY       8
+#define AO_STM_NVIC_LOW_PRIORITY       10
+
+void ao_lcd_stm_init(void);
+
+void ao_lcd_font_init(void);
+
+void ao_lcd_font_string(char *s);
+
+extern const uint32_t  ao_radio_cal;
+
+void
+ao_adc_init();
+
+/* ADC maximum reported value */
+#define AO_ADC_MAX                     4095
+
+#define AO_BOOT_APPLICATION_BASE       ((uint32_t *) 0x08001000)
+#define AO_BOOT_APPLICATION_BOUND      ((uint32_t *) (0x08000000 + stm_flash_size()))
+#define AO_BOOT_LOADER_BASE            ((uint32_t *) 0x08000000)
+#define HAS_BOOT_LOADER                        1
+
+#endif /* _AO_ARCH_H_ */
+
+
diff --git a/src/stmf0/ao_arch_funcs.h b/src/stmf0/ao_arch_funcs.h
new file mode 100644 (file)
index 0000000..3db96be
--- /dev/null
@@ -0,0 +1,400 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_ARCH_FUNCS_H_
+#define _AO_ARCH_FUNCS_H_
+
+/* ao_spi_stm.c
+ */
+
+/* PCLK is set to 16MHz (HCLK 32MHz, APB prescaler 2) */
+
+#define AO_SPI_SPEED_8MHz      STM_SPI_CR1_BR_PCLK_2
+#define AO_SPI_SPEED_4MHz      STM_SPI_CR1_BR_PCLK_4
+#define AO_SPI_SPEED_2MHz      STM_SPI_CR1_BR_PCLK_8
+#define AO_SPI_SPEED_1MHz      STM_SPI_CR1_BR_PCLK_16
+#define AO_SPI_SPEED_500kHz    STM_SPI_CR1_BR_PCLK_32
+#define AO_SPI_SPEED_250kHz    STM_SPI_CR1_BR_PCLK_64
+#define AO_SPI_SPEED_125kHz    STM_SPI_CR1_BR_PCLK_128
+#define AO_SPI_SPEED_62500Hz   STM_SPI_CR1_BR_PCLK_256
+
+#define AO_SPI_SPEED_FAST      AO_SPI_SPEED_8MHz
+
+/* Companion bus wants something no faster than 200kHz */
+
+#define AO_SPI_SPEED_200kHz    AO_SPI_SPEED_125kHz
+
+#define AO_SPI_CONFIG_1                0x00
+#define AO_SPI_1_CONFIG_PA5_PA6_PA7    AO_SPI_CONFIG_1
+#define AO_SPI_2_CONFIG_PB13_PB14_PB15 AO_SPI_CONFIG_1
+
+#define AO_SPI_CONFIG_2                0x04
+#define AO_SPI_1_CONFIG_PB3_PB4_PB5    AO_SPI_CONFIG_2
+#define AO_SPI_2_CONFIG_PD1_PD3_PD4    AO_SPI_CONFIG_2
+
+#define AO_SPI_CONFIG_3                0x08
+#define AO_SPI_1_CONFIG_PE13_PE14_PE15 AO_SPI_CONFIG_3
+
+#define AO_SPI_CONFIG_NONE     0x0c
+
+#define AO_SPI_INDEX_MASK      0x01
+#define AO_SPI_CONFIG_MASK     0x0c
+
+#define AO_SPI_1_PA5_PA6_PA7   (STM_SPI_INDEX(1) | AO_SPI_1_CONFIG_PA5_PA6_PA7)
+#define AO_SPI_1_PB3_PB4_PB5   (STM_SPI_INDEX(1) | AO_SPI_1_CONFIG_PB3_PB4_PB5)
+#define AO_SPI_1_PE13_PE14_PE15        (STM_SPI_INDEX(1) | AO_SPI_1_CONFIG_PE13_PE14_PE15)
+
+#define AO_SPI_2_PB13_PB14_PB15        (STM_SPI_INDEX(2) | AO_SPI_2_CONFIG_PB13_PB14_PB15)
+#define AO_SPI_2_PD1_PD3_PD4   (STM_SPI_INDEX(2) | AO_SPI_2_CONFIG_PD1_PD3_PD4)
+
+#define AO_SPI_INDEX(id)       ((id) & AO_SPI_INDEX_MASK)
+#define AO_SPI_CONFIG(id)      ((id) & AO_SPI_CONFIG_MASK)
+
+uint8_t
+ao_spi_try_get(uint8_t spi_index, uint32_t speed, uint8_t task_id);
+
+void
+ao_spi_get(uint8_t spi_index, uint32_t speed);
+
+void
+ao_spi_put(uint8_t spi_index);
+
+void
+ao_spi_send(const void *block, uint16_t len, uint8_t spi_index);
+
+void
+ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index);
+
+void
+ao_spi_send_sync(void *block, uint16_t len, uint8_t spi_index);
+
+void
+ao_spi_recv(void *block, uint16_t len, uint8_t spi_index);
+
+void
+ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index);
+
+extern uint16_t        ao_spi_speed[STM_NUM_SPI];
+
+void
+ao_spi_init(void);
+
+#define ao_spi_set_cs(reg,mask) ((reg)->bsrr = ((uint32_t) (mask)) << 16)
+#define ao_spi_clr_cs(reg,mask) ((reg)->bsrr = (mask))
+
+#define ao_spi_get_mask(reg,mask,bus, speed) do {              \
+               ao_spi_get(bus, speed);                         \
+               ao_spi_set_cs(reg,mask);                        \
+       } while (0)
+
+static inline uint8_t
+ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t speed, uint8_t task_id)
+{
+       if (!ao_spi_try_get(bus, speed, task_id))
+               return 0;
+       ao_spi_set_cs(reg, mask);
+       return 1;
+}
+
+#define ao_spi_put_mask(reg,mask,bus) do {     \
+               ao_spi_clr_cs(reg,mask);        \
+               ao_spi_put(bus);                \
+       } while (0)
+
+#define ao_spi_get_bit(reg,bit,pin,bus,speed) ao_spi_get_mask(reg,(1<<bit),bus,speed)
+#define ao_spi_put_bit(reg,bit,pin,bus) ao_spi_put_mask(reg,(1<<bit),bus)
+
+#define ao_enable_port(port) do {                                      \
+               if ((port) == &stm_gpioa)                               \
+                       stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN); \
+               else if ((port) == &stm_gpiob)                          \
+                       stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN); \
+               else if ((port) == &stm_gpioc)                          \
+                       stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPCEN); \
+               else if ((port) == &stm_gpiof)                          \
+                       stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPFEN); \
+       } while (0)
+
+#define ao_disable_port(port) do {                                     \
+               if ((port) == &stm_gpioa)                               \
+                       stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPAEN); \
+               else if ((port) == &stm_gpiob)                          \
+                       stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPBEN); \
+               else if ((port) == &stm_gpioc)                          \
+                       stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPCEN); \
+               else if ((port) == &stm_gpiof)                          \
+                       stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPFEN); \
+       } while (0)
+
+#define ao_gpio_set(port, bit, pin, v) stm_gpio_set(port, bit, v)
+
+#define ao_gpio_get(port, bit, pin) stm_gpio_get(port, bit)
+
+#define ao_enable_output(port,bit,pin,v) do {                  \
+               ao_enable_port(port);                           \
+               ao_gpio_set(port, bit, pin, v);                 \
+               stm_moder_set(port, bit, STM_MODER_OUTPUT);\
+       } while (0)
+
+#define ao_gpio_set_mode(port,bit,mode) do {                           \
+               if (mode == AO_EXTI_MODE_PULL_UP)                       \
+                       stm_pupdr_set(port, bit, STM_PUPDR_PULL_UP);    \
+               else if (mode == AO_EXTI_MODE_PULL_DOWN)                \
+                       stm_pupdr_set(port, bit, STM_PUPDR_PULL_DOWN);  \
+               else                                                    \
+                       stm_pupdr_set(port, bit, STM_PUPDR_NONE);       \
+       } while (0)
+
+#define ao_enable_input(port,bit,mode) do {                            \
+               ao_enable_port(port);                                   \
+               stm_moder_set(port, bit, STM_MODER_INPUT);              \
+               ao_gpio_set_mode(port, bit, mode);                      \
+       } while (0)
+
+#define ao_enable_cs(port,bit) do {                            \
+               stm_gpio_set((port), bit, 1);                   \
+               stm_moder_set((port), bit, STM_MODER_OUTPUT);   \
+       } while (0)
+
+#define ao_spi_init_cs(port, mask) do {                                \
+               ao_enable_port(port);                           \
+               if ((mask) & 0x0001) ao_enable_cs(port, 0);     \
+               if ((mask) & 0x0002) ao_enable_cs(port, 1);     \
+               if ((mask) & 0x0004) ao_enable_cs(port, 2);     \
+               if ((mask) & 0x0008) ao_enable_cs(port, 3);     \
+               if ((mask) & 0x0010) ao_enable_cs(port, 4);     \
+               if ((mask) & 0x0020) ao_enable_cs(port, 5);     \
+               if ((mask) & 0x0040) ao_enable_cs(port, 6);     \
+               if ((mask) & 0x0080) ao_enable_cs(port, 7);     \
+               if ((mask) & 0x0100) ao_enable_cs(port, 8);     \
+               if ((mask) & 0x0200) ao_enable_cs(port, 9);     \
+               if ((mask) & 0x0400) ao_enable_cs(port, 10);\
+               if ((mask) & 0x0800) ao_enable_cs(port, 11);\
+               if ((mask) & 0x1000) ao_enable_cs(port, 12);\
+               if ((mask) & 0x2000) ao_enable_cs(port, 13);\
+               if ((mask) & 0x4000) ao_enable_cs(port, 14);\
+               if ((mask) & 0x8000) ao_enable_cs(port, 15);\
+       } while (0)
+
+/* ao_dma_stm.c
+ */
+
+extern uint8_t ao_dma_done[STM_NUM_DMA];
+
+void
+ao_dma_set_transfer(uint8_t            index,
+                   volatile void       *peripheral,
+                   void                *memory,
+                   uint16_t            count,
+                   uint32_t            ccr);
+
+void
+ao_dma_set_isr(uint8_t index, void (*isr)(int index));
+
+void
+ao_dma_start(uint8_t index);
+
+void
+ao_dma_done_transfer(uint8_t index);
+
+void
+ao_dma_abort(uint8_t index);
+
+void
+ao_dma_alloc(uint8_t index);
+
+void
+ao_dma_init(void);
+
+/* ao_i2c_stm.c */
+
+void
+ao_i2c_get(uint8_t i2c_index);
+
+uint8_t
+ao_i2c_start(uint8_t i2c_index, uint16_t address);
+
+void
+ao_i2c_put(uint8_t i2c_index);
+
+uint8_t
+ao_i2c_send(void *block, uint16_t len, uint8_t i2c_index, uint8_t stop);
+
+uint8_t
+ao_i2c_recv(void *block, uint16_t len, uint8_t i2c_index, uint8_t stop);
+
+void
+ao_i2c_init(void);
+
+/* ao_serial_stm.c */
+struct ao_stm_usart {
+       struct ao_fifo          rx_fifo;
+       struct ao_fifo          tx_fifo;
+       struct stm_usart        *reg;
+       uint8_t                 tx_started;
+};
+
+#if HAS_SERIAL_1
+extern struct ao_stm_usart     ao_stm_usart1;
+#endif
+
+#if HAS_SERIAL_2
+extern struct ao_stm_usart     ao_stm_usart2;
+#endif
+
+#if HAS_SERIAL_3
+extern struct ao_stm_usart     ao_stm_usart3;
+#endif
+
+#define ARM_PUSH32(stack, val) (*(--(stack)) = (val))
+
+typedef uint32_t       ao_arch_irq_t;
+
+static inline uint32_t
+ao_arch_irqsave(void) {
+       uint32_t        primask;
+       asm("mrs %0,primask" : "=&r" (primask));
+       ao_arch_block_interrupts();
+       return primask;
+}
+
+static inline void
+ao_arch_irqrestore(uint32_t primask) {
+       asm("msr primask,%0" : : "r" (primask));
+}
+
+static inline void
+ao_arch_memory_barrier() {
+       asm volatile("" ::: "memory");
+}
+
+#if HAS_TASK
+static inline void
+ao_arch_init_stack(struct ao_task *task, void *start)
+{
+       uint32_t        *sp = (uint32_t *) (task->stack + AO_STACK_SIZE);
+       uint32_t        a = (uint32_t) start;
+       int             i;
+
+       /* Return address (goes into LR) */
+       ARM_PUSH32(sp, a);
+
+       /* Clear register values r0-r7 */
+       i = 8;
+       while (i--)
+               ARM_PUSH32(sp, 0);
+
+       /* APSR */
+       ARM_PUSH32(sp, 0);
+
+       /* PRIMASK with interrupts enabled */
+       ARM_PUSH32(sp, 0);
+
+       task->sp = sp;
+}
+
+static inline void ao_arch_save_regs(void) {
+       /* Save general registers */
+       asm("push {r0-r7,lr}\n");
+
+       /* Save APSR */
+       asm("mrs r0,apsr");
+       asm("push {r0}");
+
+       /* Save PRIMASK */
+       asm("mrs r0,primask");
+       asm("push {r0}");
+}
+
+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_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) );
+
+       /* Restore PRIMASK */
+       asm("pop {r0}");
+       asm("msr primask,r0");
+
+       /* Restore APSR */
+       asm("pop {r0}");
+       asm("msr apsr_nczvq,r0");
+
+       /* Restore general registers */
+       asm("pop {r0-r7,pc}\n");
+}
+
+#ifndef HAS_SAMPLE_PROFILE
+#define HAS_SAMPLE_PROFILE 0
+#endif
+
+#if !HAS_SAMPLE_PROFILE
+#define HAS_ARCH_START_SCHEDULER       1
+
+static inline void ao_arch_start_scheduler(void) {
+       uint32_t        sp;
+       uint32_t        control;
+
+       asm("mrs %0,msp" : "=&r" (sp));
+       asm("msr psp,%0" : : "r" (sp));
+       asm("mrs %0,control" : "=&r" (control));
+       control |= (1 << 1);
+       asm("msr control,%0" : : "r" (control));
+       asm("isb");
+}
+#endif
+
+#define ao_arch_isr_stack()
+
+#endif
+
+#define ao_arch_wait_interrupt() do {                          \
+               asm("\twfi\n");                                 \
+               ao_arch_release_interrupts();                   \
+               asm(".global ao_idle_loc\nao_idle_loc:");       \
+               ao_arch_block_interrupts();                     \
+       } while (0)
+
+#define ao_arch_critical(b) do {                       \
+               uint32_t __mask = ao_arch_irqsave();    \
+               do { b } while (0);                     \
+               ao_arch_irqrestore(__mask);             \
+       } while (0)
+
+/* ao_usb_stm.c */
+
+#if AO_USB_DIRECTIO
+uint16_t *
+ao_usb_alloc(void);
+
+void
+ao_usb_free(uint16_t *buffer);
+
+void
+ao_usb_write(uint16_t *buffer, uint16_t len);
+#endif /* AO_USB_DIRECTIO */
+
+#endif /* _AO_ARCH_FUNCS_H_ */
diff --git a/src/stmf0/ao_boot_chain.c b/src/stmf0/ao_boot_chain.c
new file mode 100644 (file)
index 0000000..83a543a
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_boot.h>
+
+void
+ao_boot_chain(uint32_t *base)
+{
+       uint32_t        sp;
+       uint32_t        pc;
+
+       sp = base[0];
+       pc = base[1];
+       if (0x08000100 <= pc && pc <= 0x08200000 && (pc & 1) == 1) {
+               asm ("mov sp, %0" : : "r" (sp));
+               asm ("mov lr, %0" : : "r" (pc));
+               asm ("bx lr");
+       }
+}
+
+#define AO_BOOT_SIGNAL 0x5a5aa5a5
+#define AO_BOOT_CHECK  0xc3c33c3c
+
+struct ao_boot {
+       uint32_t        *base;
+       uint32_t        signal;
+       uint32_t        check;
+};
+
+static struct ao_boot __attribute__ ((section(".boot"))) ao_boot;
+
+int
+ao_boot_check_chain(void)
+{
+       if (ao_boot.signal == AO_BOOT_SIGNAL && ao_boot.check == AO_BOOT_CHECK) {
+               ao_boot.signal = 0;
+               ao_boot.check = 0;
+               if (ao_boot.base == AO_BOOT_FORCE_LOADER)
+                       return 0;
+               ao_boot_chain(ao_boot.base);
+       }
+       return 1;
+}
+
+void
+ao_boot_reboot(uint32_t *base)
+{
+       ao_boot.base = base;
+       ao_boot.signal = AO_BOOT_SIGNAL;
+       ao_boot.check = AO_BOOT_CHECK;
+       ao_arch_reboot();
+}
diff --git a/src/stmf0/ao_boot_pin.c b/src/stmf0/ao_boot_pin.c
new file mode 100644 (file)
index 0000000..e825b61
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_boot.h>
+#include <ao_exti.h>
+
+void
+ao_boot_check_pin(void)
+{
+       uint16_t v;
+
+       /* Enable power interface clock */
+       stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN);
+
+       /* Enable the input pin */
+       ao_enable_input(&AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN,
+                       AO_BOOT_APPLICATION_MODE);
+
+       for (v = 0; v < 100; v++)
+               ao_arch_nop();
+
+       /* Read the value */
+       v = stm_gpio_get(&AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN);
+
+       /* Reset the chip to turn off the port and the power interface clock */
+       ao_gpio_set_mode(&AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN, 0);
+       ao_disable_port(&AO_BOOT_APPLICATION_GPIO);
+       stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_PWREN);
+       if (v == AO_BOOT_APPLICATION_VALUE)
+               ao_boot_chain(AO_BOOT_APPLICATION_BASE);
+}
diff --git a/src/stmf0/ao_crc.h b/src/stmf0/ao_crc.h
new file mode 100644 (file)
index 0000000..cd011d3
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright © 2015 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_CRC_H_
+#define _AO_CRC_H_
+
+#define AO_CRC_16_CCITT                0x1021
+#define AO_CRC_16_CDMA2000     0xc867
+#define AO_CRC_16_DECT         0x0589
+#define AO_CRC_16_T10_DIF      0x8bb7
+#define AO_CRC_16_DNP          0x3d65
+#define AO_CRC_16_ANSI         0x8005
+#define AO_CRC_16_DEFAULT      AO_CRC_16_ANSI
+
+#define AO_CRC_32_ANSI         0x04c11db7
+#define AO_CRC_32_C            0x1edc6f41
+
+#define AO_CRC_32_DEFAULT      AO_CRC_32_ANSI
+
+static inline uint16_t
+ao_crc_in_32_out_16(uint32_t v) {
+       stm_crc.dr.u32 = v;
+       return stm_crc.dr.u16;
+}
+
+static inline uint16_t
+ao_crc_in_16_out_16(uint16_t v) {
+       stm_crc.dr.u16 = v;
+       return stm_crc.dr.u16;
+}
+
+static inline uint16_t
+ao_crc_in_8_out_16(uint8_t v) {
+       stm_crc.dr.u8 = v;
+       return stm_crc.dr.u16;
+}
+
+void
+ao_crc_reset(void);
+
+void
+ao_crc_init(void);
+
+#endif /* _AO_CRC_H_ */
diff --git a/src/stmf0/ao_dma_stm.c b/src/stmf0/ao_dma_stm.c
new file mode 100644 (file)
index 0000000..78fabe1
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+struct ao_dma_config {
+       void            (*isr)(int index);
+};
+
+uint8_t ao_dma_done[STM_NUM_DMA];
+
+static struct ao_dma_config ao_dma_config[STM_NUM_DMA];
+static uint8_t ao_dma_allocated[STM_NUM_DMA];
+static uint8_t ao_dma_mutex[STM_NUM_DMA];
+static uint8_t ao_dma_active;
+
+#define id(ch)         STM_DMA_INDEX(ch)
+#define id_mask(id)    (STM_DMA_ISR_MASK << (id))
+#define ch_mask(ch)    id_mask(id(ch))
+
+static void
+ao_dma_isr(uint8_t low_index, uint8_t high_index, uint32_t mask) {
+       /* Get channel interrupt bits */
+       uint32_t        isr = stm_dma.isr & mask;
+       uint8_t         index;
+
+       /* Ack them */
+       stm_dma.ifcr = isr;
+       for (index = low_index; index <= high_index; index++) {
+               if (isr & id_mask(index)) {
+                       if (ao_dma_config[index].isr)
+                               (*ao_dma_config[index].isr)(index);
+                       else {
+                               ao_dma_done[index] = 1;
+                               ao_wakeup(&ao_dma_done[index]);
+                       }
+               }
+       }
+}
+
+void stm_dma_ch1_isr(void) { ao_dma_isr(id(1), id(1), ch_mask(1)); }
+void stm_dma_ch2_3_isr(void) { ao_dma_isr(id(2), id(3), ch_mask(2) | ch_mask(3)); }
+void stm_dma1_ch4_5_6_isr(void) { ao_dma_isr(id(4), id(6), ch_mask(4) | ch_mask(5) | ch_mask(6)); }
+
+void
+ao_dma_set_transfer(uint8_t            index,
+                   volatile void       *peripheral,
+                   void                *memory,
+                   uint16_t            count,
+                   uint32_t            ccr)
+{
+       if (ao_dma_allocated[index]) {
+               if (ao_dma_mutex[index])
+                       ao_panic(AO_PANIC_DMA);
+               ao_dma_mutex[index] = 1;
+       } else
+               ao_mutex_get(&ao_dma_mutex[index]);
+       ao_arch_critical(
+               if (ao_dma_active++ == 0)
+                       stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMAEN);
+               );
+       stm_dma.channel[index].ccr = ccr | (1 << STM_DMA_CCR_TCIE);
+       stm_dma.channel[index].cndtr = count;
+       stm_dma.channel[index].cpar = peripheral;
+       stm_dma.channel[index].cmar = memory;
+       ao_dma_config[index].isr = NULL;
+}
+
+void
+ao_dma_set_isr(uint8_t index, void (*isr)(int))
+{
+       ao_dma_config[index].isr = isr;
+}
+
+void
+ao_dma_start(uint8_t index)
+{
+       ao_dma_done[index] = 0;
+       stm_dma.channel[index].ccr |= (1 << STM_DMA_CCR_EN);
+}
+
+void
+ao_dma_done_transfer(uint8_t index)
+{
+       stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN);
+       ao_arch_critical(
+               if (--ao_dma_active == 0)
+                       stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_DMAEN);
+               );
+       if (ao_dma_allocated[index])
+               ao_dma_mutex[index] = 0;
+       else
+               ao_mutex_put(&ao_dma_mutex[index]);
+}
+
+void
+ao_dma_abort(uint8_t index)
+{
+       stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN);
+       ao_wakeup(&ao_dma_done[index]);
+}
+
+void
+ao_dma_alloc(uint8_t index)
+{
+       if (ao_dma_allocated[index])
+               ao_panic(AO_PANIC_DMA);
+       ao_dma_allocated[index] = 1;
+}
+
+#define STM_NUM_DMA_ISR        3
+
+void
+ao_dma_init(void)
+{
+       int     isr_id;
+       int     index;
+
+       for (isr_id = 0; isr_id < STM_NUM_DMA_ISR; isr_id++) {
+               stm_nvic_set_enable(STM_ISR_DMA_CH1_POS + isr_id);
+               stm_nvic_set_priority(STM_ISR_DMA_CH1_POS + isr_id, 4);
+       }
+       for (index = 0; index < STM_NUM_DMA; index++) {
+               ao_dma_allocated[index] = 0;
+               ao_dma_mutex[index] = 0;
+       }
+}
diff --git a/src/stmf0/ao_flash.h b/src/stmf0/ao_flash.h
new file mode 100644 (file)
index 0000000..09ca5ac
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_FLASH_STM_H_
+#define _AO_FLASH_STM_H_
+
+void
+ao_flash_erase_page(uint32_t *page);
+
+void
+ao_flash_page(uint32_t *page, uint32_t *src);
+
+#endif /* _AO_FLASH_STM_H_ */
diff --git a/src/stmf0/ao_flash_loader_stm.c b/src/stmf0/ao_flash_loader_stm.c
new file mode 100644 (file)
index 0000000..6bf8923
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+#include <ao_exti.h>
+#include <ao_boot.h>
+#include <ao_flash_task.h>
+
+int
+main(void)
+{
+       ao_clock_init();
+
+       ao_usb_init();
+
+#if HAS_TICK
+       ao_timer_init();
+#endif
+
+#ifdef AO_FLASH_LOADER_INIT
+       AO_FLASH_LOADER_INIT;
+#endif 
+       ao_flash_task();
+       return 0;
+}
diff --git a/src/stmf0/ao_flash_stm.c b/src/stmf0/ao_flash_stm.c
new file mode 100644 (file)
index 0000000..5fe0e61
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_flash.h>
+
+static uint8_t
+ao_flash_is_locked(void)
+{
+       return (stm_flash.cr & (1 << STM_FLASH_CR_LOCK)) != 0;
+}
+
+static void
+ao_flash_unlock(void)
+{
+       if (!ao_flash_is_locked())
+               return;
+
+       /* Unlock FLASH_CR register */
+       stm_flash.keyr = STM_FLASH_KEYR_KEY1;
+       stm_flash.keyr = STM_FLASH_KEYR_KEY2;
+       if (ao_flash_is_locked())
+               ao_panic(AO_PANIC_FLASH);
+}
+
+static void
+ao_flash_lock(void)
+{
+       stm_flash.cr |= (1 << STM_FLASH_CR_LOCK);
+}
+
+static void
+ao_flash_wait_bsy(void)
+{
+       while (stm_flash.sr & (1 << STM_FLASH_SR_BSY))
+               ;
+}
+
+static void __attribute__ ((section(".ramtext"),noinline))
+_ao_flash_erase_page(uint32_t *page)
+{
+       stm_flash.cr |= (1 << STM_FLASH_CR_PER);
+
+       stm_flash.ar = (uintptr_t) page;
+
+       stm_flash.cr |= (1 << STM_FLASH_CR_STRT);
+
+       ao_flash_wait_bsy();
+
+       stm_flash.cr &= ~(1 << STM_FLASH_CR_PER);
+}
+
+static uint32_t
+stm_flash_page_size(void)
+{
+       uint16_t        dev_id = stm_dev_id();
+
+       switch (dev_id) {
+       case 0x440:     /* stm32f05x */
+       case 0x444:     /* stm32f03x */
+       case 0x445:     /* stm32f04x */
+               return 1024;
+       case 0x442:     /* stm32f09x */
+       case 0x448:     /* stm32f07x */
+               return 2048;
+       }
+       ao_panic(AO_PANIC_FLASH);
+       return 0;
+}
+
+void
+ao_flash_erase_page(uint32_t *page)
+{
+       /* Erase the whole page at the start. This assumes we'll be flashing things
+        * in memory order
+        */
+
+       if ((uintptr_t) page & (stm_flash_page_size() - 1))
+               return;
+
+       ao_arch_block_interrupts();
+       ao_flash_unlock();
+
+       _ao_flash_erase_page(page);
+
+       ao_flash_lock();
+       ao_arch_release_interrupts();
+}
+
+static void __attribute__ ((section(".ramtext"), noinline))
+_ao_flash_page(uint16_t *dst, uint16_t *src)
+{
+       uint8_t         i;
+
+       stm_flash.cr |= (1 << STM_FLASH_CR_PG);
+
+       for (i = 0; i < 128; i++) {
+               *dst++ = *src++;
+               ao_flash_wait_bsy();
+       }
+
+       stm_flash.cr &= ~(1 << STM_FLASH_CR_PG);
+}
+
+void
+ao_flash_page(uint32_t *page, uint32_t *src)
+{
+       ao_flash_erase_page(page);
+
+       ao_arch_block_interrupts();
+       ao_flash_unlock();
+
+       _ao_flash_page((uint16_t *) page, (uint16_t *) src);
+
+       ao_flash_lock();
+       ao_arch_release_interrupts();
+}
diff --git a/src/stmf0/ao_flash_stm_pins.h b/src/stmf0/ao_flash_stm_pins.h
new file mode 100644 (file)
index 0000000..ab60b4f
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_FLASH_STM_PINS_H_
+#define _AO_FLASH_STM_PINS_H_
+
+#include <ao_flash_pins.h>
+
+/* 48MHz clock based on USB */
+#define AO_HSI48       1
+
+/* HCLK = 48MHz */
+#define AO_AHB_PRESCALER       1
+#define AO_RCC_CFGR_HPRE_DIV   STM_RCC_CFGR_HPRE_DIV_1
+
+/* APB = 48MHz */
+#define AO_APB_PRESCALER       1
+#define AO_RCC_CFGR_PPRE_DIV   STM_RCC_CFGR_PPRE_DIV_1
+
+#define HAS_USB                1
+
+#define AO_NEED_HSI    1
+
+#endif /* _AO_FLASH_STM_PINS_H_ */
diff --git a/src/stmf0/ao_interrupt.c b/src/stmf0/ao_interrupt.c
new file mode 100644 (file)
index 0000000..c6d8ef3
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include "stm32f0.h"
+#include <string.h>
+#include <ao_boot.h>
+
+#ifndef IS_FLASH_LOADER
+#error Should define IS_FLASH_LOADER
+#define IS_FLASH_LOADER        0
+#endif
+
+#if !IS_FLASH_LOADER
+#define RELOCATE_INTERRUPT     1
+#endif
+
+extern void main(void);
+extern char __stack__;
+extern char __text_start__, __text_end__;
+extern char __data_start__, __data_end__;
+extern char __bss_start__, __bss_end__;
+#if RELOCATE_INTERRUPT
+extern char __interrupt_rom__, __interrupt_start__, __interrupt_end__;
+#endif
+
+/* Interrupt functions */
+
+void stm_halt_isr(void)
+{
+       ao_panic(AO_PANIC_CRASH);
+}
+
+void stm_ignore_isr(void)
+{
+}
+
+const void *stm_interrupt_vector[];
+
+uint32_t
+stm_flash_size(void) {
+       uint16_t        dev_id = stm_dev_id();
+       uint16_t        kbytes = 0;
+
+       switch (dev_id) {
+       case 0x445:
+               kbytes = stm_flash_size_04x.f_size;
+               break;
+       }
+       return (uint32_t) kbytes * 1024;
+}
+
+void start(void)
+{
+#ifdef AO_BOOT_CHAIN
+       if (ao_boot_check_chain()) {
+#ifdef AO_BOOT_PIN
+               ao_boot_check_pin();
+#endif
+       }
+#endif
+#if RELOCATE_INTERRUPT
+       /* Turn on syscfg */
+       stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SYSCFGCOMPEN);
+
+       memcpy(&__interrupt_start__, &__interrupt_rom__, &__interrupt_end__ - &__interrupt_start__);
+       stm_syscfg.cfgr1 = (stm_syscfg.cfgr1 & ~(STM_SYSCFG_CFGR1_MEM_MODE_MASK << STM_SYSCFG_CFGR1_MEM_MODE)) |
+               (STM_SYSCFG_CFGR1_MEM_MODE_SRAM << STM_SYSCFG_CFGR1_MEM_MODE);
+#endif
+       memcpy(&__data_start__, &__text_end__, &__data_end__ - &__data_start__);
+       memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__);
+       main();
+}
+
+#define STRINGIFY(x) #x
+
+#define isr(name) \
+       void __attribute__ ((weak)) stm_ ## name ## _isr(void); \
+       _Pragma(STRINGIFY(weak stm_ ## name ## _isr = stm_ignore_isr))
+
+#define isr_halt(name) \
+       void __attribute__ ((weak)) stm_ ## name ## _isr(void); \
+       _Pragma(STRINGIFY(weak stm_ ## name ## _isr = stm_halt_isr))
+
+isr(nmi)
+isr_halt(hardfault)
+isr_halt(memmanage)
+isr_halt(busfault)
+isr_halt(usagefault)
+isr(svc)
+isr(debugmon)
+isr(pendsv)
+isr(systick)
+isr(wwdg)
+isr(pvd)
+isr(rtc)
+isr(flash)
+isr(rcc_crs)
+isr(exti0_1)
+isr(exti2_3)
+isr(exti4_15)
+isr(tsc)
+isr(dma_ch1)
+isr(dma_ch2_3)
+isr(dma_ch4_5_6)
+isr(adc_comp)
+isr(tim1_brk_up_trg_com)
+isr(tim1_cc)
+isr(tim2)
+isr(tim3)
+isr(tim6_dac)
+isr(tim7)
+isr(tim14)
+isr(tim15)
+isr(tim16)
+isr(tim17)
+isr(i2c1)
+isr(i2c2)
+isr(spi1)
+isr(spi2)
+isr(usart1)
+isr(usart2)
+isr(usart3_4_5_6_7_8)
+isr(cec_can)
+isr(usb)
+
+#define i(addr,name)   [(addr)/4] = stm_ ## name ## _isr
+
+__attribute__ ((section(".interrupt")))
+const void *stm_interrupt_vector[] = {
+       [0] = &__stack__,
+       [1] = start,
+       i(0x08, nmi),
+       i(0x0c, hardfault),
+       i(0x2c, svc),
+       i(0x30, debugmon),
+       i(0x38, pendsv),
+       i(0x3c, systick),
+       i(0x40, wwdg),          /* IRQ0 */
+       i(0x44, pvd),
+       i(0x48, rtc),
+       i(0x4c, flash),
+       i(0x50, rcc_crs),
+       i(0x54, exti0_1),
+       i(0x58, exti2_3),
+       i(0x5c, exti4_15),
+       i(0x60, tsc),
+       i(0x64, dma_ch1),
+       i(0x68, dma_ch2_3),
+       i(0x6c, dma_ch4_5_6),
+       i(0x70, adc_comp),
+       i(0x74, tim1_brk_up_trg_com),
+       i(0x78, tim1_cc),
+       i(0x7c, tim2),
+       i(0x80, tim3),
+       i(0x84, tim6_dac),
+       i(0x88, tim7),
+       i(0x8c, tim14),
+       i(0x90, tim15),
+       i(0x94, tim16),
+       i(0x98, tim17),
+       i(0x9c, i2c1),
+       i(0xa0, i2c2),
+       i(0xa4, spi1),
+       i(0xa8, spi2),
+       i(0xac, usart1),
+       i(0xb0, usart2),
+       i(0xb4, usart3_4_5_6_7_8),
+       i(0xb8, cec_can),
+       i(0xbc, usb),
+};
diff --git a/src/stmf0/ao_led.c b/src/stmf0/ao_led.c
new file mode 100644 (file)
index 0000000..9b61cf6
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+__pdata uint16_t ao_led_enable;
+
+void
+ao_led_on(uint16_t colors)
+{
+#ifdef LED_PORT
+       LED_PORT->bsrr = (colors & ao_led_enable);
+#else
+#ifdef LED_PORT_0
+       LED_PORT_0->bsrr = ((colors & ao_led_enable) & LED_PORT_0_MASK) << LED_PORT_0_SHIFT;
+#endif
+#ifdef LED_PORT_1
+       LED_PORT_1->bsrr = ((colors & ao_led_enable) & LED_PORT_1_MASK) << LED_PORT_1_SHIFT;
+#endif
+#endif
+}
+
+void
+ao_led_off(uint16_t colors)
+{
+#ifdef LED_PORT
+       LED_PORT->bsrr = (uint32_t) (colors & ao_led_enable) << 16;
+#else
+#ifdef LED_PORT_0
+       LED_PORT_0->bsrr = ((uint32_t) (colors & ao_led_enable) & LED_PORT_0_MASK) << (LED_PORT_0_SHIFT + 16);
+#endif
+#ifdef LED_PORT_1
+       LED_PORT_1->bsrr = ((uint32_t) (colors & ao_led_enable) & LED_PORT_1_MASK) << (LED_PORT_1_SHIFT + 16);
+#endif
+#endif
+}
+
+void
+ao_led_set(uint16_t colors)
+{
+       uint16_t        on = colors & ao_led_enable;
+       uint16_t        off = ~colors & ao_led_enable;
+
+       ao_led_off(off);
+       ao_led_on(on);
+}
+
+void
+ao_led_toggle(uint16_t colors)
+{
+#ifdef LED_PORT
+       LED_PORT->odr ^= (colors & ao_led_enable);
+#else
+#ifdef LED_PORT_0
+       LED_PORT_0->odr ^= ((colors & ao_led_enable) & LED_PORT_0_MASK) << LED_PORT_0_SHIFT;
+#endif
+#ifdef LED_PORT_1
+       LED_PORT_1->odr ^= ((colors & ao_led_enable) & LED_PORT_1_MASK) << LED_PORT_1_SHIFT;
+#endif
+#endif
+}
+
+void
+ao_led_for(uint16_t colors, uint16_t ticks) __reentrant
+{
+       ao_led_on(colors);
+       ao_delay(ticks);
+       ao_led_off(colors);
+}
+
+#define init_led_pin(port, bit) do { \
+               stm_moder_set(port, bit, STM_MODER_OUTPUT);             \
+               stm_otyper_set(port, bit, STM_OTYPER_PUSH_PULL);        \
+       } while (0)
+
+void
+ao_led_init(uint16_t enable)
+{
+       int     bit;
+
+       ao_led_enable = enable;
+#ifdef LED_PORT
+       stm_rcc.ahbenr |= (1 << LED_PORT_ENABLE);
+       LED_PORT->odr &= ~enable;
+#else
+#ifdef LED_PORT_0
+       stm_rcc.ahbenr |= (1 << LED_PORT_0_ENABLE);
+       LED_PORT_0->odr &= ~((enable & ao_led_enable) & LED_PORT_0_MASK) << LED_PORT_0_SHIFT;
+#endif
+#ifdef LED_PORT_1
+       stm_rcc.ahbenr |= (1 << LED_PORT_1_ENABLE);
+       LED_PORT_1->odr &= ~((enable & ao_led_enable) & LED_PORT_1_MASK) << LED_PORT_1_SHIFT;
+#endif
+#endif
+       for (bit = 0; bit < 16; bit++) {
+               if (enable & (1 << bit)) {
+#ifdef LED_PORT
+                       init_led_pin(LED_PORT, bit);
+#else
+#ifdef LED_PORT_0
+                       if (LED_PORT_0_MASK & (1 << bit))
+                               init_led_pin(LED_PORT_0, bit + LED_PORT_0_SHIFT);
+#endif
+#ifdef LED_PORT_1
+                       if (LED_PORT_1_MASK & (1 << bit))
+                               init_led_pin(LED_PORT_1, bit + LED_PORT_1_SHIFT);
+#endif
+#endif
+               }
+       }
+}
diff --git a/src/stmf0/ao_romconfig.c b/src/stmf0/ao_romconfig.c
new file mode 100644 (file)
index 0000000..5da1507
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+AO_ROMCONFIG_SYMBOL (0) uint16_t ao_romconfig_version = AO_ROMCONFIG_VERSION;
+AO_ROMCONFIG_SYMBOL (0) uint16_t ao_romconfig_check = ~AO_ROMCONFIG_VERSION;
+AO_ROMCONFIG_SYMBOL (0) uint16_t ao_serial_number = 0;
+#ifndef AO_RADIO_CAL_DEFAULT
+#define AO_RADIO_CAL_DEFAULT 0x01020304
+#endif
+AO_ROMCONFIG_SYMBOL (0) uint32_t ao_radio_cal = AO_RADIO_CAL_DEFAULT;
+
diff --git a/src/stmf0/ao_timer.c b/src/stmf0/ao_timer.c
new file mode 100644 (file)
index 0000000..3aae7e5
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+#include <ao_task.h>
+#if HAS_FAKE_FLIGHT
+#include <ao_fake_flight.h>
+#endif
+
+#ifndef HAS_TICK
+#define HAS_TICK 1
+#endif
+
+#if HAS_TICK
+volatile AO_TICK_TYPE ao_tick_count;
+
+AO_TICK_TYPE
+ao_time(void)
+{
+       return ao_tick_count;
+}
+
+#if AO_DATA_ALL
+volatile __data uint8_t        ao_data_interval = 1;
+volatile __data uint8_t        ao_data_count;
+#endif
+
+void stm_systick_isr(void)
+{
+       if (stm_systick.csr & (1 << STM_SYSTICK_CSR_COUNTFLAG)) {
+               ++ao_tick_count;
+#if HAS_TASK_QUEUE
+               if (ao_task_alarm_tick && (int16_t) (ao_tick_count - ao_task_alarm_tick) >= 0)
+                       ao_task_check_alarm((uint16_t) ao_tick_count);
+#endif
+#if AO_DATA_ALL
+               if (++ao_data_count == ao_data_interval) {
+                       ao_data_count = 0;
+#if HAS_FAKE_FLIGHT
+                       if (ao_fake_flight_active)
+                               ao_fake_flight_poll();
+                       else
+#endif
+                               ao_adc_poll();
+#if (AO_DATA_ALL & ~(AO_DATA_ADC))
+                       ao_wakeup((void *) &ao_data_count);
+#endif
+               }
+#endif
+#ifdef AO_TIMER_HOOK
+               AO_TIMER_HOOK;
+#endif
+       }
+}
+
+#if HAS_ADC
+void
+ao_timer_set_adc_interval(uint8_t interval)
+{
+       ao_arch_critical(
+               ao_data_interval = interval;
+               ao_data_count = 0;
+               );
+}
+#endif
+
+#define SYSTICK_RELOAD (AO_SYSTICK / 100 - 1)
+
+void
+ao_timer_init(void)
+{
+       stm_systick.rvr = SYSTICK_RELOAD;
+       stm_systick.cvr = 0;
+       stm_systick.csr = ((1 << STM_SYSTICK_CSR_ENABLE) |
+                          (1 << STM_SYSTICK_CSR_TICKINT) |
+                          (STM_SYSTICK_CSR_CLKSOURCE_HCLK_8 << STM_SYSTICK_CSR_CLKSOURCE));
+}
+
+#endif
+
+static void
+ao_clock_enable_crs(void)
+{
+       /* Enable crs interface clock */
+       stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_CRSEN);
+
+       /* Disable error counter */
+       stm_crs.cr = ((stm_crs.cr & (1 << 4)) |
+                     (32 << STM_CRS_CR_TRIM) |
+                     (0 << STM_CRS_CR_SWSYNC) |
+                     (0 << STM_CRS_CR_AUTOTRIMEN) |
+                     (0 << STM_CRS_CR_CEN) |
+                     (0 << STM_CRS_CR_ESYNCIE) |
+                     (0 << STM_CRS_CR_ERRIE) |
+                     (0 << STM_CRS_CR_SYNCWARNIE) |
+                     (0 << STM_CRS_CR_SYNCOKIE));
+
+       /* Configure for USB source */
+       stm_crs.cfgr = ((stm_crs.cfgr & ((1 << 30) | (1 << 27))) |
+                       (0 << STM_CRS_CFGR_SYNCPOL) |
+                       (STM_CRS_CFGR_SYNCSRC_USB << STM_CRS_CFGR_SYNCSRC) |
+                       (STM_CRS_CFGR_SYNCDIV_1 << STM_CRS_CFGR_SYNCDIV) |
+                       (0x22 << STM_CRS_CFGR_FELIM) |
+                       (((48000000 / 1000) - 1) << STM_CRS_CFGR_RELOAD));
+
+       /* Enable error counter, set auto trim */
+       stm_crs.cr = ((stm_crs.cr & (1 << 4)) |
+                     (32 << STM_CRS_CR_TRIM) |
+                     (0 << STM_CRS_CR_SWSYNC) |
+                     (1 << STM_CRS_CR_AUTOTRIMEN) |
+                     (1 << STM_CRS_CR_CEN) |
+                     (0 << STM_CRS_CR_ESYNCIE) |
+                     (0 << STM_CRS_CR_ERRIE) |
+                     (0 << STM_CRS_CR_SYNCWARNIE) |
+                     (0 << STM_CRS_CR_SYNCOKIE));
+
+}
+
+void
+ao_clock_init(void)
+{
+       uint32_t        cfgr;
+
+       /* Switch to HSI while messing about */
+       stm_rcc.cr |= (1 << STM_RCC_CR_HSION);
+       while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY)))
+               ao_arch_nop();
+
+       stm_rcc.cfgr = (stm_rcc.cfgr & ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW)) |
+               (STM_RCC_CFGR_SW_HSI << STM_RCC_CFGR_SW);
+
+       /* wait for system to switch to HSI */
+       while ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) !=
+              (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS))
+               ao_arch_nop();
+
+       /* reset the clock config, leaving us running on the HSI */
+       stm_rcc.cfgr &= (uint32_t)0x0000000f;
+
+       /* reset PLLON, CSSON, HSEBYP, HSEON */
+       stm_rcc.cr &= 0x0000ffff;
+
+       /* Disable all interrupts */
+       stm_rcc.cir = 0;
+
+#if AO_HSE
+#define STM_RCC_CFGR_SWS_TARGET_CLOCK          STM_RCC_CFGR_SWS_HSE
+#define STM_RCC_CFGR_SW_TARGET_CLOCK           STM_RCC_CFGR_SW_HSE
+#define STM_PLLSRC                             AO_HSE
+#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK       1
+
+#if AO_HSE_BYPASS
+       stm_rcc.cr |= (1 << STM_RCC_CR_HSEBYP);
+#else
+       stm_rcc.cr &= ~(1 << STM_RCC_CR_HSEBYP);
+#endif
+       /* Enable HSE clock */
+       stm_rcc.cr |= (1 << STM_RCC_CR_HSEON);
+       while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSERDY)))
+               asm("nop");
+#endif
+
+
+#if AO_HSI48
+#define STM_RCC_CFGR_SWS_TARGET_CLOCK          STM_RCC_CFGR_SWS_HSI48
+#define STM_RCC_CFGR_SW_TARGET_CLOCK           STM_RCC_CFGR_SW_HSI48
+
+       /* Turn HSI48 clock on */
+       stm_rcc.cr2 |= (1 << STM_RCC_CR2_HSI48ON);
+
+       /* Wait for clock to stabilize */
+       while ((stm_rcc.cr2 & (1 << STM_RCC_CR2_HSI48RDY)) == 0)
+               ao_arch_nop();
+
+       ao_clock_enable_crs();
+#endif
+
+#ifndef STM_RCC_CFGR_SWS_TARGET_CLOCK
+#define STM_HSI                                16000000
+#define STM_RCC_CFGR_SWS_TARGET_CLOCK          STM_RCC_CFGR_SWS_HSI
+#define STM_RCC_CFGR_SW_TARGET_CLOCK           STM_RCC_CFGR_SW_HSI
+#define STM_PLLSRC                             STM_HSI
+#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK       0
+#endif
+
+#ifdef STM_PLLSRC
+#error No code for PLL initialization yet
+#endif
+
+       /* Set flash latency to tolerate 48MHz SYSCLK  -> 1 wait state */
+
+       /* Enable prefetch */
+       stm_flash.acr |= (1 << STM_FLASH_ACR_PRFTBE);
+
+       /* 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);
+       cfgr |= (AO_RCC_CFGR_HPRE_DIV << STM_RCC_CFGR_HPRE);
+       stm_rcc.cfgr = cfgr;
+       while ((stm_rcc.cfgr & (STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE)) !=
+              (AO_RCC_CFGR_HPRE_DIV << STM_RCC_CFGR_HPRE))
+               ao_arch_nop();
+
+       /* APB Prescaler = AO_APB_PRESCALER */
+       cfgr = stm_rcc.cfgr;
+       cfgr &= ~(STM_RCC_CFGR_PPRE_MASK << STM_RCC_CFGR_PPRE);
+       cfgr |= (AO_RCC_CFGR_PPRE_DIV << STM_RCC_CFGR_PPRE);
+       stm_rcc.cfgr = cfgr;
+
+       /* Switch to the desired system clock */
+
+       cfgr = stm_rcc.cfgr;
+       cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW);
+       cfgr |= (STM_RCC_CFGR_SW_TARGET_CLOCK << STM_RCC_CFGR_SW);
+       stm_rcc.cfgr = cfgr;
+       for (;;) {
+               uint32_t        c, part, mask, val;
+
+               c = stm_rcc.cfgr;
+               mask = (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS);
+               val = (STM_RCC_CFGR_SWS_TARGET_CLOCK << STM_RCC_CFGR_SWS);
+               part = c & mask;
+               if (part == val)
+                       break;
+       }
+
+       /* Clear reset flags */
+       stm_rcc.csr |= (1 << STM_RCC_CSR_RMVF);
+
+#if !AO_HSI && !AO_NEED_HSI
+       /* Turn off the HSI clock */
+       stm_rcc.cr &= ~(1 << STM_RCC_CR_HSION);
+#endif
+#if DEBUG_THE_CLOCK
+       /* Output SYSCLK on PA8 for measurments */
+
+       stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN);
+
+       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_40MHz);
+
+       stm_rcc.cfgr |= (STM_RCC_CFGR_MCOPRE_DIV_1 << STM_RCC_CFGR_MCOPRE);
+       stm_rcc.cfgr |= (STM_RCC_CFGR_MCOSEL_HSE << STM_RCC_CFGR_MCOSEL);
+#endif
+}
diff --git a/src/stmf0/ao_usb_stm.c b/src/stmf0/ao_usb_stm.c
new file mode 100644 (file)
index 0000000..3ea7da5
--- /dev/null
@@ -0,0 +1,1150 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+#include "ao_usb.h"
+#include "ao_product.h"
+
+#define USB_DEBUG      0
+#define USB_DEBUG_DATA 0
+#define USB_ECHO       0
+
+#ifndef AO_PA11_PA12_RMP
+#error "must define AO_PA11_PA12_RMP"
+#endif
+
+#ifndef USE_USB_STDIO
+#define USE_USB_STDIO  1
+#endif
+
+#if USE_USB_STDIO
+#define AO_USB_OUT_SLEEP_ADDR  (&ao_stdin_ready)
+#else
+#define AO_USB_OUT_SLEEP_ADDR  (&ao_usb_out_avail)
+#endif
+
+#if USB_DEBUG
+#define debug(format, args...) printf(format, ## args);
+#else
+#define debug(format, args...)
+#endif
+
+#if USB_DEBUG_DATA
+#define debug_data(format, args...)    printf(format, ## args);
+#else
+#define debug_data(format, args...)
+#endif
+
+struct ao_usb_setup {
+       uint8_t         dir_type_recip;
+       uint8_t         request;
+       uint16_t        value;
+       uint16_t        index;
+       uint16_t        length;
+} ao_usb_setup;
+
+static uint8_t         ao_usb_ep0_state;
+
+/* Pending EP0 IN data */
+static const uint8_t   *ao_usb_ep0_in_data;    /* Remaining data */
+static uint8_t                 ao_usb_ep0_in_len;      /* Remaining amount */
+
+/* Temp buffer for smaller EP0 in data */
+static uint8_t ao_usb_ep0_in_buf[2];
+
+/* Pending EP0 OUT data */
+static uint8_t *ao_usb_ep0_out_data;
+static uint8_t         ao_usb_ep0_out_len;
+
+/*
+ * Objects allocated in special USB memory
+ */
+
+/* Buffer description tables */
+static union stm_usb_bdt       *ao_usb_bdt;
+/* USB address of end of allocated storage */
+static uint16_t        ao_usb_sram_addr;
+
+/* Pointer to ep0 tx/rx buffers in USB memory */
+static uint16_t        *ao_usb_ep0_tx_buffer;
+static uint16_t        *ao_usb_ep0_rx_buffer;
+
+/* Pointer to bulk data tx/rx buffers in USB memory */
+static uint16_t ao_usb_in_tx_offset;
+static uint16_t        *ao_usb_in_tx_buffer;
+static uint16_t        *ao_usb_out_rx_buffer;
+
+/* System ram shadow of USB buffer; writing individual bytes is
+ * too much of a pain (sigh) */
+static uint8_t ao_usb_tx_buffer[AO_USB_IN_SIZE];
+static uint8_t ao_usb_tx_count;
+
+static uint8_t ao_usb_rx_buffer[AO_USB_OUT_SIZE];
+static uint8_t ao_usb_rx_count, ao_usb_rx_pos;
+
+/*
+ * End point register indices
+ */
+
+#define AO_USB_CONTROL_EPR     0
+#define AO_USB_INT_EPR         1
+#define AO_USB_OUT_EPR         2
+#define AO_USB_IN_EPR          3
+
+/* Marks when we don't need to send an IN packet.
+ * This happens only when the last IN packet is not full,
+ * otherwise the host will expect to keep seeing packets.
+ * Send a zero-length packet as required
+ */
+static uint8_t ao_usb_in_flushed;
+
+/* Marks when we have delivered an IN packet to the hardware
+ * and it has not been received yet. ao_sleep on this address
+ * to wait for it to be delivered.
+ */
+static uint8_t ao_usb_in_pending;
+
+/* Marks when an OUT packet has been received by the hardware
+ * but not pulled to the shadow buffer.
+ */
+static uint8_t ao_usb_out_avail;
+uint8_t                ao_usb_running;
+static uint8_t ao_usb_configuration;
+
+#define AO_USB_EP0_GOT_RESET   1
+#define AO_USB_EP0_GOT_SETUP   2
+#define AO_USB_EP0_GOT_RX_DATA 4
+#define AO_USB_EP0_GOT_TX_ACK  8
+
+static uint8_t ao_usb_ep0_receive;
+static uint8_t ao_usb_address;
+static uint8_t ao_usb_address_pending;
+
+static inline uint32_t set_toggle(uint32_t     current_value,
+                                  uint32_t     mask,
+                                  uint32_t     desired_value)
+{
+       return (current_value ^ desired_value) & mask;
+}
+
+static inline uint16_t *ao_usb_packet_buffer_addr(uint16_t sram_addr)
+{
+       return (uint16_t *) (stm_usb_sram + sram_addr);
+}
+
+#if AO_USB_DIRECTIO
+static inline uint16_t ao_usb_packet_buffer_offset(uint16_t *addr)
+{
+       return (uint16_t) ((uint8_t *) addr - stm_usb_sram);
+}
+#endif
+
+static inline uint32_t ao_usb_epr_stat_rx(uint32_t epr) {
+       return (epr >> STM_USB_EPR_STAT_RX) & STM_USB_EPR_STAT_RX_MASK;
+}
+
+static inline uint32_t ao_usb_epr_stat_tx(uint32_t epr) {
+       return (epr >> STM_USB_EPR_STAT_TX) & STM_USB_EPR_STAT_TX_MASK;
+}
+
+static inline uint32_t ao_usb_epr_ctr_rx(uint32_t epr) {
+       return (epr >> STM_USB_EPR_CTR_RX) & 1;
+}
+
+static inline uint32_t ao_usb_epr_ctr_tx(uint32_t epr) {
+       return (epr >> STM_USB_EPR_CTR_TX) & 1;
+}
+
+static inline uint32_t ao_usb_epr_setup(uint32_t epr) {
+       return (epr >> STM_USB_EPR_SETUP) & 1;
+}
+
+static inline uint32_t ao_usb_epr_dtog_rx(uint32_t epr) {
+       return (epr >> STM_USB_EPR_DTOG_RX) & 1;
+}
+
+static inline uint32_t ao_usb_epr_dtog_tx(uint32_t epr) {
+       return (epr >> STM_USB_EPR_DTOG_TX) & 1;
+}
+
+/*
+ * Set current device address and mark the
+ * interface as active
+ */
+void
+ao_usb_set_address(uint8_t address)
+{
+       debug("ao_usb_set_address %02x\n", address);
+       stm_usb.daddr = (1 << STM_USB_DADDR_EF) | address;
+       ao_usb_address_pending = 0;
+}
+
+/*
+ * Write these values to preserve register contents under HW changes
+ */
+
+#define STM_USB_EPR_INVARIANT  ((1 << STM_USB_EPR_CTR_RX) |            \
+                                (STM_USB_EPR_DTOG_RX_WRITE_INVARIANT << STM_USB_EPR_DTOG_RX) | \
+                                (STM_USB_EPR_STAT_RX_WRITE_INVARIANT << STM_USB_EPR_STAT_RX) | \
+                                (1 << STM_USB_EPR_CTR_TX) |            \
+                                (STM_USB_EPR_DTOG_TX_WRITE_INVARIANT << STM_USB_EPR_DTOG_TX) | \
+                                (STM_USB_EPR_STAT_TX_WRITE_INVARIANT << STM_USB_EPR_STAT_TX))
+
+#define STM_USB_EPR_INVARIANT_MASK     ((1 << STM_USB_EPR_CTR_RX) |    \
+                                        (STM_USB_EPR_DTOG_RX_MASK << STM_USB_EPR_DTOG_RX) | \
+                                        (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX) | \
+                                        (1 << STM_USB_EPR_CTR_TX) |    \
+                                        (STM_USB_EPR_DTOG_TX_MASK << STM_USB_EPR_DTOG_TX) | \
+                                        (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX))
+
+/*
+ * These bits are purely under sw control, so preserve them in the
+ * register by re-writing what was read
+ */
+#define STM_USB_EPR_PRESERVE_MASK      ((STM_USB_EPR_EP_TYPE_MASK << STM_USB_EPR_EP_TYPE) | \
+                                        (1 << STM_USB_EPR_EP_KIND) |   \
+                                        (STM_USB_EPR_EA_MASK << STM_USB_EPR_EA))
+
+#define TX_DBG 0
+#define RX_DBG 0
+
+#if TX_DBG
+#define _tx_dbg0(msg) _dbg(__LINE__,msg,0)
+#define _tx_dbg1(msg,value) _dbg(__LINE__,msg,value)
+#else
+#define _tx_dbg0(msg)
+#define _tx_dbg1(msg,value)
+#endif
+
+#if RX_DBG
+#define _rx_dbg0(msg) _dbg(__LINE__,msg,0)
+#define _rx_dbg1(msg,value) _dbg(__LINE__,msg,value)
+#else
+#define _rx_dbg0(msg)
+#define _rx_dbg1(msg,value)
+#endif
+
+#if TX_DBG || RX_DBG
+static void _dbg(int line, char *msg, uint32_t value);
+#endif
+
+/*
+ * Set the state of the specified endpoint register to a new
+ * value. This is tricky because the bits toggle where the new
+ * value is one, and we need to write invariant values in other
+ * spots of the register. This hardware is strange...
+ */
+static void
+_ao_usb_set_stat_tx(int ep, uint32_t stat_tx)
+{
+       uint16_t        epr_write, epr_old;
+
+       _tx_dbg1("set_stat_tx top", stat_tx);
+       epr_old = epr_write = stm_usb.epr[ep].r;
+       epr_write &= STM_USB_EPR_PRESERVE_MASK;
+       epr_write |= STM_USB_EPR_INVARIANT;
+       epr_write |= set_toggle(epr_old,
+                             STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX,
+                             stat_tx << STM_USB_EPR_STAT_TX);
+       stm_usb.epr[ep].r = epr_write;
+       _tx_dbg1("set_stat_tx bottom", epr_write);
+}
+
+static void
+ao_usb_set_stat_tx(int ep, uint32_t stat_tx)
+{
+       ao_arch_block_interrupts();
+       _ao_usb_set_stat_tx(ep, stat_tx);
+       ao_arch_release_interrupts();
+}
+
+static void
+_ao_usb_set_stat_rx(int ep, uint32_t stat_rx) {
+       uint16_t        epr_write, epr_old;
+
+       epr_write = epr_old = stm_usb.epr[ep].r;
+       epr_write &= STM_USB_EPR_PRESERVE_MASK;
+       epr_write |= STM_USB_EPR_INVARIANT;
+       epr_write |= set_toggle(epr_old,
+                             STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX,
+                             stat_rx << STM_USB_EPR_STAT_RX);
+       stm_usb.epr[ep].r = epr_write;
+}
+
+static void
+ao_usb_set_stat_rx(int ep, uint32_t stat_rx) {
+       ao_arch_block_interrupts();
+       _ao_usb_set_stat_rx(ep, stat_rx);
+       ao_arch_release_interrupts();
+}
+
+/*
+ * Set just endpoint 0, for use during startup
+ */
+
+static void
+ao_usb_init_ep(uint8_t ep, uint32_t addr, uint32_t type, uint32_t stat_rx, uint32_t stat_tx)
+{
+       uint16_t                epr;
+
+       ao_arch_block_interrupts();
+       epr = stm_usb.epr[ep].r;
+       epr = ((0 << STM_USB_EPR_CTR_RX) |
+              (epr & (1 << STM_USB_EPR_DTOG_RX)) |
+              set_toggle(epr,
+                         (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX),
+                         (stat_rx << STM_USB_EPR_STAT_RX)) |
+              (type << STM_USB_EPR_EP_TYPE) |
+              (0 << STM_USB_EPR_EP_KIND) |
+              (0 << STM_USB_EPR_CTR_TX) |
+              (epr & (1 << STM_USB_EPR_DTOG_TX)) |
+              set_toggle(epr,
+                         (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX),
+                         (stat_tx << STM_USB_EPR_STAT_TX)) |
+              (addr << STM_USB_EPR_EA));
+       stm_usb.epr[ep].r = epr;
+       ao_arch_release_interrupts();
+       debug ("writing epr[%d] 0x%04x wrote 0x%04x\n",
+              ep, epr, stm_usb.epr[ep].r);
+}
+
+static void
+ao_usb_init_btable(void)
+{
+       ao_usb_sram_addr = 0;
+
+       ao_usb_bdt = (void *) stm_usb_sram;
+
+       ao_usb_sram_addr += 8 * STM_USB_BDT_SIZE;
+
+       /* Set up EP 0 - a Control end point with 32 bytes of in and out buffers */
+
+       ao_usb_bdt[0].single.addr_tx = ao_usb_sram_addr;
+       ao_usb_bdt[0].single.count_tx = 0;
+       ao_usb_ep0_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr);
+       ao_usb_sram_addr += AO_USB_CONTROL_SIZE;
+
+       ao_usb_bdt[0].single.addr_rx = ao_usb_sram_addr;
+       ao_usb_bdt[0].single.count_rx = ((1 << STM_USB_BDT_COUNT_RX_BL_SIZE) |
+                                 (((AO_USB_CONTROL_SIZE / 32) - 1) << STM_USB_BDT_COUNT_RX_NUM_BLOCK));
+       ao_usb_ep0_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr);
+       ao_usb_sram_addr += AO_USB_CONTROL_SIZE;
+
+}
+
+static void
+ao_usb_set_ep0(void)
+{
+       int                     e;
+
+       ao_usb_init_btable();
+
+       /* buffer table is at the start of USB memory */
+       stm_usb.btable = 0;
+
+       ao_usb_init_ep(AO_USB_CONTROL_EPR, AO_USB_CONTROL_EP,
+                      STM_USB_EPR_EP_TYPE_CONTROL,
+                      STM_USB_EPR_STAT_RX_VALID,
+                      STM_USB_EPR_STAT_TX_NAK);
+
+       /* Clear all of the other endpoints */
+       for (e = 1; e < 8; e++) {
+               ao_usb_init_ep(e, 0,
+                              STM_USB_EPR_EP_TYPE_CONTROL,
+                              STM_USB_EPR_STAT_RX_DISABLED,
+                              STM_USB_EPR_STAT_TX_DISABLED);
+       }
+
+       ao_usb_set_address(0);
+}
+
+static void
+ao_usb_set_configuration(void)
+{
+       debug ("ao_usb_set_configuration\n");
+
+       /* Set up the INT end point */
+       ao_usb_bdt[AO_USB_INT_EPR].single.addr_tx = ao_usb_sram_addr;
+       ao_usb_bdt[AO_USB_INT_EPR].single.count_tx = 0;
+       ao_usb_sram_addr += AO_USB_INT_SIZE;
+
+       ao_usb_init_ep(AO_USB_INT_EPR,
+                      AO_USB_INT_EP,
+                      STM_USB_EPR_EP_TYPE_INTERRUPT,
+                      STM_USB_EPR_STAT_RX_DISABLED,
+                      STM_USB_EPR_STAT_TX_NAK);
+
+       /* Set up the OUT end point */
+       ao_usb_bdt[AO_USB_OUT_EPR].single.addr_rx = ao_usb_sram_addr;
+       ao_usb_bdt[AO_USB_OUT_EPR].single.count_rx = ((1 << STM_USB_BDT_COUNT_RX_BL_SIZE) |
+                                                     (((AO_USB_OUT_SIZE / 32) - 1) << STM_USB_BDT_COUNT_RX_NUM_BLOCK));
+       ao_usb_out_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr);
+       ao_usb_sram_addr += AO_USB_OUT_SIZE;
+
+       ao_usb_init_ep(AO_USB_OUT_EPR,
+                      AO_USB_OUT_EP,
+                      STM_USB_EPR_EP_TYPE_BULK,
+                      STM_USB_EPR_STAT_RX_VALID,
+                      STM_USB_EPR_STAT_TX_DISABLED);
+
+       /* Set up the IN end point */
+       ao_usb_bdt[AO_USB_IN_EPR].single.addr_tx = ao_usb_sram_addr;
+       ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = 0;
+       ao_usb_in_tx_offset = ao_usb_sram_addr;
+       ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_in_tx_offset);
+       ao_usb_sram_addr += AO_USB_IN_SIZE;
+
+       ao_usb_init_ep(AO_USB_IN_EPR,
+                      AO_USB_IN_EP,
+                      STM_USB_EPR_EP_TYPE_BULK,
+                      STM_USB_EPR_STAT_RX_DISABLED,
+                      STM_USB_EPR_STAT_TX_NAK);
+
+       ao_usb_running = 1;
+}
+
+static uint16_t        control_count;
+static uint16_t int_count;
+static uint16_t        in_count;
+static uint16_t        out_count;
+static uint16_t        reset_count;
+
+/* The USB memory must be accessed in 16-bit units
+ */
+
+static void
+ao_usb_copy_tx(const uint8_t *src, uint16_t *base, uint16_t bytes)
+{
+       while (bytes >= 2) {
+               *base++ = src[0] | (src[1] << 8);
+               src += 2;
+               bytes -= 2;
+       }
+       if (bytes)
+               *base = *src;
+}
+
+static void
+ao_usb_copy_rx(uint8_t *dst, uint16_t *base, uint16_t bytes)
+{
+       while (bytes >= 2) {
+               uint16_t s = *base++;
+               dst[0] = s;
+               dst[1] = s >> 8;
+               dst += 2;
+               bytes -= 2;
+       }
+       if (bytes)
+               *dst = *base;
+}
+
+/* Send an IN data packet */
+static void
+ao_usb_ep0_flush(void)
+{
+       uint8_t this_len;
+
+       /* Check to see if the endpoint is still busy */
+       if (ao_usb_epr_stat_tx(stm_usb.epr[0].r) == STM_USB_EPR_STAT_TX_VALID) {
+               debug("EP0 not accepting IN data\n");
+               return;
+       }
+
+       this_len = ao_usb_ep0_in_len;
+       if (this_len > AO_USB_CONTROL_SIZE)
+               this_len = AO_USB_CONTROL_SIZE;
+
+       if (this_len < AO_USB_CONTROL_SIZE)
+               ao_usb_ep0_state = AO_USB_EP0_IDLE;
+
+       ao_usb_ep0_in_len -= this_len;
+
+       debug_data ("Flush EP0 len %d:", this_len);
+       ao_usb_copy_tx(ao_usb_ep0_in_data, ao_usb_ep0_tx_buffer, this_len);
+       debug_data ("\n");
+       ao_usb_ep0_in_data += this_len;
+
+       /* Mark the endpoint as TX valid to send the packet */
+       ao_usb_bdt[AO_USB_CONTROL_EPR].single.count_tx = this_len;
+       ao_usb_set_stat_tx(AO_USB_CONTROL_EPR, STM_USB_EPR_STAT_TX_VALID);
+       debug ("queue tx. epr 0 now %08x\n", stm_usb.epr[AO_USB_CONTROL_EPR]);
+}
+
+/* Read data from the ep0 OUT fifo */
+static void
+ao_usb_ep0_fill(void)
+{
+       uint16_t        len = ao_usb_bdt[0].single.count_rx & STM_USB_BDT_COUNT_RX_COUNT_RX_MASK;
+
+       if (len > ao_usb_ep0_out_len)
+               len = ao_usb_ep0_out_len;
+       ao_usb_ep0_out_len -= len;
+
+       /* Pull all of the data out of the packet */
+       debug_data ("Fill EP0 len %d:", len);
+       ao_usb_copy_rx(ao_usb_ep0_out_data, ao_usb_ep0_rx_buffer, len);
+       debug_data ("\n");
+       ao_usb_ep0_out_data += len;
+
+       /* ACK the packet */
+       ao_usb_set_stat_rx(0, STM_USB_EPR_STAT_RX_VALID);
+}
+
+static void
+ao_usb_ep0_in_reset(void)
+{
+       ao_usb_ep0_in_data = ao_usb_ep0_in_buf;
+       ao_usb_ep0_in_len = 0;
+}
+
+static void
+ao_usb_ep0_in_queue_byte(uint8_t a)
+{
+       if (ao_usb_ep0_in_len < sizeof (ao_usb_ep0_in_buf))
+               ao_usb_ep0_in_buf[ao_usb_ep0_in_len++] = a;
+}
+
+static void
+ao_usb_ep0_in_set(const uint8_t *data, uint8_t len)
+{
+       ao_usb_ep0_in_data = data;
+       ao_usb_ep0_in_len = len;
+}
+
+static void
+ao_usb_ep0_out_set(uint8_t *data, uint8_t len)
+{
+       ao_usb_ep0_out_data = data;
+       ao_usb_ep0_out_len = len;
+}
+
+static void
+ao_usb_ep0_in_start(uint16_t max)
+{
+       /* Don't send more than asked for */
+       if (ao_usb_ep0_in_len > max)
+               ao_usb_ep0_in_len = max;
+       ao_usb_ep0_flush();
+}
+
+static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8};
+
+/* Walk through the list of descriptors and find a match
+ */
+static void
+ao_usb_get_descriptor(uint16_t value)
+{
+       const uint8_t           *descriptor;
+       uint8_t         type = value >> 8;
+       uint8_t         index = value;
+
+       descriptor = ao_usb_descriptors;
+       while (descriptor[0] != 0) {
+               if (descriptor[1] == type && index-- == 0) {
+                       uint8_t len;
+                       if (type == AO_USB_DESC_CONFIGURATION)
+                               len = descriptor[2];
+                       else
+                               len = descriptor[0];
+                       ao_usb_ep0_in_set(descriptor, len);
+                       break;
+               }
+               descriptor += descriptor[0];
+       }
+}
+
+static void
+ao_usb_ep0_setup(void)
+{
+       /* Pull the setup packet out of the fifo */
+       ao_usb_ep0_out_set((uint8_t *) &ao_usb_setup, 8);
+       ao_usb_ep0_fill();
+       if (ao_usb_ep0_out_len != 0) {
+               debug ("invalid setup packet length\n");
+               return;
+       }
+
+       if ((ao_usb_setup.dir_type_recip & AO_USB_DIR_IN) || ao_usb_setup.length == 0)
+               ao_usb_ep0_state = AO_USB_EP0_DATA_IN;
+       else
+               ao_usb_ep0_state = AO_USB_EP0_DATA_OUT;
+
+       ao_usb_ep0_in_reset();
+
+       switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_TYPE_MASK) {
+       case AO_USB_TYPE_STANDARD:
+               debug ("Standard setup packet\n");
+               switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_RECIP_MASK) {
+               case AO_USB_RECIP_DEVICE:
+                       debug ("Device setup packet\n");
+                       switch(ao_usb_setup.request) {
+                       case AO_USB_REQ_GET_STATUS:
+                               debug ("get status\n");
+                               ao_usb_ep0_in_queue_byte(0);
+                               ao_usb_ep0_in_queue_byte(0);
+                               break;
+                       case AO_USB_REQ_SET_ADDRESS:
+                               debug ("set address %d\n", ao_usb_setup.value);
+                               ao_usb_address = ao_usb_setup.value;
+                               ao_usb_address_pending = 1;
+                               break;
+                       case AO_USB_REQ_GET_DESCRIPTOR:
+                               debug ("get descriptor %d\n", ao_usb_setup.value);
+                               ao_usb_get_descriptor(ao_usb_setup.value);
+                               break;
+                       case AO_USB_REQ_GET_CONFIGURATION:
+                               debug ("get configuration %d\n", ao_usb_configuration);
+                               ao_usb_ep0_in_queue_byte(ao_usb_configuration);
+                               break;
+                       case AO_USB_REQ_SET_CONFIGURATION:
+                               ao_usb_configuration = ao_usb_setup.value;
+                               debug ("set configuration %d\n", ao_usb_configuration);
+                               ao_usb_set_configuration();
+                               break;
+                       }
+                       break;
+               case AO_USB_RECIP_INTERFACE:
+                       debug ("Interface setup packet\n");
+                       switch(ao_usb_setup.request) {
+                       case AO_USB_REQ_GET_STATUS:
+                               ao_usb_ep0_in_queue_byte(0);
+                               ao_usb_ep0_in_queue_byte(0);
+                               break;
+                       case AO_USB_REQ_GET_INTERFACE:
+                               ao_usb_ep0_in_queue_byte(0);
+                               break;
+                       case AO_USB_REQ_SET_INTERFACE:
+                               break;
+                       }
+                       break;
+               case AO_USB_RECIP_ENDPOINT:
+                       debug ("Endpoint setup packet\n");
+                       switch(ao_usb_setup.request) {
+                       case AO_USB_REQ_GET_STATUS:
+                               ao_usb_ep0_in_queue_byte(0);
+                               ao_usb_ep0_in_queue_byte(0);
+                               break;
+                       }
+                       break;
+               }
+               break;
+       case AO_USB_TYPE_CLASS:
+               debug ("Class setup packet\n");
+               switch (ao_usb_setup.request) {
+               case AO_USB_SET_LINE_CODING:
+                       debug ("set line coding\n");
+                       ao_usb_ep0_out_set((uint8_t *) &ao_usb_line_coding, 7);
+                       break;
+               case AO_USB_GET_LINE_CODING:
+                       debug ("get line coding\n");
+                       ao_usb_ep0_in_set((const uint8_t *) &ao_usb_line_coding, 7);
+                       break;
+               case AO_USB_SET_CONTROL_LINE_STATE:
+                       break;
+               }
+               break;
+       }
+
+       /* If we're not waiting to receive data from the host,
+        * queue an IN response
+        */
+       if (ao_usb_ep0_state == AO_USB_EP0_DATA_IN)
+               ao_usb_ep0_in_start(ao_usb_setup.length);
+}
+
+static void
+ao_usb_ep0_handle(uint8_t receive)
+{
+       ao_usb_ep0_receive = 0;
+       if (receive & AO_USB_EP0_GOT_RESET) {
+               debug ("\treset\n");
+               ao_usb_set_ep0();
+               return;
+       }
+       if (receive & AO_USB_EP0_GOT_SETUP) {
+               debug ("\tsetup\n");
+               ao_usb_ep0_setup();
+       }
+       if (receive & AO_USB_EP0_GOT_RX_DATA) {
+               debug ("\tgot rx data\n");
+               if (ao_usb_ep0_state == AO_USB_EP0_DATA_OUT) {
+                       ao_usb_ep0_fill();
+                       if (ao_usb_ep0_out_len == 0) {
+                               ao_usb_ep0_state = AO_USB_EP0_DATA_IN;
+                               ao_usb_ep0_in_start(0);
+                       }
+               }
+       }
+       if (receive & AO_USB_EP0_GOT_TX_ACK) {
+               debug ("\tgot tx ack\n");
+
+#if HAS_FLIGHT && AO_USB_FORCE_IDLE
+               ao_flight_force_idle = 1;
+#endif
+               /* Wait until the IN packet is received from addr 0
+                * before assigning our local address
+                */
+               if (ao_usb_address_pending)
+                       ao_usb_set_address(ao_usb_address);
+               if (ao_usb_ep0_state == AO_USB_EP0_DATA_IN)
+                       ao_usb_ep0_flush();
+       }
+}
+
+void
+stm_usb_isr(void)
+{
+       uint32_t        istr = stm_usb.istr;
+
+       stm_usb.istr = ~istr;
+       if (istr & (1 << STM_USB_ISTR_CTR)) {
+               uint8_t         ep = istr & STM_USB_ISTR_EP_ID_MASK;
+               uint16_t        epr, epr_write;
+
+               /* Preserve the SW write bits, don't mess with most HW writable bits,
+                * clear the CTR_RX and CTR_TX bits
+                */
+               epr = stm_usb.epr[ep].r;
+               epr_write = epr;
+               epr_write &= STM_USB_EPR_PRESERVE_MASK;
+               epr_write |= STM_USB_EPR_INVARIANT;
+               epr_write &= ~(1 << STM_USB_EPR_CTR_RX);
+               epr_write &= ~(1 << STM_USB_EPR_CTR_TX);
+               stm_usb.epr[ep].r = epr_write;
+
+               switch (ep) {
+               case 0:
+                       ++control_count;
+                       if (ao_usb_epr_ctr_rx(epr)) {
+                               if (ao_usb_epr_setup(epr))
+                                       ao_usb_ep0_receive |= AO_USB_EP0_GOT_SETUP;
+                               else
+                                       ao_usb_ep0_receive |= AO_USB_EP0_GOT_RX_DATA;
+                       }
+                       if (ao_usb_epr_ctr_tx(epr))
+                               ao_usb_ep0_receive |= AO_USB_EP0_GOT_TX_ACK;
+                       ao_usb_ep0_handle(ao_usb_ep0_receive);
+                       break;
+               case AO_USB_OUT_EPR:
+                       ++out_count;
+                       if (ao_usb_epr_ctr_rx(epr)) {
+                               _rx_dbg1("RX ISR", epr);
+                               ao_usb_out_avail = 1;
+                               _rx_dbg0("out avail set");
+                               ao_wakeup(AO_USB_OUT_SLEEP_ADDR);
+                               _rx_dbg0("stdin awoken");
+                       }
+                       break;
+               case AO_USB_IN_EPR:
+                       ++in_count;
+                       _tx_dbg1("TX ISR", epr);
+                       if (ao_usb_epr_ctr_tx(epr)) {
+                               ao_usb_in_pending = 0;
+                               ao_wakeup(&ao_usb_in_pending);
+                       }
+                       break;
+               case AO_USB_INT_EPR:
+                       ++int_count;
+                       if (ao_usb_epr_ctr_tx(epr))
+                               _ao_usb_set_stat_tx(AO_USB_INT_EPR, STM_USB_EPR_STAT_TX_NAK);
+                       break;
+               }
+               return;
+       }
+
+       if (istr & (1 << STM_USB_ISTR_RESET)) {
+               ++reset_count;
+               ao_usb_ep0_receive |= AO_USB_EP0_GOT_RESET;
+               ao_usb_ep0_handle(ao_usb_ep0_receive);
+       }
+
+}
+
+/* Queue the current IN buffer for transmission */
+static void
+_ao_usb_in_send(void)
+{
+       _tx_dbg0("in_send start");
+       debug ("send %d\n", ao_usb_tx_count);
+       while (ao_usb_in_pending)
+               ao_sleep(&ao_usb_in_pending);
+       ao_usb_in_pending = 1;
+       if (ao_usb_tx_count != AO_USB_IN_SIZE)
+               ao_usb_in_flushed = 1;
+       ao_usb_copy_tx(ao_usb_tx_buffer, ao_usb_in_tx_buffer, ao_usb_tx_count);
+       ao_usb_bdt[AO_USB_IN_EPR].single.addr_tx = ao_usb_in_tx_offset;
+       ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = ao_usb_tx_count;
+       ao_usb_tx_count = 0;
+       _ao_usb_set_stat_tx(AO_USB_IN_EPR, STM_USB_EPR_STAT_TX_VALID);
+       _tx_dbg0("in_send end");
+}
+
+/* Wait for a free IN buffer. Interrupts are blocked */
+static void
+_ao_usb_in_wait(void)
+{
+       for (;;) {
+               /* Check if the current buffer is writable */
+               if (ao_usb_tx_count < AO_USB_IN_SIZE)
+                       break;
+
+               _tx_dbg0("in_wait top");
+               /* Wait for an IN buffer to be ready */
+               while (ao_usb_in_pending)
+                       ao_sleep(&ao_usb_in_pending);
+               _tx_dbg0("in_wait bottom");
+       }
+}
+
+void
+ao_usb_flush(void)
+{
+       if (!ao_usb_running)
+               return;
+
+       /* Anytime we've sent a character since
+        * the last time we flushed, we'll need
+        * to send a packet -- the only other time
+        * we would send a packet is when that
+        * packet was full, in which case we now
+        * want to send an empty packet
+        */
+       ao_arch_block_interrupts();
+       while (!ao_usb_in_flushed) {
+               _tx_dbg0("flush top");
+               _ao_usb_in_send();
+               _tx_dbg0("flush end");
+       }
+       ao_arch_release_interrupts();
+}
+
+void
+ao_usb_putchar(char c)
+{
+       if (!ao_usb_running)
+               return;
+
+       ao_arch_block_interrupts();
+       _ao_usb_in_wait();
+
+       ao_usb_in_flushed = 0;
+       ao_usb_tx_buffer[ao_usb_tx_count++] = (uint8_t) c;
+
+       /* Send the packet when full */
+       if (ao_usb_tx_count == AO_USB_IN_SIZE) {
+               _tx_dbg0("putchar full");
+               _ao_usb_in_send();
+               _tx_dbg0("putchar flushed");
+       }
+       ao_arch_release_interrupts();
+}
+
+static void
+_ao_usb_out_recv(void)
+{
+       _rx_dbg0("out_recv top");
+       ao_usb_out_avail = 0;
+
+       ao_usb_rx_count = ao_usb_bdt[AO_USB_OUT_EPR].single.count_rx & STM_USB_BDT_COUNT_RX_COUNT_RX_MASK;
+
+       _rx_dbg1("out_recv count", ao_usb_rx_count);
+       debug ("recv %d\n", ao_usb_rx_count);
+       debug_data("Fill OUT len %d:", ao_usb_rx_count);
+       ao_usb_copy_rx(ao_usb_rx_buffer, ao_usb_out_rx_buffer, ao_usb_rx_count);
+       debug_data("\n");
+       ao_usb_rx_pos = 0;
+
+       /* ACK the packet */
+       _ao_usb_set_stat_rx(AO_USB_OUT_EPR, STM_USB_EPR_STAT_RX_VALID);
+}
+
+int
+_ao_usb_pollchar(void)
+{
+       uint8_t c;
+
+       if (!ao_usb_running)
+               return AO_READ_AGAIN;
+
+       for (;;) {
+               if (ao_usb_rx_pos != ao_usb_rx_count)
+                       break;
+
+               _rx_dbg0("poll check");
+               /* Check to see if a packet has arrived */
+               if (!ao_usb_out_avail) {
+                       _rx_dbg0("poll none");
+                       return AO_READ_AGAIN;
+               }
+               _ao_usb_out_recv();
+       }
+
+       /* Pull a character out of the fifo */
+       c = ao_usb_rx_buffer[ao_usb_rx_pos++];
+       return c;
+}
+
+char
+ao_usb_getchar(void)
+{
+       int     c;
+
+       ao_arch_block_interrupts();
+       while ((c = _ao_usb_pollchar()) == AO_READ_AGAIN)
+               ao_sleep(AO_USB_OUT_SLEEP_ADDR);
+       ao_arch_release_interrupts();
+       return c;
+}
+
+#if AO_USB_DIRECTIO
+uint16_t *
+ao_usb_alloc(void)
+{
+       uint16_t        *buffer;
+
+       if (!ao_usb_running)
+               return NULL;
+       buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr);
+       ao_usb_sram_addr += AO_USB_IN_SIZE;
+       return buffer;
+}
+
+void
+ao_usb_free(uint16_t *addr)
+{
+       uint16_t        offset = ao_usb_packet_buffer_offset(addr);
+       if (offset < ao_usb_sram_addr)
+               ao_usb_sram_addr = offset;
+}
+
+void
+ao_usb_write(uint16_t *buffer, uint16_t len)
+{
+       ao_arch_block_interrupts();
+
+       /* Flush any pending regular */
+       if (ao_usb_tx_count)
+               _ao_usb_in_send();
+
+       while (ao_usb_in_pending)
+               ao_sleep(&ao_usb_in_pending);
+       ao_usb_in_pending = 1;
+       ao_usb_in_flushed = (len != AO_USB_IN_SIZE);
+       ao_usb_bdt[AO_USB_IN_EPR].single.addr_tx = ao_usb_packet_buffer_offset(buffer);
+       ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = len;
+       _ao_usb_set_stat_tx(AO_USB_IN_EPR, STM_USB_EPR_STAT_TX_VALID);
+       ao_arch_release_interrupts();
+}
+#endif
+
+void
+ao_usb_disable(void)
+{
+       ao_arch_block_interrupts();
+       stm_usb.cntr = (1 << STM_USB_CNTR_FRES);
+       stm_usb.istr = 0;
+
+       /* Disable USB pull-up */
+       stm_usb.bcdr &= ~(1 << STM_USB_BCDR_DPPU);
+
+       /* Switch off the device */
+       stm_usb.cntr = (1 << STM_USB_CNTR_PDWN) | (1 << STM_USB_CNTR_FRES);
+
+       /* Disable the interface */
+       stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_USBEN);
+       ao_arch_release_interrupts();
+}
+
+void
+ao_usb_enable(void)
+{
+       int     t;
+
+       /* Select HSI48 as USB clock source */
+       stm_rcc.cfgr3 &= ~(1 << STM_RCC_CFGR3_USBSW);
+
+       /* Enable USB device */
+       stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USBEN);
+
+       /* Clear reset condition */
+       stm_rcc.apb1rstr &= ~(1 << STM_RCC_APB1RSTR_USBRST);
+
+       /* Disable USB pull-up */
+       stm_usb.bcdr &= ~(1 << STM_USB_BCDR_DPPU);
+
+       /* Do not touch the GPIOA configuration; USB takes priority
+        * over GPIO on pins A11 and A12, but if you select alternate
+        * input 10 (the documented correct selection), then USB is
+        * pulled low and doesn't work at all
+        */
+
+       ao_arch_block_interrupts();
+
+       /* Route interrupts */
+       stm_nvic_set_enable(STM_ISR_USB_POS);
+       stm_nvic_set_priority(STM_ISR_USB_POS, 3);
+
+       ao_usb_configuration = 0;
+
+       /* Set up buffer descriptors */
+       ao_usb_init_btable();
+
+       /* Reset the USB controller */
+       stm_usb.cntr = (1 << STM_USB_CNTR_FRES);
+
+       /* Clear the reset bit */
+       stm_usb.cntr = 0;
+
+       /* Clear any spurious interrupts */
+       stm_usb.istr = 0;
+
+       ao_usb_set_ep0();
+
+       debug ("ao_usb_enable\n");
+
+       /* Enable interrupts */
+       stm_usb.cntr = ((1 << STM_USB_CNTR_CTRM) |
+                       (0 << STM_USB_CNTR_PMAOVRM) |
+                       (0 << STM_USB_CNTR_ERRM) |
+                       (0 << STM_USB_CNTR_WKUPM) |
+                       (0 << STM_USB_CNTR_SUSPM) |
+                       (1 << STM_USB_CNTR_RESETM) |
+                       (0 << STM_USB_CNTR_SOFM) |
+                       (0 << STM_USB_CNTR_ESOFM) |
+                       (0 << STM_USB_CNTR_RESUME) |
+                       (0 << STM_USB_CNTR_FSUSP) |
+                       (0 << STM_USB_CNTR_LP_MODE) |
+                       (0 << STM_USB_CNTR_PDWN) |
+                       (0 << STM_USB_CNTR_FRES));
+
+       ao_arch_release_interrupts();
+
+       for (t = 0; t < 1000; t++)
+               ao_arch_nop();
+
+       /* Enable USB pull-up */
+       stm_usb.bcdr |= (1 << STM_USB_BCDR_DPPU);
+}
+
+#if USB_ECHO
+struct ao_task ao_usb_echo_task;
+
+static void
+ao_usb_echo(void)
+{
+       char    c;
+
+       for (;;) {
+               c = ao_usb_getchar();
+               ao_usb_putchar(c);
+               ao_usb_flush();
+       }
+}
+#endif
+
+#if USB_DEBUG
+static void
+ao_usb_irq(void)
+{
+       printf ("control: %d out: %d in: %d int: %d reset: %d\n",
+               control_count, out_count, in_count, int_count, reset_count);
+}
+
+__code struct ao_cmds ao_usb_cmds[] = {
+       { ao_usb_irq, "I\0Show USB interrupt counts" },
+       { 0, NULL }
+};
+#endif
+
+void
+ao_usb_init(void)
+{
+       /* Turn on syscfg */
+       stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SYSCFGCOMPEN);
+
+       /* Set PA11/PA12 remapping bit */
+       stm_syscfg.cfgr1 |= (AO_PA11_PA12_RMP << STM_SYSCFG_CFGR1_PA11_PA12_RMP);
+
+       ao_usb_enable();
+
+       debug ("ao_usb_init\n");
+       ao_usb_ep0_state = AO_USB_EP0_IDLE;
+#if USB_ECHO
+       ao_add_task(&ao_usb_echo_task, ao_usb_echo, "usb echo");
+#endif
+#if USB_DEBUG
+       ao_cmd_register(&ao_usb_cmds[0]);
+#endif
+#if !USB_ECHO
+#if USE_USB_STDIO
+       ao_add_stdio(_ao_usb_pollchar, ao_usb_putchar, ao_usb_flush);
+#endif
+#endif
+}
+
+#if TX_DBG || RX_DBG
+
+struct ao_usb_dbg {
+       int             line;
+       char            *msg;
+       uint32_t        value;
+       uint32_t        primask;
+#if TX_DBG
+       uint16_t        in_count;
+       uint32_t        in_epr;
+       uint32_t        in_pending;
+       uint32_t        tx_count;
+       uint32_t        in_flushed;
+#endif
+#if RX_DBG
+       uint8_t         rx_count;
+       uint8_t         rx_pos;
+       uint8_t         out_avail;
+       uint32_t        out_epr;
+#endif
+};
+
+#define NUM_USB_DBG    128
+
+static struct ao_usb_dbg dbg[128];
+static int dbg_i;
+
+static void _dbg(int line, char *msg, uint32_t value)
+{
+       uint32_t        primask;
+       dbg[dbg_i].line = line;
+       dbg[dbg_i].msg = msg;
+       dbg[dbg_i].value = value;
+       asm("mrs %0,primask" : "=&r" (primask));
+       dbg[dbg_i].primask = primask;
+#if TX_DBG
+       dbg[dbg_i].in_count = in_count;
+       dbg[dbg_i].in_epr = stm_usb.epr[AO_USB_IN_EPR];
+       dbg[dbg_i].in_pending = ao_usb_in_pending;
+       dbg[dbg_i].tx_count = ao_usb_tx_count;
+       dbg[dbg_i].in_flushed = ao_usb_in_flushed;
+#endif
+#if RX_DBG
+       dbg[dbg_i].rx_count = ao_usb_rx_count;
+       dbg[dbg_i].rx_pos = ao_usb_rx_pos;
+       dbg[dbg_i].out_avail = ao_usb_out_avail;
+       dbg[dbg_i].out_epr = stm_usb.epr[AO_USB_OUT_EPR];
+#endif
+       if (++dbg_i == NUM_USB_DBG)
+               dbg_i = 0;
+}
+#endif
diff --git a/src/stmf0/registers.ld b/src/stmf0/registers.ld
new file mode 100644 (file)
index 0000000..598fc1a
--- /dev/null
@@ -0,0 +1,57 @@
+stm_gpiof  = 0x48001400;
+stm_gpioc  = 0x48000800;
+stm_gpiob  = 0x48000400;
+stm_gpioa  = 0x48000000;
+
+stm_tsc    = 0x40024000;
+stm_crc    = 0x40023000;
+stm_flash  = 0x40022000;
+stm_rcc    = 0x40021000;
+stm_dma    = 0x40020000;
+stm_dbgmcu = 0x40015800;
+stm_tim17  = 0x40014800;
+stm_tim16  = 0x40014400;
+stm_usart1 = 0x40013800;
+stm_spi1   = 0x40013000;
+stm_tim1   = 0x40012c00;
+stm_adc    = 0x40012400;
+
+stm_exti   = 0x40010400;
+stm_syscfg = 0x40010000;
+
+stm_cec    = 0x40007800;
+
+stm_pwr    = 0x40007000;
+stm_crs    = 0x40006c00;
+
+stm_bxcan  = 0x40006400;
+stm_usb_sram = 0x40006000;
+stm_usb    = 0x40005c00;
+
+stm_i2c1   = 0x40005400;
+
+stm_usart2 = 0x40004400;
+
+stm_spi2   = 0x40003800;       /* docs are broken here */
+
+stm_iwdg   = 0x40003000;
+stm_wwdg   = 0x40002c00;
+stm_rtc    = 0x40002800;
+
+stm_tim14  = 0x40002000;
+
+stm_tim3   = 0x40000400;
+stm_tim2   = 0x40000000;
+
+stm_systick = 0xe000e010;
+
+stm_nvic   = 0xe000e100;
+
+stm_scb    = 0xe000ed00;
+
+stm_mpu    = 0xe000ed90;
+
+/* calibration data in system memory */
+stm_cal = 0x1ffff7b8;
+stm_flash_size_04x = 0x1ffff7cc;
+stm_device_id = 0x1ff80050;
diff --git a/src/stmf0/stm32f0.h b/src/stmf0/stm32f0.h
new file mode 100644 (file)
index 0000000..ce8ca45
--- /dev/null
@@ -0,0 +1,1667 @@
+/*
+ * Copyright © 2015 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _STM32F0_H_
+#define _STM32F0_H_
+
+#include <stdint.h>
+
+typedef volatile uint32_t      vuint32_t;
+typedef volatile void *                vvoid_t;
+typedef volatile uint16_t      vuint16_t;
+typedef volatile uint8_t       vuint8_t;
+
+struct stm_gpio {
+       vuint32_t       moder;
+       vuint32_t       otyper;
+       vuint32_t       ospeedr;
+       vuint32_t       pupdr;
+
+       vuint32_t       idr;
+       vuint32_t       odr;
+       vuint32_t       bsrr;
+       vuint32_t       lckr;
+
+       vuint32_t       afrl;
+       vuint32_t       afrh;
+       vuint32_t       brr;
+};
+
+#define STM_MODER_SHIFT(pin)           ((pin) << 1)
+#define STM_MODER_MASK                 3
+#define STM_MODER_INPUT                        0
+#define STM_MODER_OUTPUT               1
+#define STM_MODER_ALTERNATE            2
+#define STM_MODER_ANALOG               3
+
+static inline void
+stm_moder_set(struct stm_gpio *gpio, int pin, vuint32_t value) {
+       gpio->moder = ((gpio->moder &
+                       ~(STM_MODER_MASK << STM_MODER_SHIFT(pin))) |
+                      value << STM_MODER_SHIFT(pin));
+}
+
+static inline uint32_t
+stm_moder_get(struct stm_gpio *gpio, int pin) {
+       return (gpio->moder >> STM_MODER_SHIFT(pin)) & STM_MODER_MASK;
+}
+
+#define STM_OTYPER_SHIFT(pin)          (pin)
+#define STM_OTYPER_MASK                        1
+#define STM_OTYPER_PUSH_PULL           0
+#define STM_OTYPER_OPEN_DRAIN          1
+
+static inline void
+stm_otyper_set(struct stm_gpio *gpio, int pin, vuint32_t value) {
+       gpio->otyper = ((gpio->otyper &
+                        ~(STM_OTYPER_MASK << STM_OTYPER_SHIFT(pin))) |
+                       value << STM_OTYPER_SHIFT(pin));
+}
+
+static inline uint32_t
+stm_otyper_get(struct stm_gpio *gpio, int pin) {
+       return (gpio->otyper >> STM_OTYPER_SHIFT(pin)) & STM_OTYPER_MASK;
+}
+
+#define STM_OSPEEDR_SHIFT(pin)         ((pin) << 1)
+#define STM_OSPEEDR_MASK               3
+#define STM_OSPEEDR_LOW                        0       /* 2MHz */
+#define STM_OSPEEDR_MEDIUM             1       /* 10MHz */
+#define STM_OSPEEDR_HIGH               3       /* 10-50MHz */
+
+static inline void
+stm_ospeedr_set(struct stm_gpio *gpio, int pin, vuint32_t value) {
+       gpio->ospeedr = ((gpio->ospeedr &
+                       ~(STM_OSPEEDR_MASK << STM_OSPEEDR_SHIFT(pin))) |
+                      value << STM_OSPEEDR_SHIFT(pin));
+}
+
+static inline uint32_t
+stm_ospeedr_get(struct stm_gpio *gpio, int pin) {
+       return (gpio->ospeedr >> STM_OSPEEDR_SHIFT(pin)) & STM_OSPEEDR_MASK;
+}
+
+#define STM_PUPDR_SHIFT(pin)           ((pin) << 1)
+#define STM_PUPDR_MASK                 3
+#define STM_PUPDR_NONE                 0
+#define STM_PUPDR_PULL_UP              1
+#define STM_PUPDR_PULL_DOWN            2
+#define STM_PUPDR_RESERVED             3
+
+static inline void
+stm_pupdr_set(struct stm_gpio *gpio, int pin, uint32_t value) {
+       gpio->pupdr = ((gpio->pupdr &
+                       ~(STM_PUPDR_MASK << STM_PUPDR_SHIFT(pin))) |
+                      value << STM_PUPDR_SHIFT(pin));
+}
+
+static inline uint32_t
+stm_pupdr_get(struct stm_gpio *gpio, int pin) {
+       return (gpio->pupdr >> STM_PUPDR_SHIFT(pin)) & STM_PUPDR_MASK;
+}
+
+#define STM_AFR_SHIFT(pin)             ((pin) << 2)
+#define STM_AFR_MASK                   0xf
+#define STM_AFR_NONE                   0
+#define STM_AFR_AF0                    0x0
+#define STM_AFR_AF1                    0x1
+#define STM_AFR_AF2                    0x2
+#define STM_AFR_AF3                    0x3
+#define STM_AFR_AF4                    0x4
+#define STM_AFR_AF5                    0x5
+#define STM_AFR_AF6                    0x6
+#define STM_AFR_AF7                    0x7
+
+static inline void
+stm_afr_set(struct stm_gpio *gpio, int pin, uint32_t value) {
+       /*
+        * Set alternate pin mode too
+        */
+       stm_moder_set(gpio, pin, STM_MODER_ALTERNATE);
+       if (pin < 8)
+               gpio->afrl = ((gpio->afrl &
+                              ~(STM_AFR_MASK << STM_AFR_SHIFT(pin))) |
+                             value << STM_AFR_SHIFT(pin));
+       else {
+               pin -= 8;
+               gpio->afrh = ((gpio->afrh &
+                              ~(STM_AFR_MASK << STM_AFR_SHIFT(pin))) |
+                             value << STM_AFR_SHIFT(pin));
+       }
+}
+
+static inline uint32_t
+stm_afr_get(struct stm_gpio *gpio, int pin) {
+       if (pin < 8)
+               return (gpio->afrl >> STM_AFR_SHIFT(pin)) & STM_AFR_MASK;
+       else {
+               pin -= 8;
+               return (gpio->afrh >> STM_AFR_SHIFT(pin)) & STM_AFR_MASK;
+       }
+}
+
+static inline void
+stm_gpio_set(struct stm_gpio *gpio, int pin, uint8_t value) {
+       /* Use the bit set/reset register to do this atomically */
+       gpio->bsrr = ((uint32_t) (value ^ 1) << (pin + 16)) | ((uint32_t) value << pin);
+}
+
+static inline uint8_t
+stm_gpio_get(struct stm_gpio *gpio, int pin) {
+       return (gpio->idr >> pin) & 1;
+}
+
+static inline uint16_t
+stm_gpio_get_all(struct stm_gpio *gpio) {
+       return gpio->idr;
+}
+
+/*
+ * We can't define these in registers.ld or our fancy
+ * ao_enable_gpio macro will expand into a huge pile of code
+ * as the compiler won't do correct constant folding and
+ * dead-code elimination
+ */
+
+extern struct stm_gpio stm_gpioa;
+extern struct stm_gpio stm_gpiob;
+extern struct stm_gpio stm_gpioc;
+extern struct stm_gpio stm_gpiof;
+
+#define stm_gpiof  (*((struct stm_gpio *) 0x48001400))
+#define stm_gpioc  (*((struct stm_gpio *) 0x48000800))
+#define stm_gpiob  (*((struct stm_gpio *) 0x48000400))
+#define stm_gpioa  (*((struct stm_gpio *) 0x48000000))
+
+/* Flash interface */
+
+struct stm_flash {
+       vuint32_t       acr;
+       vuint32_t       keyr;
+       vuint32_t       optkeyr;
+       vuint32_t       sr;
+
+       vuint32_t       cr;
+       vuint32_t       ar;
+       vuint32_t       unused_0x18;
+       vuint32_t       obr;
+
+       vuint32_t       wrpr;
+};
+
+extern struct stm_flash        stm_flash;
+
+#define STM_FLASH_ACR_PRFTBS   (5)
+#define STM_FLASH_ACR_PRFTBE   (4)
+#define STM_FLASH_ACR_LATENCY  (0)
+#define  STM_FLASH_ACR_LATENCY_0               0
+#define  STM_FLASH_ACR_LATENCY_1               1
+
+#define STM_FLASH_PECR_OBL_LAUNCH      18
+#define STM_FLASH_PECR_ERRIE           17
+#define STM_FLASH_PECR_EOPIE           16
+#define STM_FLASH_PECR_FPRG            10
+#define STM_FLASH_PECR_ERASE           9
+#define STM_FLASH_PECR_FTDW            8
+#define STM_FLASH_PECR_DATA            4
+#define STM_FLASH_PECR_PROG            3
+#define STM_FLASH_PECR_OPTLOCK         2
+#define STM_FLASH_PECR_PRGLOCK         1
+#define STM_FLASH_PECR_PELOCK          0
+
+#define STM_FLASH_SR_EOP               5
+#define STM_FLASH_SR_WRPRTERR          4
+#define STM_FLASH_SR_PGERR             2
+#define STM_FLASH_SR_BSY               0
+
+#define STM_FLASH_CR_OBL_LAUNCH                13
+#define STM_FLASH_CR_EOPIE             12
+#define STM_FLASH_CR_ERRIE             10
+#define STM_FLASH_CR_OPTWRE            9
+#define STM_FLASH_CR_LOCK              7
+#define STM_FLASH_CR_STRT              6
+#define STM_FLASH_CR_OPTER             5
+#define STM_FLASH_CR_OPTPG             4
+#define STM_FLASH_CR_MER               2
+#define STM_FLASH_CR_PER               1
+#define STM_FLASH_CR_PG                        0
+
+#define STM_FLASH_OBR_DATA1            24
+#define STM_FLASH_OBR_DATA0            16
+#define STM_FLASH_OBR_BOOT_SEL         15
+#define STM_FLASH_OBR_RAM_PARITY_CHECK 14
+#define STM_FLASH_OBR_VDDA_MONITOR     13
+#define STM_FLASH_OBR_NBOOT1           12
+#define STM_FLASH_OBR_NBOOT0           11
+#define STM_FLASH_OBR_NRST_STDBY       10
+#define STM_FLASH_OBR_NRST_STOP                9
+#define STM_FLASH_OBR_WDG_SW           8
+#define STM_FLASH_OBR_RDPRT            1
+#define  STM_FLASH_OBR_RDPRT_LEVEL0            0
+#define  STM_FLASH_OBR_RDPRT_LEVEL1            1
+#define  STM_FLASH_OBR_RDPRT_LEVEL2            3
+#define STM_FLASH_OBR_OPTERR           0
+
+#define STM_FLASH_KEYR_KEY1    0x45670123
+#define STM_FLASH_KEYR_KEY2    0xcdef89ab
+
+struct stm_rcc {
+       vuint32_t       cr;
+       vuint32_t       cfgr;
+       vuint32_t       cir;
+       vuint32_t       apb2rstr;
+
+       vuint32_t       apb1rstr;
+       vuint32_t       ahbenr;
+       vuint32_t       apb2enr;
+       vuint32_t       apb1enr;
+
+       vuint32_t       bdcr;
+       vuint32_t       csr;
+       vuint32_t       ahbrstr;
+       vuint32_t       cfgr2;
+
+       vuint32_t       cfgr3;
+       vuint32_t       cr2;
+};
+
+extern struct stm_rcc stm_rcc;
+
+/* Nominal high speed internal oscillator frequency is 16MHz */
+#define STM_HSI_FREQ           16000000
+
+#define STM_RCC_CR_PLLRDY      (25)
+#define STM_RCC_CR_PLLON       (24)
+#define STM_RCC_CR_CSSON       (19)
+#define STM_RCC_CR_HSEBYP      (18)
+#define STM_RCC_CR_HSERDY      (17)
+#define STM_RCC_CR_HSEON       (16)
+#define STM_RCC_CR_HSICAL      (8)
+#define STM_RCC_CR_HSITRIM     (3)
+#define STM_RCC_CR_HSIRDY      (1)
+#define STM_RCC_CR_HSION       (0)
+
+#define STM_RCC_CFGR_PLL_NODIV (31)
+#define  STM_RCC_CFGR_PLL_NODIV_DIV_1  1
+#define  STM_RCC_CFGR_PLL_NODIV_DIV_2  0
+
+#define STM_RCC_CFGR_MCOPRE    (28)
+#define  STM_RCC_CFGR_MCOPRE_DIV_1     0
+#define  STM_RCC_CFGR_MCOPRE_DIV_2     1
+#define  STM_RCC_CFGR_MCOPRE_DIV_4     2
+#define  STM_RCC_CFGR_MCOPRE_DIV_8     3
+#define  STM_RCC_CFGR_MCOPRE_DIV_16    4
+#define  STM_RCC_CFGR_MCOPRE_DIV_32    5
+#define  STM_RCC_CFGR_MCOPRE_DIV_64    6
+#define  STM_RCC_CFGR_MCOPRE_DIV_128   7
+#define  STM_RCC_CFGR_MCOPRE_DIV_MASK  7
+
+#define STM_RCC_CFGR_MCO       (24)
+# define STM_RCC_CFGR_MCO_DISABLE      0
+
+#define STM_RCC_CFGR_PLLMUL    (18)
+#define  STM_RCC_CFGR_PLLMUL_2         0
+#define  STM_RCC_CFGR_PLLMUL_3         1
+#define  STM_RCC_CFGR_PLLMUL_4         2
+#define  STM_RCC_CFGR_PLLMUL_5         3
+#define  STM_RCC_CFGR_PLLMUL_6         4
+#define  STM_RCC_CFGR_PLLMUL_7         5
+#define  STM_RCC_CFGR_PLLMUL_8         6
+#define  STM_RCC_CFGR_PLLMUL_9         7
+#define  STM_RCC_CFGR_PLLMUL_10                8
+#define  STM_RCC_CFGR_PLLMUL_11                9
+#define  STM_RCC_CFGR_PLLMUL_12                10
+#define  STM_RCC_CFGR_PLLMUL_13                11
+#define  STM_RCC_CFGR_PLLMUL_14                12
+#define  STM_RCC_CFGR_PLLMUL_15                13
+#define  STM_RCC_CFGR_PLLMUL_16                14
+#define  STM_RCC_CFGR_PLLMUL_MASK      0xf
+
+#define STM_RCC_CFGR_PLLXTPRE  (17)
+
+#define STM_RCC_CFGR_PLLSRC    (15)
+# define STM_RCC_CFGR_PLLSRC_HSI_DIV_2 0
+# define STM_RCC_CFGR_PLLSRC_HSI       1
+# define STM_RCC_CFGR_PLLSRC_HSE       2
+# define STM_RCC_CFGR_PLLSRC_HSI48     3
+
+#define STM_RCC_CFGR_ADCPRE    (14)
+
+#define STM_RCC_CFGR_PPRE      (8)
+#define  STM_RCC_CFGR_PPRE_DIV_1       0
+#define  STM_RCC_CFGR_PPRE_DIV_2       4
+#define  STM_RCC_CFGR_PPRE_DIV_4       5
+#define  STM_RCC_CFGR_PPRE_DIV_8       6
+#define  STM_RCC_CFGR_PPRE_DIV_16      7
+#define  STM_RCC_CFGR_PPRE_MASK                7
+
+#define STM_RCC_CFGR_HPRE      (4)
+#define  STM_RCC_CFGR_HPRE_DIV_1       0
+#define  STM_RCC_CFGR_HPRE_DIV_2       8
+#define  STM_RCC_CFGR_HPRE_DIV_4       9
+#define  STM_RCC_CFGR_HPRE_DIV_8       0xa
+#define  STM_RCC_CFGR_HPRE_DIV_16      0xb
+#define  STM_RCC_CFGR_HPRE_DIV_64      0xc
+#define  STM_RCC_CFGR_HPRE_DIV_128     0xd
+#define  STM_RCC_CFGR_HPRE_DIV_256     0xe
+#define  STM_RCC_CFGR_HPRE_DIV_512     0xf
+#define  STM_RCC_CFGR_HPRE_MASK                0xf
+
+#define STM_RCC_CFGR_SWS       (2)
+#define  STM_RCC_CFGR_SWS_HSI          0
+#define  STM_RCC_CFGR_SWS_HSE          1
+#define  STM_RCC_CFGR_SWS_PLL          2
+#define  STM_RCC_CFGR_SWS_HSI48                3
+#define  STM_RCC_CFGR_SWS_MASK         3
+
+#define STM_RCC_CFGR_SW                (0)
+#define  STM_RCC_CFGR_SW_HSI           0
+#define  STM_RCC_CFGR_SW_HSE           1
+#define  STM_RCC_CFGR_SW_PLL           2
+#define  STM_RCC_CFGR_SW_HSI48         3
+#define  STM_RCC_CFGR_SW_MASK          3
+
+#define STM_RCC_APB2RSTR_DBGMCURST     22
+#define STM_RCC_APB2RSTR_TIM17RST      18
+#define STM_RCC_APB2RSTR_TIM16RST      17
+#define STM_RCC_APB2RSTR_TIM15RST      16
+#define STM_RCC_APB2RSTR_USART1RST     14
+#define STM_RCC_APB2RSTR_SPI1RST       12
+#define STM_RCC_APB2RSTR_TIM1RST       11
+#define STM_RCC_APB2RSTR_ADCRST                9
+#define STM_RCC_APB2RSTR_USART8RST     7
+#define STM_RCC_APB2RSTR_USART7RST     6
+#define STM_RCC_APB2RSTR_USART6RST     5
+#define STM_RCC_APB2RSTR_SYSCFGRST     1
+
+#define STM_RCC_APB1RSTR_CECRST                30
+#define STM_RCC_APB1RSTR_DACRST                29
+#define STM_RCC_APB1RSTR_PWRRST                28
+#define STM_RCC_APB1RSTR_CRSRST                27
+#define STM_RCC_APB1RSTR_CANRST                25
+#define STM_RCC_APB1RSTR_USBRST                23
+#define STM_RCC_APB1RSTR_I2C2RST       22
+#define STM_RCC_APB1RSTR_I1C1RST       21
+#define STM_RCC_APB1RSTR_USART5RST     20
+#define STM_RCC_APB1RSTR_USART4RST     19
+#define STM_RCC_APB1RSTR_USART3RST     18
+#define STM_RCC_APB1RSTR_USART2RST     17
+#define STM_RCC_APB1RSTR_SPI2RST       14
+#define STM_RCC_APB1RSTR_WWDGRST       11
+#define STM_RCC_APB1RSTR_TIM14RST      8
+#define STM_RCC_APB1RSTR_TIM7RST       5
+#define STM_RCC_APB1RSTR_TIM6RST       4
+#define STM_RCC_APB1RSTR_TIM3RST       1
+#define STM_RCC_APB1RSTR_TIM2RST       0
+
+#define STM_RCC_AHBENR_TSCEN   24
+#define STM_RCC_AHBENR_IOPFEN  22
+#define STM_RCC_AHBENR_IOPEEN  21
+#define STM_RCC_AHBENR_IOPDEN  20
+#define STM_RCC_AHBENR_IOPCEN  19
+#define STM_RCC_AHBENR_IOPBEN  18
+#define STM_RCC_AHBENR_IOPAEN  17
+#define STM_RCC_AHBENR_CRCEN   6
+#define STM_RCC_AHBENR_FLITFEN 4
+#define STM_RCC_AHBENR_SRAMEN  2
+#define STM_RCC_AHBENR_DMA2EN  1
+#define STM_RCC_AHBENR_DMAEN   0
+
+#define STM_RCC_APB2ENR_DBGMCUEN       22
+#define STM_RCC_APB2ENR_TIM17EN                18
+#define STM_RCC_APB2ENR_TIM16EN                17
+#define STM_RCC_APB2ENR_TIM15EN                16
+#define STM_RCC_APB2ENR_USART1EN       14
+#define STM_RCC_APB2ENR_SPI1EN         12
+#define STM_RCC_APB2ENR_TIM1EN         11
+#define STM_RCC_APB2ENR_ADCEN          9
+#define STM_RCC_APB2ENR_USART8EN       7
+#define STM_RCC_APB2ENR_USART7EN       6
+#define STM_RCC_APB2ENR_USART6EN       5
+#define STM_RCC_APB2ENR_SYSCFGCOMPEN   0
+
+#define STM_RCC_APB1ENR_CECEN          30
+#define STM_RCC_APB1ENR_DACEN          29
+#define STM_RCC_APB1ENR_PWREN          28
+#define STM_RCC_APB1ENR_CRSEN          27
+#define STM_RCC_APB1ENR_CANEN          25
+#define STM_RCC_APB1ENR_USBEN          23
+#define STM_RCC_APB1ENR_I2C2EN         22
+#define STM_RCC_APB1ENR_IC21EN         21
+#define STM_RCC_APB1ENR_USART5EN       20
+#define STM_RCC_APB1ENR_USART4EN       19
+#define STM_RCC_APB1ENR_USART3EN       18
+#define STM_RCC_APB1ENR_USART2EN       17
+#define STM_RCC_APB1ENR_SPI2EN         14
+#define STM_RCC_APB1ENR_WWDGEN         11
+#define STM_RCC_APB1ENR_TIM14EN                8
+#define STM_RCC_APB1ENR_TIM7EN         5
+#define STM_RCC_APB1ENR_TIM6EN         4
+#define STM_RCC_APB1ENR_TIM3EN         1
+#define STM_RCC_APB1ENR_TIM2EN         0
+
+#define STM_RCC_CSR_LPWRRSTF           (31)
+#define STM_RCC_CSR_WWDGRSTF           (30)
+#define STM_RCC_CSR_IWDGRSTF           (29)
+#define STM_RCC_CSR_SFTRSTF            (28)
+#define STM_RCC_CSR_PORRSTF            (27)
+#define STM_RCC_CSR_PINRSTF            (26)
+#define STM_RCC_CSR_OBLRSTF            (25)
+#define STM_RCC_CSR_RMVF               (24)
+#define STM_RCC_CSR_V18PWRRSTF         (23)
+#define STM_RCC_CSR_LSIRDY             (1)
+#define STM_RCC_CSR_LSION              (0)
+
+#define STM_RCC_CR2_HSI48CAL           24
+#define STM_RCC_CR2_HSI48RDY           17
+#define STM_RCC_CR2_HSI48ON            16
+#define STM_RCC_CR2_HSI14CAL           8
+#define STM_RCC_CR2_HSI14TRIM          3
+#define STM_RCC_CR2_HSI14DIS           2
+#define STM_RCC_CR2_HSI14RDY           1
+#define STM_RCC_CR2_HSI14ON            0
+
+#define STM_RCC_CFGR3_USART3SW         18
+#define STM_RCC_CFGR3_USART2SW         16
+#define STM_RCC_CFGR3_ADCSW            8
+#define STM_RCC_CFGR3_USBSW            7
+#define STM_RCC_CFGR3_CECSW            6
+#define STM_RCC_CFGR3_I2C1SW           4
+#define STM_RCC_CFGR3_USART1SW         0
+
+struct stm_crs {
+       vuint32_t       cr;
+       vuint32_t       cfgr;
+       vuint32_t       isr;
+       vuint32_t       icr;
+};
+
+extern struct stm_crs stm_crs;
+
+#define STM_CRS_CR_TRIM                8
+#define STM_CRS_CR_SWSYNC      7
+#define STM_CRS_CR_AUTOTRIMEN  6
+#define STM_CRS_CR_CEN         5
+#define STM_CRS_CR_ESYNCIE     3
+#define STM_CRS_CR_ERRIE       2
+#define STM_CRS_CR_SYNCWARNIE  1
+#define STM_CRS_CR_SYNCOKIE    0
+
+#define STM_CRS_CFGR_SYNCPOL   31
+#define STM_CRS_CFGR_SYNCSRC   28
+#define  STM_CRS_CFGR_SYNCSRC_GPIO     0
+#define  STM_CRS_CFGR_SYNCSRC_LSE      1
+#define  STM_CRS_CFGR_SYNCSRC_USB      2
+#define STM_CRS_CFGR_SYNCDIV   24
+#define  STM_CRS_CFGR_SYNCDIV_1                0
+#define  STM_CRS_CFGR_SYNCDIV_2                1
+#define  STM_CRS_CFGR_SYNCDIV_4                2
+#define  STM_CRS_CFGR_SYNCDIV_8                3
+#define  STM_CRS_CFGR_SYNCDIV_16       4
+#define  STM_CRS_CFGR_SYNCDIV_32       5
+#define  STM_CRS_CFGR_SYNCDIV_64       6
+#define  STM_CRS_CFGR_SYNCDIV_128      7
+#define STM_CRS_CFGR_FELIM     16
+#define STM_CRS_CFGR_RELOAD    0
+
+#define STM_CRS_ISR_FECAP      16
+#define STM_CRS_ISR_FEDIR      15
+#define STM_CRS_ISR_TRIMOVF    10
+#define STM_CRS_ISR_SYNCMISS   9
+#define STM_CRS_ISR_SYNCERR    8
+#define STM_CRS_ISR_ESYNCF     3
+#define STM_CRS_ISR_ERRF       2
+#define STM_CRS_ISR_SYNCWARNF  1
+#define STM_CRS_ISR_SYNCOKF    0
+
+#define STM_CRS_ICR_ESYNCC     3
+#define STM_CRS_ICR_ERRC       2
+#define STM_CRS_ICR_SYNCWARNC  1
+#define STM_CRS_ICR_SYNCOKC    0
+
+struct stm_pwr {
+       vuint32_t       cr;
+       vuint32_t       csr;
+};
+
+extern struct stm_pwr stm_pwr;
+
+#define STM_PWR_CR_DBP         (8)
+
+#define STM_PWR_CR_PLS         (5)
+#define  STM_PWR_CR_PLS_2_0    0
+#define  STM_PWR_CR_PLS_2_1    1
+#define  STM_PWR_CR_PLS_2_2    2
+#define  STM_PWR_CR_PLS_2_3    3
+#define  STM_PWR_CR_PLS_2_4    4
+#define  STM_PWR_CR_PLS_2_5    5
+#define  STM_PWR_CR_PLS_2_6    6
+#define  STM_PWR_CR_PLS_EXT    7
+#define  STM_PWR_CR_PLS_MASK   7
+
+#define STM_PWR_CR_PVDE                (4)
+#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_CSR_EWUP3      (10)
+#define STM_PWR_CSR_EWUP2      (9)
+#define STM_PWR_CSR_EWUP1      (8)
+#define STM_PWR_CSR_REGLPF     (5)
+#define STM_PWR_CSR_VOSF       (4)
+#define STM_PWR_CSR_VREFINTRDYF        (3)
+#define STM_PWR_CSR_PVDO       (2)
+#define STM_PWR_CSR_SBF                (1)
+#define STM_PWR_CSR_WUF                (0)
+
+struct stm_crc {
+       union {
+               vuint32_t       u32;
+               vuint16_t       u16;
+               vuint8_t        u8;
+       }               dr;
+       vuint32_t       idr;
+       vuint32_t       cr;
+       uint32_t        _0c;
+
+       vuint32_t       init;
+       vuint32_t       pol;
+};
+
+extern struct stm_crc  stm_crc;
+
+#define stm_crc        (*((struct stm_crc *) 0x40023000))
+
+#define STM_CRC_CR_REV_OUT     7
+#define STM_CRC_CR_REV_IN      5
+#define  STM_CRC_CR_REV_IN_NONE                0
+#define  STM_CRC_CR_REV_IN_BY_BYTE     1
+#define  STM_CRC_CR_REV_IN_BY_HALF_WORD        2
+#define  STM_CRC_CR_REV_IN_BY_WORD     3
+#define STM_CRC_CR_POLYSIZE    3
+#define  STM_CRC_CR_POLYSIZE_32                0
+#define  STM_CRC_CR_POLYSIZE_16                1
+#define  STM_CRC_CR_POLYSIZE_8         2
+#define  STM_CRC_CR_POLYSIZE_7         3
+#define STM_CRC_CR_RESET       0
+
+/* The SYSTICK starts at 0xe000e010 */
+
+struct stm_systick {
+       vuint32_t       csr;
+       vuint32_t       rvr;
+       vuint32_t       cvr;
+       vuint32_t       calib;
+};
+
+extern struct stm_systick stm_systick;
+
+#define STM_SYSTICK_CSR_ENABLE         0
+#define STM_SYSTICK_CSR_TICKINT                1
+#define STM_SYSTICK_CSR_CLKSOURCE      2
+#define  STM_SYSTICK_CSR_CLKSOURCE_EXTERNAL            0
+#define  STM_SYSTICK_CSR_CLKSOURCE_HCLK_8              1
+#define STM_SYSTICK_CSR_COUNTFLAG      16
+
+/* The NVIC starts at 0xe000e100, so add that to the offsets to find the absolute address */
+
+struct stm_nvic {
+       vuint32_t       iser;           /* 0x000 0xe000e100 Set Enable Register */
+
+       uint8_t         _unused020[0x080 - 0x004];
+
+       vuint32_t       icer;           /* 0x080 0xe000e180 Clear Enable Register */
+
+       uint8_t         _unused0a0[0x100 - 0x084];
+
+       vuint32_t       ispr;           /* 0x100 0xe000e200 Set Pending Register */
+
+       uint8_t         _unused120[0x180 - 0x104];
+
+       vuint32_t       icpr;           /* 0x180 0xe000e280 Clear Pending Register */
+
+       uint8_t         _unused1a0[0x300 - 0x184];
+
+       vuint32_t       ipr[8];         /* 0x300 0xe000e400 Priority Register */
+};
+
+extern struct stm_nvic stm_nvic;
+
+#define IRQ_MASK(irq)  (1 << (irq))
+#define IRQ_BOOL(v,irq)        (((v) >> (irq)) & 1)
+
+static inline void
+stm_nvic_set_enable(int irq) {
+       stm_nvic.iser = IRQ_MASK(irq);
+}
+
+static inline void
+stm_nvic_clear_enable(int irq) {
+       stm_nvic.icer = IRQ_MASK(irq);
+}
+
+static inline int
+stm_nvic_enabled(int irq) {
+       return IRQ_BOOL(stm_nvic.iser, irq);
+}
+
+static inline void
+stm_nvic_set_pending(int irq) {
+       stm_nvic.ispr = IRQ_MASK(irq);
+}
+
+static inline void
+stm_nvic_clear_pending(int irq) {
+       stm_nvic.icpr = IRQ_MASK(irq);
+}
+
+static inline int
+stm_nvic_pending(int irq) {
+       return IRQ_BOOL(stm_nvic.ispr, irq);
+}
+
+#define IRQ_PRIO_REG(irq)      ((irq) >> 2)
+#define IRQ_PRIO_BIT(irq)      (((irq) & 3) << 3)
+#define IRQ_PRIO_MASK(irq)     (0xff << IRQ_PRIO_BIT(irq))
+
+static inline void
+stm_nvic_set_priority(int irq, uint8_t prio) {
+       int             n = IRQ_PRIO_REG(irq);
+       uint32_t        v;
+
+       v = stm_nvic.ipr[n];
+       v &= ~IRQ_PRIO_MASK(irq);
+       v |= (prio) << IRQ_PRIO_BIT(irq);
+       stm_nvic.ipr[n] = v;
+}
+
+static inline uint8_t
+stm_nvic_get_priority(int irq) {
+       return (stm_nvic.ipr[IRQ_PRIO_REG(irq)] >> IRQ_PRIO_BIT(irq)) & IRQ_PRIO_MASK(0);
+}
+
+struct stm_scb {
+       vuint32_t       cpuid;
+       vuint32_t       icsr;
+       vuint32_t       vtor;
+       vuint32_t       aircr;
+
+       vuint32_t       scr;
+       vuint32_t       ccr;
+       vuint32_t       shpr1;
+       vuint32_t       shpr2;
+
+       vuint32_t       shpr3;
+       vuint32_t       shcrs;
+       vuint32_t       cfsr;
+       vuint32_t       hfsr;
+
+       uint32_t        unused_30;
+       vuint32_t       mmfar;
+       vuint32_t       bfar;
+};
+
+extern struct stm_scb stm_scb;
+
+#define STM_SCB_AIRCR_VECTKEY          16
+#define  STM_SCB_AIRCR_VECTKEY_KEY             0x05fa
+#define STM_SCB_AIRCR_PRIGROUP         8
+#define STM_SCB_AIRCR_SYSRESETREQ      2
+#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_ISR_WWDG_POS               0
+#define STM_ISR_PVD_VDDIO2_POS         1
+#define STM_ISR_RTC_POS                        2
+#define STM_ISR_FLASH_POS              3
+#define STM_ISR_RCC_CRS_POS            4
+#define STM_ISR_EXTI0_1_POS            5
+#define STM_ISR_EXTI2_3_POS            6
+#define STM_ISR_EXTI4_15_POS           7
+#define STM_ISR_TSC_POS                        8
+#define STM_ISR_DMA_CH1_POS            9
+#define STM_ISR_DMA_CH2_3_DMA2_CH1_2_POS       10
+#define STM_ISR_DMA_CH44_5_6_7_DMA2_CH3_4_5_POS        11
+#define STM_ISR_ADC_COMP_POS           12
+#define STM_ISR_TIM1_BRK_UP_TRG_COM_POS        13
+#define STM_ISR_TIM1_CC_POS            14
+#define STM_ISR_TIM2_POS               15
+#define STM_ISR_TIM3_POS               16
+#define STM_ISR_TIM6_DAC_POS           17
+#define STM_ISR_TIM7_POS               18
+#define STM_ISR_TIM14_POS              19
+#define STM_ISR_TIM15_POS              20
+#define STM_ISR_TIM16_POS              21
+#define STM_ISR_TIM17_POS              22
+#define STM_ISR_I2C1_POS               23
+#define STM_ISR_I2C2_POS               24
+#define STM_ISR_SPI1_POS               25
+#define STM_ISR_SPI2_POS               26
+#define STM_ISR_USART1_POS             27
+#define STM_ISR_USART2_POS             28
+#define STM_ISR_UASART3_4_5_6_7_8_POS  29
+#define STM_ISR_CEC_CAN_POS            30
+#define STM_ISR_USB_POS                        31
+
+struct stm_syscfg {
+       vuint32_t       cfgr1;
+       vuint32_t       exticr[4];
+       vuint32_t       cfgr2;
+};
+
+extern struct stm_syscfg stm_syscfg;
+
+#define STM_SYSCFG_CFGR1_TIM3_DMA_RMP  30
+#define STM_SYSCFG_CFGR1_TIM2_DMA_RMP  29
+#define STM_SYSCFG_CFGR1_TIM1_DMA_RMP  28
+#define STM_SYSCFG_CFGR1_I2C1_DMA_RMP  27
+#define STM_SYSCFG_CFGR1_USART3_DMA_RMP        26
+#define STM_SYSCFG_CFGR1_USART2_DMA_RMP        25
+#define STM_SYSCFG_CFGR1_SPI2_DMA_RMP  24
+#define STM_SYSCFG_CFGR1_I2C_PA10_FMP  23
+#define STM_SYSCFG_CFGR1_I2C_PA9_FMP   22
+#define STM_SYSCFG_CFGR1_I2C2_FMP      21
+#define STM_SYSCFG_CFGR1_I2C1_FMP      20
+#define STM_SYSCFG_CFGR1_I2C_PB9_FMP   19
+#define STM_SYSCFG_CFGR1_I2C_PB8_FMP   18
+#define STM_SYSCFG_CFGR1_I2C_PB7_FMP   17
+#define STM_SYSCFG_CFGR1_I2C_PB6_FMP   16
+#define STM_SYSCFG_CFGR1_TIM17_DMA_RMP2        14
+#define STM_SYSCFG_CFGR1_TIM16_DMA_RMP2        13
+#define STM_SYSCFG_CFGR1_TIM17_DMA_RMP 12
+#define STM_SYSCFG_CFGR1_TIM16_DMA_RMP 11
+#define STM_SYSCFG_CFGR1_USART1_RX_DMA_RMP     10
+#define STM_SYSCFG_CFGR1_USART1_TX_DMA_RMP     9
+#define STM_SYSCFG_CFGR1_ADC_DMA_RMP           8
+#define STM_SYSCFG_CFGR1_IRDA_ENV_SEL  6
+#define  STM_SYSCFG_CFGR1_IRDA_ENV_SEL_TIMER16 0
+#define  STM_SYSCFG_CFGR1_IRDA_ENV_SEL_USART1  1
+#define  STM_SYSCFG_CFGR1_IRDA_ENV_SEL_USART4  2
+#define STM_SYSCFG_CFGR1_PA11_PA12_RMP 4
+#define STM_SYSCFG_CFGR1_MEM_MODE      0
+#define  STM_SYSCFG_CFGR1_MEM_MODE_MAIN_FLASH  0
+#define  STM_SYSCFG_CFGR1_MEM_MODE_SYSTEM_FLASH        1
+#define  STM_SYSCFG_CFGR1_MEM_MODE_SRAM                3
+#define  STM_SYSCFG_CFGR1_MEM_MODE_MASK                3
+
+#if 0
+static inline void
+stm_exticr_set(struct stm_gpio *gpio, int pin) {
+       uint8_t reg = pin >> 2;
+       uint8_t shift = (pin & 3) << 2;
+       uint8_t val = 0;
+
+       /* Enable SYSCFG */
+       stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SYSCFGCOMPEN);
+
+       if (gpio == &stm_gpioa)
+               val = STM_SYSCFG_EXTICR_PA;
+       else if (gpio == &stm_gpiob)
+               val = STM_SYSCFG_EXTICR_PB;
+       else if (gpio == &stm_gpioc)
+               val = STM_SYSCFG_EXTICR_PC;
+       else if (gpio == &stm_gpiof)
+               val = STM_SYSCFG_EXTICR_PF;
+
+       stm_syscfg.exticr[reg] = (stm_syscfg.exticr[reg] & ~(0xf << shift)) | val << shift;
+}
+#endif
+
+
+struct stm_dma_channel {
+       vuint32_t       ccr;
+       vuint32_t       cndtr;
+       vvoid_t         cpar;
+       vvoid_t         cmar;
+       vuint32_t       reserved;
+};
+
+#define STM_NUM_DMA    6
+
+struct stm_dma {
+       vuint32_t               isr;
+       vuint32_t               ifcr;
+       struct stm_dma_channel  channel[STM_NUM_DMA];
+};
+
+extern struct stm_dma stm_dma;
+
+/* DMA channels go from 1 to 6, instead of 0 to 5 (sigh)
+ */
+
+#define STM_DMA_INDEX(channel)         ((channel) - 1)
+
+#define STM_DMA_ISR(index)             ((index) << 2)
+#define STM_DMA_ISR_MASK                       0xf
+#define STM_DMA_ISR_TEIF                       3
+#define STM_DMA_ISR_HTIF                       2
+#define STM_DMA_ISR_TCIF                       1
+#define STM_DMA_ISR_GIF                                0
+
+#define STM_DMA_IFCR(index)            ((index) << 2)
+#define STM_DMA_IFCR_MASK                      0xf
+#define STM_DMA_IFCR_CTEIF                     3
+#define STM_DMA_IFCR_CHTIF                     2
+#define STM_DMA_IFCR_CTCIF                     1
+#define STM_DMA_IFCR_CGIF                      0
+
+#define STM_DMA_CCR_MEM2MEM            (14)
+
+#define STM_DMA_CCR_PL                 (12)
+#define  STM_DMA_CCR_PL_LOW                    (0)
+#define  STM_DMA_CCR_PL_MEDIUM                 (1)
+#define  STM_DMA_CCR_PL_HIGH                   (2)
+#define  STM_DMA_CCR_PL_VERY_HIGH              (3)
+#define  STM_DMA_CCR_PL_MASK                   (3)
+
+#define STM_DMA_CCR_MSIZE              (10)
+#define  STM_DMA_CCR_MSIZE_8                   (0)
+#define  STM_DMA_CCR_MSIZE_16                  (1)
+#define  STM_DMA_CCR_MSIZE_32                  (2)
+#define  STM_DMA_CCR_MSIZE_MASK                        (3)
+
+#define STM_DMA_CCR_PSIZE              (8)
+#define  STM_DMA_CCR_PSIZE_8                   (0)
+#define  STM_DMA_CCR_PSIZE_16                  (1)
+#define  STM_DMA_CCR_PSIZE_32                  (2)
+#define  STM_DMA_CCR_PSIZE_MASK                        (3)
+
+#define STM_DMA_CCR_MINC               (7)
+#define STM_DMA_CCR_PINC               (6)
+#define STM_DMA_CCR_CIRC               (5)
+#define STM_DMA_CCR_DIR                        (4)
+#define  STM_DMA_CCR_DIR_PER_TO_MEM            0
+#define  STM_DMA_CCR_DIR_MEM_TO_PER            1
+#define STM_DMA_CCR_TEIE               (3)
+#define STM_DMA_CCR_HTIE               (2)
+#define STM_DMA_CCR_TCIE               (1)
+#define STM_DMA_CCR_EN                 (0)
+
+/* DMA channel assignments. When a peripheral has multiple channels
+ * (indicated with _<number>), then it can be configured to either
+ * channel using syscfg.cfgr1
+ */
+
+#define STM_DMA_CHANNEL_ADC_1          1
+#define STM_DMA_CHANNEL_ADC_2          2
+
+#define STM_DMA_CHANNEL_SPI1_RX                2
+#define STM_DMA_CHANNEL_SPI1_TX                3
+
+#define STM_DMA_CHANNEL_SPI2_RX                4
+#define STM_DMA_CHANNEL_SPI2_TX                5
+
+#define STM_DMA_CHANNEL_USART1_TX_1    2
+#define STM_DMA_CHANNEL_USART1_RX_1    3
+#define STM_DMA_CHANNEL_USART1_TX_2    4
+#define STM_DMA_CHANNEL_USART1_RX_2    5
+
+#define STM_DMA_CHANNEL_USART2_RX      4
+#define STM_DMA_CHANNEL_USART2_TX      5
+
+#define STM_DMA_CHANNEL_I2C1_TX                2
+#define STM_DMA_CHANNEL_I2C1_RX                3
+
+#define STM_DMA_CHANNEL_I2C2_TX                4
+#define STM_DMA_CHANNEL_I2C2_RX                5
+
+#define STM_DMA_CHANNEL_TIM1_CH1       2
+#define STM_DMA_CHANNEL_TIM1_CH2       3
+#define STM_DMA_CHANNEL_TIM1_CH4       4
+#define STM_DMA_CHANNEL_TIM1_TRIG      4
+#define STM_DMA_CHANNEL_TIM1_COM       4
+#define STM_DMA_CHANNEL_TIM1_CH3       5
+#define STM_DMA_CHANNEL_TIM1_UP                5
+
+#define STM_DMA_CHANNEL_TIM2_CH3       1
+#define STM_DMA_CHANNEL_TIM2_UP                2
+#define STM_DMA_CHANNEL_TIM2_CH2       3
+#define STM_DMA_CHANNEL_TIM2_CH4       4
+#define STM_DMA_CHANNEL_TIM2_CH1       5
+
+#define STM_DMA_CHANNEL_TIM3_CH3       2
+#define STM_DMA_CHANNEL_TIM3_CH4       3
+#define STM_DMA_CHANNEL_TIM3_UP                3
+#define STM_DMA_CHANNEL_TIM3_CH1       4
+#define STM_DMA_CHANNEL_TIM3_TRIG      4
+
+#define STM_DMA_CHANNEL_TIM6_UP_DAC    2
+
+#define STM_DMA_CHANNEL_TIM15_CH1      5
+#define STM_DMA_CHANNEL_TIM15_UP       5
+#define STM_DMA_CHANNEL_TIM15_TRIG     5
+#define STM_DMA_CHANNEL_TIM15_COM      5
+
+#define STM_DMA_CHANNEL_TIM16_CH1_1    3
+#define STM_DMA_CHANNEL_TIM16_UP_1     3
+#define STM_DMA_CHANNEL_TIM16_CH1_2    4
+#define STM_DMA_CHANNEL_TIM16_UP_2     4
+
+#define STM_DMA_CHANNEL_TIM17_CH1_1    1
+#define STM_DMA_CHANNEL_TIM17_UP_1     1
+#define STM_DMA_CHANNEL_TIM17_CH1_2    2
+#define STM_DMA_CHANNEL_TIM17_UP_2     2
+
+/*
+ * Only spi channel 1 and 2 can use DMA
+ */
+#define STM_NUM_SPI    2
+
+struct stm_spi {
+       vuint32_t       cr1;
+       vuint32_t       cr2;
+       vuint32_t       sr;
+       vuint32_t       dr;
+       vuint32_t       crcpr;
+       vuint32_t       rxcrcr;
+       vuint32_t       txcrcr;
+};
+
+extern struct stm_spi stm_spi1, stm_spi2, stm_spi3;
+
+/* SPI channels go from 1 to 3, instead of 0 to 2 (sigh)
+ */
+
+#define STM_SPI_INDEX(channel)         ((channel) - 1)
+
+#define STM_SPI_CR1_BIDIMODE           15
+#define STM_SPI_CR1_BIDIOE             14
+#define STM_SPI_CR1_CRCEN              13
+#define STM_SPI_CR1_CRCNEXT            12
+#define STM_SPI_CR1_DFF                        11
+#define STM_SPI_CR1_RXONLY             10
+#define STM_SPI_CR1_SSM                        9
+#define STM_SPI_CR1_SSI                        8
+#define STM_SPI_CR1_LSBFIRST           7
+#define STM_SPI_CR1_SPE                        6
+#define STM_SPI_CR1_BR                 3
+#define  STM_SPI_CR1_BR_PCLK_2                 0
+#define  STM_SPI_CR1_BR_PCLK_4                 1
+#define  STM_SPI_CR1_BR_PCLK_8                 2
+#define  STM_SPI_CR1_BR_PCLK_16                        3
+#define  STM_SPI_CR1_BR_PCLK_32                        4
+#define  STM_SPI_CR1_BR_PCLK_64                        5
+#define  STM_SPI_CR1_BR_PCLK_128               6
+#define  STM_SPI_CR1_BR_PCLK_256               7
+#define  STM_SPI_CR1_BR_MASK                   7
+
+#define STM_SPI_CR1_MSTR               2
+#define STM_SPI_CR1_CPOL               1
+#define STM_SPI_CR1_CPHA               0
+
+#define STM_SPI_CR2_TXEIE      7
+#define STM_SPI_CR2_RXNEIE     6
+#define STM_SPI_CR2_ERRIE      5
+#define STM_SPI_CR2_SSOE       2
+#define STM_SPI_CR2_TXDMAEN    1
+#define STM_SPI_CR2_RXDMAEN    0
+
+#define STM_SPI_SR_BSY         7
+#define STM_SPI_SR_OVR         6
+#define STM_SPI_SR_MODF                5
+#define STM_SPI_SR_CRCERR      4
+#define STM_SPI_SR_TXE         1
+#define STM_SPI_SR_RXNE                0
+
+struct stm_adc {
+       vuint32_t       isr;
+       vuint32_t       ier;
+       vuint32_t       cr;
+       vuint32_t       cfgr1;
+
+       vuint32_t       cfgr2;
+       vuint32_t       smpr;
+       vuint32_t       r_18;
+       vuint32_t       r_1c;
+
+       vuint32_t       tr;
+       vuint32_t       r_24;
+       vuint32_t       chselr;
+       vuint32_t       r_2c;
+
+       vuint32_t       r_30[4];
+
+       vuint32_t       dr;
+
+       uint8_t         r_44[0x308 - 0x44];
+       vuint32_t       ccr;
+};
+
+extern struct stm_adc stm_adc;
+
+#define STM_ADC_ISR_AWD                7
+#define STM_ADC_ISR_OVR                4
+#define STM_ADC_ISR_EOSEQ      3
+#define STM_ADC_ISR_EOC                2
+#define STM_ADC_ISR_EOSMP      1
+#define STM_ADC_ISR_ADRDY      0
+
+#define STM_ADC_IER_AWDIE      7
+#define STM_ADC_IER_OVRIE      4
+#define STM_ADC_IER_EOSEQIE    3
+#define STM_ADC_IER_EOCIE      2
+#define STM_ADC_IER_EOSMPIE    1
+#define STM_ADC_IER_ADRDYIE    0
+
+#define STM_ADC_CR_ADCAL       31
+#define STM_ADC_CR_ADSTP       4
+#define STM_ADC_CR_ADSTART     2
+#define STM_ADC_CR_ADDIS       1
+#define STM_ADC_CR_ADEN                0
+
+#define STM_ADC_CFGR1_AWDCH    26
+#define STM_ADC_CFGR1_AWDEN    23
+#define STM_ADC_CFGR1_AWDSGL   22
+#define STM_ADC_CFGR1_DISCEN   16
+#define STM_ADC_CFGR1_AUTOOFF  15
+#define STM_ADC_CFGR1_WAIT     14
+#define STM_ADC_CFGR1_CONT     13
+#define STM_ADC_CFGR1_OVRMOD   12
+#define STM_ADC_CFGR1_EXTEN    10
+#define  STM_ADC_CFGR1_EXTEN_DISABLE   0
+#define  STM_ADC_CFGR1_EXTEN_RISING    1
+#define  STM_ADC_CFGR1_EXTEN_FALLING   2
+#define  STM_ADC_CFGR1_EXTEN_BOTH      3
+#define  STM_ADC_CFGR1_EXTEN_MASK      3
+
+#define STM_ADC_CFGR1_EXTSEL   6
+#define STM_ADC_CFGR1_ALIGN    5
+#define STM_ADC_CFGR1_RES      3
+#define  STM_ADC_CFGR1_RES_12          0
+#define  STM_ADC_CFGR1_RES_10          1
+#define  STM_ADC_CFGR1_RES_8           2
+#define  STM_ADC_CFGR1_RES_6           3
+#define  STM_ADC_CFGR1_RES_MASK                3
+#define STM_ADC_CFGR1_SCANDIR  2
+#define  STM_ADC_CFGR1_SCANDIR_UP      0
+#define  STM_ADC_CFGR1_SCANDIR_DOWN    1
+#define STM_ADC_CFGR1_DMACFG   1
+#define  STM_ADC_CFGR1_DMACFG_ONESHOT  0
+#define  STM_ADC_CFGR1_DMACFG_CIRCULAR 1
+#define STM_ADC_CFGR1_DMAEN    0
+
+#define STM_ADC_CFGR2_CKMODE   30
+#define  STM_ADC_CFGR2_CKMODE_ADCCLK   0
+#define  STM_ADC_CFGR2_CKMODE_PCLK_2   1
+#define  STM_ADC_CFGR2_CKMODE_PCLK_4   2
+
+#define STM_ADC_SMPR_SMP       0
+#define  STM_ADC_SMPR_SMP_1_5          0
+#define  STM_ADC_SMPR_SMP_7_5          1
+#define  STM_ADC_SMPR_SMP_13_5         2
+#define  STM_ADC_SMPR_SMP_28_5         3
+#define  STM_ADC_SMPR_SMP_41_5         4
+#define  STM_ADC_SMPR_SMP_55_5         5
+#define  STM_ADC_SMPR_SMP_71_5         6
+#define  STM_ADC_SMPR_SMP_239_5                7
+
+#define STM_ADC_TR_HT          16
+#define STM_ADC_TR_LT          0
+
+#define STM_ADC_CCR_VBATEN     24
+#define STM_ADC_CCR_TSEN       23
+#define STM_ADC_CCR_VREFEN     22
+
+struct stm_cal {
+       uint16_t        ts_cal_cold;    /* 30°C */
+       uint16_t        vrefint_cal;
+       uint16_t        unused_c0;
+       uint16_t        ts_cal_hot;     /* 110°C */
+};
+
+extern struct stm_cal  stm_cal;
+
+#define stm_temp_cal_cold      30
+#define stm_temp_cal_hot       110
+
+struct stm_dbgmcu {
+       uint32_t        idcode;
+};
+
+extern struct stm_dbgmcu       stm_dbgmcu;
+
+static inline uint16_t
+stm_dev_id(void) {
+       return stm_dbgmcu.idcode & 0xfff;
+}
+
+struct stm_flash_size {
+       uint16_t        f_size;
+};
+
+extern struct stm_flash_size   stm_flash_size_04x;
+
+/* Returns flash size in bytes */
+extern uint32_t
+stm_flash_size(void);
+
+struct stm_device_id {
+       uint32_t        u_id0;
+       uint32_t        u_id1;
+       uint32_t        u_id2;
+};
+
+extern struct stm_device_id    stm_device_id;
+
+#define STM_NUM_I2C    2
+
+#define STM_I2C_INDEX(channel) ((channel) - 1)
+
+struct stm_i2c {
+       vuint32_t       cr1;
+       vuint32_t       cr2;
+       vuint32_t       oar1;
+       vuint32_t       oar2;
+       vuint32_t       dr;
+       vuint32_t       sr1;
+       vuint32_t       sr2;
+       vuint32_t       ccr;
+       vuint32_t       trise;
+};
+
+extern struct stm_i2c stm_i2c1, stm_i2c2;
+
+#define STM_I2C_CR1_SWRST      15
+#define STM_I2C_CR1_ALERT      13
+#define STM_I2C_CR1_PEC                12
+#define STM_I2C_CR1_POS                11
+#define STM_I2C_CR1_ACK                10
+#define STM_I2C_CR1_STOP       9
+#define STM_I2C_CR1_START      8
+#define STM_I2C_CR1_NOSTRETCH  7
+#define STM_I2C_CR1_ENGC       6
+#define STM_I2C_CR1_ENPEC      5
+#define STM_I2C_CR1_ENARP      4
+#define STM_I2C_CR1_SMBTYPE    3
+#define STM_I2C_CR1_SMBUS      1
+#define STM_I2C_CR1_PE         0
+
+#define STM_I2C_CR2_LAST       12
+#define STM_I2C_CR2_DMAEN      11
+#define STM_I2C_CR2_ITBUFEN    10
+#define STM_I2C_CR2_ITEVTEN    9
+#define STM_I2C_CR2_ITERREN    8
+#define STM_I2C_CR2_FREQ       0
+#define  STM_I2C_CR2_FREQ_2_MHZ                2
+#define  STM_I2C_CR2_FREQ_4_MHZ                4
+#define  STM_I2C_CR2_FREQ_8_MHZ                8
+#define  STM_I2C_CR2_FREQ_16_MHZ       16
+#define  STM_I2C_CR2_FREQ_32_MHZ       32
+#define  STM_I2C_CR2_FREQ_MASK         0x3f
+
+#define STM_I2C_SR1_SMBALERT   15
+#define STM_I2C_SR1_TIMEOUT    14
+#define STM_I2C_SR1_PECERR     12
+#define STM_I2C_SR1_OVR                11
+#define STM_I2C_SR1_AF         10
+#define STM_I2C_SR1_ARLO       9
+#define STM_I2C_SR1_BERR       8
+#define STM_I2C_SR1_TXE                7
+#define STM_I2C_SR1_RXNE       6
+#define STM_I2C_SR1_STOPF      4
+#define STM_I2C_SR1_ADD10      3
+#define STM_I2C_SR1_BTF                2
+#define STM_I2C_SR1_ADDR       1
+#define STM_I2C_SR1_SB         0
+
+#define STM_I2C_SR2_PEC                8
+#define  STM_I2C_SR2_PEC_MASK  0xff00
+#define STM_I2C_SR2_DUALF      7
+#define STM_I2C_SR2_SMBHOST    6
+#define STM_I2C_SR2_SMBDEFAULT 5
+#define STM_I2C_SR2_GENCALL    4
+#define STM_I2C_SR2_TRA                2
+#define STM_I2C_SR2_BUSY               1
+#define STM_I2C_SR2_MSL                0
+
+#define STM_I2C_CCR_FS         15
+#define STM_I2C_CCR_DUTY       14
+#define STM_I2C_CCR_CCR                0
+#define  STM_I2C_CCR_MASK      0x7ff
+
+struct stm_tim234 {
+       vuint32_t       cr1;
+       vuint32_t       cr2;
+       vuint32_t       smcr;
+       vuint32_t       dier;
+
+       vuint32_t       sr;
+       vuint32_t       egr;
+       vuint32_t       ccmr1;
+       vuint32_t       ccmr2;
+
+       vuint32_t       ccer;
+       vuint32_t       cnt;
+       vuint32_t       psc;
+       vuint32_t       arr;
+
+       uint32_t        reserved_30;
+       vuint32_t       ccr1;
+       vuint32_t       ccr2;
+       vuint32_t       ccr3;
+
+       vuint32_t       ccr4;
+       uint32_t        reserved_44;
+       vuint32_t       dcr;
+       vuint32_t       dmar;
+
+       uint32_t        reserved_50;
+};
+
+extern struct stm_tim234 stm_tim2, stm_tim3, stm_tim4;
+
+#define STM_TIM234_CR1_CKD     8
+#define  STM_TIM234_CR1_CKD_1          0
+#define  STM_TIM234_CR1_CKD_2          1
+#define  STM_TIM234_CR1_CKD_4          2
+#define  STM_TIM234_CR1_CKD_MASK       3
+#define STM_TIM234_CR1_ARPE    7
+#define STM_TIM234_CR1_CMS     5
+#define  STM_TIM234_CR1_CMS_EDGE       0
+#define  STM_TIM234_CR1_CMS_CENTER_1   1
+#define  STM_TIM234_CR1_CMS_CENTER_2   2
+#define  STM_TIM234_CR1_CMS_CENTER_3   3
+#define  STM_TIM234_CR1_CMS_MASK       3
+#define STM_TIM234_CR1_DIR     4
+#define  STM_TIM234_CR1_DIR_UP         0
+#define  STM_TIM234_CR1_DIR_DOWN       1
+#define STM_TIM234_CR1_OPM     3
+#define STM_TIM234_CR1_URS     2
+#define STM_TIM234_CR1_UDIS    1
+#define STM_TIM234_CR1_CEN     0
+
+#define STM_TIM234_CR2_TI1S    7
+#define STM_TIM234_CR2_MMS     4
+#define  STM_TIM234_CR2_MMS_RESET              0
+#define  STM_TIM234_CR2_MMS_ENABLE             1
+#define  STM_TIM234_CR2_MMS_UPDATE             2
+#define  STM_TIM234_CR2_MMS_COMPARE_PULSE      3
+#define  STM_TIM234_CR2_MMS_COMPARE_OC1REF     4
+#define  STM_TIM234_CR2_MMS_COMPARE_OC2REF     5
+#define  STM_TIM234_CR2_MMS_COMPARE_OC3REF     6
+#define  STM_TIM234_CR2_MMS_COMPARE_OC4REF     7
+#define  STM_TIM234_CR2_MMS_MASK               7
+#define STM_TIM234_CR2_CCDS    3
+
+#define STM_TIM234_SMCR_ETP    15
+#define STM_TIM234_SMCR_ECE    14
+#define STM_TIM234_SMCR_ETPS   12
+#define  STM_TIM234_SMCR_ETPS_OFF              0
+#define  STM_TIM234_SMCR_ETPS_DIV_2            1
+#define  STM_TIM234_SMCR_ETPS_DIV_4            2
+#define  STM_TIM234_SMCR_ETPS_DIV_8            3
+#define  STM_TIM234_SMCR_ETPS_MASK             3
+#define STM_TIM234_SMCR_ETF    8
+#define  STM_TIM234_SMCR_ETF_NONE              0
+#define  STM_TIM234_SMCR_ETF_INT_N_2           1
+#define  STM_TIM234_SMCR_ETF_INT_N_4           2
+#define  STM_TIM234_SMCR_ETF_INT_N_8           3
+#define  STM_TIM234_SMCR_ETF_DTS_2_N_6         4
+#define  STM_TIM234_SMCR_ETF_DTS_2_N_8         5
+#define  STM_TIM234_SMCR_ETF_DTS_4_N_6         6
+#define  STM_TIM234_SMCR_ETF_DTS_4_N_8         7
+#define  STM_TIM234_SMCR_ETF_DTS_8_N_6         8
+#define  STM_TIM234_SMCR_ETF_DTS_8_N_8         9
+#define  STM_TIM234_SMCR_ETF_DTS_16_N_5                10
+#define  STM_TIM234_SMCR_ETF_DTS_16_N_6                11
+#define  STM_TIM234_SMCR_ETF_DTS_16_N_8                12
+#define  STM_TIM234_SMCR_ETF_DTS_32_N_5                13
+#define  STM_TIM234_SMCR_ETF_DTS_32_N_6                14
+#define  STM_TIM234_SMCR_ETF_DTS_32_N_8                15
+#define  STM_TIM234_SMCR_ETF_MASK              15
+#define STM_TIM234_SMCR_MSM    7
+#define STM_TIM234_SMCR_TS     4
+#define  STM_TIM234_SMCR_TS_ITR0               0
+#define  STM_TIM234_SMCR_TS_ITR1               1
+#define  STM_TIM234_SMCR_TS_ITR2               2
+#define  STM_TIM234_SMCR_TS_ITR3               3
+#define  STM_TIM234_SMCR_TS_TI1F_ED            4
+#define  STM_TIM234_SMCR_TS_TI1FP1             5
+#define  STM_TIM234_SMCR_TS_TI2FP2             6
+#define  STM_TIM234_SMCR_TS_ETRF               7
+#define  STM_TIM234_SMCR_TS_MASK               7
+#define STM_TIM234_SMCR_OCCS   3
+#define STM_TIM234_SMCR_SMS    0
+#define  STM_TIM234_SMCR_SMS_DISABLE           0
+#define  STM_TIM234_SMCR_SMS_ENCODER_MODE_1    1
+#define  STM_TIM234_SMCR_SMS_ENCODER_MODE_2    2
+#define  STM_TIM234_SMCR_SMS_ENCODER_MODE_3    3
+#define  STM_TIM234_SMCR_SMS_RESET_MODE                4
+#define  STM_TIM234_SMCR_SMS_GATED_MODE                5
+#define  STM_TIM234_SMCR_SMS_TRIGGER_MODE      6
+#define  STM_TIM234_SMCR_SMS_EXTERNAL_CLOCK    7
+#define  STM_TIM234_SMCR_SMS_MASK              7
+
+#define STM_TIM234_SR_CC4OF    12
+#define STM_TIM234_SR_CC3OF    11
+#define STM_TIM234_SR_CC2OF    10
+#define STM_TIM234_SR_CC1OF    9
+#define STM_TIM234_SR_TIF      6
+#define STM_TIM234_SR_CC4IF    4
+#define STM_TIM234_SR_CC3IF    3
+#define STM_TIM234_SR_CC2IF    2
+#define STM_TIM234_SR_CC1IF    1
+#define STM_TIM234_SR_UIF      0
+
+#define STM_TIM234_EGR_TG      6
+#define STM_TIM234_EGR_CC4G    4
+#define STM_TIM234_EGR_CC3G    3
+#define STM_TIM234_EGR_CC2G    2
+#define STM_TIM234_EGR_CC1G    1
+#define STM_TIM234_EGR_UG      0
+
+#define STM_TIM234_CCMR1_OC2CE 15
+#define STM_TIM234_CCMR1_OC2M  12
+#define  STM_TIM234_CCMR1_OC2M_FROZEN                  0
+#define  STM_TIM234_CCMR1_OC2M_SET_HIGH_ON_MATCH       1
+#define  STM_TIM234_CCMR1_OC2M_SET_LOW_ON_MATCH                2
+#define  STM_TIM234_CCMR1_OC2M_TOGGLE                  3
+#define  STM_TIM234_CCMR1_OC2M_FORCE_LOW               4
+#define  STM_TIM234_CCMR1_OC2M_FORCE_HIGH              5
+#define  STM_TIM234_CCMR1_OC2M_PWM_MODE_1              6
+#define  STM_TIM234_CCMR1_OC2M_PWM_MODE_2              7
+#define  STM_TIM234_CCMR1_OC2M_MASK                    7
+#define STM_TIM234_CCMR1_OC2PE 11
+#define STM_TIM234_CCMR1_OC2FE 10
+#define STM_TIM234_CCMR1_CC2S  8
+#define  STM_TIM234_CCMR1_CC2S_OUTPUT                  0
+#define  STM_TIM234_CCMR1_CC2S_INPUT_TI2               1
+#define  STM_TIM234_CCMR1_CC2S_INPUT_TI1               2
+#define  STM_TIM234_CCMR1_CC2S_INPUT_TRC               3
+#define  STM_TIM234_CCMR1_CC2S_MASK                    3
+
+#define STM_TIM234_CCMR1_OC1CE 7
+#define STM_TIM234_CCMR1_OC1M  4
+#define  STM_TIM234_CCMR1_OC1M_FROZEN                  0
+#define  STM_TIM234_CCMR1_OC1M_SET_HIGH_ON_MATCH       1
+#define  STM_TIM234_CCMR1_OC1M_SET_LOW_ON_MATCH                2
+#define  STM_TIM234_CCMR1_OC1M_TOGGLE                  3
+#define  STM_TIM234_CCMR1_OC1M_FORCE_LOW               4
+#define  STM_TIM234_CCMR1_OC1M_FORCE_HIGH              5
+#define  STM_TIM234_CCMR1_OC1M_PWM_MODE_1              6
+#define  STM_TIM234_CCMR1_OC1M_PWM_MODE_2              7
+#define  STM_TIM234_CCMR1_OC1M_MASK                    7
+#define STM_TIM234_CCMR1_OC1PE 11
+#define STM_TIM234_CCMR1_OC1FE 2
+#define STM_TIM234_CCMR1_CC1S  0
+#define  STM_TIM234_CCMR1_CC1S_OUTPUT                  0
+#define  STM_TIM234_CCMR1_CC1S_INPUT_TI1               1
+#define  STM_TIM234_CCMR1_CC1S_INPUT_TI2               2
+#define  STM_TIM234_CCMR1_CC1S_INPUT_TRC               3
+#define  STM_TIM234_CCMR1_CC1S_MASK                    3
+
+#define STM_TIM234_CCMR2_OC4CE 15
+#define STM_TIM234_CCMR2_OC4M  12
+#define  STM_TIM234_CCMR2_OC4M_FROZEN                  0
+#define  STM_TIM234_CCMR2_OC4M_SET_HIGH_ON_MATCH       1
+#define  STM_TIM234_CCMR2_OC4M_SET_LOW_ON_MATCH                2
+#define  STM_TIM234_CCMR2_OC4M_TOGGLE                  3
+#define  STM_TIM234_CCMR2_OC4M_FORCE_LOW               4
+#define  STM_TIM234_CCMR2_OC4M_FORCE_HIGH              5
+#define  STM_TIM234_CCMR2_OC4M_PWM_MODE_1              6
+#define  STM_TIM234_CCMR2_OC4M_PWM_MODE_2              7
+#define  STM_TIM234_CCMR2_OC4M_MASK                    7
+#define STM_TIM234_CCMR2_OC4PE 11
+#define STM_TIM234_CCMR2_OC4FE 10
+#define STM_TIM234_CCMR2_CC4S  8
+#define  STM_TIM234_CCMR2_CC4S_OUTPUT                  0
+#define  STM_TIM234_CCMR2_CC4S_INPUT_TI4               1
+#define  STM_TIM234_CCMR2_CC4S_INPUT_TI3               2
+#define  STM_TIM234_CCMR2_CC4S_INPUT_TRC               3
+#define  STM_TIM234_CCMR2_CC4S_MASK                    3
+
+#define STM_TIM234_CCMR2_OC3CE 7
+#define STM_TIM234_CCMR2_OC3M  4
+#define  STM_TIM234_CCMR2_OC3M_FROZEN                  0
+#define  STM_TIM234_CCMR2_OC3M_SET_HIGH_ON_MATCH       1
+#define  STM_TIM234_CCMR2_OC3M_SET_LOW_ON_MATCH                2
+#define  STM_TIM234_CCMR2_OC3M_TOGGLE                  3
+#define  STM_TIM234_CCMR2_OC3M_FORCE_LOW               4
+#define  STM_TIM234_CCMR2_OC3M_FORCE_HIGH              5
+#define  STM_TIM234_CCMR2_OC3M_PWM_MODE_1              6
+#define  STM_TIM234_CCMR2_OC3M_PWM_MODE_2              7
+#define  STM_TIM234_CCMR2_OC3M_MASK                    7
+#define STM_TIM234_CCMR2_OC3PE 11
+#define STM_TIM234_CCMR2_OC3FE 2
+#define STM_TIM234_CCMR2_CC3S  0
+#define  STM_TIM234_CCMR2_CC3S_OUTPUT                  0
+#define  STM_TIM234_CCMR2_CC3S_INPUT_TI3               1
+#define  STM_TIM234_CCMR2_CC3S_INPUT_TI4               2
+#define  STM_TIM234_CCMR2_CC3S_INPUT_TRC               3
+#define  STM_TIM234_CCMR2_CC3S_MASK                    3
+
+#define STM_TIM234_CCER_CC4NP  15
+#define STM_TIM234_CCER_CC4P   13
+#define STM_TIM234_CCER_CC4E   12
+#define STM_TIM234_CCER_CC3NP  11
+#define STM_TIM234_CCER_CC3P   9
+#define STM_TIM234_CCER_CC3E   8
+#define STM_TIM234_CCER_CC2NP  7
+#define STM_TIM234_CCER_CC2P   5
+#define STM_TIM234_CCER_CC2E   4
+#define STM_TIM234_CCER_CC1NP  3
+#define STM_TIM234_CCER_CC1P   1
+#define STM_TIM234_CCER_CC1E   0
+
+struct stm_usb {
+       struct {
+               vuint16_t       r;
+               uint16_t        _;
+       } epr[8];
+       uint8_t         reserved_20[0x40 - 0x20];
+       vuint16_t       cntr;
+       uint16_t        reserved_42;
+       vuint16_t       istr;
+       uint16_t        reserved_46;
+       vuint16_t       fnr;
+       uint16_t        reserved_4a;
+       vuint16_t       daddr;
+       uint16_t        reserved_4e;
+       vuint16_t       btable;
+       uint16_t        reserved_52;
+       vuint16_t       lpmcsr;
+       uint16_t        reserved_56;
+       vuint16_t       bcdr;
+       uint16_t        reserved_5a;
+};
+
+extern struct stm_usb stm_usb;
+
+#define STM_USB_EPR_CTR_RX     15
+#define  STM_USB_EPR_CTR_RX_WRITE_INVARIANT            1
+#define STM_USB_EPR_DTOG_RX    14
+#define STM_USB_EPR_DTOG_RX_WRITE_INVARIANT            0
+#define STM_USB_EPR_STAT_RX    12
+#define  STM_USB_EPR_STAT_RX_DISABLED                  0
+#define  STM_USB_EPR_STAT_RX_STALL                     1
+#define  STM_USB_EPR_STAT_RX_NAK                       2
+#define  STM_USB_EPR_STAT_RX_VALID                     3
+#define  STM_USB_EPR_STAT_RX_MASK                      3
+#define  STM_USB_EPR_STAT_RX_WRITE_INVARIANT           0
+#define STM_USB_EPR_SETUP      11
+#define STM_USB_EPR_EP_TYPE    9
+#define  STM_USB_EPR_EP_TYPE_BULK                      0
+#define  STM_USB_EPR_EP_TYPE_CONTROL                   1
+#define  STM_USB_EPR_EP_TYPE_ISO                       2
+#define  STM_USB_EPR_EP_TYPE_INTERRUPT                 3
+#define  STM_USB_EPR_EP_TYPE_MASK                      3
+#define STM_USB_EPR_EP_KIND    8
+#define  STM_USB_EPR_EP_KIND_DBL_BUF                   1       /* Bulk */
+#define  STM_USB_EPR_EP_KIND_STATUS_OUT                        1       /* Control */
+#define STM_USB_EPR_CTR_TX     7
+#define  STM_USB_CTR_TX_WRITE_INVARIANT                        1
+#define STM_USB_EPR_DTOG_TX    6
+#define  STM_USB_EPR_DTOG_TX_WRITE_INVARIANT           0
+#define STM_USB_EPR_STAT_TX    4
+#define  STM_USB_EPR_STAT_TX_DISABLED                  0
+#define  STM_USB_EPR_STAT_TX_STALL                     1
+#define  STM_USB_EPR_STAT_TX_NAK                       2
+#define  STM_USB_EPR_STAT_TX_VALID                     3
+#define  STM_USB_EPR_STAT_TX_WRITE_INVARIANT           0
+#define  STM_USB_EPR_STAT_TX_MASK                      3
+#define STM_USB_EPR_EA         0
+#define  STM_USB_EPR_EA_MASK                           0xf
+
+#define STM_USB_CNTR_CTRM      15
+#define STM_USB_CNTR_PMAOVRM   14
+#define STM_USB_CNTR_ERRM      13
+#define STM_USB_CNTR_WKUPM     12
+#define STM_USB_CNTR_SUSPM     11
+#define STM_USB_CNTR_RESETM    10
+#define STM_USB_CNTR_SOFM      9
+#define STM_USB_CNTR_ESOFM     8
+#define STM_USB_CNTR_RESUME    4
+#define STM_USB_CNTR_FSUSP     3
+#define STM_USB_CNTR_LP_MODE   2
+#define STM_USB_CNTR_PDWN      1
+#define STM_USB_CNTR_FRES      0
+
+#define STM_USB_ISTR_CTR       15
+#define STM_USB_ISTR_PMAOVR    14
+#define STM_USB_ISTR_ERR       13
+#define STM_USB_ISTR_WKUP      12
+#define STM_USB_ISTR_SUSP      11
+#define STM_USB_ISTR_RESET     10
+#define STM_USB_ISTR_SOF       9
+#define STM_USB_ISTR_ESOF      8
+#define STM_USB_L1REQ          7
+#define STM_USB_ISTR_DIR       4
+#define STM_USB_ISTR_EP_ID     0
+#define  STM_USB_ISTR_EP_ID_MASK               0xf
+
+#define STM_USB_FNR_RXDP       15
+#define STM_USB_FNR_RXDM       14
+#define STM_USB_FNR_LCK                13
+#define STM_USB_FNR_LSOF       11
+#define  STM_USB_FNR_LSOF_MASK                 0x3
+#define STM_USB_FNR_FN         0
+#define  STM_USB_FNR_FN_MASK                   0x7ff
+
+#define STM_USB_DADDR_EF       7
+#define STM_USB_DADDR_ADD      0
+#define  STM_USB_DADDR_ADD_MASK                        0x7f
+
+#define STM_USB_BCDR_DPPU      15
+#define STM_USB_BCDR_PS2DET    7
+#define STM_USB_BCDR_SDET      6
+#define STM_USB_BCDR_PDET      5
+#define STM_USB_BCDR_DCDET     4
+#define STM_USB_BCDR_SDEN      3
+#define STM_USB_BCDR_PDEN      2
+#define STM_USB_BCDR_DCDEN     1
+#define STM_USB_BCDR_BCDEN     0
+
+union stm_usb_bdt {
+       struct {
+               vuint16_t       addr_tx;
+               vuint16_t       count_tx;
+               vuint16_t       addr_rx;
+               vuint16_t       count_rx;
+       } single;
+       struct {
+               vuint16_t       addr;
+               vuint16_t       count;
+       } double_tx[2];
+       struct {
+               vuint16_t       addr;
+               vuint16_t       count;
+       } double_rx[2];
+};
+
+#define STM_USB_BDT_COUNT_RX_BL_SIZE   15
+#define STM_USB_BDT_COUNT_RX_NUM_BLOCK 10
+#define  STM_USB_BDT_COUNT_RX_NUM_BLOCK_MASK   0x1f
+#define STM_USB_BDT_COUNT_RX_COUNT_RX  0
+#define  STM_USB_BDT_COUNT_RX_COUNT_RX_MASK    0x1ff
+
+#define STM_USB_BDT_SIZE       8
+
+extern uint8_t stm_usb_sram[];
+
+struct stm_exti {
+       vuint32_t       imr;
+       vuint32_t       emr;
+       vuint32_t       rtsr;
+       vuint32_t       ftsr;
+
+       vuint32_t       swier;
+       vuint32_t       pr;
+};
+
+extern struct stm_exti stm_exti;
+
+#endif /* _STM32F0_H_ */
diff --git a/src/telebt-v3.0/Makefile b/src/telebt-v3.0/Makefile
new file mode 100644 (file)
index 0000000..a7ef4d6
--- /dev/null
@@ -0,0 +1,94 @@
+#
+# AltOS build
+#
+#
+
+include ../stm/Makefile.defs
+
+INC = \
+       ao.h \
+       ao_arch.h \
+       ao_arch_funcs.h \
+       ao_boot.h \
+       ao_pins.h \
+       ao_product.h \
+       ao_cc1200_CC1200.h \
+       ao_profile.h \
+       ao_task.h \
+       stm32l.h \
+       Makefile
+
+#PROFILE=ao_profile.c
+#PROFILE_DEF=-DAO_PROFILE=1
+
+#SAMPLE_PROFILE=ao_sample_profile.c \
+#      ao_sample_profile_timer.c
+#SAMPLE_PROFILE_DEF=-DHAS_SAMPLE_PROFILE=1
+
+#STACK_GUARD=ao_mpu_stm.c
+#STACK_GUARD_DEF=-DHAS_STACK_GUARD=1
+
+ALTOS_SRC = \
+       ao_boot_chain.c \
+       ao_interrupt.c \
+       ao_product.c \
+       ao_romconfig.c \
+       ao_cmd.c \
+       ao_config.c \
+       ao_data.c \
+       ao_task.c \
+       ao_led.c \
+       ao_stdio.c \
+       ao_panic.c \
+       ao_timer.c \
+       ao_mutex.c \
+       ao_serial_stm.c \
+       ao_freq.c \
+       ao_dma_stm.c \
+       ao_spi_stm.c \
+       ao_cc1200.c \
+       ao_adc_stm.c \
+       ao_btm.c \
+       ao_usb_stm.c \
+       ao_exti_stm.c \
+       ao_eeprom_stm.c \
+       ao_convert_volt.c \
+       ao_packet_master.c \
+       ao_packet.c \
+       ao_monitor.c \
+       $(PROFILE) \
+       $(SAMPLE_PROFILE) \
+       $(STACK_GUARD)
+
+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
+
+PROGNAME=telebt-v3.0
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_telebt.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+$(OBJ): $(INC)
+
+ao_product.h: ao-make-product.5c ../Version
+       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+distclean:     clean
+
+clean:
+       rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+       rm -f ao_product.h
+
+install:
+
+uninstall:
diff --git a/src/telebt-v3.0/ao_pins.h b/src/telebt-v3.0/ao_pins.h
new file mode 100644 (file)
index 0000000..838f0df
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define HAS_TASK_QUEUE         1
+
+/* 8MHz High speed external crystal */
+#define AO_HSE                 8000000
+
+/* PLLVCO = 96MHz (so that USB will work) */
+#define AO_PLLMUL              12
+#define AO_RCC_CFGR_PLLMUL     (STM_RCC_CFGR_PLLMUL_12)
+
+/* SYSCLK = 32MHz (no need to go faster than CPU) */
+#define AO_PLLDIV              3
+#define AO_RCC_CFGR_PLLDIV     (STM_RCC_CFGR_PLLDIV_3)
+
+/* HCLK = 32MHz (CPU clock) */
+#define AO_AHB_PRESCALER       1
+#define AO_RCC_CFGR_HPRE_DIV   STM_RCC_CFGR_HPRE_DIV_1
+
+/* Run APB1 at 16MHz (HCLK/2) */
+#define AO_APB1_PRESCALER      2
+#define AO_RCC_CFGR_PPRE1_DIV  STM_RCC_CFGR_PPRE2_DIV_2
+
+/* Run APB2 at 16MHz (HCLK/2) */
+#define AO_APB2_PRESCALER      2
+#define AO_RCC_CFGR_PPRE2_DIV  STM_RCC_CFGR_PPRE2_DIV_2
+
+#define HAS_SERIAL_1           0
+#define USE_SERIAL_1_STDIN     0
+#define SERIAL_1_PB6_PB7       0
+#define SERIAL_1_PA9_PA10      1
+
+#define HAS_SERIAL_2           1
+#define USE_SERIAL_2_STDIN     1
+#define DELAY_SERIAL_2_STDIN   1
+#define USE_SERIAL_2_FLOW      1
+#define SERIAL_2_PA2_PA3       1
+#define SERIAL_2_PD5_PD6       0
+
+#define HAS_SERIAL_3           0
+#define USE_SERIAL_3_STDIN     0
+#define SERIAL_3_PB10_PB11     1
+#define SERIAL_3_PC10_PC11     0
+#define SERIAL_3_PD8_PD9       0
+
+#define AO_CONFIG_MAX_SIZE                     1024
+
+#define HAS_EEPROM             1
+#define USE_INTERNAL_FLASH     0
+#define USE_EEPROM_CONFIG      1
+#define USE_STORAGE_CONFIG     0
+#define HAS_USB                        1
+#define HAS_BEEP               0
+#define HAS_BATTERY_REPORT     0
+#define HAS_RADIO              1
+#define HAS_TELEMETRY          0
+#define HAS_APRS               0
+#define HAS_ACCEL              0
+
+#define HAS_SPI_1              1
+#define SPI_1_PA5_PA6_PA7      1       /* CC1200 */
+#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              0
+#define SPI_2_PB13_PB14_PB15   0
+#define SPI_2_PD1_PD3_PD4      0
+#define SPI_2_OSPEEDR          STM_OSPEEDR_10MHz
+
+#define HAS_I2C_1              0
+#define I2C_1_PB8_PB9          0
+
+#define HAS_I2C_2              0
+#define I2C_2_PB10_PB11                0
+
+#define PACKET_HAS_SLAVE       0
+#define PACKET_HAS_MASTER      1
+
+#define LOW_LEVEL_DEBUG                0
+
+#define LED_PORT_0_ENABLE      STM_RCC_AHBENR_GPIOAEN
+#define LED_PORT_1_ENABLE      STM_RCC_AHBENR_GPIOCEN
+#define LED_PORT_0             (&stm_gpioa)
+#define LED_PORT_1             (&stm_gpioc)
+#define LED_PORT_0_SHIFT       0
+#define LED_PORT_1_SHIFT       0
+#define LED_PIN_RED            (4 + LED_PORT_0_SHIFT)
+#define LED_PIN_BLUE           (15 + LED_PORT_1_SHIFT)
+#define AO_LED_RED             (1 << LED_PIN_RED)
+#define AO_LED_BLUE            (1 << LED_PIN_BLUE)
+#define LED_PORT_0_MASK                (AO_LED_RED)
+#define LED_PORT_1_MASK                (AO_LED_BLUE)
+#define AO_BT_LED              AO_LED_BLUE
+
+#define LEDS_AVAILABLE         (AO_LED_RED | AO_LED_BLUE)
+
+#define HAS_GPS                        0
+#define HAS_FLIGHT             0
+#define HAS_ADC                        1
+#define HAS_ADC_TEMP           0
+#define HAS_LOG                        0
+
+/*
+ * ADC
+ */
+#define AO_DATA_RING           32
+#define AO_ADC_NUM_SENSE       2
+
+struct ao_adc {
+       int16_t                 v_batt;
+};
+
+#define AO_ADC_DUMP(p) \
+       printf("tick: %5u %5d batt: %5d\n", \
+              (p)->tick, \
+              (p)->adc.v_batt);
+
+#define AO_ADC_V_BATT          8
+#define AO_ADC_V_BATT_PORT     (&stm_gpiob)
+#define AO_ADC_V_BATT_PIN      0
+
+#define AO_ADC_RCC_AHBENR      ((1 << STM_RCC_AHBENR_GPIOEEN))
+
+#define AO_NUM_ADC_PIN         1
+
+#define AO_ADC_PIN0_PORT       AO_ADC_V_BATT_PORT
+#define AO_ADC_PIN0_PIN                AO_ADC_V_BATT_PIN
+
+#define AO_NUM_ADC             (AO_NUM_ADC_PIN)
+
+#define AO_ADC_SQ1             AO_ADC_V_BATT
+
+/*
+ * Voltage divider on ADC battery sampler
+ */
+#define AO_BATTERY_DIV_PLUS    51      /* 5.6k */
+#define AO_BATTERY_DIV_MINUS   100     /* 10k */
+
+/*
+ * ADC reference in decivolts
+ */
+#define AO_ADC_REFERENCE_DV    33
+
+/*
+ * BTM
+ */
+#define HAS_BTM                        1
+
+#define ao_serial_btm_getchar  ao_serial2_getchar
+#define ao_serial_btm_putchar  ao_serial2_putchar
+#define _ao_serial_btm_pollchar        _ao_serial2_pollchar
+#define _ao_serial_btm_sleep   _ao_serial2_sleep
+#define ao_serial_btm_set_speed ao_serial2_set_speed
+#define ao_serial_btm_drain    ao_serial2_drain
+#define ao_serial_btm_rx_fifo  (ao_stm_usart2.rx_fifo)
+
+#define AO_BTM_INT_PORT                (&stm_gpioa)
+#define AO_BTM_INT_PIN         15
+#define AO_BTM_RESET_PORT      (&stm_gpiob)
+#define AO_BTM_RESET_PIN       3
+
+/*
+ * Radio (cc1200)
+ */
+
+/* gets pretty close to 434.550 */
+
+#define AO_RADIO_CAL_DEFAULT   5695485
+
+#define AO_FEC_DEBUG           0
+#define AO_CC1200_SPI_CS_PORT  (&stm_gpiob)
+#define AO_CC1200_SPI_CS_PIN   10
+#define AO_CC1200_SPI_BUS      AO_SPI_1_PA5_PA6_PA7
+#define AO_CC1200_SPI          stm_spi1
+
+#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_BOOT_RADIO         0
+
+/* Monitor bits */
+#define HAS_MONITOR            1
+#define LEGACY_MONITOR         0
+#define AO_MONITOR_LED         AO_LED_RED
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/telebt-v3.0/ao_telebt.c b/src/telebt-v3.0/ao_telebt.c
new file mode 100644 (file)
index 0000000..44ee4f3
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright © 2015 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_exti.h>
+#include <ao_packet.h>
+#include <ao_eeprom.h>
+#include <ao_profile.h>
+#include <ao_btm.h>
+#if HAS_SAMPLE_PROFILE
+#include <ao_sample_profile.h>
+#endif
+
+int
+main(void)
+{
+       ao_clock_init();
+
+       ao_task_init();
+       ao_serial_init();
+       ao_led_init(LEDS_AVAILABLE);
+       ao_led_on(AO_LED_RED);
+       ao_timer_init();
+
+       ao_spi_init();
+       ao_dma_init();
+       ao_exti_init();
+
+       ao_adc_init();
+       ao_btm_init();
+       ao_cmd_init();
+
+       ao_eeprom_init();
+
+       ao_usb_init();
+       ao_radio_init();
+       ao_packet_master_init();
+       ao_monitor_init();
+
+       ao_config_init();
+
+       ao_led_off(AO_LED_RED);
+
+       ao_start_scheduler();
+       return 0;
+}
diff --git a/src/telebt-v3.0/flash-loader/Makefile b/src/telebt-v3.0/flash-loader/Makefile
new file mode 100644 (file)
index 0000000..a1c5168
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=telebt-v3.0
+include $(TOPDIR)/stm/Makefile-flash.defs
diff --git a/src/telebt-v3.0/flash-loader/ao_pins.h b/src/telebt-v3.0/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..8711548
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+/* External crystal at 8MHz */
+#define AO_HSE         8000000
+
+#include <ao_flash_stm_pins.h>
+
+/* Blue LED */
+
+#define AO_BOOT_PIN                    1
+#define AO_BOOT_APPLICATION_GPIO       stm_gpioc
+#define AO_BOOT_APPLICATION_PIN                15
+#define AO_BOOT_APPLICATION_VALUE      0
+#define AO_BOOT_APPLICATION_MODE       AO_EXTI_MODE_PULL_DOWN
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/teledongle-v1.8/.gitignore b/src/teledongle-v1.8/.gitignore
new file mode 100644 (file)
index 0000000..9a30cbb
--- /dev/null
@@ -0,0 +1,2 @@
+ao_product.h
+teledongle-*.elf
diff --git a/src/teledongle-v1.8/Makefile b/src/teledongle-v1.8/Makefile
new file mode 100644 (file)
index 0000000..6c05ce9
--- /dev/null
@@ -0,0 +1,88 @@
+#
+# AltOS build
+#
+#
+
+include ../stm/Makefile.defs
+
+INC = \
+       ao.h \
+       ao_arch.h \
+       ao_arch_funcs.h \
+       ao_boot.h \
+       ao_pins.h \
+       ao_product.h \
+       ao_task.h \
+       ao_whiten.h \
+       stm32l.h \
+       ao_cc1200.h \
+       ao_cc1200_CC1200.h \
+       Makefile
+
+#PROFILE=ao_profile.c
+#PROFILE_DEF=-DAO_PROFILE=1
+
+#SAMPLE_PROFILE=ao_sample_profile.c \
+#      ao_sample_profile_timer.c
+#SAMPLE_PROFILE_DEF=-DHAS_SAMPLE_PROFILE=1
+
+#STACK_GUARD=ao_mpu_stm.c
+#STACK_GUARD_DEF=-DHAS_STACK_GUARD=1
+
+ALTOS_SRC = \
+       ao_boot_chain.c \
+       ao_interrupt.c \
+       ao_product.c \
+       ao_romconfig.c \
+       ao_cc1200.c \
+       ao_cmd.c \
+       ao_config.c \
+       ao_task.c \
+       ao_led.c \
+       ao_stdio.c \
+       ao_panic.c \
+       ao_timer.c \
+       ao_mutex.c \
+       ao_freq.c \
+       ao_dma_stm.c \
+       ao_spi_stm.c \
+       ao_usb_stm.c \
+       ao_exti_stm.c \
+       ao_send_packet.c \
+       ao_eeprom_stm.c \
+       ao_monitor.c \
+       ao_packet_master.c \
+       ao_packet.c
+
+PRODUCT=TeleDongle-v1.8
+PRODUCT_DEF=-DTELEDONGLE
+IDPRODUCT=0x000c
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g
+
+PROGNAME=teledongle-v1.8
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_teledongle.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+$(OBJ): $(INC)
+
+ao_product.h: ao-make-product.5c ../Version
+       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+distclean:     clean
+
+clean:
+       rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+       rm -f ao_product.h
+
+install:
+
+uninstall:
diff --git a/src/teledongle-v1.8/ao_pins.h b/src/teledongle-v1.8/ao_pins.h
new file mode 100644 (file)
index 0000000..cff3e5e
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+/* Using TeleMetrum v1.9 board */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define HAS_TASK_QUEUE         1
+
+/* 8MHz High speed external crystal */
+#define AO_HSE                 8000000
+
+/* PLLVCO = 96MHz (so that USB will work) */
+#define AO_PLLMUL              12
+#define AO_RCC_CFGR_PLLMUL     (STM_RCC_CFGR_PLLMUL_12)
+
+/* SYSCLK = 32MHz (no need to go faster than CPU) */
+#define AO_PLLDIV              3
+#define AO_RCC_CFGR_PLLDIV     (STM_RCC_CFGR_PLLDIV_3)
+
+/* HCLK = 32MHz (CPU clock) */
+#define AO_AHB_PRESCALER       1
+#define AO_RCC_CFGR_HPRE_DIV   STM_RCC_CFGR_HPRE_DIV_1
+
+/* Run APB1 at 16MHz (HCLK/2) */
+#define AO_APB1_PRESCALER      2
+#define AO_RCC_CFGR_PPRE1_DIV  STM_RCC_CFGR_PPRE2_DIV_2
+
+/* Run APB2 at 16MHz (HCLK/2) */
+#define AO_APB2_PRESCALER      2
+#define AO_RCC_CFGR_PPRE2_DIV  STM_RCC_CFGR_PPRE2_DIV_2
+
+#define HAS_SERIAL_1           0
+#define USE_SERIAL_1_STDIN     0
+#define SERIAL_1_PB6_PB7       0
+#define SERIAL_1_PA9_PA10      0
+
+#define HAS_SERIAL_2           0
+#define USE_SERIAL_2_STDIN     0
+#define SERIAL_2_PA2_PA3       0
+#define SERIAL_2_PD5_PD6       0
+
+#define HAS_SERIAL_3           0
+#define USE_SERIAL_3_STDIN     0
+#define SERIAL_3_PB10_PB11     0
+#define SERIAL_3_PC10_PC11     0
+#define SERIAL_3_PD8_PD9       0
+
+#define HAS_EEPROM             1
+#define USE_INTERNAL_FLASH     1
+#define USE_STORAGE_CONFIG     0
+#define USE_EEPROM_CONFIG      1
+#define HAS_USB                        1
+#define HAS_BEEP               0
+#define HAS_RADIO              1
+#define HAS_TELEMETRY          0
+#define HAS_RSSI               0
+
+#define HAS_SPI_1              0
+#define SPI_1_PA5_PA6_PA7      0       /* Barometer */
+#define SPI_1_PB3_PB4_PB5      0
+#define SPI_1_PE13_PE14_PE15   0       /* Accelerometer */
+
+#define HAS_SPI_2              1
+#define SPI_2_PB13_PB14_PB15   1       /* Radio */
+#define SPI_2_PD1_PD3_PD4      0
+#define SPI_2_OSPEEDR          STM_OSPEEDR_10MHz
+
+#define SPI_2_PORT             (&stm_gpiob)
+#define SPI_2_SCK_PIN          13
+#define SPI_2_MISO_PIN         14
+#define SPI_2_MOSI_PIN         15
+
+#define PACKET_HAS_SLAVE       0
+#define PACKET_HAS_MASTER      1
+
+#define LOW_LEVEL_DEBUG                0
+
+#define LED_PORT_0_ENABLE      STM_RCC_AHBENR_GPIOCEN
+#define LED_PORT_0             (&stm_gpioc)
+#define LED_PORT_0_MASK                (0xffff)
+#define LED_PORT_0_SHIFT       0
+#define LED_PIN_RED            8
+#define LED_PIN_GREEN          9
+#define AO_LED_RED             (1 << LED_PIN_RED)
+#define AO_LED_GREEN           (1 << LED_PIN_GREEN)
+
+#define LEDS_AVAILABLE         (AO_LED_RED | AO_LED_GREEN)
+
+#define HAS_GPS                        0
+#define HAS_FLIGHT             0
+#define HAS_ADC                        0
+#define HAS_LOG                        0
+
+/*
+ * Telemetry monitoring
+ */
+#define HAS_MONITOR            1
+#define LEGACY_MONITOR         0
+#define HAS_MONITOR_PUT                1
+#define AO_MONITOR_LED         AO_LED_GREEN
+#define AO_MONITOR_BAD         AO_LED_RED
+
+/*
+ * Radio (cc1200)
+ */
+
+/* gets pretty close to 434.550 */
+
+#define AO_RADIO_CAL_DEFAULT   5695733
+
+#define AO_FEC_DEBUG           0
+#define AO_CC1200_SPI_CS_PORT  (&stm_gpioc)
+#define AO_CC1200_SPI_CS_PIN   5
+#define AO_CC1200_SPI_BUS      AO_SPI_2_PB13_PB14_PB15
+#define AO_CC1200_SPI          stm_spi2
+
+#define AO_CC1200_INT_PORT     (&stm_gpioe)
+#define AO_CC1200_INT_PIN      1
+
+#define AO_CC1200_INT_GPIO     2
+#define AO_CC1200_INT_GPIO_IOCFG       CC1200_IOCFG2
+
+/*
+ * Profiling Viterbi decoding
+ */
+
+#ifndef AO_PROFILE
+#define AO_PROFILE             0
+#endif
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/teledongle-v1.8/ao_teledongle.c b/src/teledongle-v1.8/ao_teledongle.c
new file mode 100644 (file)
index 0000000..5ce6b15
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_exti.h>
+#include <ao_packet.h>
+#include <ao_send_packet.h>
+
+int
+main(void)
+{
+       ao_clock_init();
+
+#if HAS_STACK_GUARD
+       ao_mpu_init();
+#endif
+
+       ao_task_init();
+       ao_led_init(LEDS_AVAILABLE);
+       ao_led_on(AO_LED_RED);
+       ao_timer_init();
+
+       ao_spi_init();
+       ao_dma_init();
+       ao_exti_init();
+
+       ao_cmd_init();
+
+       ao_usb_init();
+       ao_radio_init();
+       ao_monitor_init();
+       ao_packet_master_init();
+       ao_send_packet_init();
+
+       ao_config_init();
+
+       ao_led_off(AO_LED_RED);
+       ao_start_scheduler();
+       return 0;
+}
diff --git a/src/teledongle-v3.0/.gitignore b/src/teledongle-v3.0/.gitignore
new file mode 100644 (file)
index 0000000..9a30cbb
--- /dev/null
@@ -0,0 +1,2 @@
+ao_product.h
+teledongle-*.elf
diff --git a/src/teledongle-v3.0/Makefile b/src/teledongle-v3.0/Makefile
new file mode 100644 (file)
index 0000000..a656cde
--- /dev/null
@@ -0,0 +1,79 @@
+#
+# AltOS build
+#
+#
+
+include ../lpc/Makefile.defs
+
+INC = \
+       ao.h \
+       ao_arch.h \
+       ao_arch_funcs.h \
+       ao_boot.h \
+       ao_pins.h \
+       ao_product.h \
+       ao_task.h \
+       ao_whiten.h \
+       lpc.h \
+       ao_cc1200.h \
+       ao_cc1200_CC1200.h \
+       Makefile
+
+ALTOS_SRC = \
+       ao_boot_chain.c \
+       ao_interrupt.c \
+       ao_product.c \
+       ao_romconfig.c \
+       ao_cc1200.c \
+       ao_cmd.c \
+       ao_config.c \
+       ao_task.c \
+       ao_led_lpc.c \
+       ao_stdio.c \
+       ao_panic.c \
+       ao_timer_lpc.c \
+       ao_mutex.c \
+       ao_freq.c \
+       ao_spi_lpc.c \
+       ao_usb_lpc.c \
+       ao_exti_lpc.c \
+       ao_send_packet.c \
+       ao_monitor.c \
+       ao_packet_master.c \
+       ao_packet.c
+
+PRODUCT=TeleDongle-v3.0
+PRODUCT_DEF=-DTELEDONGLE
+IDPRODUCT=0x000c
+
+CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) -Os -g
+
+PROGNAME=teledongle-v3.0
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_teledongle.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+$(OBJ): $(INC)
+
+ao_product.h: ao-make-product.5c ../Version
+       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+load: $(PROG)
+       lpc-load $(PROG)
+
+distclean:     clean
+
+clean:
+       rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+       rm -f ao_product.h
+
+install:
+
+uninstall:
diff --git a/src/teledongle-v3.0/ao_pins.h b/src/teledongle-v3.0/ao_pins.h
new file mode 100644 (file)
index 0000000..52a86fc
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+/* Using TeleDongle v3.0 board */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define AO_STACK_SIZE  320
+
+#define HAS_TASK_QUEUE         1
+
+#define IS_FLASH_LOADER        0
+
+/* Crystal on the board */
+#define AO_LPC_CLKIN   12000000
+
+/* Main clock frequency. 48MHz for USB so we don't use the USB PLL */
+#define AO_LPC_CLKOUT  48000000
+
+/* System clock frequency */
+#define AO_LPC_SYSCLK  24000000
+
+#define HAS_EEPROM             0
+#define USE_INTERNAL_FLASH     0
+#define USE_STORAGE_CONFIG     0
+#define USE_EEPROM_CONFIG      0
+
+#define HAS_USB                        1
+#define HAS_USB_CONNECT                0
+#define HAS_USB_VBUS           0
+#define HAS_USB_PULLUP         1
+#define AO_USB_PULLUP_PORT     0
+#define AO_USB_PULLUP_PIN      20
+
+#define HAS_BEEP               0
+#define HAS_RADIO              1
+#define HAS_TELEMETRY          0
+#define HAS_RSSI               0
+
+#define HAS_SPI_0              1
+#define SPI_SCK0_P0_6          1
+
+#define PACKET_HAS_SLAVE       0
+#define PACKET_HAS_MASTER      1
+
+#define LOW_LEVEL_DEBUG                0
+
+#define LED_PORT               0
+#define LED_PIN_RED            14
+#define LED_PIN_GREEN          7
+#define AO_LED_RED             (1 << LED_PIN_RED)
+#define AO_LED_GREEN           (1 << LED_PIN_GREEN)
+
+#define LEDS_AVAILABLE         (AO_LED_RED | AO_LED_GREEN)
+
+#define HAS_GPS                        0
+#define HAS_FLIGHT             0
+#define HAS_ADC                        0
+#define HAS_LOG                        0
+
+/*
+ * Telemetry monitoring
+ */
+#define HAS_MONITOR            1
+#define LEGACY_MONITOR         0
+#define HAS_MONITOR_PUT                1
+#define AO_MONITOR_LED         AO_LED_GREEN
+#define AO_MONITOR_BAD         AO_LED_RED
+
+/*
+ * Radio (cc1200)
+ */
+
+/* gets pretty close to 434.550 */
+
+#define AO_RADIO_CAL_DEFAULT   5695733
+
+#define AO_FEC_DEBUG           0
+#define AO_CC1200_SPI_CS_PORT  0
+#define AO_CC1200_SPI_CS_PIN   3
+#define AO_CC1200_SPI_BUS      0
+#define AO_CC1200_SPI          0
+
+#define AO_CC1200_INT_PORT     0
+#define AO_CC1200_INT_PIN      2
+
+#define AO_CC1200_INT_GPIO     2
+#define AO_CC1200_INT_GPIO_IOCFG       CC1200_IOCFG2
+
+/*
+ * Profiling Viterbi decoding
+ */
+
+#ifndef AO_PROFILE
+#define AO_PROFILE             0
+#endif
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/teledongle-v3.0/ao_teledongle.c b/src/teledongle-v3.0/ao_teledongle.c
new file mode 100644 (file)
index 0000000..02b93ef
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_exti.h>
+#include <ao_packet.h>
+#include <ao_send_packet.h>
+
+int
+main(void)
+{
+       ao_clock_init();
+
+#if HAS_STACK_GUARD
+       ao_mpu_init();
+#endif
+
+       ao_task_init();
+       ao_led_init(LEDS_AVAILABLE);
+       ao_led_on(AO_LED_RED);
+       ao_timer_init();
+
+       ao_spi_init();
+       ao_exti_init();
+
+       ao_cmd_init();
+
+       ao_usb_init();
+       ao_radio_init();
+       ao_monitor_init();
+       ao_packet_master_init();
+       ao_send_packet_init();
+
+       ao_config_init();
+
+       ao_led_off(AO_LED_RED);
+       ao_start_scheduler();
+       return 0;
+}
diff --git a/src/teledongle-v3.0/flash-loader/Makefile b/src/teledongle-v3.0/flash-loader/Makefile
new file mode 100644 (file)
index 0000000..b832511
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# AltOS flash loader build
+#
+
+TOPDIR=../..
+HARDWARE=teledongle-v3.0
+include $(TOPDIR)/lpc/Makefile-flash.defs
diff --git a/src/teledongle-v3.0/flash-loader/ao_pins.h b/src/teledongle-v3.0/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..aee5be2
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#include <ao_flash_lpc_pins.h>
+
+/* Debug port TXD (pin 6) */
+
+#define AO_BOOT_PIN                    1
+#define AO_BOOT_APPLICATION_GPIO       0
+#define AO_BOOT_APPLICATION_PIN                19
+#define AO_BOOT_APPLICATION_VALUE      1
+#define AO_BOOT_APPLICATION_MODE       AO_EXTI_MODE_PULL_UP
+
+#define HAS_USB_PULLUP 1
+#define AO_USB_PULLUP_PORT     0
+#define AO_USB_PULLUP_PIN      20
+
+#endif /* _AO_PINS_H_ */
index b8b2513e5b54f57c9df6d95c8692832dd56b0493..9237780b7be35c3b02449b69e8f937f6877a304a 100644 (file)
@@ -15,5 +15,6 @@ ao_fat_test
 ao_fec_test
 ao_flight_test_mm
 ao_flight_test_noisy_accel
+ao_flight_test_metrum
 ao_micropeak_test
 ao_aes_test
index 8b737ca1e71a9b123f720da3ad5c0b249a91d0c3..fbbc4bd97004997850c1c78939dd48b6d35abe7e 100644 (file)
@@ -600,7 +600,7 @@ ao_insert(void)
 
 #if 1
                        printf("%7.2f height %8.2f accel %8.3f "
-#if TELEMEGA && 0
+#if TELEMEGA && 1
                               "angle %5d "
                               "accel_x %8.3f accel_y %8.3f accel_z %8.3f gyro_x %8.3f gyro_y %8.3f gyro_z %8.3f mag_x %8d mag_y %8d, mag_z %8d mag_angle %4d "
 #endif
@@ -608,7 +608,7 @@ ao_insert(void)
                               time,
                               height,
                               accel,
-#if TELEMEGA && 0
+#if TELEMEGA && 1
                               ao_sample_orient,
 
                               ao_mpu6000_accel(ao_data_static.mpu6000.accel_x),
@@ -764,6 +764,8 @@ ao_sleep(void *wchan)
                                        ao_data_static.hmc5883.z = int16(bytes, 24);
 #if HAS_MMA655X
                                        ao_data_static.mma655x = int16(bytes, 26);
+                                       if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP)
+                                               ao_data_static.mma655x = ao_data_accel_invert(ao_data_static.mma655x);
 #endif
                                        ao_records_read++;
                                        ao_insert();
@@ -900,6 +902,9 @@ ao_sleep(void *wchan)
                        } else if (nword >= 3 && strcmp(words[0], "Apogee") == 0 &&
                                   strcmp(words[1], "lockout:") == 0) {
                                ao_config.apogee_lockout = atoi(words[2]);
+                       } else if (nword >= 3 && strcmp(words[0], "Pad") == 0 &&
+                                  strcmp(words[1], "orientation:") == 0) {
+                               ao_config.pad_orientation = atoi(words[2]);
                        } else if (nword >= 36 && strcmp(words[0], "CALL") == 0) {
                                tick = atoi(words[10]);
                                if (!ao_flight_started) {
index 5ea205d66792fd1e6ce4391cb516a24e6d764859..83efbb4fcf01ce650d9317c9f552800e81495333 100644 (file)
@@ -59,6 +59,7 @@ struct ao_telemetry_location {
 
 typedef int32_t                gps_alt_t;
 #define AO_TELEMETRY_LOCATION_ALTITUDE(l)      (((gps_alt_t) (l)->altitude_high << 16) | ((l)->altitude_low))
+#define AO_GPS_ORIG_ALTITUDE(l)                        AO_TELEMETRY_LOCATION_ALTITUDE(l)
 #define AO_TELEMETRY_LOCATION_SET_ALTITUDE(l,a) (((l)->altitude_high = (a) >> 16), \
                                                 ((l)->altitude_low = (a)))
 
diff --git a/src/usbtrng-v2.0/.gitignore b/src/usbtrng-v2.0/.gitignore
new file mode 100644 (file)
index 0000000..93b38d1
--- /dev/null
@@ -0,0 +1,2 @@
+ao_product.h
+usbtrng-*
diff --git a/src/usbtrng-v2.0/Makefile b/src/usbtrng-v2.0/Makefile
new file mode 100644 (file)
index 0000000..abbdbbc
--- /dev/null
@@ -0,0 +1,68 @@
+#
+# AltOS build
+#
+#
+
+include ../stmf0/Makefile.defs
+
+INC = \
+       ao.h \
+       ao_arch.h \
+       ao_arch_funcs.h \
+       ao_pins.h \
+       ao_product.h \
+       ao_task.h \
+       stm32f0.h
+
+#
+# Common AltOS sources
+#
+ALTOS_SRC = \
+       ao_interrupt.c \
+       ao_timer.c \
+       ao_panic.c \
+       ao_mutex.c \
+       ao_dma_stm.c \
+       ao_adc_fast.c \
+       ao_crc_stm.c \
+       ao_stdio.c \
+       ao_led.c \
+       ao_romconfig.c \
+       ao_boot_chain.c \
+       ao_cmd.c \
+       ao_usb_stm.c \
+       ao_task.c \
+       ao_product.c
+
+PRODUCT=usbtrng-v2.0
+PRODUCT_DEF=-DUSBTRNG_V_2_0
+IDPRODUCT=0x0028
+
+CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -g -Os
+
+PROGNAME=usbtrng-v2.0
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_usbtrng.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+ao_product.h: ao-make-product.5c ../Version
+       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+$(OBJ): $(INC)
+
+distclean:     clean
+
+clean:
+       rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+       rm -f ao_product.h
+
+install:
+
+uninstall:
diff --git a/src/usbtrng-v2.0/ao_pins.h b/src/usbtrng-v2.0/ao_pins.h
new file mode 100644 (file)
index 0000000..2375944
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright © 2015 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define LED_PORT_ENABLE        STM_RCC_AHBENR_IOPAEN
+#define LED_PORT       (&stm_gpioa)
+#define LED_PIN_RED    2
+#define LED_PIN_GREEN  3
+#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_BEEP       0
+
+/* 48MHz clock based on USB */
+#define AO_HSI48       1
+
+/* HCLK = 48MHz */
+#define AO_AHB_PRESCALER       1
+#define AO_RCC_CFGR_HPRE_DIV   STM_RCC_CFGR_HPRE_DIV_1
+
+/* APB = 48MHz */
+#define AO_APB_PRESCALER       1
+#define AO_RCC_CFGR_PPRE_DIV   STM_RCC_CFGR_PPRE_DIV_1
+
+#define HAS_USB                        1
+#define AO_USB_DIRECTIO                1
+#define AO_PA11_PA12_RMP       0
+
+#define IS_FLASH_LOADER        0
+
+/* ADC */
+
+#define AO_ADC_PIN0_PORT       (&stm_gpioa)
+#define AO_ADC_PIN0_PIN                6
+#define AO_ADC_PIN0_CH         6
+
+#define AO_ADC_RCC_AHBENR      ((1 << STM_RCC_AHBENR_IOPAEN))
+
+#define AO_NUM_ADC             1
+
+/* CRC */
+#define AO_CRC_WIDTH   32
+#define AO_CRC_INIT    0xffffffff
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/usbtrng-v2.0/ao_usbtrng.c b/src/usbtrng-v2.0/ao_usbtrng.c
new file mode 100644 (file)
index 0000000..e1f43cd
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright © 2014 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_adc_fast.h>
+#include <ao_crc.h>
+
+static void
+ao_trng_fetch(void)
+{
+       static uint16_t *buffer[2];
+       uint32_t        kbytes = 1;
+       uint32_t        count;
+       int             usb_buf_id;
+       int             i;
+       uint16_t        *buf;
+       uint32_t        *rnd;
+
+       if (!buffer[0]) {
+               buffer[0] = ao_usb_alloc();
+               buffer[1] = ao_usb_alloc();
+               if (!buffer[0])
+                       return;
+       }
+
+       ao_cmd_decimal();
+       if (ao_cmd_status == ao_cmd_success)
+               kbytes = ao_cmd_lex_u32;
+       else
+               ao_cmd_status = ao_cmd_success;
+       usb_buf_id = 0;
+       count = kbytes * (1024/AO_USB_IN_SIZE);
+
+       ao_crc_reset();
+
+       ao_led_on(AO_LED_GREEN);
+       while (count--) {
+               buf = buffer[usb_buf_id];
+//             printf ("before get: head %3d tail %3d running %d\n", ao_adc_ring_head, ao_adc_ring_tail, ao_adc_running); flush();
+               rnd = (uint32_t *) ao_adc_get(AO_USB_IN_SIZE);  /* one 16-bit value per output byte */
+//             printf ("after get: head %3d tail %3d running %d\n", ao_adc_ring_head, ao_adc_ring_tail, ao_adc_running); flush();
+               for (i = 0; i < 32; i++)
+                       *buf++ = ao_crc_in_32_out_16(*rnd++);
+               ao_adc_ack(AO_USB_IN_SIZE);
+//             printf ("after ack: head %3d tail %3d running %d\n", ao_adc_ring_head, ao_adc_ring_tail, ao_adc_running); flush();
+               ao_led_toggle(AO_LED_GREEN|AO_LED_RED);
+               ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE);
+               ao_led_toggle(AO_LED_GREEN|AO_LED_RED);
+               usb_buf_id = 1-usb_buf_id;
+       }
+       ao_led_off(AO_LED_GREEN|AO_LED_RED);
+       flush();
+}
+
+static const struct ao_cmds usbtrng_cmds[] = {
+       { ao_trng_fetch,        "f <kbytes>\0Fetch a block of numbers" },
+       { 0, NULL },
+};
+
+void main(void)
+{
+       ao_led_init(LEDS_AVAILABLE);
+       ao_led_on(AO_LED_RED);
+       ao_clock_init();
+       ao_task_init();
+       ao_timer_init();
+       ao_dma_init();
+       ao_adc_init();
+       ao_crc_init();
+
+       ao_cmd_init();
+
+       ao_usb_init();
+
+       ao_cmd_register(usbtrng_cmds);
+       ao_led_off(AO_LED_RED);
+
+       ao_start_scheduler();
+}
diff --git a/src/usbtrng-v2.0/flash-loader/.gitignore b/src/usbtrng-v2.0/flash-loader/.gitignore
new file mode 100644 (file)
index 0000000..32dbbbc
--- /dev/null
@@ -0,0 +1,2 @@
+ao_product.h
+usbtrng*
diff --git a/src/usbtrng-v2.0/flash-loader/Makefile b/src/usbtrng-v2.0/flash-loader/Makefile
new file mode 100644 (file)
index 0000000..a2bf199
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=usbtrng-v2.0
+include $(TOPDIR)/stmf0/Makefile-flash.defs
diff --git a/src/usbtrng-v2.0/flash-loader/ao_pins.h b/src/usbtrng-v2.0/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..9fa8b71
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#include <ao_flash_stm_pins.h>
+
+/* Red LED */
+
+#define AO_BOOT_PIN                    1
+#define AO_BOOT_APPLICATION_GPIO       stm_gpioa
+#define AO_BOOT_APPLICATION_PIN                2
+#define AO_BOOT_APPLICATION_VALUE      0
+#define AO_BOOT_APPLICATION_MODE       AO_EXTI_MODE_PULL_DOWN
+
+#endif /* _AO_PINS_H_ */
index b1fa6eb9e945682d63a9b98ecc2bc4997c8b0393..0f2b1ea60f2fb8d826db8619852d18db6e24b981 100644 (file)
@@ -71,3 +71,5 @@
  */
 #define HAS_SCK1               0
 #define HAS_MOSI1              0
+
+#define AO_ADC_6               1
index 6b4d20fe54e6a8849ab14d84dd8b6529b4ff157b..66e12337fc0fabdddc0d80776bb983fae5de2104 100644 (file)
 #include <ao.h>
 
 #define AO_TRNG_SPI_BUS                1
-#define AO_TRNG_SPI_SPEED      AO_SPI_SPEED_250kHz
+
+static uint32_t                        spi_speed = AO_SPI_SPEED_4MHz;
+
+#define AO_TRNG_SPI_BUF                1024
+
+#if 0
+
+static uint8_t *spi_buf;
+static uint8_t *spi_head, *spi_tail;
+static uint8_t spi_wakeup;
+
+static void
+ao_trng_run(void)
+{
+       int     this_time;
+       uint8_t *end;
+
+       if (!spi_buf)
+               spi_buf = ao_usb_alloc(AO_TRNG_SPI_BUF);
+       flush();
+       ao_spi_get(AO_TRNG_SPI_BUS, spi_speed);
+       spi_tail = spi_buf;
+       spi_head = spi_buf;
+       ao_spi_recv_ring_start(spi_buf, AO_TRNG_SPI_BUF, &spi_head, &spi_tail, &spi_wakeup, AO_TRNG_SPI_BUS);
+       while (!ao_usb_out_avail) {
+               ao_arch_block_interrupts();
+               while (spi_head == spi_tail) {
+                       spi_wakeup = 0;
+                       ao_sleep(&spi_wakeup);
+               }
+               ao_arch_release_interrupts();
+               if (spi_tail > spi_head)
+                       end = spi_buf + AO_TRNG_SPI_BUF;
+               else
+                       end = spi_head;
+               this_time = end - spi_tail;
+               if (this_time > 64)
+                       this_time = 64;
+               ao_usb_write(spi_tail, this_time);
+               spi_tail += this_time;
+               if (spi_tail == spi_buf + AO_TRNG_SPI_BUF)
+                       spi_tail = spi_buf;
+       }
+       ao_spi_put(AO_TRNG_SPI_BUS);
+       getchar();
+}
+
 
 static void
 ao_trng_test(void)
@@ -26,16 +72,153 @@ ao_trng_test(void)
        static uint8_t  random[32];
        uint8_t         i;
 
-       ao_spi_get(AO_TRNG_SPI_BUS, AO_TRNG_SPI_SPEED);
+       ao_spi_get(AO_TRNG_SPI_BUS, spi_speed);
        ao_spi_recv(random, sizeof (random), AO_TRNG_SPI_BUS);
        ao_spi_put(AO_TRNG_SPI_BUS);
        for (i = 0; i < sizeof (random); i++)
                printf (" %02x", random[i]);
        printf ("\n");
 }
+#endif
+
+#define ADC_RING_SIZE  512
+
+static uint8_t *adc_ring;
+static uint16_t        adc_head, adc_tail;
+static uint16_t adc_wake;
+
+void  lpc_adc_isr(void)
+{
+       uint16_t        avail;
+       uint16_t        this, next;
+
+       this = adc_head;
+       next = (this + 1) & (ADC_RING_SIZE - 1);
+       if  (next == adc_tail) {
+               lpc_adc.inten = 0;
+               return;
+       }
+       adc_ring[this] = lpc_adc.dr[6] >> 8;
+       adc_head = next;
+
+       /* If there are enough entries, wake up any waiters
+        */
+       avail = (next - adc_tail) & (ADC_RING_SIZE - 1);
+       if (avail >= adc_wake) {
+               adc_wake = 0;
+               ao_wakeup(&adc_wake);
+       }
+}
+
+#define AO_ADC_CLKDIV  (AO_LPC_SYSCLK / 450000)
+
+static void
+ao_trng_adc_init(void)
+{
+       adc_ring = ao_usb_alloc(ADC_RING_SIZE);
+
+       lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_ADC);
+       lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_ADC_PD);
+
+       /* Enable interrupt when AO_ADC_6 is complete */
+       lpc_adc.inten = 0;
+
+       lpc_nvic_set_enable(LPC_ISR_ADC_POS);
+       lpc_nvic_set_priority(LPC_ISR_ADC_POS, AO_LPC_NVIC_CLOCK_PRIORITY);
+
+#if AO_ADC_0
+       ao_enable_analog(0, 11, 0);
+#endif
+#if AO_ADC_1
+       ao_enable_analog(0, 12, 1);
+#endif
+#if AO_ADC_2
+       ao_enable_analog(0, 13, 2);
+#endif
+#if AO_ADC_3
+       ao_enable_analog(0, 14, 3);
+#endif
+#if AO_ADC_4
+       ao_enable_analog(0, 15, 4);
+#endif
+#if AO_ADC_5
+       ao_enable_analog(0, 16, 5);
+#endif
+#if AO_ADC_6
+       ao_enable_analog(0, 22, 6);
+#endif
+#if AO_ADC_7
+       ao_enable_analog(0, 23, 7);
+#endif
+
+       lpc_adc.cr = ((1 << (LPC_ADC_CR_SEL + 6)) |
+                     (AO_ADC_CLKDIV << LPC_ADC_CR_CLKDIV) |
+                     (1 << LPC_ADC_CR_BURST) |
+                     (LPC_ADC_CR_CLKS_9 << LPC_ADC_CR_CLKS));
+}
+
+static void
+ao_trng_adc_dump(void)
+{
+       int     i;
+
+       while (((adc_head - adc_tail) & (ADC_RING_SIZE - 1)) < 16) {
+               lpc_adc.inten = (1 << (LPC_ADC_INTEN_ADINTEN + 6));
+               adc_wake = 16;
+               ao_sleep(&adc_wake);
+       }
+       printf("adc_head %d tail %d\n", adc_head, adc_tail);
+
+       for (i = 0; i < 16; i++) {
+               printf(" %4d", adc_ring[adc_tail]);
+               adc_tail = (adc_tail + 1) & (ADC_RING_SIZE - 1);
+       }
+       printf("\n");
+       lpc_adc.inten = 0;
+}
+
+static void
+ao_trng_run(void)
+{
+       uint16_t        this_time;
+       flush();
+
+       while (!ao_usb_out_avail) {
+               ao_arch_block_interrupts();
+               while (((adc_head - adc_tail) & (ADC_RING_SIZE - 1)) < 64) {
+                       lpc_adc.inten = (1 << (LPC_ADC_INTEN_ADINTEN + 6));
+                       adc_wake = 64;
+                       ao_sleep(&adc_wake);
+               }
+               ao_arch_release_interrupts();
+
+               this_time = ADC_RING_SIZE - adc_tail;
+               if (this_time > 64)
+                       this_time = 64;
+               ao_usb_write(&adc_ring[adc_tail], this_time);
+               adc_tail = (adc_tail + this_time) & (ADC_RING_SIZE - 1);
+       }
+       lpc_adc.inten = 0;
+}
+
+static void
+ao_trng_speed(void)
+{
+       ao_cmd_decimal();
+
+       if (ao_cmd_lex_u32 == 0 || ao_cmd_status != ao_cmd_success) {
+               ao_cmd_status = ao_cmd_success;
+               printf ("Current spi speed %d\n", spi_speed);
+       } else {
+               spi_speed = ao_cmd_lex_u32;
+       }
+}
 
 static const struct ao_cmds ao_trng_cmds[] = {
-       { ao_trng_test, "R\0Dump some random numbers" },
+//     { ao_trng_test, "R\0Dump some random numbers" },
+       { ao_trng_run,  "s\0Send random bits until char" },
+       { ao_trng_speed, "S <speed>\0Set SPI speed (48MHz/speed)" },
+       { ao_trng_adc_dump, "a\0Dump ADC data" },
        { 0, NULL }
 };
 
@@ -46,15 +229,15 @@ main(void)
        ao_task_init();
        ao_timer_init();
 
-       ao_spi_init();
+//     ao_spi_init();
        ao_usb_init();
 
+       ao_trng_adc_init();
+
        ao_serial_init();
 
        ao_led_init(LEDS_AVAILABLE);
 
-       ao_led_on(AO_LED_GREEN);
-
        ao_cmd_init();
 
        ao_cmd_register(ao_trng_cmds);
index 3b33428ea6b2f2937fdebb703c081ecdb219c13b..4caf43f4c3766558c05027ff980a2f3b7ae062d1 100644 (file)
@@ -97,7 +97,8 @@ LINUX_MIMETYPE        =\
 
 # Firmware
 FIRMWARE_TD_0_2=$(top_srcdir)/src/teledongle-v0.2/teledongle-v0.2-$(VERSION).ihx
-FIRMWARE_TD=$(FIRMWARE_TD_0_2)
+FIRMWARE_TD_3_0=$(top_srcdir)/src/teledongle-v3.0/teledongle-v3.0-$(VERSION).ihx
+FIRMWARE_TD=$(FIRMWARE_TD_0_2) $(FIRMWARE_TD_3_0)
 
 FIRMWARE_TBT_1_0=$(top_srcdir)/src/telebt-v1.0/telebt-v1.0-$(VERSION).ihx
 FIRMWARE_TBT=$(FIRMWARE_TBT_1_0)
index a4b221e814b5444df1630fb46cd82fb15273b580..fe3351762a926b8086e72d0b17ad619a6cafa057 100644 (file)
@@ -23,8 +23,8 @@ import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
 import java.util.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class TeleGPS
        extends AltosUIFrame
@@ -67,7 +67,6 @@ public class TeleGPS
 
        TeleGPSStatus           telegps_status;
        TeleGPSStatusUpdate     status_update;
-       javax.swing.Timer       status_timer;
 
        JTabbedPane             pane;
 
@@ -147,6 +146,7 @@ public class TeleGPS
        public void show(AltosState state, AltosListenerState listener_state) {
                try {
                        status_update.saved_state = state;
+                       status_update.saved_listener_state = listener_state;
 
                        if (state == null)
                                state = new AltosState();
@@ -178,11 +178,7 @@ public class TeleGPS
        void disconnect() {
                setTitle("TeleGPS");
                stop_display();
-               if (status_timer != null) {
-                       status_timer.stop();
-                       status_timer = null;
-                       status_update = null;
-               }
+               telegps_status.stop();
 
                telegps_status.disable_receive();
                disable_frequency_menu();
@@ -404,8 +400,7 @@ public class TeleGPS
        public void set_reader(AltosFlightReader reader, AltosDevice device) {
                status_update = new TeleGPSStatusUpdate(telegps_status);
 
-               status_timer = new javax.swing.Timer(100, status_update);
-               status_timer.start();
+               telegps_status.start(status_update);
 
                setTitle(String.format("TeleGPS %s", reader.name));
                thread = new TeleGPSDisplayThread(this, voice(), this, reader);
index e607a5a5510f0c52e173ca2fa9756c55d5fd7729..55763e22458493ad451b15857107678a0bc4ea54 100644 (file)
@@ -22,8 +22,8 @@ import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
 import java.text.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class TeleGPSConfig implements ActionListener {
 
index e2e3d782f3359e5a5be272228f0e61c81e86841b..5e700b72c2bebaa68264458f97506bf8c3383fca 100644 (file)
@@ -21,8 +21,8 @@ import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
 import javax.swing.event.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class TeleGPSConfigUI
        extends AltosUIDialog
index 18b8d9fcd7fe29d0bd086756da27b8277286b07c..09610f5908a5dda08123e481beef37e552ca3cef 100644 (file)
@@ -21,8 +21,8 @@ import java.awt.*;
 import javax.swing.*;
 import java.io.*;
 import java.text.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class TeleGPSDisplayThread extends Thread {
 
@@ -168,8 +168,10 @@ public class TeleGPSDisplayThread extends Thread {
                        for (;;) {
                                try {
                                        state = reader.read();
-                                       if (state == null)
+                                       if (state == null) {
+                                               listener_state.running = false;
                                                break;
+                                       }
                                        reader.update(state);
                                        show_safely();
                                        told = tell();
index b59b122cd4faa11d377e78c9cfec3787082c7247..d3adc748aa5055b9cb772b68f44e7c0ffbe1b5c2 100644 (file)
@@ -26,8 +26,8 @@ import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
 import java.util.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 import org.jfree.chart.ChartPanel;
 import org.jfree.chart.JFreeChart;
index 1b4751b924c35dba49ecb491471473ce0fecd1ba..f20a88300bc6ae04b13071a21e8d68182c04db45 100644 (file)
@@ -21,8 +21,8 @@ import java.util.*;
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class TeleGPSInfo extends AltosUIFlightTab {
 
index 2738ceea687084ebffb7d1337026866b94f3a609..6d7b8985569e189bca8e76303ed7825c4a9ac639 100644 (file)
@@ -22,7 +22,7 @@ import java.awt.event.*;
 import java.beans.*;
 import javax.swing.*;
 import javax.swing.event.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class TeleGPSPreferences
        extends AltosUIConfigure
index 27321c73b3566ebe7428d040ac025baa24ae9f24..18f500b907d56ef726d65cbfd4b52d6cdcdabfe3 100644 (file)
@@ -21,8 +21,8 @@ import java.util.*;
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class TeleGPSState extends AltosUIFlightTab {
 
index 1d4415d6064d400444891ea769c3a0643a3ac0ea..050a844969821899abcf6e7477ee732aa9f09de4 100644 (file)
@@ -19,8 +19,8 @@ package org.altusmetrum.telegps;
 
 import java.awt.*;
 import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
 
 public class TeleGPSStatus extends JComponent implements AltosFlightDisplay {
        GridBagLayout   layout;
@@ -179,11 +179,15 @@ public class TeleGPSStatus extends JComponent implements AltosFlightDisplay {
                long    last_secs = -1;
 
                void show(AltosState state, AltosListenerState listener_state) {
-                       long secs = (System.currentTimeMillis() - state.received_time + 500) / 1000;
-
-                       if (secs != last_secs) {
-                               value.setText(String.format("%d", secs));
-                               last_secs = secs;
+                       if (listener_state.running) {
+                               long secs = (System.currentTimeMillis() - state.received_time + 500) / 1000;
+
+                               if (secs != last_secs) {
+                                       value.setText(String.format("%d", secs));
+                                       last_secs = secs;
+                               }
+                       } else {
+                               value.setText("done");
                        }
                }
 
@@ -232,6 +236,8 @@ public class TeleGPSStatus extends JComponent implements AltosFlightDisplay {
                flight.show(state, listener_state);
                rssi.show(state, listener_state);
                last_packet.show(state, listener_state);
+               if (!listener_state.running)
+                       stop();
        }
 
        public int height() {
@@ -239,6 +245,22 @@ public class TeleGPSStatus extends JComponent implements AltosFlightDisplay {
                return d.height;
        }
 
+       TeleGPSStatusUpdate     status_update;
+       javax.swing.Timer       timer;
+
+       public void start(TeleGPSStatusUpdate status_update) {
+               this.status_update = status_update;
+               timer = new javax.swing.Timer(100, status_update);
+               timer.start();
+       }
+
+       public void stop() {
+               if (timer != null) {
+                       timer.stop();
+                       timer = null;
+               }
+       }
+
        public TeleGPSStatus() {
                layout = new GridBagLayout();
 
index 3d2b7f348670f30cbdad7caff44432936d9b12f4..9c085a5b000ea39f78f9e6c08b306b162f813224 100644 (file)
@@ -18,7 +18,7 @@
 package org.altusmetrum.telegps;
 
 import java.awt.event.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
 
 public class TeleGPSStatusUpdate implements ActionListener {
 
index 603d4971faf6ca5e93d2a01340790c665367092a..446567157c1f25877d9720aec561c8a974c9675f 100644 (file)
@@ -108,7 +108,7 @@ Section "${REG_NAME} Application"
 
        File "../icon/${WIN_APP_ICON}"
 
-       CreateShortCut "$SMPROGRAMS\${REG_NAME}.lnk" "$SYSDIR\javaw.exe" "-jar ${FAT_NAME}" "$INSTDIR\${WIN_APP_ICON}"
+       CreateShortCut "$SMPROGRAMS\${REG_NAME}.lnk" "$INSTDIR\${FAT_NAME}" "" "$INSTDIR\${WIN_APP_ICON}"
 SectionEnd
 
 Section "${REG_NAME} Desktop Shortcut"
@@ -121,6 +121,7 @@ Section "TeleGPS, TeleDongle and TeleBT Firmware"
 
        File "../src/telegps-v1.0/telegps-v1.0-${VERSION}.ihx"
        File "../src/teledongle-v0.2/teledongle-v0.2-${VERSION}.ihx"
+       File "../src/teledongle-v3.0/teledongle-v3.0-${VERSION}.ihx"
        File "../src/telebt-v1.0/telebt-v1.0-${VERSION}.ihx"
 
 SectionEnd
@@ -152,13 +153,15 @@ Section "File Associations"
        DeleteRegKey   HKCR ".telem\${PROG_ID_EEPROM}"
        DeleteRegValue HKCR ".telem\OpenWithProgids" "${PROG_ID_EEPROM}"
 
+       SearchPath $1 "javaw.exe"
+
        ; .eeprom elements
 
        WriteRegStr HKCR "${PROG_ID_EEPROM}"            ""                              "Altus Metrum Log File"
        WriteRegStr HKCR "${PROG_ID_EEPROM}"            "FriendlyTypeName"              "Altus Metrum Log File"
        WriteRegStr HKCR "${PROG_ID_EEPROM}\CurVer"     ""                              "${PROG_ID_EEPROM}"
        WriteRegStr HKCR "${PROG_ID_EEPROM}\DefaultIcon" ""                             '"$INSTDIR\${WIN_EEPROM_EXE}",-101'
-  WriteRegExpandStr HKCR "${PROG_ID_EEPROM}\shell\open\command" ""                     '"%SYSTEMROOT%\System32\javaw.exe" -Djava.library.path="$INSTDIR" -jar "$INSTDIR\${FAT_NAME}" "%1"'
+  WriteRegExpandStr HKCR "${PROG_ID_EEPROM}\shell\open\command" ""                     '"$1" -Djava.library.path="$INSTDIR" -jar "$INSTDIR\${FAT_NAME}" "%1"'
 
        WriteRegStr HKCR ".eeprom"                      ""                              "${PROG_ID_EEPROM}"
        WriteRegStr HKCR ".eeprom"                      "PerceivedType"                 "Altus Metrum Log File"
@@ -173,7 +176,7 @@ Section "File Associations"
        WriteRegStr HKCR "${PROG_ID_TELEM}"             "FriendlyTypeName"              "Altus Metrum Telemetry File"
        WriteRegStr HKCR "${PROG_ID_TELEM}\CurVer"      ""                              "${PROG_ID_TELEM}"
        WriteRegStr HKCR "${PROG_ID_TELEM}\DefaultIcon" ""                              '"$INSTDIR\${WIN_TELEM_EXE}",-101'
-  WriteRegExpandStr HKCR "${PROG_ID_TELEM}\shell\open\command" ""                      '"%SYSTEMROOT%\System32\javaw.exe" -Djava.library.path="$INSTDIR" -jar "$INSTDIR\${FAT_NAME}" "%1"'
+  WriteRegExpandStr HKCR "${PROG_ID_TELEM}\shell\open\command" ""                      '"$1" -Djava.library.path="$INSTDIR" -jar "$INSTDIR\${FAT_NAME}" "%1"'
 
        WriteRegStr HKCR ".telem"                       ""                              "${PROG_ID_TELEM}"
        WriteRegStr HKCR ".telem"                       "PerceivedType"                 "Altus Metrum Telemetry File"