summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog1284
-rw-r--r--Makefile.am6
-rw-r--r--Releasing2
-rw-r--r--altosdroid/.gitignore1
-rw-r--r--altosdroid/AndroidManifest.xml.in24
-rw-r--r--altosdroid/Makefile.am2
-rw-r--r--altosdroid/res/layout/device_list.xml24
-rw-r--r--altosdroid/res/layout/frequency.xml33
-rw-r--r--altosdroid/res/layout/idle_mode.xml54
-rw-r--r--altosdroid/res/layout/igniter_status.xml38
-rw-r--r--altosdroid/res/layout/igniters.xml48
-rw-r--r--altosdroid/res/layout/manage_frequencies.xml96
-rw-r--r--altosdroid/res/layout/setup.xml124
-rw-r--r--altosdroid/res/menu/option_menu.xml24
-rw-r--r--altosdroid/res/values/strings.xml32
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java2
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/AltosDebug.java2
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java273
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidLink.java9
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapInterface.java4
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapSourceListener.java22
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java27
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java10
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java8
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOffline.java36
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOnline.java19
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/AltosUsb.java2
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java2
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/IdleModeActivity.java130
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/IgniterActivity.java413
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/ManageFrequenciesActivity.java289
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/MapTypeActivity.java2
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java15
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/SetupActivity.java339
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/TabFlight.java4
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java21
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java2
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/TabRecover.java2
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java2
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java2
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java255
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/TelemetryState.java4
-rw-r--r--altoslib/AltosAccel.java2
-rw-r--r--altoslib/AltosCRCException.java2
-rw-r--r--altoslib/AltosCSV.java2
-rw-r--r--altoslib/AltosCompanion.java2
-rw-r--r--altoslib/AltosConfigData.java20
-rw-r--r--altoslib/AltosConfigDataException.java2
-rw-r--r--altoslib/AltosConfigValues.java4
-rw-r--r--altoslib/AltosConvert.java10
-rw-r--r--altoslib/AltosDebug.java2
-rw-r--r--altoslib/AltosDistance.java2
-rw-r--r--altoslib/AltosEeprom.java2
-rw-r--r--altoslib/AltosEepromChunk.java4
-rw-r--r--altoslib/AltosEepromDownload.java2
-rw-r--r--altoslib/AltosEepromFile.java4
-rw-r--r--altoslib/AltosEepromGPS.java2
-rw-r--r--altoslib/AltosEepromHeader.java2
-rw-r--r--altoslib/AltosEepromIterable.java2
-rw-r--r--altoslib/AltosEepromList.java2
-rw-r--r--altoslib/AltosEepromLog.java2
-rw-r--r--altoslib/AltosEepromMega.java2
-rw-r--r--altoslib/AltosEepromMetrum2.java2
-rw-r--r--altoslib/AltosEepromMini.java2
-rw-r--r--altoslib/AltosEepromMonitor.java2
-rw-r--r--altoslib/AltosEepromTM.java2
-rw-r--r--altoslib/AltosEepromTMini.java (renamed from altoslib/AltosEepromTm.java)12
-rw-r--r--altoslib/AltosFile.java2
-rw-r--r--altoslib/AltosFlash.java2
-rw-r--r--altoslib/AltosFlashListener.java2
-rw-r--r--altoslib/AltosFlightDisplay.java2
-rw-r--r--altoslib/AltosFlightReader.java2
-rw-r--r--altoslib/AltosFlightStats.java28
-rw-r--r--altoslib/AltosFontListener.java2
-rw-r--r--altoslib/AltosFrequency.java12
-rw-r--r--altoslib/AltosGPS.java2
-rw-r--r--altoslib/AltosGPSSat.java7
-rw-r--r--altoslib/AltosGreatCircle.java2
-rw-r--r--altoslib/AltosHeight.java2
-rw-r--r--altoslib/AltosHexfile.java2
-rw-r--r--altoslib/AltosHexsym.java2
-rw-r--r--altoslib/AltosIMU.java2
-rw-r--r--altoslib/AltosIdle.java2
-rw-r--r--altoslib/AltosIdleFetch.java10
-rw-r--r--altoslib/AltosIdleMonitor.java24
-rw-r--r--altoslib/AltosIdleMonitorListener.java3
-rw-r--r--altoslib/AltosIgnite.java17
-rw-r--r--altoslib/AltosImage.java2
-rw-r--r--altoslib/AltosKML.java2
-rw-r--r--altoslib/AltosLatLon.java2
-rw-r--r--altoslib/AltosLatitude.java2
-rw-r--r--altoslib/AltosLaunchSite.java2
-rw-r--r--altoslib/AltosLaunchSiteListener.java2
-rw-r--r--altoslib/AltosLaunchSites.java10
-rw-r--r--altoslib/AltosLib.java3
-rw-r--r--altoslib/AltosLine.java2
-rw-r--r--altoslib/AltosLink.java22
-rw-r--r--altoslib/AltosListenerState.java2
-rw-r--r--altoslib/AltosLocation.java2
-rw-r--r--altoslib/AltosLog.java2
-rw-r--r--altoslib/AltosLongitude.java2
-rw-r--r--altoslib/AltosMag.java2
-rw-r--r--altoslib/AltosMap.java30
-rw-r--r--altoslib/AltosMapCache.java80
-rw-r--r--altoslib/AltosMapCacheListener.java2
-rw-r--r--altoslib/AltosMapInterface.java4
-rw-r--r--altoslib/AltosMapLine.java2
-rw-r--r--altoslib/AltosMapLoader.java76
-rw-r--r--altoslib/AltosMapLoaderListener.java2
-rw-r--r--altoslib/AltosMapMark.java2
-rw-r--r--altoslib/AltosMapPath.java2
-rw-r--r--altoslib/AltosMapPathPoint.java2
-rw-r--r--altoslib/AltosMapRectangle.java2
-rw-r--r--altoslib/AltosMapStore.java49
-rw-r--r--altoslib/AltosMapStoreListener.java2
-rw-r--r--altoslib/AltosMapTile.java66
-rw-r--r--altoslib/AltosMapTileListener.java4
-rw-r--r--altoslib/AltosMapTransform.java2
-rw-r--r--altoslib/AltosMapTypeListener.java22
-rw-r--r--altoslib/AltosMapZoomListener.java2
-rw-r--r--altoslib/AltosMma655x.java16
-rw-r--r--altoslib/AltosMs5607.java2
-rw-r--r--altoslib/AltosNoSymbol.java2
-rw-r--r--altoslib/AltosOrient.java2
-rw-r--r--altoslib/AltosParse.java2
-rw-r--r--altoslib/AltosPointDouble.java2
-rw-r--r--altoslib/AltosPointInt.java2
-rw-r--r--altoslib/AltosPreferences.java130
-rw-r--r--altoslib/AltosPreferencesBackend.java78
-rw-r--r--altoslib/AltosProgrammer.java2
-rw-r--r--altoslib/AltosPyro.java2
-rw-r--r--altoslib/AltosQuaternion.java2
-rw-r--r--altoslib/AltosRectangle.java2
-rw-r--r--altoslib/AltosReplayReader.java2
-rw-r--r--altoslib/AltosRomconfig.java2
-rw-r--r--altoslib/AltosRotation.java2
-rw-r--r--altoslib/AltosSavedState.java2
-rw-r--r--altoslib/AltosSelfFlash.java2
-rw-r--r--altoslib/AltosSensorEMini.java2
-rw-r--r--altoslib/AltosSensorMM.java2
-rw-r--r--altoslib/AltosSensorMega.java2
-rw-r--r--altoslib/AltosSensorMetrum.java2
-rw-r--r--altoslib/AltosSensorTGPS.java2
-rw-r--r--altoslib/AltosSensorTM.java2
-rw-r--r--altoslib/AltosSensorTMini.java2
-rw-r--r--altoslib/AltosSpeed.java12
-rw-r--r--altoslib/AltosState.java2
-rw-r--r--altoslib/AltosStateIterable.java2
-rw-r--r--altoslib/AltosStateUpdate.java6
-rw-r--r--altoslib/AltosTelemetry.java2
-rw-r--r--altoslib/AltosTelemetryCompanion.java2
-rw-r--r--altoslib/AltosTelemetryConfiguration.java2
-rw-r--r--altoslib/AltosTelemetryFile.java2
-rw-r--r--altoslib/AltosTelemetryIterable.java2
-rw-r--r--altoslib/AltosTelemetryLegacy.java2
-rw-r--r--altoslib/AltosTelemetryLocation.java2
-rw-r--r--altoslib/AltosTelemetryMap.java2
-rw-r--r--altoslib/AltosTelemetryMegaData.java2
-rw-r--r--altoslib/AltosTelemetryMegaSensor.java2
-rw-r--r--altoslib/AltosTelemetryMetrumData.java2
-rw-r--r--altoslib/AltosTelemetryMetrumSensor.java2
-rw-r--r--altoslib/AltosTelemetryMini.java2
-rw-r--r--altoslib/AltosTelemetryRaw.java2
-rw-r--r--altoslib/AltosTelemetryReader.java2
-rw-r--r--altoslib/AltosTelemetrySatellite.java2
-rw-r--r--altoslib/AltosTelemetrySensor.java2
-rw-r--r--altoslib/AltosTelemetryStandard.java2
-rw-r--r--altoslib/AltosTemperature.java2
-rw-r--r--altoslib/AltosUnits.java2
-rw-r--r--altoslib/AltosUnitsListener.java2
-rw-r--r--altoslib/AltosUnknownProduct.java26
-rw-r--r--altoslib/AltosVersion.java.in4
-rw-r--r--altoslib/AltosVoltage.java2
-rw-r--r--altoslib/AltosWriter.java2
-rw-r--r--altoslib/Makefile.am4
-rw-r--r--altosui/Altos.java4
-rw-r--r--altosui/AltosAscent.java4
-rw-r--r--altosui/AltosCompanionInfo.java4
-rw-r--r--altosui/AltosConfig.java4
-rw-r--r--altosui/AltosConfigPyroUI.java4
-rw-r--r--altosui/AltosConfigTD.java4
-rw-r--r--altosui/AltosConfigTDUI.java4
-rw-r--r--altosui/AltosConfigUI.java23
-rw-r--r--altosui/AltosConfigureUI.java2
-rw-r--r--altosui/AltosDescent.java4
-rw-r--r--altosui/AltosFlightStatus.java4
-rw-r--r--altosui/AltosFlightStatusTableModel.java2
-rw-r--r--altosui/AltosFlightStatusUpdate.java2
-rw-r--r--altosui/AltosFlightUI.java4
-rw-r--r--altosui/AltosGraphUI.java4
-rw-r--r--altosui/AltosIdleMonitorUI.java17
-rw-r--r--altosui/AltosIgniteUI.java11
-rw-r--r--altosui/AltosIgnitor.java4
-rw-r--r--altosui/AltosLanded.java4
-rw-r--r--altosui/AltosLaunch.java2
-rw-r--r--altosui/AltosLaunchUI.java2
-rw-r--r--altosui/AltosPad.java4
-rw-r--r--altosui/AltosUI.java4
-rw-r--r--altosui/Instdrv/NSIS/Includes/java.nsh261
-rw-r--r--altosuilib/AltosBTDevice.java4
-rw-r--r--altosuilib/AltosBTDeviceIterator.java4
-rw-r--r--altosuilib/AltosBTKnown.java4
-rw-r--r--altosuilib/AltosBTManage.java4
-rw-r--r--altosuilib/AltosCSVUI.java4
-rw-r--r--altosuilib/AltosConfigFreqUI.java4
-rw-r--r--altosuilib/AltosDataChooser.java4
-rw-r--r--altosuilib/AltosDevice.java2
-rw-r--r--altosuilib/AltosDeviceDialog.java2
-rw-r--r--altosuilib/AltosDeviceUIDialog.java2
-rw-r--r--altosuilib/AltosDisplayThread.java4
-rw-r--r--altosuilib/AltosEepromDelete.java4
-rw-r--r--altosuilib/AltosEepromManage.java4
-rw-r--r--altosuilib/AltosEepromMonitor.java2
-rw-r--r--altosuilib/AltosEepromMonitorUI.java4
-rw-r--r--altosuilib/AltosEepromSelect.java4
-rw-r--r--altosuilib/AltosFlashUI.java4
-rw-r--r--altosuilib/AltosFlightInfoTableModel.java2
-rw-r--r--altosuilib/AltosFlightStatsTable.java10
-rw-r--r--altosuilib/AltosGraph.java4
-rw-r--r--altosuilib/AltosGraphDataPoint.java4
-rw-r--r--altosuilib/AltosGraphDataSet.java4
-rw-r--r--altosuilib/AltosInfoTable.java4
-rw-r--r--altosuilib/AltosLed.java2
-rw-r--r--altosuilib/AltosLights.java2
-rw-r--r--altosuilib/AltosPositionListener.java2
-rw-r--r--altosuilib/AltosRomconfigUI.java4
-rw-r--r--altosuilib/AltosScanUI.java4
-rw-r--r--altosuilib/AltosSerial.java4
-rw-r--r--altosuilib/AltosSerialInUseException.java2
-rw-r--r--altosuilib/AltosUIAxis.java4
-rw-r--r--altosuilib/AltosUIConfigure.java4
-rw-r--r--altosuilib/AltosUIDataMissing.java2
-rw-r--r--altosuilib/AltosUIDataPoint.java2
-rw-r--r--altosuilib/AltosUIDataSet.java2
-rw-r--r--altosuilib/AltosUIDialog.java2
-rw-r--r--altosuilib/AltosUIEnable.java4
-rw-r--r--altosuilib/AltosUIFlightTab.java4
-rw-r--r--altosuilib/AltosUIFrame.java2
-rw-r--r--altosuilib/AltosUIFreqList.java4
-rw-r--r--altosuilib/AltosUIGraph.java4
-rw-r--r--altosuilib/AltosUIGrapher.java4
-rw-r--r--altosuilib/AltosUIImage.java2
-rw-r--r--altosuilib/AltosUIIndicator.java4
-rw-r--r--altosuilib/AltosUILib.java7
-rw-r--r--altosuilib/AltosUIListener.java2
-rw-r--r--altosuilib/AltosUIMapNew.java22
-rw-r--r--altosuilib/AltosUIMapPreloadNew.java16
-rw-r--r--altosuilib/AltosUIMarker.java4
-rw-r--r--altosuilib/AltosUIPreferences.java4
-rw-r--r--altosuilib/AltosUIPreferencesBackend.java10
-rw-r--r--altosuilib/AltosUIRateList.java4
-rw-r--r--altosuilib/AltosUISeries.java4
-rw-r--r--altosuilib/AltosUITelemetryList.java4
-rw-r--r--altosuilib/AltosUIUnitsIndicator.java4
-rw-r--r--altosuilib/AltosUIVoltageIndicator.java4
-rw-r--r--altosuilib/AltosUSBDevice.java2
-rw-r--r--altosuilib/AltosVoice.java2
-rw-r--r--altosuilib/GrabNDrag.java2
-rwxr-xr-xaltosuilib/OSXAdapter.java2
-rwxr-xr-xao-bringup/cal-freq2
-rwxr-xr-xao-bringup/test-telemega1
-rwxr-xr-xao-bringup/turnon_chaoskey33
-rw-r--r--ao-tools/Makefile.am2
-rw-r--r--ao-tools/ao-chaosread/.gitignore1
-rw-r--r--ao-tools/ao-chaosread/Makefile.am9
-rw-r--r--ao-tools/ao-chaosread/ao-chaosread.136
-rw-r--r--ao-tools/ao-chaosread/ao-chaosread.c272
-rw-r--r--ao-tools/ao-dump-up/ao-dump-up.c14
-rw-r--r--ao-tools/ao-makebin/Makefile.am12
-rw-r--r--ao-tools/ao-makebin/ao-makebin.147
-rw-r--r--ao-tools/ao-makebin/ao-makebin.c172
-rw-r--r--ao-tools/lib/Makefile.am2
-rw-r--r--ao-tools/lib/ao-dfu.c202
-rw-r--r--ao-tools/lib/ao-dfu.h35
-rw-r--r--ao-tools/lib/ao-elf.c6
-rw-r--r--ao-tools/lib/ao-hex.c33
-rw-r--r--ao-tools/lib/ao-hex.h3
-rw-r--r--configure.ac14
-rw-r--r--doc/Makefile1
-rw-r--r--doc/altosdroid.inc122
-rw-r--r--doc/altusmetrum-docinfo.xml8
-rw-r--r--doc/easymini-docinfo.xml7
-rw-r--r--doc/easymini-release-notes.inc4
-rw-r--r--doc/release-notes-1.6.3.inc92
-rw-r--r--doc/release-notes.inc4
-rw-r--r--doc/telegps-release-notes.inc4
-rw-r--r--doc/usage.inc9
-rw-r--r--icon/.gitignore2
-rw-r--r--libaltos/Makefile-standalone20
-rw-r--r--libaltos/Makefile.am29
-rw-r--r--libaltos/libaltos.c1535
-rwxr-xr-xlibaltos/libaltos.dylibbin41596 -> 46228 bytes
-rw-r--r--libaltos/libaltos_common.c83
-rw-r--r--libaltos/libaltos_darwin.c253
-rw-r--r--libaltos/libaltos_linux.c528
-rw-r--r--libaltos/libaltos_posix.c201
-rw-r--r--libaltos/libaltos_posix.h40
-rw-r--r--libaltos/libaltos_private.h63
-rw-r--r--libaltos/libaltos_windows.c761
-rw-r--r--micropeak/MicroData.java4
-rw-r--r--micropeak/MicroDataPoint.java2
-rw-r--r--micropeak/MicroDeviceDialog.java2
-rw-r--r--micropeak/MicroDownload.java4
-rw-r--r--micropeak/MicroExport.java4
-rw-r--r--micropeak/MicroFile.java4
-rw-r--r--micropeak/MicroFileChooser.java4
-rw-r--r--micropeak/MicroFrame.java2
-rw-r--r--micropeak/MicroGraph.java4
-rw-r--r--micropeak/MicroPeak.java4
-rw-r--r--micropeak/MicroRaw.java4
-rw-r--r--micropeak/MicroSave.java4
-rw-r--r--micropeak/MicroSerial.java2
-rw-r--r--micropeak/MicroSerialLog.java2
-rw-r--r--micropeak/MicroStats.java4
-rw-r--r--micropeak/MicroStatsTable.java4
-rw-r--r--micropeak/MicroUSB.java4
-rw-r--r--micropeak/micropeak-windows.nsi.in18
-rw-r--r--src/Makefile7
-rw-r--r--src/cc1111/ao_arch_funcs.h4
-rw-r--r--src/chaoskey-v0.1/Makefile5
-rw-r--r--src/chaoskey-v0.1/ao_pins.h31
-rw-r--r--src/chaoskey-v1.0/.gitignore2
-rw-r--r--src/chaoskey-v1.0/Makefile73
-rw-r--r--src/chaoskey-v1.0/ao_chaoskey.c38
-rw-r--r--src/chaoskey-v1.0/ao_pins.h83
-rw-r--r--src/chaoskey-v1.0/flash-loader/.gitignore2
-rw-r--r--src/chaoskey-v1.0/flash-loader/Makefile8
-rw-r--r--src/chaoskey-v1.0/flash-loader/ao_pins.h36
-rw-r--r--src/detherm/.gitignore2
-rw-r--r--src/detherm/Makefile82
-rw-r--r--src/detherm/ao_detherm.c50
-rw-r--r--src/detherm/ao_pins.h115
-rw-r--r--src/detherm/flash-loader/.gitignore2
-rw-r--r--src/detherm/flash-loader/Makefile8
-rw-r--r--src/detherm/flash-loader/ao_pins.h36
-rw-r--r--src/drivers/ao_button.c52
-rw-r--r--src/drivers/ao_cc1200.c9
-rw-r--r--src/drivers/ao_event.c16
-rw-r--r--src/drivers/ao_event.h3
-rw-r--r--src/drivers/ao_lco_two.c314
-rw-r--r--src/drivers/ao_ms5607.c6
-rw-r--r--src/drivers/ao_packet_master.c1
-rw-r--r--src/drivers/ao_pad.c73
-rw-r--r--src/drivers/ao_servo.c118
-rw-r--r--src/drivers/ao_servo.h41
-rw-r--r--src/drivers/ao_trng_send.c228
-rw-r--r--src/easymega-v1.0/ao_pins.h1
-rw-r--r--src/kernel/ao.h12
-rw-r--r--src/kernel/ao_config.c48
-rw-r--r--src/kernel/ao_config.h6
-rw-r--r--src/kernel/ao_data.h4
-rw-r--r--src/kernel/ao_fast_timer.h (renamed from src/stm/ao_fast_timer.h)0
-rw-r--r--src/kernel/ao_flight.c2
-rw-r--r--src/kernel/ao_log.h1
-rw-r--r--src/kernel/ao_log_mini.c2
-rw-r--r--src/kernel/ao_panic.c11
-rw-r--r--src/kernel/ao_power.c80
-rw-r--r--src/kernel/ao_power.h53
-rw-r--r--src/kernel/ao_product.c67
-rw-r--r--src/kernel/ao_task.c4
-rw-r--r--src/kernel/ao_task.h4
-rw-r--r--src/kernel/ao_usb.h17
-rw-r--r--src/lpc/ao_arch_funcs.h22
-rw-r--r--src/lpc/ao_fast_timer_lpc.c110
-rw-r--r--src/lpc/ao_timer_lpc.c14
-rw-r--r--src/lpc/lpc.h120
-rw-r--r--src/lpc/registers.ld2
-rw-r--r--src/stm/ao_arch.h2
-rw-r--r--src/stm/ao_arch_funcs.h74
-rw-r--r--src/stm/ao_serial_stm.c173
-rw-r--r--src/stm/ao_timer.c1
-rw-r--r--src/stm/stm32l.h10
-rw-r--r--src/stmf0/Makefile-flash.defs11
-rw-r--r--src/stmf0/ao_adc_fast.c14
-rw-r--r--src/stmf0/ao_arch.h11
-rw-r--r--src/stmf0/ao_arch_funcs.h87
-rw-r--r--src/stmf0/ao_dma_stm.c34
-rw-r--r--src/stmf0/ao_exti.h2
-rw-r--r--src/stmf0/ao_exti_stm.c149
-rw-r--r--src/stmf0/ao_gpio.c71
-rw-r--r--src/stmf0/ao_pwm.c214
-rw-r--r--src/stmf0/ao_spi_stm.c478
-rw-r--r--src/stmf0/ao_timer.c130
-rw-r--r--src/stmf0/ao_usb_stm.c300
-rw-r--r--src/stmf0/registers.ld2
-rw-r--r--src/stmf0/stm32f0.h460
-rw-r--r--src/telebt-v3.0/.gitignore2
-rw-r--r--src/telebt-v3.0/ao_pins.h5
-rw-r--r--src/telebt-v3.0/ao_telebt.c1
-rw-r--r--src/telefire-v0.1/ao_pins.h2
-rw-r--r--src/telefiretwo-v0.1/.gitignore2
-rw-r--r--src/telefiretwo-v0.1/Makefile89
-rw-r--r--src/telefiretwo-v0.1/ao_pins.h211
-rw-r--r--src/telefiretwo-v0.1/ao_telefiretwo.c54
-rw-r--r--src/telefiretwo-v0.1/flash-loader/.gitignore2
-rw-r--r--src/telefiretwo-v0.1/flash-loader/Makefile8
-rw-r--r--src/telefiretwo-v0.1/flash-loader/ao_pins.h32
-rw-r--r--src/telefiretwo-v0.2/.gitignore2
-rw-r--r--src/telefiretwo-v0.2/Makefile90
-rw-r--r--src/telefiretwo-v0.2/ao_pins.h210
-rw-r--r--src/telefiretwo-v0.2/ao_telefiretwo.c54
-rw-r--r--src/telefiretwo-v0.2/flash-loader/.gitignore2
-rw-r--r--src/telefiretwo-v0.2/flash-loader/Makefile8
-rw-r--r--src/telefiretwo-v0.2/flash-loader/ao_pins.h32
-rw-r--r--src/telelco-v0.2/Makefile2
-rw-r--r--src/telelco-v0.3/Makefile2
-rw-r--r--src/telelcotwo-v0.1/.gitignore2
-rw-r--r--src/telelcotwo-v0.1/Makefile96
-rw-r--r--src/telelcotwo-v0.1/ao_pins.h172
-rw-r--r--src/telelcotwo-v0.1/ao_telelcotwo.c65
-rw-r--r--src/telelcotwo-v0.1/flash-loader/Makefile8
-rw-r--r--src/telelcotwo-v0.1/flash-loader/ao_pins.h34
-rw-r--r--src/telemega-v0.1/ao_pins.h1
-rw-r--r--src/telemega-v1.0/ao_pins.h1
-rw-r--r--src/telemega-v2.0/ao_pins.h1
-rw-r--r--src/telerepeat-v1.0/.gitignore2
-rw-r--r--src/telerepeat-v1.0/.sdcdbrc2
-rwxr-xr-xsrc/test/plotem10
-rw-r--r--telegps/TeleGPS.java4
-rw-r--r--telegps/TeleGPSConfig.java4
-rw-r--r--telegps/TeleGPSConfigUI.java21
-rw-r--r--telegps/TeleGPSDisplayThread.java4
-rw-r--r--telegps/TeleGPSGraphUI.java4
-rw-r--r--telegps/TeleGPSInfo.java4
-rw-r--r--telegps/TeleGPSPreferences.java2
-rw-r--r--telegps/TeleGPSState.java4
-rw-r--r--telegps/TeleGPSStatus.java4
-rw-r--r--telegps/TeleGPSStatusUpdate.java2
428 files changed, 12416 insertions, 3141 deletions
diff --git a/ChangeLog b/ChangeLog
index 7f0d12b1..3353ea3d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,1287 @@
+commit 15ae97fbdb4e75a74ea2e716194661d19dec46ff
+Merge: ac7be4a 1216c0c
+Author: Bdale Garbee <bdale@gag.com>
+Date: Fri May 6 18:11:01 2016 -0600
+
+ Merge branch 'master' into branch-1.6
+
+commit 1216c0ccece4ca1492967a341c5d01e9e5068ed8
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri May 6 17:10:14 2016 -0700
+
+ Ignore some built files for 1.6.3
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ac7be4a40df88ee3a0992e041635e4ac4cf5ac48
+Merge: b53c78e ce4c8a8
+Author: Bdale Garbee <bdale@gag.com>
+Date: Fri May 6 17:59:39 2016 -0600
+
+ Merge branch 'master' into branch-1.6
+
+commit ce4c8a8ad57515e851207b0a82f3af791bb30d3e
+Merge: aa9630c 320e312
+Author: Bdale Garbee <bdale@gag.com>
+Date: Fri May 6 17:49:30 2016 -0600
+
+ Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos
+
+commit aa9630c30ee09bf358e77bf47ed0815a19237fca
+Author: Bdale Garbee <bdale@gag.com>
+Date: Fri May 6 17:49:09 2016 -0600
+
+ add beep to TeleMega turnon script
+
+commit 320e312db36fb6519a0bb1530d79595af18cdc86
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri May 6 16:46:57 2016 -0700
+
+ windows: Change install to look for browser in a different place
+
+ The windows registry is a mystery.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e0081f7ba6fc9f1e4484d3e291fd30065ad5b620
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu May 5 02:25:52 2016 -0700
+
+ altoslib: Fix map preloading callbacks, run in separate thread
+
+ The map storage and tile callbacks were muddled together. Create
+ clearly separate states for map data and have status updates be
+ delivered when registering for new status events so that registration
+ is sufficient to track the state without an explicit call to get the
+ current state.
+
+ Run the map tile creation in a separate thread so that even checking
+ status of files on disk runs out of the UI thread.
+
+ These fixes serve to make the pacifier update more smoothly, and also
+ not over/under count tile loading so that the loading actually
+ completes when all of the tiles are loaded.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 13179f614a99cad3016832ac1b365eaa4208c10f
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 4 23:56:44 2016 -0700
+
+ micropeak: Change order of windows install so that java detect works
+
+ I have no idea why this matters, but if you run the FTDI script before
+ trying to detect java, then the javaw.exe program isn't found and java
+ detection fails.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 85191fe911a5ea4af384bff9b2ed9986679cd9fd
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 4 21:13:31 2016 -0700
+
+ doc: 1.6.3 release notes note TeleBT rts/cts and TM 2.0 monitor idle fixes
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 541996f95f9e26299618dbb79e723b82a52afd31
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 4 21:12:46 2016 -0700
+
+ doc: Update AltosDroid chapter for 1.6.3
+
+ New menu structure, idle mode and frequency configuration
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b540f6f5b034f33b8e1d1c3b91e2403a56479caa
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon May 2 16:19:39 2016 -0700
+
+ altos: Make sure AO_MMA655X_INVERT is declared where needed
+
+ Add #define AO_MMA655X_INVERT 0 to existing products which didn't
+ declare it at all. This will make sure the value is set correctly for
+ each new board.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0b0b359cbce6b818257b44b2a6aee0edcbaee40d
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon May 2 16:13:53 2016 -0700
+
+ altoslib: Deal with TeleMetrum v2.0 MMA6555 being inverted
+
+ Dumping the MMA655X data with the 'A' command provides the raw sensor
+ value. On TM v2.0 boards, the sensor is inverted, and all of the
+ firmware uses the inverted value except for the 'dump the raw data'
+ command. As a result, MonitorIdle was using the un-inverted value and
+ displaying mystic values.
+
+ I've fixed this in the ground station code by checking the product
+ name and conditionally inverting the value (4095 - value) for
+ TeleMetrum v2.0 products. Unknown products will generate a warning
+ dialog on AltosUI so we'll catch places where we've failed to add a
+ new product name.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1a797f5fd5d25ba635fd79ad7604763253caabf2
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 30 18:38:42 2016 -0700
+
+ publish AltosDroid in keithp-fat target
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 59466c1c2dbf95c427c2bb52304049eaac4d124f
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 30 18:37:05 2016 -0700
+
+ altoslib: Flush during set_state. Don't store listener state.
+
+ The listener state wasn't used anyways, so don't bother storing
+ it. Also, flush the state during set_state, which actually causes the
+ state to be written out.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4219fd7720caeec196bf6cb1b4cf78c8fadaf3cd
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 30 18:33:25 2016 -0700
+
+ altoslib: Correct stats for flights without a real landing
+
+ The landing time was miscomputed when the flight ended without
+ entering the landed state, as when the recording terminates at
+ apogee.
+
+ This led to an uncomputed average boost accel, so that is now checked
+ separately from max accel (which is done over the whole flight, not
+ just boost).
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9734f1198429dc8939eebf48b6e6acc1cef96485
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 30 18:30:16 2016 -0700
+
+ altosdroid: max height is a height, not a speed
+
+ Was using the wrong units in the flight tab
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7695da327ff8861a858b6695f4849fa1399548d8
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 30 08:46:52 2016 -0700
+
+ Revert "altos/stm: Run scheduler code on interrupt stack"
+
+ This reverts commit 6a9546413d6a236c010e806b50506d870961d074.
+
+ This causes the device to stop reliably handling interrupts.
+
+commit 7db1cba64a2f6c80c5fe6e3073a0ff65be9c04c1
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Apr 29 21:49:43 2016 -0700
+
+ doc: Add idle mode info to 1.6.3 release note
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ec20e2f72460010c4f59e6d59775671260e01026
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Apr 28 12:29:16 2016 -0700
+
+ altoslib: Make AltosPreferencesBackend abstract. Add set/put Serializable
+
+ This lets us add functionality to this directly, such as the new
+ serializable APIs.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3c7b68b8a513b611500dfd734182e1a2e7bdd40c
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Apr 27 01:40:47 2016 -0400
+
+ altosdroid: Add configurable frequency set
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 02f47fa98536eb0ecd58cd8f063600ced60e0a8a
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Apr 27 01:39:01 2016 -0400
+
+ Fix key in AndroidManifest.xml.in
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d81f94fd5339d513de9bde5a2e19f8eca526344f
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Apr 26 21:01:44 2016 -0400
+
+ altosdroid: Split setup functions to separate dialog
+
+ Remove them from the options menu, handle all preferences through
+ listeners.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 204ae5142702044eb8ad2697a55028e904067958
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Apr 25 23:12:34 2016 -0400
+
+ altosdroid: Add idle mode monitoring, reboot. Start igniters
+
+ This adds three idle mode operations -- monitor idle, reboot flight
+ computer and test igniters. The igniter test isn't quite wired up.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 565404599fe9edf9ba16aec348eeb19ea31af743
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Apr 25 18:50:58 2016 -0400
+
+ altos: Clear packet queue when starting packet master
+
+ This avoids overfilling the packet buffer when
+ disconnected. Applications using packet mode shouldn't expect that
+ output be saved across master sessions.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c816bea3536d025568dab313d7c8944a56ba0801
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Apr 25 18:49:45 2016 -0400
+
+ altos/telebt-v3.0: Flip CTS/RTS pins for BT module
+
+ These are wired backwards, so ask that the right pins be used, which
+ requires switching to software control of the pins.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 27319e4edbc503f193475b437fa5fe2937d47cbe
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Apr 25 18:48:47 2016 -0400
+
+ altos/stm32l: Add support for software-driven HW flow control
+
+ This allows applications to request that the flow control bits be
+ driven from software rather than hardware, permitting more flexible
+ pin configuration.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7c9a111ac1c88467ce28e03b4a9d3eabc9d7015b
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jan 19 23:53:27 2016 -0800
+
+ altos: Use TXE instead of TC for serial on STM32l
+
+ Using TXE allows for full-speed communication, rather than waiting for
+ each byte to be transmitted before inserting the next into the queue.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit eee2ca7fa7fd77be8ca5806cad7e250053465048
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Apr 25 11:47:45 2016 -0400
+
+ Debug bits for telebt
+
+commit a995d73838c8e7ec5126e563baa2e59d5e071b28
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Apr 22 19:15:51 2016 -0400
+
+ altoslib: Don't try to drag lines around until map is loaded
+
+ When the transform is null, it's hard to draw lines.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a5373e2f9d2f1af211aa98029d448aeb518b45ce
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Apr 22 19:15:05 2016 -0400
+
+ altoslib: Report exceptions caught while opening launch sites URL
+
+ This just dumps them to stdout, which helps debug on Linux at least.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6bca0ed8183b85e5825eb0f4093dcd749592faf3
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Apr 22 19:00:46 2016 -0400
+
+ altoslib: Use feet per second for imperial speed
+
+ This is more useful during descent than miles per hour...
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f49fd5d2be68de97ebe65fa4f6484746e91dd677
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Apr 22 18:53:32 2016 -0400
+
+ altosdroid: Run even without Bluetooth
+
+ This lets us view old state information on USB-only devices, or when
+ the bluetooth device can't be enabled.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ea89feedd4185a5f583fa8ddf33a2ec0906e0dc0
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Apr 22 18:52:42 2016 -0400
+
+ altosdroid: Redraw offline map when my location changes
+
+ Update the map view even if there isn't any current telemetry data.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 39af826ce9032e339929eb7917b1d29c87d03f69
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Apr 22 17:32:10 2016 -0400
+
+ altosdroid: Track device location in app, not telemetry service
+
+ This means we get location even if there isn't a telemetry device
+ connected, making it possible to walk to old device locations
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b3f0c4d5c4ab8288db5fcabb0e848627031c4fd1
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Apr 22 17:31:49 2016 -0400
+
+ Bump version to 1.6.3
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 57c1320962ad08d52e89d39bd5852f8d228dd872
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Apr 21 22:37:35 2016 -0400
+
+ altosdroid: Can only use message once
+
+ And here I thought re-using the message was clever. That generates a
+ nice exception and crashes the program.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4d4a39b569d7982405748b961b93dcd33e59b833
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Apr 21 21:32:50 2016 -0400
+
+ Add preliminary 1.6.3 release notes
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 565d8f22c23c7c6c6817d11ef1ca02e70ba5d2ae
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Apr 20 20:27:47 2016 -0400
+
+ libaltos: Fix for Mac OS X El Capitan
+
+ USB enumeration for serial devices changed
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f10fbff6758dfcfbeeeb224f8ab02fa107aae5f6
+Author: Justin Vreeland <vreeland.justin@gmail.com>
+Date: Thu Apr 21 08:30:10 2016 -0400
+
+ Fix java class differing only by case
+
+ OSX and Windows cannot handle files with names differing only by
+ case. When these files are present in either there's a constant
+ unfixable change viewable in git status and git diff.
+
+ Since this code can be run and compiled on both platforms
+ names different only by case should be avoided.
+
+ Signed-off-by: Justin Vreeland <vreeland.justin@gmail.com>
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c989237366ada094cdc817f50b7f58bbcf5b377a
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Apr 21 21:11:29 2016 -0400
+
+ Prepare for new Android release by updating version number
+
+ 10->11
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 18b10ddf0e713431cb3e1065e62b0e6f597ce9d7
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Apr 21 21:12:06 2016 -0400
+
+ AltosDroid play store keys have moved, update configure.ac
+
+ The actual build files were already updated, but the configure.ac bits
+ which detect that they are available were not.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 21d176f161b90f18f236ef887cef9676d712eee3
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Apr 21 21:12:40 2016 -0400
+
+ Update java library version numbers
+
+ Prepare for 1.6.3 release.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4db6074bb15c66bd23c513e1e41b408e5408cff8
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Apr 19 23:19:59 2016 -0400
+
+ altos: avoid mixed declarations and code in ao_task.c
+
+ sdcc can't handle this.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 09acb6821ab490d69f679a195e70acb4a71ba342
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Apr 19 23:18:46 2016 -0400
+
+ altoslib: switch from keySet() to keys() in altos map tiles
+
+ Android appears to not have the keySet() API in the same way that
+ regular java does, so use the alternate older keys() api instead.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 49c3e3dffe748d0d155d4876efcaf7d39e1cc8e3
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Apr 19 23:17:50 2016 -0400
+
+ altoslib: Make AltosGPSSat implement Serializable
+
+ This is required to save state values in AltosDroid.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 45bcf595d0a6a6001459f7f2055cd15e4839550b
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Apr 19 23:17:01 2016 -0400
+
+ altoslib: Add debugging to AltosPreferences.state() etc
+
+ This let me find why AltosDroid was losing the last state information
+ for each target.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 90ba010aaa84a7d8b93c63543568a16ab0cb5984
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Apr 19 23:15:26 2016 -0400
+
+ altosdroid: Don't set target location if lat/lon is MISSING
+
+ Otherwise, we get a nice pointer to some random location on the planet.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit fd0ca040a5cccae18145bd29b3e4c09f14df3865
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Apr 13 06:14:33 2016 -0700
+
+ altos/telefiretwo-v0.2: Change alarm names in comment
+
+ The PCB is labeled 'A' and 'B'.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3abc0fc5e4484d862709501133d35563aa0c25fa
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Apr 13 06:11:44 2016 -0700
+
+ altos/stmf0: Fix external interrupts
+
+ Missing a reserved address in the registers broke everything nicely,
+ but the priority values were also wrong - stm32f0 exposes 8 bits per
+ priority, like the stm32l, but it uses only the top two bits.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 14fecd672807982ce6232fa3b4bdce0aebe132e8
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Apr 6 22:32:36 2016 -0700
+
+ Add TeleFireTwo v0.2 project
+
+ This is much like TeleFireTwo v0.1, with only one pyro channel and
+ added siren and strobe
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 70e46100acf597014ce54cf3b642254ce1cba59b
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Apr 5 23:45:52 2016 -0700
+
+ altos/telelcotwo: Add idle timeout
+
+ Puts TeleLCOTwo in a low power state (drawing about 80µA) after a
+ timeout (default two minutes) to keep from killing the battery if the
+ device is left turned on.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit aef5049cf8311927fada922730f85f31c8ddf177
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Dec 25 20:46:40 2015 -0800
+
+ altos: Use simpler debounce logic for buttons
+
+ Instead of waiting for a while after the transition to decide if it
+ has stuck, signal the event right away and then ignore other
+ transitions for the debounce interval.
+
+ This seems to work just as reliably, but has the benefit of
+ eliminating button latency at press time.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4c2a7503373c0584de77f9b0e5632a58ab8bbd1f
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Dec 25 11:26:34 2015 -0800
+
+ altos: Add ao_lco_two.c; alternate LCO interface code
+
+ The LCO interface is likely to end up very device specific as the
+ interactions depends on the input devices. Here's a version for
+ TeleLCOTwo, which has two arming switches and a firing button.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 26023cfbf7e117114a4d62b7dbfc0f907efdfb47
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Dec 21 21:52:31 2015 -0800
+
+ altos: Fix telefiretwo .gitignore
+
+ Was ignoring the wrong built files
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 11f8ab90d2267715010e652d709beec363f74ed5
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Dec 21 21:50:43 2015 -0800
+
+ altos: Add TeleLCOTwo firmware
+
+ The LCO side of a two-channel launch controller setup.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e6bad553009704af69b08b4a22fb5eb8ac6921f8
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Dec 21 21:48:37 2015 -0800
+
+ altos: Support pad/lco boxes with fixed box numbers
+
+ This allows for a configuration without adjustable box numbers on
+ either end of the link, simplifying the UI.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 93100ae8d4c8bd8fd6bdeff2cdc87b613c5d8058
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Dec 21 21:47:10 2015 -0800
+
+ altos: Allow for pad boxes with different sensor configurations
+
+ This allows for a pad box without a resistor from power to each
+ FET. That resistor is needed to detect welded relays, but in a
+ solid-state system, that's not a possibility.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f2038dd2cfed5bbf049144172e3f7436b6cd3a55
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Dec 17 19:54:23 2015 -0800
+
+ altos: telefiretwo-v0.1 bits
+
+ Get this board running.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 26ce7a9a213bdd35a13937054988e7b8fa749632
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Dec 17 19:30:35 2015 -0800
+
+ altos: Add pad support for new telefire versions
+
+ Makes the voltage divider values configurable, and allows for pyro
+ channels that don't have the resistors necessary to check for a stuck
+ relay.
+
+ Also supports STM32L processors with wider GPIO registers, and uses
+ the new ao_gpio_set/clr_bits functions to fire igniters rather than
+ cc1111-specific code.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 553c89f8c64398cb1a815b1fa248980cd3f62ef8
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Dec 17 19:29:36 2015 -0800
+
+ altos: Support telefire products in cc1200 driver
+
+ Need to disable the pad code while testing the radio.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b8a19e83b7b1b8e2a1fcbdd58e41f9f974ae28ff
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Apr 13 06:16:01 2016 -0700
+
+ altos/detherm: Add servo driver
+
+ This just provides commands to test the servo with.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit cfb91ec7ef6ef485d813af96a0f206bb7a2204dd
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Apr 5 22:03:37 2016 -0700
+
+ altos/detherm: Add ms5607 to detherm
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8da29480a2fdf890d553b30eab58fc884210c1a5
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Dec 23 23:15:16 2015 -0800
+
+ altos: Add easy mini plotting helper in test code
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e3f0c5eb8e5d57cbd8882587477d1381e2a83226
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Dec 17 19:27:42 2015 -0800
+
+ altos: Add ao_gpi_set/clr_bits functions
+
+ These set or clear a group of bits in a single GPIO register all together.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 097c156b13ae975c742f294b46429e8ff14c365b
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 2 22:41:06 2016 -0700
+
+ altos/stmf0: Add pwm and exti drivers
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0f227683e29062224a612c4a2ab5c8b2fc166059
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 2 22:40:23 2016 -0700
+
+ altos: Add detherm product
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit eeceee3520fae66b35a9a9b39c866c1c2e3b0c9a
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 2 19:44:06 2016 -0700
+
+ doc: Note that EasyMega and TeleMega report A-D continuity
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f95c781bc16d332ea5442590521074396d6981ae
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 2 19:43:32 2016 -0700
+
+ altos/stmf0: Support HPE clock source
+
+ Allows the use of crystals instead of requiring USB.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9f9d77b6d025d8285e362e53a8f728ec47adb234
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 2 19:42:44 2016 -0700
+
+ altos/stmf0: Add SPI driver.
+
+ This also changes the DMA interface a bit so we can select for
+ interrupts on only the interesting channels.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f5e6caab78f4ca0e5c8a2d96ef53b8752d64f4b3
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 2 19:41:21 2016 -0700
+
+ altos: Use mini logging for detherm, just without ADC
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6ead4c570a264afdc4e45eed6e87bf541668be6f
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 2 19:40:19 2016 -0700
+
+ altos: Add Detherm log format (easymini without ADC)
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0ee235e1126f34987522fe852ba6ab3ac92d6cfd
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 2 19:39:07 2016 -0700
+
+ altos: Allow for flight hardware without any ADC values
+
+ Detherm has no ADC connections, so we don't need to disable the ADC
+ when going to landed state.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7348cc4736c9a94f9ad299edd78199b544d0e95a
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Mar 24 19:25:33 2016 -0600
+
+ altos: Add one-byte SPI output routine for LPC and STM cores
+
+ This allows for SPI output at interrupt time, one byte at a time.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b31c6fd153825ae5ad0fcea7189472af1a9cffff
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Mar 24 19:28:16 2016 -0600
+
+ altos/lpc: Add fast timer
+
+ This offers a faster timer callback for higher-precision operation
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a86d98b708d84c6e0b85cb950e3f1ee16cfc56f5
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Mar 26 15:59:26 2016 -0700
+
+ altos/stm: Allow apps to define different stack size
+
+ While 512 bytes is a reasonable size, sometimes apps don't have that
+ much stack space.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4fa71ecf168e275b24534a5a20e3dd4e178c7bbd
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Mar 26 15:54:24 2016 -0700
+
+ altos/stm: Validate current task SP in interrupt by looking at PSP
+
+ We use a separate stack pointer for task code, which means we can
+ verify that it is in range in any interrupt handler. This adds checks
+ for the task stack (under #ifdef DEBUG) that run in ao_wakeup as well
+ as at every timer interrupt.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6a9546413d6a236c010e806b50506d870961d074
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Mar 26 15:49:59 2016 -0700
+
+ altos/stm: Run scheduler code on interrupt stack
+
+ This provides a bit more room for tasks on their stack
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 55db3b3e8addaa2dc0af50470d3bc8c25cb57df3
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Mar 21 22:28:39 2016 -0600
+
+ altosui,telegps: Do not allow radio calibration to be edited
+
+ This leads to sorrow for almost everyone. If you want to edit this,
+ use a terminal program.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c61014914c80ad0dba72224109d9b147bb343562
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Mar 26 15:57:59 2016 -0700
+
+ altosuilib: Control map debugging output with Serial.debug
+
+ This uses the same debug control as the serial output to monitor map downloading
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4f8a325949ed3cece4b646c808ad68677b16d1b6
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Mar 26 15:57:21 2016 -0700
+
+ altoslib: use env var LAUNCH_SITES to override default URL
+
+ This makes it easier to debug new launch site data before uploading.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2fc47e7052a08de464f08d890e222afd7dec75d8
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Mar 20 23:11:49 2016 -0700
+
+ libaltos: Fix warning in linux libaltos code
+
+ Just returned the wrong name of the value
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4dddf0a9134690d94217ad12bc7372683276f8ba
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Mar 20 22:01:07 2016 -0700
+
+ altosuilib: Note that Windows now supports Bluetooth
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 054f2896b98a14051e0b818090f2de178bb77283
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Mar 20 21:54:08 2016 -0700
+
+ altosui: Delay between polling for igniter status in Fire Igniters
+
+ This gives a remote like time to report the full status instead of
+ sending another request before the reply has been processed.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1594691ea88ca84634eea237ac8137a5bdc19f5c
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Mar 20 21:52:53 2016 -0700
+
+ libaltos: Add Windows BT support. Split into separate source files.
+
+ Add Bluetooth support to Windows. Split libaltos into separate files.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit afba05c41f30c9273668d5ed71e0dc8c1ca53141
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Mar 18 11:17:46 2016 -0700
+
+ ao-bringup: Use dfu-util to install flash loader on chaoskey
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4635203e9be530f53b697ac0349838916e146983
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Mar 18 11:16:59 2016 -0700
+
+ altos/stmf0: Construct .bin files for flash loaders
+
+ This builds a .bin file which can be used with dfu-util instead of
+ using openocd to load the initial flash loader.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f393482ec47e857db654fa071d4df95e98dab381
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Mar 18 11:15:57 2016 -0700
+
+ ao-tools: Add ao-makebin
+
+ This constructs a raw binary or DFU format file for use with dfu-util,
+ which can be used with a bare STM processor to load code before the
+ boot loader is available.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1d7f88bf7521fa6d301da072f95f97fa42d9d247
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Mar 18 10:52:03 2016 -0700
+
+ ao-tools/lib: Add ao_hex_image_cat function
+
+ This takes two images and constructs a third containing the union of
+ the contents along with 0xff bytes for any area between them.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4e738dff6dec4685b8712d3e96742971fa39c8f1
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Mar 18 10:51:20 2016 -0700
+
+ ao-tools/lib: Remove trailing whitespace from ao-elf.c
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 45d61b79665197ff99f415cda7bd5907830233e9
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Mar 18 10:50:32 2016 -0700
+
+ ao-tools/ao-dump-up: Remove spurious flight state strings
+
+ MicroPeak doesn't have flight states like this...
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 25cdbf15e7284eb963070b28dd886aa299af6487
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Mar 18 10:48:49 2016 -0700
+
+ Change how we detect and install java
+
+ Detect by finding 'javaw.exe' in the current path and extracting the
+ version from the program itself.
+
+ Install by simply opening the web browser to java.com and letting the
+ user install it themselves.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a7c7e10b3bbfbdf9667d071634cdd6fdf12a1f85
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Mar 18 10:17:24 2016 -0700
+
+ altos: Expose fast timer API from kernel/
+
+ This allows multiple SoCs to provide the same driver interface
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d1af180c2d2a2caf1e13f00d83f2b86ba26de27f
+Author: Bart Massey <bart@cs.pdx.edu>
+Date: Sat Mar 5 17:38:19 2016 -0800
+
+ altos: Fixed timing of panic display LED to be readable
+
+ When we don't have a beeper, there's no way to signal a 'warble' for
+ panic. So, elide that bit.
+
+ Second, panic can't use the scheduler and timer because those may not
+ be running (or may have failed), and so it uses a delay loop. Add a
+ configurable scale value to the panic loop so that the LED blinks can
+ be read. For stm32f0 devices, scale that by the sysclk value to
+ automatically make them of reasonable length.
+
+commit 20d9286402b7da74fef9b7c98e79d13671f6c82b
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Mar 6 15:05:51 2016 -0800
+
+ libaltos: Add unistd.h to get defines for various syscalls
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ad07578d04926cb4b96c40a446c47ad3f9bad7df
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Mar 6 15:04:23 2016 -0800
+
+ libaltos: jni_md.h moved to linux subdir in Java install
+
+ Add the linux subdir to CFLAGS to find it.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7cb388a33104fd78c8cb1fa08a6f114e3e1e372d
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Mar 5 14:37:40 2016 -0800
+
+ altos/stmf0: Fix build without second USB IN endpoint
+
+ The code for the second IN endpoint was using the wrong ifdef.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 99d3248a390379cfabf821ea4a195072799861eb
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Mar 2 14:36:31 2016 -0800
+
+ ao-tools: Add ao-chaosread
+
+ This reads from the raw descriptor to help validate the hardware.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 88ee4ac0c91e12a02cc1954ffad0fd8603e24e55
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Mar 2 14:01:00 2016 -0800
+
+ ao-bringup: Switch to v1.0 for chaoskey
+
+ Not going to build any more v0.1 boards. Also, chaoskey now uses the
+ unique ID for a serial, so we don't need to provide a serial number.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3a355d5c84e9d975897fa69a103952a1f1558947
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Mar 2 14:00:06 2016 -0800
+
+ altos: Add ChaosKey v1.0 product
+
+ Much like ChaosKey v0.1, just different SoC package and a few wiring changes.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 05fcb717bfc44aba3c1cfd43281e323505a46402
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Mar 2 13:54:58 2016 -0800
+
+ altos/chaoskey: Add another USB endpoint to read raw data
+
+ This replaces having the single output switch based on a pin value and
+ allows us to box the device and still fetch raw data.
+
+ For now, this will use a special libusb2 program, ao-chaosread, to
+ pull bits as I haven't figure out how to make linux provide two
+ /dev entries for one USB device.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 05354b8fee6a9af05d66bb7f4761f597da038fdd
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Feb 15 15:26:00 2016 -0800
+
+ altos/chaoskey: Use SoC device ID as serial number
+
+ To make manufacturing these devices tractable, we don't want to
+ require a custom firmware load for each device, but we still want a
+ unique serial number. Fortunately, the SoC provides a 96-bit ID which
+ we can use.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5637c1b2fd7232842245af1437e33b5bb1583c7d
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Feb 15 15:24:35 2016 -0800
+
+ altos/stmf0: Use device ID as usb serial number if requested
+
+ This exposes the hardware device ID (which is unique per-chip) as the
+ USB serial number, avoiding the need to create a custom ROM image for
+ each device.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e4006444d3d7b0c499139f58f13353988d38dbb4
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Feb 15 15:23:15 2016 -0800
+
+ altos/chaoskey: Encode both hardware and software versions in product ID
+
+ We have no other way of reporting the software version, so just encode
+ it in the product ID.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit afef70bb8f31075de364ddf713f3ccf1d9c6361d
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Feb 15 14:04:04 2016 -0800
+
+ altos/stmf0: Fix location of device_id register
+
+ Copied from stm32l and never fixed.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0bae4b25882983cd0b7950b3e80b6d93a72f0847
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Feb 8 19:15:31 2016 -0800
+
+ altos: Another fix for non CDC-ACM devices
+
+ Need to set the bInterfaceNumber for the actual interface to zero when
+ there isn't an INT interface before it.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e36117ccbf7cbe3704c6b44d3ad429e720a1e16c
+Author: Bart Massey <bart.massey@gmail.com>
+Date: Mon Feb 8 18:55:28 2016 -0800
+
+ Clean up stmf0 adc init.
+
+ This better matches the documented cal sequence.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5ce26345784459f5864ef59c96c8aa633d2ddf64
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Feb 7 22:30:27 2016 -0800
+
+ altos/stmf0: Add missing ao_gpio.c
+
+ This contains the code for power managing the GPIO pins
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit bab082605e3fca6b6d11447c45cd948ddfe74bb9
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Feb 7 22:28:34 2016 -0800
+
+ altos: Add simple stats test to TRNG code
+
+ This detects broken hardware by making sure the standard deviation in
+ the raw values used to compute each buffer is at least 128.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 147f0df6a29b37fbfb0824ecd276482f0eecb397
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Feb 7 15:33:42 2016 -0800
+
+ altos: Delay TRNG ADC long enough for HV supply to stabilize
+
+ Looks like it takes about 70ms for the supply to start running right,
+ so delay after powering it up for that long.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1473f9234ffd34d8f37bc489dfc9fc4d7f1b3eed
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Feb 7 00:15:47 2016 +1100
+
+ altos/chaoskey-v0.1: Add power management and change USB classes
+
+ Enable power management.
+ Expose only a single IN endpoint.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 235198b85f1583d2792c7028decace61d1b4229e
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Feb 7 00:14:22 2016 +1100
+
+ altos: Add power management to TRNG driver
+
+ Support suspend/resume of the TRNG power supply, delaying after resume
+ to wait for it to stabilize.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2ad756bd1b63a2c8450edd7001628b92279fd1b8
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Feb 7 00:10:57 2016 +1100
+
+ altos: Allow USB drivers to skip CDC-ACM -specific descriptors
+
+ For devices not providing the standard CDC-ACM interface, let them
+ skip the various descriptors and interfaces to provide a more limited
+ set of capabilities.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a5607aad694c01c01c48229172b289f005a1b6bb
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Feb 6 22:51:32 2016 +1100
+
+ altos/stmf0: Add suspend/resume support
+
+ Allow USB suspend to suspend USB, GPIOs and master clock.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 36c6d74048283d27c890054814eee2cb39b7cbb7
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Feb 6 22:47:23 2016 +1100
+
+ altos: Add power management APIs
+
+ This provides sequenced suspend/resume functionality, allowing modules
+ to register for power management at configuration time.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit fbb07cf50ba7fa278d1f8201ef376ec12480e9aa
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jan 19 23:55:52 2016 -0800
+
+ altos/stmf0: Allow projects to specify non-default stack size
+
+ 512 may not be suitable for everyone.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1d7463befc18f415d8982f04e52729d3bf5b95a9
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jan 19 23:55:32 2016 -0800
+
+ altos: remove blank line in stmf0/ao_timer.c
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 35407e664886bed21dcef7764843aac03be8490c
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jan 28 13:58:43 2016 -0800
+
+ altos/chaoskey: Delay ADC reading for 250ms at startup
+
+ This lets the HV supply stabilize before we start sampling values.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f2d3202de9a5847923f72afe2969eb7ccd7342c7
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jan 28 00:14:36 2016 -0800
+
+ altos/chaoskey: Add support for flipping between raw and cooked bits
+
+ Plug the 'force bootloader' thing onto the board while it's running
+ and it will generate raw bits instead of running them through the CRC
+ to whiten. Useful for validating the raw hardware.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 02fd767ab60a9957faa2bff29c62ed954abc34e7
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jan 19 18:30:57 2016 -0800
+
+ src/chaoskey-v0.1: Add HV enable support
+
+ Turn on the HV supply when the OS starts.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e5be0be35f724507d7efff48339a297df73d2641
+Author: Robert Garbee <robert@gag.com>
+Date: Sat Jan 16 10:19:47 2016 -0700
+
+ fix argument to ao-cal-freq so devices other than /dev/ttyACM0 work
+
+commit 6a7644a0d179e1eb7d665123157ad76c956e524a
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Jan 10 21:39:38 2016 -0800
+
+ Releasing: Copy TeleMega v2.0 bits to Binaries
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b53c78e75879d647935a30acb88fdd69467617a7
+Merge: a2ea621 64adfbb
+Author: Bdale Garbee <bdale@gag.com>
+Date: Sun Jan 10 19:15:16 2016 -0700
+
+ Merge branch 'master' into branch-1.6
+
+commit 64adfbbb80c90dfe244179d81beaef8a84ed8bd6
+Author: Bdale Garbee <bdale@gag.com>
+Date: Thu Jul 16 14:47:10 2015 -0600
+
+ process updates from 1.6.1 release
+
+commit a2ea621eac3263348aff50885c79296f8ece26ed
+Author: Bdale Garbee <bdale@gag.com>
+Date: Sun Jan 10 19:08:12 2016 -0700
+
+ update Changelog from git log
+
commit 1681776abc0873bcbbbc5b2b17e15d54a1031f51
Merge: 8830926 aebdcaf
Author: Bdale Garbee <bdale@gag.com>
diff --git a/Makefile.am b/Makefile.am
index e4b9664b..0bb01619 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -38,9 +38,13 @@ fat_windows = \
telegps/TeleGPS-Windows-$(VERSION_DASH).exe \
micropeak/MicroPeak-Windows-$(VERSION_DASH).exe
+fat_android = \
+ altosdroid/bin/AltosDroid-debug.apk \
+ altosdroid/bin/AltosDroid-release.apk
+
keithp-fat: fat
ssh keithp.com mkdir -p public_html/altos-$(VERSION)
- scp -p $(fat_linux) $(fat_mac) $(fat_windows) keithp.com:public_html/altos-$(VERSION)
+ scp -p $(fat_linux) $(fat_mac) $(fat_windows) $(fat_android) keithp.com:public_html/altos-$(VERSION)
set-java-versions:
$(top_srcdir)/fix-java-versions org.altusmetrum.altoslib=$(ALTOSLIB_VERSION) org.altusmetrum.altosuilib=$(ALTOSUILIB_VERSION)
diff --git a/Releasing b/Releasing
index a570645a..fd522797 100644
--- a/Releasing
+++ b/Releasing
@@ -74,6 +74,7 @@ These are Bdale's notes on how to do a release.
src/teledongle-v3.0/*.elf \
src/telegps-v1.0/*.elf \
src/telemega-v1.0/*.elf \
+ src/telemega-v2.0/*.elf \
src/telemetrum-v2.0/*.elf \
~/altusmetrumllc/Binaries/
cp src/easymega-v1.0/flash-loader/*.elf \
@@ -82,6 +83,7 @@ These are Bdale's notes on how to do a release.
src/teledongle-v3.0/flash-loader/*.elf \
src/telegps-v1.0/flash-loader/*.elf \
src/telemega-v1.0/flash-loader/*.elf \
+ src/telemega-v2.0/flash-loader/*.elf \
src/telemetrum-v2.0/flash-loader/*.elf \
~/altusmetrumllc/Binaries/loaders/
(cd ~/altusmetrumllc ; git add Binaries ; git commit -a)
diff --git a/altosdroid/.gitignore b/altosdroid/.gitignore
index 7f0858ea..cf7ad5a8 100644
--- a/altosdroid/.gitignore
+++ b/altosdroid/.gitignore
@@ -5,3 +5,4 @@ libs
google-play-services_lib
src/org/altusmetrum/AltosDroid/BuildInfo.java
res/drawable/*led.png
+AndroidManifest.xml
diff --git a/altosdroid/AndroidManifest.xml.in b/altosdroid/AndroidManifest.xml.in
index 24035796..2644d747 100644
--- a/altosdroid/AndroidManifest.xml.in
+++ b/altosdroid/AndroidManifest.xml.in
@@ -39,7 +39,7 @@
<uses-permission android:name="org.altusmetrum.AltosDroid.permission.MAPS_RECEIVE"/>
<!-- Permissions needed to access USB OTG -->
- <uses-feature android:name="android.hardware.usb.host" />
+ <uses-feature android:name="android.hardware.usb.host" android:required="false" />
<application android:label="@string/app_name"
android:icon="@drawable/app_icon"
@@ -82,10 +82,30 @@
android:theme="@android:style/Theme.Dialog"
android:configChanges="orientation|keyboardHidden" />
+ <activity android:name=".IdleModeActivity"
+ android:label="@string/idle_mode"
+ android:theme="@android:style/Theme.Dialog"
+ android:configChanges="orientation|keyboardHidden" />
+
+ <activity android:name=".IgniterActivity"
+ android:label="@string/igniters"
+ android:theme="@android:style/Theme.Dialog"
+ android:configChanges="orientation|keyboardHidden" />
+
+ <activity android:name=".SetupActivity"
+ android:label="@string/setup"
+ android:theme="@android:style/Theme.Dialog"
+ android:configChanges="orientation" />
+
+ <activity android:name=".ManageFrequenciesActivity"
+ android:label="@string/manage_frequencies"
+ android:theme="@android:style/Theme.Dialog"
+ android:configChanges="orientation|keyboard" />
+
<service android:name=".TelemetryService" />
<meta-data android:name="com.google.android.maps.v2.API_KEY"
- android:value="AIzaSyDSr6u4i9TJmVGhgGk4g0wUUhTy9FGyn0s"/>
+ android:value="@GOOGLEKEY@"/>
<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
</application>
diff --git a/altosdroid/Makefile.am b/altosdroid/Makefile.am
index 26e14ee7..295abbc5 100644
--- a/altosdroid/Makefile.am
+++ b/altosdroid/Makefile.am
@@ -47,7 +47,7 @@ DRAWABLES=\
LAYOUTS=$(LAYOUT_DIR)/*.xml
MENUS=$(MENU_DIR)/*.xml
VALUES=$(VALUES_DIR)/*.xml
-XMLS=$(XML_DIR)/*.xml
+XMLS=$(XML_DIR)/*.xml AndroidManifest.xml
RES=$(LAYOUTS) $(MENUS) $(VALUES) $(XMLS)
diff --git a/altosdroid/res/layout/device_list.xml b/altosdroid/res/layout/device_list.xml
index bf295e4c..57e5501e 100644
--- a/altosdroid/res/layout/device_list.xml
+++ b/altosdroid/res/layout/device_list.xml
@@ -1,17 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!--
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Copyright © 2016 Keith Packard <keithp@keithp.com>
- http://www.apache.org/licenses/LICENSE-2.0
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
diff --git a/altosdroid/res/layout/frequency.xml b/altosdroid/res/layout/frequency.xml
new file mode 100644
index 00000000..7f8d4041
--- /dev/null
+++ b/altosdroid/res/layout/frequency.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright © 2016 Keith Packard <keithp@keithp.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+
+-->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="horizontal"
+ >
+ <TextView
+ android:id="@+id/frequency"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:padding="10dp"
+ android:layout_weight="1"
+ />
+</LinearLayout>
diff --git a/altosdroid/res/layout/idle_mode.xml b/altosdroid/res/layout/idle_mode.xml
new file mode 100644
index 00000000..d6a05fbb
--- /dev/null
+++ b/altosdroid/res/layout/idle_mode.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright © 2016 Keith Packard <keithp@keithp.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ >
+ <TextView android:id="@+id/set_callsign_label"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/set_callsign_label"
+ />
+ <EditText android:id="@+id/set_callsign"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:hint="@string/set_callsign_label"/>
+ <Button android:id="@+id/connect_idle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/connect_idle"
+ />
+ <Button android:id="@+id/disconnect_idle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/disconnect_idle"
+ />
+ <Button android:id="@+id/reboot_idle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/reboot_idle"
+ />
+ <Button android:id="@+id/igniters_idle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/igniters_idle"
+ />
+</LinearLayout>
diff --git a/altosdroid/res/layout/igniter_status.xml b/altosdroid/res/layout/igniter_status.xml
new file mode 100644
index 00000000..298f9155
--- /dev/null
+++ b/altosdroid/res/layout/igniter_status.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright © 2016 Keith Packard <keithp@keithp.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+
+-->
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+ <TextView
+ android:id="@+id/igniter_status"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:padding="10dp"
+ android:layout_alignParentRight="true"
+ />
+ <TextView
+ android:id="@+id/igniter_name"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:padding="10dp"
+ android:layout_alignParentLeft="@+id/igniter_status"
+ />
+</RelativeLayout>
diff --git a/altosdroid/res/layout/igniters.xml b/altosdroid/res/layout/igniters.xml
new file mode 100644
index 00000000..350a1e58
--- /dev/null
+++ b/altosdroid/res/layout/igniters.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright © 2016 Keith Packard <keithp@keithp.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ >
+
+ <ListView android:id="@+id/igniters"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:fadeScrollbars="false"
+ android:scrollbars="vertical"
+ android:choiceMode="singleChoice"
+ />
+
+ <ToggleButton android:id="@+id/igniter_arm"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textOn="@string/igniter_armed"
+ android:textOff="@string/igniter_arm"
+ />
+
+ <Button android:id="@+id/igniter_fire"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/igniter_fire"
+ />
+
+</LinearLayout>
diff --git a/altosdroid/res/layout/manage_frequencies.xml b/altosdroid/res/layout/manage_frequencies.xml
new file mode 100644
index 00000000..77ded1d9
--- /dev/null
+++ b/altosdroid/res/layout/manage_frequencies.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright © 2016 Keith Packard <keithp@keithp.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ >
+
+ <LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/set_layout"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ >
+ <EditText
+ android:id="@+id/set_frequency"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:padding="10dp"
+ android:layout_weight="1"
+ android:hint="@string/frequency"
+ android:inputType="number|numberDecimal"/>
+ />
+ <TextView
+ android:id="@+id/mhz"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:padding="10dp"
+ android:layout_weight="0"
+ android:text="@string/mhz"
+ />
+ <EditText
+ android:id="@+id/set_description"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:padding="10dp"
+ android:layout_weight="2"
+ android:hint="@string/description"
+ />
+ </LinearLayout>
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ >
+ <Button android:id="@+id/set"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/set"
+ android:layout_weight="1"
+ />
+
+ <Button android:id="@+id/remove"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/remove"
+ android:layout_weight="1"
+ />
+
+ <Button android:id="@+id/done"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/done"
+ android:layout_weight="1"
+ />
+ </LinearLayout>
+
+ <ListView android:id="@+id/frequencies"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:fadeScrollbars="false"
+ android:scrollbars="vertical"
+ android:choiceMode="singleChoice"
+ />
+
+
+</LinearLayout>
diff --git a/altosdroid/res/layout/setup.xml b/altosdroid/res/layout/setup.xml
new file mode 100644
index 00000000..630378a1
--- /dev/null
+++ b/altosdroid/res/layout/setup.xml
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright © 2016 Keith Packard <keithp@keithp.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ >
+ <TableLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:stretchColumns="2,3"
+ android:layout_weight="0"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TableRow
+ android:layout_gravity="center"
+ android:layout_weight="1"
+ android:padding="2dip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <TextView
+ android:id="@+id/select_rate_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/telemetry_rate"
+ />
+ <Spinner android:id="@+id/select_rate"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:prompt="@string/telemetry_rate"
+ android:spinnerMode="dropdown"
+ />
+ </TableRow>
+ <TableRow
+ android:layout_gravity="center"
+ android:layout_weight="1"
+ android:padding="2dip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <TextView
+ android:id="@+id/set_units_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/set_units"
+ />
+ <Spinner android:id="@+id/set_units"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:prompt="@string/set_units"
+ android:spinnerMode="dropdown"
+ />
+ </TableRow>
+ <TableRow
+ android:layout_gravity="center"
+ android:layout_weight="1"
+ android:padding="2dip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <TextView
+ android:id="@+id/map_type_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/map_type"
+ />
+ <Spinner android:id="@+id/map_type"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:prompt="@string/map_type"
+ android:spinnerMode="dropdown"
+ />
+ </TableRow>
+ <TableRow
+ android:layout_gravity="center"
+ android:layout_weight="1"
+ android:padding="2dip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <TextView
+ android:id="@+id/map_source_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/map_source"
+ />
+ <Spinner android:id="@+id/map_source"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:prompt="@string/map_source"
+ android:spinnerMode="dropdown"
+ />
+ </TableRow>
+ </TableLayout>
+ <Button android:id="@+id/preload_maps"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/preload_maps"
+ />
+ <Button android:id="@+id/manage_frequencies"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/manage_frequencies"
+ />
+ <Button android:id="@+id/done"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/done"
+ />
+</LinearLayout>
diff --git a/altosdroid/res/menu/option_menu.xml b/altosdroid/res/menu/option_menu.xml
index 7e08c803..b2ca01a4 100644
--- a/altosdroid/res/menu/option_menu.xml
+++ b/altosdroid/res/menu/option_menu.xml
@@ -25,27 +25,21 @@
<item android:id="@+id/select_freq"
android:icon="@android:drawable/ic_menu_preferences"
android:title="@string/select_freq" />
- <item android:id="@+id/select_rate"
- android:icon="@android:drawable/ic_menu_preferences"
- android:title="@string/select_rate" />
- <item android:id="@+id/change_units"
- android:icon="@android:drawable/ic_menu_view"
- android:title="@string/change_units" />
- <item android:id="@+id/preload_maps"
- android:icon="@android:drawable/ic_menu_mapmode"
- android:title="@string/preload_maps" />
- <item android:id="@+id/map_type"
- android:icon="@android:drawable/ic_menu_mapmode"
- android:title="@string/map_type" />
- <item android:id="@+id/map_source"
- android:icon="@android:drawable/ic_menu_mapmode"
- android:title="@string/map_source" />
+
<item android:id="@+id/select_tracker"
android:icon="@android:drawable/ic_menu_view"
android:title="@string/select_tracker"/>
<item android:id="@+id/delete_track"
android:icon="@android:drawable/ic_notification_clear_all"
android:title="@string/delete_track"/>
+
+ <item android:id="@+id/setup"
+ android:icon="@android:drawable/ic_menu_preferences"
+ android:title="@string/setup" />
+ <item android:id="@+id/idle_mode"
+ android:icon="@android:drawable/ic_menu_preferences"
+ android:title="@string/idle_mode" />
+
<item android:id="@+id/quit"
android:icon="@android:drawable/ic_menu_close_clear_cancel"
android:title="@string/quit" />
diff --git a/altosdroid/res/values/strings.xml b/altosdroid/res/values/strings.xml
index e7014fc9..4380d62d 100644
--- a/altosdroid/res/values/strings.xml
+++ b/altosdroid/res/values/strings.xml
@@ -29,6 +29,7 @@
<string name="connect_device">Connect a device</string>
<string name="disconnect_device">Disconnect device</string>
<string name="quit">Quit</string>
+ <string name="setup">Setup</string>
<string name="select_freq">Select radio frequency</string>
<string name="select_rate">Select data rate</string>
<string name="change_units">Change units</string>
@@ -111,4 +112,35 @@
<string name="preload_radius">Radius</string>
<string name="preload_load">Load Map</string>
+
+ <!-- Idle mode -->
+ <string name="idle_mode">Idle Mode</string>
+ <string name="set_callsign_label">Callsign</string>
+ <string name="connect_idle">Monitor</string>
+ <string name="disconnect_idle">Disconnect</string>
+ <string name="reboot_idle">Reboot</string>
+ <string name="igniters_idle">Fire Igniters</string>
+
+ <!-- igniters -->
+ <string name="igniters">Igniters</string>
+ <string name="igniter_arm">Arm</string>
+ <string name="igniter_armed">Armed</string>
+ <string name="igniter_fire">Fire</string>
+
+ <!-- setup -->
+ <string name="telemetry_rate">Telemetry Rate</string>
+ <string name="set_units">Units</string>
+ <string name="map_type">Map Type</string>
+ <string name="map_source">Map Source</string>
+ <string name="preload_maps">Preload Maps</string>
+ <string name="manage_frequencies">Manage Frequencies</string>
+ <string name="done">OK</string>
+
+ <!-- manage frequencies -->
+ <string name="set">Set</string>
+ <string name="mhz">MHz</string>
+ <string name="remove">Remove</string>
+ <string name="done">OK</string>
+ <string name="frequency">Frequency</string>
+ <string name="description">Description</string>
</resources>
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java
index baf38fb7..15efc0e2 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java
@@ -30,7 +30,7 @@ import android.bluetooth.BluetoothSocket;
import android.os.Handler;
//import android.os.Message;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosBluetooth extends AltosDroidLink {
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDebug.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDebug.java
index df348c9d..64980dc7 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDebug.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDebug.java
@@ -20,7 +20,7 @@ import java.util.Arrays;
import java.io.*;
import java.lang.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import android.app.Activity;
import android.graphics.*;
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java
index b26a9bc8..026e836d 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java
@@ -45,13 +45,15 @@ import android.view.*;
import android.widget.*;
import android.app.AlertDialog;
import android.location.Location;
+import android.location.LocationManager;
+import android.location.LocationListener;
import android.hardware.usb.*;
import android.graphics.*;
import android.graphics.drawable.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
-public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
+public class AltosDroid extends FragmentActivity implements AltosUnitsListener, LocationListener {
// Actions sent to the telemetry server at startup time
@@ -62,14 +64,26 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
public static final int MSG_STATE = 1;
public static final int MSG_UPDATE_AGE = 2;
+ public static final int MSG_IDLE_MODE = 3;
+ public static final int MSG_IGNITER_STATUS = 4;
// Intent request codes
public static final int REQUEST_CONNECT_DEVICE = 1;
public static final int REQUEST_ENABLE_BT = 2;
public static final int REQUEST_PRELOAD_MAPS = 3;
- public static final int REQUEST_MAP_TYPE = 4;
+ public static final int REQUEST_IDLE_MODE = 5;
+ public static final int REQUEST_IGNITERS = 6;
+ public static final int REQUEST_SETUP = 7;
- public int map_type = AltosMap.maptype_hybrid;
+ public static final String EXTRA_IDLE_MODE = "idle_mode";
+ public static final String EXTRA_IDLE_RESULT = "idle_result";
+ public static final String EXTRA_TELEMETRY_SERVICE = "telemetry_service";
+
+ // Setup result bits
+ public static final int SETUP_BAUD = 1;
+ public static final int SETUP_UNITS = 2;
+ public static final int SETUP_MAP_SOURCE = 4;
+ public static final int SETUP_MAP_TYPE = 8;
public static FragmentManager fm;
@@ -95,8 +109,9 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
// field to display the version at the bottom of the screen
private TextView mVersion;
- private double frequency;
- private int telemetry_rate;
+ private boolean idle_mode = false;
+
+ public Location location = null;
// Tabs
TabHost mTabHost;
@@ -142,6 +157,10 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
case MSG_UPDATE_AGE:
ad.update_age();
break;
+ case MSG_IDLE_MODE:
+ ad.idle_mode = (Boolean) msg.obj;
+ ad.update_state(null);
+ break;
}
}
};
@@ -212,8 +231,8 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
switch (telemetry_state.connect) {
case TelemetryState.CONNECT_CONNECTED:
if (telemetry_state.config != null) {
- String str = String.format("S/N %d %6.3f MHz", telemetry_state.config.serial,
- telemetry_state.frequency);
+ String str = String.format("S/N %d %6.3f MHz%s", telemetry_state.config.serial,
+ telemetry_state.frequency, idle_mode ? " (idle)" : "");
if (telemetry_state.telemetry_rate != AltosLib.ao_telemetry_rate_38400)
str = str.concat(String.format(" %d bps",
AltosLib.ao_telemetry_rate_values[telemetry_state.telemetry_rate]));
@@ -314,7 +333,7 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
state = newest_state;
}
- update_ui(telemetry_state, state, telemetry_state.location);
+ update_ui(telemetry_state, state);
start_timer();
}
@@ -379,7 +398,7 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
}
}
- void update_ui(TelemetryState telem_state, AltosState state, Location location) {
+ void update_ui(TelemetryState telem_state, AltosState state) {
int prev_state = AltosLib.ao_flight_invalid;
@@ -440,7 +459,10 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
mCallsignView.setText(state.callsign);
}
if (saved_state == null || state.serial != saved_state.serial) {
- mSerialView.setText(String.format("%d", state.serial));
+ if (state.serial == AltosLib.MISSING)
+ mSerialView.setText("");
+ else
+ mSerialView.setText(String.format("%d", state.serial));
}
if (saved_state == null || state.flight != saved_state.flight) {
if (state.flight == AltosLib.MISSING)
@@ -457,7 +479,10 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
}
}
if (saved_state == null || state.rssi != saved_state.rssi) {
- mRSSIView.setText(String.format("%d", state.rssi));
+ if (state.rssi == AltosLib.MISSING)
+ mRSSIView.setText("");
+ else
+ mRSSIView.setText(String.format("%d", state.rssi));
}
}
@@ -510,11 +535,6 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
return tab_view;
}
- public void set_map_source(int source) {
- for (AltosDroidTab mTab : mTabs)
- mTab.set_map_source(source);
- }
-
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -560,22 +580,15 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
mAgeOldColor = getResources().getColor(R.color.old_color);
}
- private boolean ensureBluetooth() {
+ private void ensureBluetooth() {
// Get local Bluetooth adapter
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
- // If the adapter is null, then Bluetooth is not supported
- if (mBluetoothAdapter == null) {
- Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();
- return false;
- }
-
- if (!mBluetoothAdapter.isEnabled()) {
+ /* if there is a BT adapter and it isn't turned on, then turn it on */
+ if (mBluetoothAdapter != null && !mBluetoothAdapter.isEnabled()) {
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, AltosDroid.REQUEST_ENABLE_BT);
}
-
- return true;
}
private boolean check_usb() {
@@ -641,9 +654,7 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
return;
}
AltosDebug.debug("Starting by looking for bluetooth devices");
- if (ensureBluetooth())
- return;
- finish();
+ ensureBluetooth();
}
}
@@ -679,12 +690,27 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
public void onResume() {
super.onResume();
AltosDebug.debug("+ ON RESUME +");
+
+ // Listen for GPS and Network position updates
+ LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
+ locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, this);
+
+ location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
+
+ if (location != null)
+ AltosDebug.debug("Resume, location is %f,%f\n",
+ location.getLatitude(),
+ location.getLongitude());
+
+ update_ui(telemetry_state, saved_state);
}
@Override
public void onPause() {
super.onPause();
AltosDebug.debug("- ON PAUSE -");
+ // Stop listening for location updates
+ ((LocationManager) getSystemService(Context.LOCATION_SERVICE)).removeUpdates(this);
}
@Override
@@ -720,19 +746,46 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
if (resultCode == Activity.RESULT_OK) {
// Bluetooth is now enabled, so set up a chat session
//setupChat();
+ AltosDebug.debug("BT enabled");
+ bluetoothEnabled(data);
} else {
// User did not enable Bluetooth or an error occured
- AltosDebug.error("BT not enabled");
- stopService(new Intent(AltosDroid.this, TelemetryService.class));
- Toast.makeText(this, R.string.bt_not_enabled, Toast.LENGTH_SHORT).show();
- finish();
+ AltosDebug.debug("BT not enabled");
}
break;
- case REQUEST_MAP_TYPE:
+ case REQUEST_IDLE_MODE:
if (resultCode == Activity.RESULT_OK)
- set_map_type(data);
+ idle_mode(data);
+ break;
+ case REQUEST_IGNITERS:
break;
+ case REQUEST_SETUP:
+ if (resultCode == Activity.RESULT_OK)
+ note_setup_changes(data);
+ break;
+ }
+ }
+
+ private void note_setup_changes(Intent data) {
+ int changes = data.getIntExtra(SetupActivity.EXTRA_SETUP_CHANGES, 0);
+
+ if ((changes & SETUP_BAUD) != 0) {
+ try {
+ mService.send(Message.obtain(null, TelemetryService.MSG_SETBAUD,
+ AltosPreferences.telemetry_rate(1)));
+ } catch (RemoteException re) {
+ }
+ }
+ if ((changes & SETUP_UNITS) != 0) {
+ /* nothing to do here */
+ }
+ if ((changes & SETUP_MAP_SOURCE) != 0) {
+ /* nothing to do here */
}
+ if ((changes & SETUP_MAP_TYPE) != 0) {
+ /* nothing to do here */
+ }
+ set_switch_time();
}
private void connectUsb(UsbDevice device) {
@@ -749,6 +802,14 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
}
}
+ private void bluetoothEnabled(Intent data) {
+ try {
+ mService.send(Message.obtain(null, TelemetryService.MSG_BLUETOOTH_ENABLED, null));
+ } catch (RemoteException e) {
+ AltosDebug.debug("send BT enabled message failed");
+ }
+ }
+
private void connectDevice(Intent data) {
// Attempt to connect to the device
try {
@@ -771,14 +832,37 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
}
}
- private void set_map_type(Intent data) {
- int type = data.getIntExtra(MapTypeActivity.EXTRA_MAP_TYPE, -1);
+ private void idle_mode(Intent data) {
+ int type = data.getIntExtra(IdleModeActivity.EXTRA_IDLE_RESULT, -1);
+ Message msg;
- AltosDebug.debug("intent set_map_type %d\n", type);
- if (type != -1) {
- map_type = type;
- for (AltosDroidTab mTab : mTabs)
- mTab.set_map_type(map_type);
+ AltosDebug.debug("intent idle_mode %d", type);
+ switch (type) {
+ case IdleModeActivity.IDLE_MODE_CONNECT:
+ msg = Message.obtain(null, TelemetryService.MSG_MONITOR_IDLE_START);
+ try {
+ mService.send(msg);
+ } catch (RemoteException re) {
+ }
+ break;
+ case IdleModeActivity.IDLE_MODE_DISCONNECT:
+ msg = Message.obtain(null, TelemetryService.MSG_MONITOR_IDLE_STOP);
+ try {
+ mService.send(msg);
+ } catch (RemoteException re) {
+ }
+ break;
+ case IdleModeActivity.IDLE_MODE_REBOOT:
+ msg = Message.obtain(null, TelemetryService.MSG_REBOOT);
+ try {
+ mService.send(msg);
+ } catch (RemoteException re) {
+ }
+ break;
+ case IdleModeActivity.IDLE_MODE_IGNITERS:
+ Intent serverIntent = new Intent(this, IgniterActivity.class);
+ startActivityForResult(serverIntent, REQUEST_IGNITERS);
+ break;
}
}
@@ -797,11 +881,8 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
}
}
- void setFrequency(String freq) {
- try {
- setFrequency (AltosParse.parse_double_net(freq.substring(11, 17)));
- } catch (ParseException e) {
- }
+ void setFrequency(AltosFrequency frequency) {
+ setFrequency (frequency.frequency);
}
void setBaud(int baud) {
@@ -889,11 +970,10 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
Intent serverIntent = null;
switch (item.getItemId()) {
case R.id.connect_scan:
- if (ensureBluetooth()) {
- // Launch the DeviceListActivity to see devices and do scan
- serverIntent = new Intent(this, DeviceListActivity.class);
- startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
- }
+ ensureBluetooth();
+ // Launch the DeviceListActivity to see devices and do scan
+ serverIntent = new Intent(this, DeviceListActivity.class);
+ startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
return true;
case R.id.disconnect:
/* Disconnect the device
@@ -905,25 +985,21 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
disconnectDevice();
finish();
return true;
+ case R.id.setup:
+ serverIntent = new Intent(this, SetupActivity.class);
+ startActivityForResult(serverIntent, REQUEST_SETUP);
+ return true;
case R.id.select_freq:
// Set the TBT radio frequency
- final String[] frequencies = {
- "Channel 0 (434.550MHz)",
- "Channel 1 (434.650MHz)",
- "Channel 2 (434.750MHz)",
- "Channel 3 (434.850MHz)",
- "Channel 4 (434.950MHz)",
- "Channel 5 (435.050MHz)",
- "Channel 6 (435.150MHz)",
- "Channel 7 (435.250MHz)",
- "Channel 8 (435.350MHz)",
- "Channel 9 (435.450MHz)"
- };
+ final AltosFrequency[] frequencies = AltosPreferences.common_frequencies();
+ String[] frequency_strings = new String[frequencies.length];
+ for (int i = 0; i < frequencies.length; i++)
+ frequency_strings[i] = frequencies[i].toString();
AlertDialog.Builder builder_freq = new AlertDialog.Builder(this);
builder_freq.setTitle("Pick a frequency");
- builder_freq.setItems(frequencies,
+ builder_freq.setItems(frequency_strings,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
setFrequency(frequencies[item]);
@@ -932,44 +1008,6 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
AlertDialog alert_freq = builder_freq.create();
alert_freq.show();
return true;
- case R.id.select_rate:
- // Set the TBT baud rate
-
- final String[] rates = {
- "38400",
- "9600",
- "2400",
- };
-
- AlertDialog.Builder builder_rate = new AlertDialog.Builder(this);
- builder_rate.setTitle("Pick a baud rate");
- builder_rate.setItems(rates,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int item) {
- setBaud(rates[item]);
- }
- });
- AlertDialog alert_rate = builder_rate.create();
- alert_rate.show();
- return true;
- case R.id.change_units:
- boolean imperial = AltosPreferences.imperial_units();
- AltosPreferences.set_imperial_units(!imperial);
- return true;
- case R.id.preload_maps:
- serverIntent = new Intent(this, PreloadMapActivity.class);
- startActivityForResult(serverIntent, REQUEST_PRELOAD_MAPS);
- return true;
- case R.id.map_type:
- serverIntent = new Intent(this, MapTypeActivity.class);
- startActivityForResult(serverIntent, REQUEST_MAP_TYPE);
- return true;
- case R.id.map_source:
- int source = AltosDroidPreferences.map_source();
- int new_source = source == AltosDroidPreferences.MAP_SOURCE_ONLINE ? AltosDroidPreferences.MAP_SOURCE_OFFLINE : AltosDroidPreferences.MAP_SOURCE_ONLINE;
- AltosDroidPreferences.set_map_source(new_source);
- set_map_source(new_source);
- return true;
case R.id.select_tracker:
if (serials != null) {
String[] trackers = new String[serials.length+1];
@@ -1010,12 +1048,17 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
}
return true;
+ case R.id.idle_mode:
+ serverIntent = new Intent(this, IdleModeActivity.class);
+ serverIntent.putExtra(EXTRA_IDLE_MODE, idle_mode);
+ startActivityForResult(serverIntent, REQUEST_IDLE_MODE);
+ return true;
}
return false;
}
static String direction(AltosGreatCircle from_receiver,
- Location receiver) {
+ Location receiver) {
if (from_receiver == null)
return null;
@@ -1044,4 +1087,24 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
else
return String.format("right %d°", iheading);
}
+
+ public void onLocationChanged(Location location) {
+ this.location = location;
+ AltosDebug.debug("Location changed to %f,%f",
+ location.getLatitude(),
+ location.getLongitude());
+ update_ui(telemetry_state, saved_state);
+ }
+
+ public void onStatusChanged(String provider, int status, Bundle extras) {
+ AltosDebug.debug("Location status now %d\n", status);
+ }
+
+ public void onProviderEnabled(String provider) {
+ AltosDebug.debug("Location provider enabled %s\n", provider);
+ }
+
+ public void onProviderDisabled(String provider) {
+ AltosDebug.debug("Location provider disabled %s\n", provider);
+ }
}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidLink.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidLink.java
index 0e3511d3..0fd9af75 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidLink.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidLink.java
@@ -24,7 +24,7 @@ import java.util.UUID;
import android.os.Handler;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public abstract class AltosDroidLink extends AltosLink {
@@ -170,8 +170,8 @@ public abstract class AltosDroidLink extends AltosLink {
}
buffer_off = 0;
}
- if (AltosDebug.D)
- debug_input(in_buffer[buffer_off]);
+// if (AltosDebug.D)
+// debug_input(in_buffer[buffer_off]);
return in_buffer[buffer_off++];
}
@@ -207,10 +207,9 @@ public abstract class AltosDroidLink extends AltosLink {
public void print(String data) {
byte[] bytes = data.getBytes();
- AltosDebug.debug("print(): begin");
+// AltosDebug.debug(data.replace('\n', '\\'));
for (byte b : bytes)
putchar(b);
- AltosDebug.debug("print(): Wrote bytes: '" + data.replace('\n', '\\') + "'");
}
public AltosDroidLink(Handler handler) {
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapInterface.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapInterface.java
index 59f08c34..43abef0f 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapInterface.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapInterface.java
@@ -20,11 +20,13 @@ package org.altusmetrum.AltosDroid;
import java.util.*;
import java.io.*;
import android.location.Location;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public interface AltosDroidMapInterface {
public void onCreateView(AltosDroid altos_droid);
+ public void onDestroyView();
+
public void set_visible(boolean visible);
public void center(double lat, double lon, double accuracy);
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapSourceListener.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapSourceListener.java
new file mode 100644
index 00000000..e2775ef5
--- /dev/null
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapSourceListener.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+public interface AltosDroidMapSourceListener {
+ public void map_source_changed(int map_source);
+}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java
index 02defbcb..dd86c818 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java
@@ -16,8 +16,12 @@
*/
package org.altusmetrum.AltosDroid;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
import android.content.Context;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosDroidPreferences extends AltosPreferences {
@@ -65,12 +69,19 @@ public class AltosDroidPreferences extends AltosPreferences {
}
}
+ static LinkedList<AltosDroidMapSourceListener> map_source_listeners;
+
public static void set_map_source(int map_source) {
synchronized(backend) {
AltosDroidPreferences.map_source = map_source;
backend.putInt(mapSourcePreference, map_source);
flush_preferences();
}
+ if (map_source_listeners != null) {
+ for (AltosDroidMapSourceListener l : map_source_listeners) {
+ l.map_source_changed(map_source);
+ }
+ }
}
public static int map_source() {
@@ -78,4 +89,18 @@ public class AltosDroidPreferences extends AltosPreferences {
return map_source;
}
}
+
+ public static void register_map_source_listener(AltosDroidMapSourceListener l) {
+ synchronized(backend) {
+ if (map_source_listeners == null)
+ map_source_listeners = new LinkedList<AltosDroidMapSourceListener>();
+ map_source_listeners.add(l);
+ }
+ }
+
+ public static void unregister_map_source_listener(AltosDroidMapSourceListener l) {
+ synchronized(backend) {
+ map_source_listeners.remove(l);
+ }
+ }
}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java
index 14e6ce73..5c7ec513 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java
@@ -24,9 +24,9 @@ import android.content.SharedPreferences;
import android.os.Environment;
import android.util.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
-public class AltosDroidPreferencesBackend implements AltosPreferencesBackend {
+public class AltosDroidPreferencesBackend extends AltosPreferencesBackend {
public final static String NAME = "org.altusmetrum.AltosDroid";
private Context context = null;
private SharedPreferences prefs = null;
@@ -53,6 +53,8 @@ public class AltosDroidPreferencesBackend implements AltosPreferencesBackend {
}
public AltosPreferencesBackend node(String key) {
+ if (!nodeExists(key))
+ putBoolean(key, true);
return new AltosDroidPreferencesBackend(context, key);
}
@@ -120,4 +122,8 @@ public class AltosDroidPreferencesBackend implements AltosPreferencesBackend {
public File homeDirectory() {
return Environment.getExternalStorageDirectory();
}
+
+ public void debug(String format, Object ... arguments) {
+ AltosDebug.debug(format, arguments);
+ }
}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java
index 792d0621..77dbbcb1 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java
@@ -17,7 +17,7 @@
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import android.location.Location;
import android.app.Activity;
import android.graphics.Color;
@@ -39,12 +39,6 @@ public abstract class AltosDroidTab extends Fragment implements AltosUnitsListen
public abstract String tab_name();
- public void set_map_type(int map_type) {
- }
-
- public void set_map_source(int map_source) {
- }
-
public void units_changed(boolean imperial_units) {
if (!isHidden())
show(last_telem_state, last_state, last_from_receiver, last_receiver);
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOffline.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOffline.java
index 28752110..ab142b17 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOffline.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOffline.java
@@ -20,7 +20,7 @@ package org.altusmetrum.AltosDroid;
import java.util.*;
import java.io.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import android.app.Activity;
import android.graphics.*;
@@ -79,7 +79,7 @@ class Rocket implements Comparable {
}
}
-public class AltosMapOffline extends View implements ScaleGestureDetector.OnScaleGestureListener, AltosMapInterface, AltosDroidMapInterface {
+public class AltosMapOffline extends View implements ScaleGestureDetector.OnScaleGestureListener, AltosMapInterface, AltosDroidMapInterface, AltosMapTypeListener {
ScaleGestureDetector scale_detector;
boolean scaling;
AltosMap map;
@@ -133,7 +133,7 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal
if (canvas.quickReject(pt.x, pt.y, pt.x + px_size, pt.y + px_size, Canvas.EdgeType.AA))
return;
- AltosImage altos_image = cache.get(this, store, px_size, px_size);
+ AltosImage altos_image = this.get_image();
MapImage map_image = (MapImage) altos_image;
@@ -150,8 +150,8 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal
if (t.has_location()) {
String message = null;
switch (status) {
- case AltosMapTile.loading:
- message = "Loading...";
+ case AltosMapTile.fetching:
+ message = "Fetching...";
break;
case AltosMapTile.bad_request:
message = "Internal error";
@@ -181,14 +181,14 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal
}
}
- public MapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
- super(listener, upper_left, center, zoom, maptype, px_size, 2);
+ public MapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
+ super(cache, upper_left, center, zoom, maptype, px_size, 2);
}
}
- public AltosMapTile new_tile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
- return new MapTile(listener, upper_left, center, zoom, maptype, px_size);
+ public AltosMapTile new_tile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
+ return new MapTile(cache, upper_left, center, zoom, maptype, px_size);
}
public AltosMapPath new_path() {
@@ -441,6 +441,8 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal
}
public void show(TelemetryState telem_state, AltosState state, AltosGreatCircle from_receiver, Location receiver) {
+ boolean changed = false;
+
if (state != null) {
map.show(state, null);
if (state.pad_lat != AltosLib.MISSING && pad == null)
@@ -479,14 +481,20 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal
}
}
if (receiver != null) {
- here = new AltosLatLon(receiver.getLatitude(), receiver.getLongitude());
+ AltosLatLon new_here = new AltosLatLon(receiver.getLatitude(), receiver.getLongitude());
+ if (!new_here.equals(here)) {
+ here = new_here;
+ AltosDebug.debug("Location changed, redraw");
+ repaint();
+ }
}
}
public void onCreateView(AltosDroid altos_droid) {
this.altos_droid = altos_droid;
map = new AltosMap(this);
- map.set_maptype(altos_droid.map_type);
+ AltosPreferences.register_map_type_listener(this);
+ map.set_maptype(AltosPreferences.map_type());
pad_bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pad);
/* arrow at the bottom of the launchpad image */
@@ -504,7 +512,11 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal
here_off_y = here_bitmap.getHeight() / 2;
}
- public void set_map_type(int map_type) {
+ public void onDestroyView() {
+ AltosPreferences.unregister_map_type_listener(this);
+ }
+
+ public void map_type_changed(int map_type) {
if (map != null)
map.set_maptype(map_type);
}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOnline.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOnline.java
index 10327091..fcdb930b 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOnline.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOnline.java
@@ -19,7 +19,7 @@ package org.altusmetrum.AltosDroid;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import com.google.android.gms.maps.*;
import com.google.android.gms.maps.model.*;
@@ -102,7 +102,7 @@ class RocketOnline implements Comparable {
}
}
-public class AltosMapOnline implements AltosDroidMapInterface, GoogleMap.OnMarkerClickListener, GoogleMap.OnMapClickListener {
+public class AltosMapOnline implements AltosDroidMapInterface, GoogleMap.OnMarkerClickListener, GoogleMap.OnMapClickListener, AltosMapTypeListener {
public SupportMapFragment mMapFragment;
private GoogleMap mMap;
private boolean mapLoaded = false;
@@ -124,7 +124,8 @@ public class AltosMapOnline implements AltosDroidMapInterface, GoogleMap.OnMarke
public void onCreateView(AltosDroid altos_droid) {
this.altos_droid = altos_droid;
- final int map_type = altos_droid.map_type;
+ final int map_type = AltosPreferences.map_type();
+ AltosPreferences.register_map_type_listener(this);
mMapFragment = new SupportMapFragment() {
@Override
public void onActivityCreated(Bundle savedInstanceState) {
@@ -144,9 +145,9 @@ public class AltosMapOnline implements AltosDroidMapInterface, GoogleMap.OnMarke
};
}
-// public void onActivityCreated() {
-// getChildFragmentManager().beginTransaction().add(R.id.map, mMapFragment).commit();
-// }
+ public void onDestroyView() {
+ AltosPreferences.unregister_map_type_listener(this);
+ }
private double pixel_distance(LatLng a, LatLng b) {
Projection projection = mMap.getProjection();
@@ -190,7 +191,7 @@ public class AltosMapOnline implements AltosDroidMapInterface, GoogleMap.OnMarke
public void setupMap(int map_type) {
mMap = mMapFragment.getMap();
if (mMap != null) {
- set_map_type(map_type);
+ map_type_changed(map_type);
mMap.setMyLocationEnabled(true);
mMap.getUiSettings().setTiltGesturesEnabled(false);
mMap.getUiSettings().setZoomControlsEnabled(false);
@@ -281,7 +282,7 @@ public class AltosMapOnline implements AltosDroidMapInterface, GoogleMap.OnMarke
mPadMarker.setVisible(true);
}
}
- if (state.gps != null) {
+ if (state.gps != null && state.gps.lat != AltosLib.MISSING) {
target_position = new AltosLatLon(state.gps.lat, state.gps.lon);
if (state.gps.locked && state.gps.nsat >= 4)
@@ -308,7 +309,7 @@ public class AltosMapOnline implements AltosDroidMapInterface, GoogleMap.OnMarke
}
- public void set_map_type(int map_type) {
+ public void map_type_changed(int map_type) {
if (mMap != null) {
if (map_type == AltosMap.maptype_hybrid)
mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosUsb.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosUsb.java
index 12055dc5..4660512a 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosUsb.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosUsb.java
@@ -28,7 +28,7 @@ import android.hardware.usb.*;
import android.app.*;
import android.os.Handler;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosUsb extends AltosDroidLink {
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java
index bdc80003..542ba1f5 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java
@@ -22,7 +22,7 @@ import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
import android.location.Location;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosVoice {
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/IdleModeActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/IdleModeActivity.java
new file mode 100644
index 00000000..ec12c192
--- /dev/null
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/IdleModeActivity.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.util.*;
+import org.altusmetrum.AltosDroid.R;
+
+import android.app.Activity;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.view.View;
+import android.view.Window;
+import android.view.View.OnClickListener;
+import android.widget.*;
+import android.widget.AdapterView.*;
+
+import org.altusmetrum.altoslib_10.*;
+
+public class IdleModeActivity extends Activity {
+ private EditText callsign;
+ private Button connect;
+ private Button disconnect;
+ private Button reboot;
+ private Button igniters;
+
+ public static final String EXTRA_IDLE_MODE = "idle_mode";
+ public static final String EXTRA_IDLE_RESULT = "idle_result";
+
+ public static final int IDLE_MODE_CONNECT = 1;
+ public static final int IDLE_MODE_REBOOT = 2;
+ public static final int IDLE_MODE_IGNITERS = 3;
+ public static final int IDLE_MODE_DISCONNECT = 4;
+
+ private void done(int type) {
+ AltosPreferences.set_callsign(callsign());
+ Intent intent = new Intent();
+ intent.putExtra(EXTRA_IDLE_RESULT, type);
+ setResult(Activity.RESULT_OK, intent);
+ finish();
+ }
+
+ private String callsign() {
+ return callsign.getEditableText().toString();
+ }
+
+ public void connect_idle() {
+ done(IDLE_MODE_CONNECT);
+ }
+
+ public void disconnect_idle() {
+ AltosDebug.debug("Disconnect idle button pressed");
+ done(IDLE_MODE_DISCONNECT);
+ }
+
+ public void reboot_idle() {
+ done(IDLE_MODE_REBOOT);
+ }
+
+ public void igniters_idle() {
+ done(IDLE_MODE_IGNITERS);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Setup the window
+ requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+ setContentView(R.layout.idle_mode);
+
+ callsign = (EditText) findViewById(R.id.set_callsign);
+ callsign.setText(new StringBuffer(AltosPreferences.callsign()));
+
+ connect = (Button) findViewById(R.id.connect_idle);
+ connect.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ connect_idle();
+ }
+ });
+ disconnect = (Button) findViewById(R.id.disconnect_idle);
+ disconnect.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ disconnect_idle();
+ }
+ });
+
+ boolean idle_mode = getIntent().getBooleanExtra(AltosDroid.EXTRA_IDLE_MODE, false);
+
+ if (idle_mode)
+ connect.setVisibility(View.GONE);
+ else
+ disconnect.setVisibility(View.GONE);
+
+ reboot = (Button) findViewById(R.id.reboot_idle);
+ reboot.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ reboot_idle();
+ }
+ });
+ igniters = (Button) findViewById(R.id.igniters_idle);
+ igniters.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ igniters_idle();
+ }
+ });
+
+ // Set result CANCELED incase the user backs out
+ setResult(Activity.RESULT_CANCELED);
+ }
+}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/IgniterActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/IgniterActivity.java
new file mode 100644
index 00000000..931c3cfd
--- /dev/null
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/IgniterActivity.java
@@ -0,0 +1,413 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.lang.ref.WeakReference;
+import java.util.*;
+import org.altusmetrum.AltosDroid.R;
+
+import android.app.Activity;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.content.*;
+import android.graphics.*;
+import android.os.*;
+import android.view.*;
+import android.view.View.*;
+import android.widget.*;
+import android.widget.AdapterView.*;
+
+import org.altusmetrum.altoslib_10.*;
+
+class IgniterItem {
+ public String name;
+ public String pretty;
+ public String status;
+ public LinearLayout igniter_view = null;
+ public TextView pretty_view = null;
+ public TextView status_view = null;
+
+ private void update() {
+ if (pretty_view != null)
+ pretty_view.setText(pretty);
+ if (status_view != null)
+ status_view.setText(status);
+ }
+
+ public void set(String name, String pretty, String status) {
+ if (!name.equals(this.name) ||
+ !pretty.equals(this.pretty) ||
+ !status.equals(this.status))
+ {
+ this.name = name;
+ this.pretty = pretty;
+ this.status = status;
+ update();
+ }
+ }
+
+ public void realize(LinearLayout igniter_view,
+ TextView pretty_view,
+ TextView status_view) {
+ if (igniter_view != this.igniter_view ||
+ pretty_view != this.pretty_view ||
+ status_view != this.status_view)
+ {
+ this.igniter_view = igniter_view;
+ this.pretty_view = pretty_view;
+ this.status_view = status_view;
+ update();
+ }
+ }
+
+ public IgniterItem() {
+ }
+}
+
+class IgniterAdapter extends ArrayAdapter<IgniterItem> {
+ int resource;
+ int selected_item = -1;
+
+ public IgniterAdapter(Context context, int in_resource) {
+ super(context, in_resource);
+ resource = in_resource;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ IgniterItem item = getItem(position);
+ if (item.igniter_view == null) {
+ LinearLayout igniter_view = new LinearLayout(getContext());
+ String inflater = Context.LAYOUT_INFLATER_SERVICE;
+ LayoutInflater li = (LayoutInflater) getContext().getSystemService(inflater);
+ li.inflate(resource, igniter_view, true);
+
+ item.realize(igniter_view,
+ (TextView) igniter_view.findViewById(R.id.igniter_name),
+ (TextView) igniter_view.findViewById(R.id.igniter_status));
+ }
+ if (position == selected_item)
+ item.igniter_view.setBackgroundColor(Color.RED);
+ else
+ item.igniter_view.setBackgroundColor(Color.BLACK);
+ return item.igniter_view;
+ }
+}
+
+public class IgniterActivity extends Activity {
+ private ListView igniters_view;
+ private ToggleButton arm;
+ private Button fire;
+
+ private HashMap<String,IgniterItem> igniters = new HashMap<String,IgniterItem>();;
+
+ private IgniterAdapter igniters_adapter;
+
+ private boolean is_bound;
+ private Messenger service = null;
+ private final Messenger messenger = new Messenger(new IncomingHandler(this));
+
+ private Timer query_timer;
+ private boolean query_timer_running;
+
+ private Timer arm_timer;
+ private int arm_remaining;
+
+ public static final int IGNITER_QUERY = 1;
+ public static final int IGNITER_FIRE = 2;
+
+ // The Handler that gets information back from the Telemetry Service
+ static class IncomingHandler extends Handler {
+ private final WeakReference<IgniterActivity> igniter_activity;
+ IncomingHandler(IgniterActivity ia) { igniter_activity = new WeakReference<IgniterActivity>(ia); }
+
+ @Override
+ public void handleMessage(Message msg) {
+ IgniterActivity ia = igniter_activity.get();
+
+ switch (msg.what) {
+ case AltosDroid.MSG_IGNITER_STATUS:
+ ia.igniter_status((HashMap <String,Integer>) msg.obj);
+ break;
+ }
+ }
+ };
+
+
+ private ServiceConnection connection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className, IBinder binder) {
+ service = new Messenger(binder);
+ query_timer_tick();
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ // This is called when the connection with the service has been unexpectedly disconnected - process crashed.
+ service = null;
+ }
+ };
+
+ void doBindService() {
+ bindService(new Intent(this, TelemetryService.class), connection, Context.BIND_AUTO_CREATE);
+ is_bound = true;
+ }
+
+ void doUnbindService() {
+ if (is_bound) {
+ // If we have received the service, and hence registered with it, then now is the time to unregister.
+ unbindService(connection);
+ is_bound = false;
+ }
+ }
+
+ private void done() {
+ Intent intent = new Intent();
+ setResult(Activity.RESULT_OK, intent);
+ finish();
+ }
+
+ class FireThread extends Thread {
+ private final String igniter;
+
+ @Override
+ public void run() {
+ Message msg = Message.obtain(null, TelemetryService.MSG_IGNITER_FIRE, igniter);
+ try {
+ service.send(msg);
+ } catch (RemoteException re) {
+ }
+ }
+
+ public FireThread(String igniter) {
+ this.igniter = igniter;
+ }
+ }
+
+ private void fire_igniter() {
+ if (igniters_adapter.selected_item >= 0) {
+ IgniterItem item = igniters_adapter.getItem(igniters_adapter.selected_item);
+ FireThread ft = new FireThread(item.name);
+ ft.run();
+ arm.setChecked(false);
+ }
+ }
+
+ private void arm_igniter(boolean is_checked) {
+ if (is_checked) {
+ arm_timer_stop();
+ arm_timer = new Timer();
+ arm_remaining = 10;
+ arm_set_text();
+ fire.setEnabled(true);
+ arm_timer.scheduleAtFixedRate(new TimerTask() {
+ public void run() {
+ arm_timer_tick();
+ }},
+ 1000L, 1000L);
+ } else {
+ arm_timer_stop();
+ fire.setEnabled(false);
+ }
+ }
+
+ private synchronized void query_timer_tick() {
+ if (query_timer_running)
+ return;
+ if (service == null)
+ return;
+ query_timer_running = true;
+ Thread thread = new Thread(new Runnable() {
+ public void run() {
+ try {
+ Message msg = Message.obtain(null, TelemetryService.MSG_IGNITER_QUERY);
+ msg.replyTo = messenger;
+ if (service == null) {
+ synchronized(IgniterActivity.this) {
+ query_timer_running = false;
+ }
+ } else
+ service.send(msg);
+ } catch (RemoteException re) {
+ AltosDebug.debug("igniter query thread failed");
+ synchronized(IgniterActivity.this) {
+ query_timer_running = false;
+ }
+ }
+ }
+ });
+ thread.start();
+ }
+
+ private boolean set_igniter(HashMap <String,Integer> status, String name, String pretty) {
+ if (!status.containsKey(name))
+ return false;
+
+ IgniterItem item;
+ if (!igniters.containsKey(name)) {
+ item = new IgniterItem();
+ igniters.put(name, item);
+ igniters_adapter.add(item);
+ } else
+ item = igniters.get(name);
+
+ item.set(name, pretty, AltosIgnite.status_string(status.get(name)));
+ return true;
+ }
+
+ private synchronized void igniter_status(HashMap <String,Integer> status) {
+ query_timer_running = false;
+ if (status == null) {
+ AltosDebug.debug("no igniter status");
+ return;
+ }
+ set_igniter(status, "drogue", "Apogee");
+ set_igniter(status, "main", "Main");
+ for (int extra = 0;; extra++) {
+ String name = String.format("%d", extra);
+ String pretty = String.format("%c", 'A' + extra);
+ if (!set_igniter(status, name, pretty))
+ break;
+ }
+ }
+
+ private synchronized void arm_timer_stop() {
+ if (arm_timer != null) {
+ arm_timer.cancel();
+ arm_timer = null;
+ }
+ arm_remaining = 0;
+ }
+
+ private void arm_set_text() {
+ String text = String.format("Armed %d", arm_remaining);
+
+ if (arm.isChecked())
+ arm.setText(text);
+ arm.setTextOn(text);
+ }
+
+ private void arm_timer_tick() {
+ --arm_remaining;
+ if (arm_remaining <= 0) {
+ arm_timer_stop();
+ runOnUiThread(new Runnable() {
+ public void run() {
+ arm.setChecked(false);
+ fire.setEnabled(false);
+ }
+ });
+ } else {
+ runOnUiThread(new Runnable() {
+ public void run() {
+ arm_set_text();
+ }
+ });
+ }
+ }
+
+ private void select_item(int position) {
+ if (position != igniters_adapter.selected_item) {
+ if (igniters_adapter.selected_item >= 0)
+ igniters_view.setItemChecked(igniters_adapter.selected_item, false);
+ if (position >= 0) {
+ igniters_view.setItemChecked(position, true);
+ arm.setEnabled(true);
+ } else
+ arm.setEnabled(false);
+ igniters_adapter.selected_item = position;
+ }
+ }
+
+ private class IgniterItemClickListener implements ListView.OnItemClickListener {
+ @Override
+ public void onItemClick(AdapterView<?> av, View v, int position, long id) {
+ AltosDebug.debug("select %d\n", position);
+ select_item(position);
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Setup the window
+ requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+ setContentView(R.layout.igniters);
+
+ igniters_view = (ListView) findViewById(R.id.igniters);
+ igniters_view.setClickable(true);
+
+ igniters_adapter = new IgniterAdapter(this, R.layout.igniter_status);
+
+ igniters_view.setAdapter(igniters_adapter);
+ igniters_view.setOnItemClickListener(new IgniterItemClickListener());
+
+ fire = (Button) findViewById(R.id.igniter_fire);
+ fire.setEnabled(false);
+ fire.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ fire_igniter();
+ }
+ });
+
+ arm = (ToggleButton) findViewById(R.id.igniter_arm);
+ arm.setEnabled(false);
+ arm.setOnCheckedChangeListener(new ToggleButton.OnCheckedChangeListener() {
+ public void onCheckedChanged(CompoundButton v, boolean is_checked) {
+ arm_igniter(is_checked);
+ }
+ });
+
+ // Set result CANCELED incase the user backs out
+ setResult(Activity.RESULT_CANCELED);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ doBindService();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ query_timer = new Timer(true);
+ query_timer.scheduleAtFixedRate(new TimerTask() {
+ public void run() {
+ query_timer_tick();
+ }},
+ 0L, 5000L);
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ if (query_timer != null) {
+ query_timer.cancel();
+ query_timer = null;
+ }
+ arm_timer_stop();
+ arm.setChecked(false);
+ fire.setEnabled(false);
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ doUnbindService();
+ }
+}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/ManageFrequenciesActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/ManageFrequenciesActivity.java
new file mode 100644
index 00000000..401cdc9d
--- /dev/null
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/ManageFrequenciesActivity.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.lang.ref.WeakReference;
+import java.util.*;
+import java.text.*;
+import org.altusmetrum.AltosDroid.R;
+
+import android.app.Activity;
+import android.content.*;
+import android.graphics.*;
+import android.os.*;
+import android.view.*;
+import android.view.View.*;
+import android.view.inputmethod.*;
+import android.widget.*;
+import android.widget.AdapterView.*;
+
+import org.altusmetrum.altoslib_10.*;
+
+class FrequencyItem {
+ public AltosFrequency frequency;
+ public LinearLayout frequency_view = null;
+ public TextView pretty_view = null;
+
+ private void update() {
+ if (pretty_view != null && frequency != null)
+ pretty_view.setText(frequency.toString());
+ }
+
+ public void realize(LinearLayout frequency_view,
+ TextView pretty_view) {
+ if (frequency_view != this.frequency_view ||
+ pretty_view != this.pretty_view)
+ {
+ this.frequency_view = frequency_view;
+ this.pretty_view = pretty_view;
+ update();
+ }
+ }
+
+ public void set_frequency(AltosFrequency frequency) {
+ this.frequency = frequency;
+ update();
+ }
+
+ public FrequencyItem(AltosFrequency frequency) {
+ this.frequency = frequency;
+ }
+}
+
+class FrequencyAdapter extends ArrayAdapter<FrequencyItem> {
+ int resource;
+ int selected_item = -1;
+
+ public FrequencyAdapter(Context context, int in_resource) {
+ super(context, in_resource);
+ resource = in_resource;
+ }
+
+ public int count() {
+ int count;
+
+ for (count = 0;; count++) {
+ try {
+ getItem(count);
+ } catch (IndexOutOfBoundsException ie) {
+ return count;
+ }
+ }
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ FrequencyItem item = getItem(position);
+ if (item.frequency_view == null) {
+ LinearLayout frequency_view = new LinearLayout(getContext());
+ String inflater = Context.LAYOUT_INFLATER_SERVICE;
+ LayoutInflater li = (LayoutInflater) getContext().getSystemService(inflater);
+ li.inflate(resource, frequency_view, true);
+
+ item.realize(frequency_view,
+ (TextView) frequency_view.findViewById(R.id.frequency));
+ }
+ if (position == selected_item)
+ item.frequency_view.setBackgroundColor(Color.RED);
+ else
+ item.frequency_view.setBackgroundColor(Color.BLACK);
+ return item.frequency_view;
+ }
+}
+
+public class ManageFrequenciesActivity extends Activity {
+ private ListView frequencies_view;
+
+ private Button set;
+ private Button remove;
+ private Button done;
+
+ private EditText set_frequency;
+ private EditText set_description;
+
+ private HashMap<String,FrequencyItem> frequencies = new HashMap<String,FrequencyItem>();;
+
+ private FrequencyAdapter frequencies_adapter;
+
+ private boolean is_bound;
+ private boolean changed = false;
+
+ private void done() {
+
+ if (changed) {
+ AltosFrequency[] frequencies = new AltosFrequency[frequencies_adapter.count()];
+ for (int i = 0; i < frequencies.length; i++)
+ frequencies[i] = frequencies_adapter.getItem(i).frequency;
+ AltosPreferences.set_common_frequencies(frequencies);
+ }
+
+ Intent intent = new Intent();
+ setResult(Activity.RESULT_OK, intent);
+ finish();
+ }
+
+ private void load_item() {
+ if (frequencies_adapter.selected_item >= 0) {
+ FrequencyItem item = frequencies_adapter.getItem(frequencies_adapter.selected_item);
+
+ set_frequency.setText(item.frequency.frequency_string());
+ set_description.setText(item.frequency.description);
+ } else {
+ set_frequency.setText("");
+ set_description.setText("");
+ }
+ }
+
+ private void select_item(int position) {
+ if (position != frequencies_adapter.selected_item) {
+ if (frequencies_adapter.selected_item >= 0)
+ frequencies_view.setItemChecked(frequencies_adapter.selected_item, false);
+ if (position >= 0)
+ frequencies_view.setItemChecked(position, true);
+ frequencies_adapter.selected_item = position;
+ } else {
+ if (frequencies_adapter.selected_item >= 0)
+ frequencies_view.setItemChecked(frequencies_adapter.selected_item, false);
+ frequencies_adapter.selected_item = -1;
+ }
+ load_item();
+ }
+
+ private int insert_item(AltosFrequency frequency) {
+ FrequencyItem new_item = new FrequencyItem(frequency);
+ int pos;
+ for (pos = 0; pos < frequencies_adapter.getCount(); pos++) {
+ FrequencyItem item = frequencies_adapter.getItem(pos);
+ if (item.frequency.frequency == new_item.frequency.frequency) {
+ item.set_frequency(frequency);
+ return pos;
+ }
+ if (item.frequency.frequency > new_item.frequency.frequency)
+ break;
+ }
+ frequencies_adapter.insert(new_item, pos);
+ return pos;
+ }
+
+ private class FrequencyItemClickListener implements ListView.OnItemClickListener {
+ @Override
+ public void onItemClick(AdapterView<?> av, View v, int position, long id) {
+ select_item(position);
+ }
+ }
+
+ private void hide_keyboard() {
+ InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
+ View view = getCurrentFocus();
+ if (view != null)
+ imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
+ }
+
+ private void set() {
+ String frequency_text = set_frequency.getEditableText().toString();
+ String description_text = set_description.getEditableText().toString();
+
+ try {
+ double f = AltosParse.parse_double_locale(frequency_text);
+
+ int pos = insert_item(new AltosFrequency(f, description_text));
+ frequencies_adapter.selected_item = -1;
+ select_item(pos);
+ changed = true;
+ } catch (ParseException pe) {
+ }
+ hide_keyboard();
+ }
+
+ private void remove() {
+ if (frequencies_adapter.selected_item >= 0) {
+ frequencies_adapter.remove(frequencies_adapter.getItem(frequencies_adapter.selected_item));
+ select_item(-1);
+ frequencies_view.setAdapter(frequencies_adapter);
+ changed = true;
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Setup the window
+ requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+ setContentView(R.layout.manage_frequencies);
+
+ frequencies_view = (ListView) findViewById(R.id.frequencies);
+ frequencies_view.setClickable(true);
+
+ frequencies_adapter = new FrequencyAdapter(this, R.layout.frequency);
+
+ frequencies_view.setAdapter(frequencies_adapter);
+ frequencies_view.setOnItemClickListener(new FrequencyItemClickListener());
+
+ AltosFrequency[] frequencies = AltosPreferences.common_frequencies();
+ for (AltosFrequency frequency : frequencies)
+ insert_item(frequency);
+
+ set_frequency = (EditText) findViewById(R.id.set_frequency);
+ set_description = (EditText) findViewById(R.id.set_description);
+
+ set = (Button) findViewById(R.id.set);
+ set.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ set();
+ }
+ });
+
+ remove = (Button) findViewById(R.id.remove);
+ remove.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ remove();
+ }
+ });
+
+ done = (Button) findViewById(R.id.done);
+ done.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ done();
+ }
+ });
+
+ // Set result CANCELED incase the user backs out
+ setResult(Activity.RESULT_CANCELED);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ }
+}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/MapTypeActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/MapTypeActivity.java
index e1677ce6..cfbcdafc 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/MapTypeActivity.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/MapTypeActivity.java
@@ -34,7 +34,7 @@ import android.view.View.OnClickListener;
import android.widget.*;
import android.widget.AdapterView.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class MapTypeActivity extends Activity {
private Button hybrid;
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java
index e6ce3809..13a44e1f 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java
@@ -41,7 +41,7 @@ import android.location.LocationManager;
import android.location.LocationListener;
import android.location.Criteria;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
/**
* This Activity appears as a dialog. It lists any paired devices and
@@ -107,7 +107,6 @@ public class PreloadMapActivity extends Activity implements AltosLaunchSiteListe
}
AltosMap map;
- AltosMapLoader loader;
class PreloadMapImage implements AltosImage {
public void flush() {
@@ -137,14 +136,14 @@ public class PreloadMapActivity extends Activity implements AltosLaunchSiteListe
public void paint(AltosMapTransform t) {
}
- public PreloadMapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
- super(listener, upper_left, center, zoom, maptype, px_size, 2);
+ public PreloadMapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
+ super(cache, upper_left, center, zoom, maptype, px_size, 2);
}
}
- public AltosMapTile new_tile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
- return new PreloadMapTile(listener, upper_left, center, zoom, maptype, px_size);
+ public AltosMapTile new_tile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
+ return new PreloadMapTile(cache, upper_left, center, zoom, maptype, px_size);
}
public int width() {
@@ -265,7 +264,7 @@ public class PreloadMapActivity extends Activity implements AltosLaunchSiteListe
AltosDebug.debug("PreloadMap load %f %f %d %d %f %d\n",
lat, lon, min, max, r, t);
- loader.load(lat, lon, min, max, r, t);
+ new AltosMapLoader(map, this, lat, lon, min, max, r, t);
} catch (ParseException e) {
AltosDebug.debug("PreloadMap load raised exception %s", e.toString());
}
@@ -398,8 +397,6 @@ public class PreloadMapActivity extends Activity implements AltosLaunchSiteListe
map = new AltosMap(this);
- loader = new AltosMapLoader(map, this);
-
// Listen for GPS and Network position updates
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/SetupActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/SetupActivity.java
new file mode 100644
index 00000000..fdffc2b0
--- /dev/null
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/SetupActivity.java
@@ -0,0 +1,339 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.lang.ref.WeakReference;
+import java.util.*;
+import org.altusmetrum.AltosDroid.R;
+
+import android.app.Activity;
+import android.bluetooth.*;
+import android.content.*;
+import android.os.*;
+import android.view.*;
+import android.view.View.*;
+import android.widget.*;
+import android.widget.AdapterView.*;
+
+import org.altusmetrum.altoslib_10.*;
+
+public class SetupActivity extends Activity {
+ private Spinner select_rate;
+ private Spinner set_units;
+ private Spinner map_type;
+ private Spinner map_source;
+ private Button manage_frequencies;
+ private Button preload_maps;
+ private Button done;
+
+ private boolean is_bound;
+ private Messenger service = null;
+
+ public final static String EXTRA_SETUP_CHANGES = "setup_changes";
+
+ private ServiceConnection connection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className, IBinder binder) {
+ service = new Messenger(binder);
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ // This is called when the connection with the service has been unexpectedly disconnected - process crashed.
+ service = null;
+ }
+ };
+
+ void doBindService() {
+ bindService(new Intent(this, TelemetryService.class), connection, Context.BIND_AUTO_CREATE);
+ is_bound = true;
+ }
+
+ void doUnbindService() {
+ if (is_bound) {
+ // If we have received the service, and hence registered with it, then now is the time to unregister.
+ unbindService(connection);
+ is_bound = false;
+ }
+ }
+
+ static final String[] rates = {
+ "38400",
+ "9600",
+ "2400",
+ };
+
+ static final String[] map_types = {
+ "Hybrid",
+ "Satellite",
+ "Roadmap",
+ "Terrain"
+ };
+
+ static final int[] map_type_values = {
+ AltosMap.maptype_hybrid,
+ AltosMap.maptype_satellite,
+ AltosMap.maptype_roadmap,
+ AltosMap.maptype_terrain,
+ };
+
+ static final String[] map_sources = {
+ "Online",
+ "Offline"
+ };
+
+ private int set_telemetry_rate;
+ private int set_map_source;
+ private int set_map_type;
+ private boolean set_imperial_units;
+
+ private int changes = 0;
+
+ private void add_change(int change) {
+ changes |= change;
+ }
+
+ private void done() {
+ Intent intent = new Intent();
+ if ((changes & AltosDroid.SETUP_BAUD) != 0)
+ AltosPreferences.set_telemetry_rate(1, set_telemetry_rate);
+ if ((changes & AltosDroid.SETUP_UNITS) != 0)
+ AltosPreferences.set_imperial_units(set_imperial_units);
+ if ((changes & AltosDroid.SETUP_MAP_SOURCE) != 0)
+ AltosDroidPreferences.set_map_source(set_map_source);
+ if ((changes & AltosDroid.SETUP_MAP_TYPE) != 0)
+ AltosPreferences.set_map_type(set_map_type);
+ intent.putExtra(EXTRA_SETUP_CHANGES, changes);
+ setResult(Activity.RESULT_OK, intent);
+ finish();
+ }
+
+ private void add_strings(Spinner spinner, String[] strings, int def) {
+ ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item);
+
+ for (int i = 0; i < strings.length; i++)
+ adapter.add(strings[i]);
+
+ spinner.setAdapter(adapter);
+ if (def >= 0)
+ spinner.setSelection(def);
+ }
+
+ private int default_rate_pos() {
+ int default_rate = AltosPreferences.telemetry_rate(1);
+
+ for (int pos = 0; pos < rates.length; pos++) {
+ if (string_to_rate(rates[pos]) == default_rate)
+ return pos;
+ }
+ return -1;
+ }
+
+ private void setBaud(int baud) {
+ try {
+ service.send(Message.obtain(null, TelemetryService.MSG_SETBAUD, baud));
+ set_telemetry_rate = baud;
+ add_change(AltosDroid.SETUP_BAUD);
+ } catch (RemoteException e) {
+ }
+ }
+
+ private int string_to_rate(String baud) {
+ int rate = AltosLib.ao_telemetry_rate_38400;
+ try {
+ int value = Integer.parseInt(baud);
+ switch (value) {
+ case 2400:
+ rate = AltosLib.ao_telemetry_rate_2400;
+ break;
+ case 9600:
+ rate = AltosLib.ao_telemetry_rate_9600;
+ break;
+ case 38400:
+ rate = AltosLib.ao_telemetry_rate_38400;
+ break;
+ }
+ } catch (NumberFormatException e) {
+ }
+ return rate;
+ }
+
+ private void setBaud(String baud) {
+ setBaud(string_to_rate(baud));
+ }
+
+ private void select_rate(int pos) {
+ setBaud(rates[pos]);
+ }
+
+ static final String[] units = {
+ "Metric",
+ "Imperial"
+ };
+
+ private int default_units_pos() {
+ boolean imperial = AltosPreferences.imperial_units();
+
+ if (imperial)
+ return 1;
+ return 0;
+ }
+
+ private void set_units(int pos) {
+ switch (pos) {
+ default:
+ set_imperial_units = false;
+ break;
+ case 1:
+ set_imperial_units = true;
+ break;
+ }
+ add_change(AltosDroid.SETUP_UNITS);
+ }
+
+ private int default_map_type_pos() {
+ int default_map_type = AltosPreferences.map_type();
+
+ for (int pos = 0; pos < map_types.length; pos++)
+ if (map_type_values[pos] == default_map_type)
+ return pos;
+ return 0;
+ }
+
+ private void select_map_type(int pos) {
+ set_map_type = map_type_values[pos];
+ add_change(AltosDroid.SETUP_MAP_TYPE);
+ }
+
+ private int default_map_source_pos() {
+ int default_source = AltosDroidPreferences.map_source();
+
+ switch (default_source) {
+ case AltosDroidPreferences.MAP_SOURCE_OFFLINE:
+ return 1;
+ default:
+ return 0;
+ }
+ }
+
+ private void select_map_source(int pos) {
+ switch (pos) {
+ default:
+ set_map_source = AltosDroidPreferences.MAP_SOURCE_ONLINE;
+ break;
+ case 1:
+ set_map_source = AltosDroidPreferences.MAP_SOURCE_OFFLINE;
+ break;
+ }
+ add_change(AltosDroid.SETUP_MAP_SOURCE);
+ }
+
+ private void manage_frequencies(){
+ Intent intent = new Intent(this, ManageFrequenciesActivity.class);
+ startActivity(intent);
+ }
+
+ private void preload_maps(){
+ Intent intent = new Intent(this, PreloadMapActivity.class);
+ startActivity(intent);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Setup the window
+ requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+ setContentView(R.layout.setup);
+
+ select_rate = (Spinner) findViewById(R.id.select_rate);
+ add_strings(select_rate, rates, default_rate_pos());
+ select_rate.setOnItemSelectedListener(new OnItemSelectedListener() {
+ public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+ select_rate(pos);
+ }
+ public void onNothingSelected(AdapterView<?> parent) {
+ }
+ });
+
+ set_units = (Spinner) findViewById(R.id.set_units);
+ add_strings(set_units, units, default_units_pos());
+ set_units.setOnItemSelectedListener(new OnItemSelectedListener() {
+ public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+ set_units(pos);
+ }
+ public void onNothingSelected(AdapterView<?> parent) {
+ }
+ });
+
+ map_type = (Spinner) findViewById(R.id.map_type);
+ add_strings(map_type, map_types, default_map_type_pos());
+ map_type.setOnItemSelectedListener(new OnItemSelectedListener() {
+ public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+ select_map_type(pos);
+ }
+ public void onNothingSelected(AdapterView<?> parent) {
+ }
+ });
+
+ map_source = (Spinner) findViewById(R.id.map_source);
+ add_strings(map_source, map_sources, default_map_source_pos());
+ map_source.setOnItemSelectedListener(new OnItemSelectedListener() {
+ public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+ select_map_source(pos);
+ }
+ public void onNothingSelected(AdapterView<?> parent) {
+ }
+ });
+
+
+ manage_frequencies = (Button) findViewById(R.id.manage_frequencies);
+ manage_frequencies.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ manage_frequencies();
+ }
+ });
+
+ preload_maps = (Button) findViewById(R.id.preload_maps);
+ preload_maps.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ preload_maps();
+ }
+ });
+
+ done = (Button) findViewById(R.id.done);
+ done.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ done();
+ }
+ });
+
+ // Set result for when the user backs out
+ setResult(Activity.RESULT_CANCELED);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ doBindService();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ doUnbindService();
+ }
+}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabFlight.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabFlight.java
index 095d6b33..9bbdc060 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/TabFlight.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabFlight.java
@@ -17,7 +17,7 @@
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import android.app.Activity;
import android.os.Bundle;
@@ -87,7 +87,7 @@ public class TabFlight extends AltosDroidTab {
set_value(speed_view, AltosConvert.speed, 6, state.speed());
set_value(height_view, AltosConvert.height, 6, state.height());
set_value(max_speed_view, AltosConvert.speed, 6, state.max_speed());
- set_value(max_height_view, AltosConvert.speed, 6, state.max_height());
+ set_value(max_height_view, AltosConvert.height, 6, state.max_height());
if (from_receiver != null) {
elevation_view.setText(AltosDroid.number("%3.0f°", from_receiver.elevation));
set_value(range_view, AltosConvert.distance, 6, from_receiver.range);
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java
index 3c236d58..19ce86c9 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java
@@ -20,7 +20,7 @@ package org.altusmetrum.AltosDroid;
import java.util.*;
import java.io.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import android.app.Activity;
import android.graphics.*;
@@ -32,7 +32,7 @@ import android.widget.*;
import android.location.Location;
import android.content.*;
-public class TabMap extends AltosDroidTab {
+public class TabMap extends AltosDroidTab implements AltosDroidMapSourceListener {
AltosLatLon here;
@@ -74,7 +74,8 @@ public class TabMap extends AltosDroidTab {
map_offline.onCreateView(altos_droid);
map_online = new AltosMapOnline(view.getContext());
map_online.onCreateView(altos_droid);
- set_map_source(AltosDroidPreferences.map_source());
+ map_source_changed(AltosDroidPreferences.map_source());
+ AltosDroidPreferences.register_map_source_listener(this);
return view;
}
@@ -88,6 +89,9 @@ public class TabMap extends AltosDroidTab {
@Override
public void onDestroyView() {
super.onDestroyView();
+ map_offline.onDestroyView();
+ map_online.onDestroyView();
+ AltosDroidPreferences.unregister_map_source_listener(this);
}
public String tab_name() { return AltosDroid.tab_map_name; }
@@ -144,16 +148,7 @@ public class TabMap extends AltosDroidTab {
}
}
- @Override
- public void set_map_type(int map_type) {
- if (map_offline != null)
- map_offline.set_map_type(map_type);
- if (map_online != null)
- map_online.set_map_type(map_type);
- }
-
- @Override
- public void set_map_source(int map_source) {
+ public void map_source_changed(int map_source) {
this.map_source = map_source;
if (map_source == AltosDroidPreferences.MAP_SOURCE_OFFLINE) {
if (map_online != null)
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java
index f5fbaf61..1194eb00 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java
@@ -17,7 +17,7 @@
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import android.app.Activity;
import android.os.Bundle;
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabRecover.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabRecover.java
index ee82d391..8742227b 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/TabRecover.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabRecover.java
@@ -17,7 +17,7 @@
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import android.app.Activity;
import android.os.Bundle;
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java
index 6f595817..bdea0986 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java
@@ -1,6 +1,6 @@
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import android.content.BroadcastReceiver;
import android.content.Context;
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java
index 473a4bfb..0ac6bb5c 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java
@@ -25,7 +25,7 @@ import java.util.*;
import java.util.concurrent.*;
import android.os.Handler;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class TelemetryReader extends Thread {
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java
index 92a7ecfa..3c1a1782 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java
@@ -38,14 +38,11 @@ import android.os.Messenger;
import android.os.RemoteException;
import android.os.Looper;
import android.widget.Toast;
-import android.location.Location;
-import android.location.LocationManager;
-import android.location.LocationListener;
import android.location.Criteria;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
-public class TelemetryService extends Service implements LocationListener {
+public class TelemetryService extends Service implements AltosIdleMonitorListener {
static final int MSG_REGISTER_CLIENT = 1;
static final int MSG_UNREGISTER_CLIENT = 2;
@@ -60,6 +57,12 @@ public class TelemetryService extends Service implements LocationListener {
static final int MSG_SETBAUD = 11;
static final int MSG_DISCONNECT = 12;
static final int MSG_DELETE_SERIAL = 13;
+ static final int MSG_BLUETOOTH_ENABLED = 14;
+ static final int MSG_MONITOR_IDLE_START= 15;
+ static final int MSG_MONITOR_IDLE_STOP = 16;
+ static final int MSG_REBOOT = 17;
+ static final int MSG_IGNITER_QUERY = 18;
+ static final int MSG_IGNITER_FIRE = 19;
// Unique Identification Number for the Notification.
// We use it on Notification start, and to cancel it.
@@ -82,6 +85,13 @@ public class TelemetryService extends Service implements LocationListener {
// Last data seen; send to UI when it starts
private TelemetryState telemetry_state;
+ // Idle monitor if active
+ AltosIdleMonitor idle_monitor = null;
+
+ // Igniter bits
+ AltosIgnite ignite = null;
+ boolean ignite_running;
+
// Handler of incoming messages from clients.
static class IncomingHandler extends Handler {
private final WeakReference<TelemetryService> service;
@@ -89,10 +99,13 @@ public class TelemetryService extends Service implements LocationListener {
@Override
public void handleMessage(Message msg) {
+ DeviceAddress address;
+
TelemetryService s = service.get();
AltosDroidLink bt = null;
if (s == null)
return;
+
switch (msg.what) {
/* Messages from application */
@@ -104,7 +117,7 @@ public class TelemetryService extends Service implements LocationListener {
break;
case MSG_CONNECT:
AltosDebug.debug("Connect command received");
- DeviceAddress address = (DeviceAddress) msg.obj;
+ address = (DeviceAddress) msg.obj;
AltosDroidPreferences.set_active_device(address);
s.start_altos_bluetooth(address, false);
break;
@@ -206,6 +219,32 @@ public class TelemetryService extends Service implements LocationListener {
s.telemetry_state.crc_errors = (Integer) msg.obj;
s.send_to_clients();
break;
+ case MSG_BLUETOOTH_ENABLED:
+ AltosDebug.debug("TelemetryService notes that BT is now enabled");
+ address = AltosDroidPreferences.active_device();
+ if (address != null && !address.address.startsWith("USB"))
+ s.start_altos_bluetooth(address, false);
+ break;
+ case MSG_MONITOR_IDLE_START:
+ AltosDebug.debug("start monitor idle");
+ s.start_idle_monitor();
+ break;
+ case MSG_MONITOR_IDLE_STOP:
+ AltosDebug.debug("stop monitor idle");
+ s.stop_idle_monitor();
+ break;
+ case MSG_REBOOT:
+ AltosDebug.debug("reboot");
+ s.reboot_remote();
+ break;
+ case MSG_IGNITER_QUERY:
+ AltosDebug.debug("igniter query");
+ s.igniter_query(msg.replyTo);
+ break;
+ case MSG_IGNITER_FIRE:
+ AltosDebug.debug("igniter fire");
+ s.igniter_fire((String) msg.obj);
+ break;
default:
super.handleMessage(msg);
}
@@ -224,7 +263,7 @@ public class TelemetryService extends Service implements LocationListener {
telem.update_state(state);
telemetry_state.states.put(telem.serial, state);
if (state != null) {
- AltosPreferences.set_state(telem.serial, state, null);
+ AltosPreferences.set_state(state);
}
send_to_clients();
}
@@ -248,7 +287,8 @@ public class TelemetryService extends Service implements LocationListener {
/* On connect, send the current state to the new client
*/
- send_to_client(client, message());
+ send_to_client(client);
+ send_idle_mode_to_client(client);
/* If we've got an address from a previous session, then
* go ahead and try to reconnect to the device
@@ -275,7 +315,8 @@ public class TelemetryService extends Service implements LocationListener {
}
}
- private void send_to_client(Messenger client, Message m) {
+ private void send_to_client(Messenger client) {
+ Message m = message();
try {
client.send(m);
} catch (RemoteException e) {
@@ -285,22 +326,33 @@ public class TelemetryService extends Service implements LocationListener {
}
private void send_to_clients() {
- Message m = message();
for (Messenger client : clients)
- send_to_client(client, m);
+ send_to_client(client);
}
- private void disconnect(boolean notify) {
- AltosDebug.debug("disconnect(): begin");
-
- telemetry_state.connect = TelemetryState.CONNECT_DISCONNECTED;
- telemetry_state.address = null;
+ private void send_idle_mode_to_client(Messenger client) {
+ Message m = Message.obtain(null, AltosDroid.MSG_IDLE_MODE, idle_monitor != null);
+ try {
+ client.send(m);
+ } catch (RemoteException e) {
+ AltosDebug.error("Client %s disappeared", client.toString());
+ remove_client(client);
+ }
+ }
- if (altos_link != null)
- altos_link.closing();
+ private void send_idle_mode_to_clients() {
+ for (Messenger client : clients)
+ send_idle_mode_to_client(client);
+ }
- stop_receiver_voltage_timer();
+ private void telemetry_start() {
+ if (telemetry_reader == null && idle_monitor == null && !ignite_running) {
+ telemetry_reader = new TelemetryReader(altos_link, handler);
+ telemetry_reader.start();
+ }
+ }
+ private void telemetry_stop() {
if (telemetry_reader != null) {
AltosDebug.debug("disconnect(): stopping TelemetryReader");
telemetry_reader.interrupt();
@@ -310,6 +362,23 @@ public class TelemetryService extends Service implements LocationListener {
}
telemetry_reader = null;
}
+ }
+
+ private void disconnect(boolean notify) {
+ AltosDebug.debug("disconnect(): begin");
+
+ telemetry_state.connect = TelemetryState.CONNECT_DISCONNECTED;
+ telemetry_state.address = null;
+
+ if (idle_monitor != null)
+ stop_idle_monitor();
+
+ if (altos_link != null)
+ altos_link.closing();
+
+ stop_receiver_voltage_timer();
+
+ telemetry_stop();
if (telemetry_logger != null) {
AltosDebug.debug("disconnect(): stopping TelemetryLogger");
telemetry_logger.stop();
@@ -319,6 +388,7 @@ public class TelemetryService extends Service implements LocationListener {
AltosDebug.debug("disconnect(): stopping AltosDroidLink");
altos_link.close();
altos_link = null;
+ ignite = null;
}
telemetry_state.config = null;
if (notify) {
@@ -351,10 +421,14 @@ public class TelemetryService extends Service implements LocationListener {
}
private void start_altos_bluetooth(DeviceAddress address, boolean pause) {
- // Get the BLuetoothDevice object
- BluetoothDevice device = bluetooth_adapter.getRemoteDevice(address.address);
+ if (bluetooth_adapter == null || !bluetooth_adapter.isEnabled())
+ return;
disconnect(false);
+
+ // Get the BluetoothDevice object
+ BluetoothDevice device = bluetooth_adapter.getRemoteDevice(address.address);
+
this.address = address;
AltosDebug.debug("start_altos_bluetooth(): Connecting to %s (%s)", device.getName(), device.getAddress());
altos_link = new AltosBluetooth(device, handler, pause);
@@ -363,14 +437,95 @@ public class TelemetryService extends Service implements LocationListener {
send_to_clients();
}
+ private void start_idle_monitor() {
+ if (altos_link != null && idle_monitor == null) {
+ telemetry_stop();
+ idle_monitor = new AltosIdleMonitor(this, altos_link, true, false);
+ idle_monitor.set_callsign(AltosPreferences.callsign());
+ idle_monitor.start();
+ send_idle_mode_to_clients();
+ }
+ }
+
+ private void stop_idle_monitor() {
+ if (idle_monitor != null) {
+ try {
+ idle_monitor.abort();
+ } catch (InterruptedException ie) {
+ }
+ idle_monitor = null;
+ telemetry_start();
+ send_idle_mode_to_clients();
+ }
+ }
+
+ private void reboot_remote() {
+ if (altos_link != null) {
+ stop_idle_monitor();
+ try {
+ altos_link.start_remote();
+ altos_link.printf("r eboot\n");
+ altos_link.flush_output();
+ } catch (TimeoutException te) {
+ } catch (InterruptedException ie) {
+ } finally {
+ try {
+ altos_link.stop_remote();
+ } catch (InterruptedException ie) {
+ }
+ }
+ }
+ }
+
+ private void ensure_ignite() {
+ if (ignite == null)
+ ignite = new AltosIgnite(altos_link, true, false);
+ }
+
+ private synchronized void igniter_query(Messenger client) {
+ ensure_ignite();
+ HashMap<String,Integer> status_map = null;
+ ignite_running = true;
+ try {
+ stop_idle_monitor();
+ try {
+ status_map = ignite.status();
+ } catch (InterruptedException ie) {
+ AltosDebug.debug("ignite.status interrupted");
+ } catch (TimeoutException te) {
+ AltosDebug.debug("ignite.status timeout");
+ }
+ } finally {
+ ignite_running = false;
+ }
+ Message m = Message.obtain(null, AltosDroid.MSG_IGNITER_STATUS, status_map);
+ try {
+ client.send(m);
+ } catch (RemoteException e) {
+ }
+ }
+
+ private synchronized void igniter_fire(String igniter) {
+ ensure_ignite();
+ ignite_running = true;
+ stop_idle_monitor();
+ try {
+ ignite.fire(igniter);
+ } catch (InterruptedException ie) {
+ } finally {
+ ignite_running = false;
+ }
+ }
+
// Timer for receiver battery voltage monitoring
Timer receiver_voltage_timer;
private void update_receiver_voltage() {
- if (altos_link != null) {
+ if (altos_link != null && idle_monitor == null && !ignite_running) {
try {
double voltage = altos_link.monitor_battery();
telemetry_state.receiver_battery = voltage;
+ send_to_clients();
} catch (InterruptedException ie) {
}
}
@@ -418,8 +573,7 @@ public class TelemetryService extends Service implements LocationListener {
telemetry_state.connect = TelemetryState.CONNECT_CONNECTED;
telemetry_state.address = address;
- telemetry_reader = new TelemetryReader(altos_link, handler);
- telemetry_reader.start();
+ telemetry_start();
AltosDebug.debug("connected TelemetryReader started");
@@ -444,11 +598,6 @@ public class TelemetryService extends Service implements LocationListener {
// Get local Bluetooth adapter
bluetooth_adapter = BluetoothAdapter.getDefaultAdapter();
- // If the adapter is null, then Bluetooth is not supported
- if (bluetooth_adapter == null) {
- Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();
- }
-
telemetry_state = new TelemetryState();
// Create a reference to the NotificationManager so that we can update our notifcation text later
@@ -464,31 +613,23 @@ public class TelemetryService extends Service implements LocationListener {
telemetry_state.latest_serial = AltosPreferences.latest_state();
for (int serial : serials) {
- AltosSavedState saved_state = AltosPreferences.state(serial);
+ AltosState saved_state = AltosPreferences.state(serial);
if (saved_state != null) {
- if (serial == 0) {
- serial = saved_state.state.serial;
- AltosPreferences.set_state(serial, saved_state.state, saved_state.listener_state);
- AltosPreferences.remove_state(0);
- }
if (telemetry_state.latest_serial == 0)
telemetry_state.latest_serial = serial;
- AltosDebug.debug("recovered old state serial %d flight %d\n",
+ AltosDebug.debug("recovered old state serial %d flight %d",
serial,
- saved_state.state.flight);
- if (saved_state.state.gps != null)
- AltosDebug.debug("\tposition %f,%f\n",
- saved_state.state.gps.lat,
- saved_state.state.gps.lon);
- telemetry_state.states.put(serial, saved_state.state);
+ saved_state.flight);
+ if (saved_state.gps != null)
+ AltosDebug.debug("\tposition %f,%f",
+ saved_state.gps.lat,
+ saved_state.gps.lon);
+ telemetry_state.states.put(serial, saved_state);
+ } else {
+ AltosDebug.debug("Failed to recover state for %d", serial);
}
}
-
- // Listen for GPS and Network position updates
- LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
-
- locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, this);
}
@Override
@@ -535,9 +676,6 @@ public class TelemetryService extends Service implements LocationListener {
@Override
public void onDestroy() {
- // Stop listening for location updates
- ((LocationManager) getSystemService(Context.LOCATION_SERVICE)).removeUpdates(this);
-
// Stop the bluetooth Comms threads
disconnect(true);
@@ -553,20 +691,17 @@ public class TelemetryService extends Service implements LocationListener {
return messenger.getBinder();
}
-
- public void onLocationChanged(Location location) {
- telemetry_state.location = location;
- AltosDebug.debug("location changed");
+ /* AltosIdleMonitorListener */
+ public void update(AltosState state, AltosListenerState listener_state) {
+ telemetry_state.states.put(state.serial, state);
+ telemetry_state.receiver_battery = listener_state.battery;
send_to_clients();
}
- public void onStatusChanged(String provider, int status, Bundle extras) {
+ public void failed() {
}
- public void onProviderEnabled(String provider) {
+ public void error(String reason) {
+ stop_idle_monitor();
}
-
- public void onProviderDisabled(String provider) {
- }
-
}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryState.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryState.java
index c81dfcd2..d3ccf0a9 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryState.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryState.java
@@ -18,7 +18,7 @@
package org.altusmetrum.AltosDroid;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import android.location.Location;
public class TelemetryState {
@@ -30,7 +30,6 @@ public class TelemetryState {
int connect;
DeviceAddress address;
AltosConfigData config;
- Location location;
int crc_errors;
double receiver_battery;
double frequency;
@@ -44,7 +43,6 @@ public class TelemetryState {
connect = CONNECT_NONE;
config = null;
states = new HashMap<Integer,AltosState>();
- location = null;
crc_errors = 0;
receiver_battery = AltosLib.MISSING;
frequency = AltosPreferences.frequency(0);
diff --git a/altoslib/AltosAccel.java b/altoslib/AltosAccel.java
index e12b6375..2c563f66 100644
--- a/altoslib/AltosAccel.java
+++ b/altoslib/AltosAccel.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
diff --git a/altoslib/AltosCRCException.java b/altoslib/AltosCRCException.java
index d2337512..03dad137 100644
--- a/altoslib/AltosCRCException.java
+++ b/altoslib/AltosCRCException.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosCRCException extends Exception {
public int rssi;
diff --git a/altoslib/AltosCSV.java b/altoslib/AltosCSV.java
index 8a389812..fa515b31 100644
--- a/altoslib/AltosCSV.java
+++ b/altoslib/AltosCSV.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
diff --git a/altoslib/AltosCompanion.java b/altoslib/AltosCompanion.java
index 87e701cf..dc33dacc 100644
--- a/altoslib/AltosCompanion.java
+++ b/altoslib/AltosCompanion.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
diff --git a/altoslib/AltosConfigData.java b/altoslib/AltosConfigData.java
index 7a518ab4..812296f3 100644
--- a/altoslib/AltosConfigData.java
+++ b/altoslib/AltosConfigData.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.*;
import java.text.*;
@@ -476,6 +476,18 @@ public class AltosConfigData implements Iterable<String> {
}
+ public boolean mma655x_inverted() throws AltosUnknownProduct {
+ if (product.startsWith("EasyMega-v1"))
+ return false;
+ if (product.startsWith("TeleMetrum-v2"))
+ return true;
+ if (product.startsWith("TeleMega-v2"))
+ return false;
+ if (product.startsWith("TeleMega-v1"))
+ return false;
+ throw new AltosUnknownProduct(product);
+ }
+
public void get_values(AltosConfigValues source) throws AltosConfigDataException {
/* HAS_FLIGHT */
@@ -493,8 +505,6 @@ public class AltosConfigData implements Iterable<String> {
radio_enable = source.radio_enable();
if (callsign != null)
callsign = source.callsign();
- if (radio_calibration >= 0)
- radio_calibration = source.radio_calibration();
if (telemetry_rate >= 0)
telemetry_rate = source.telemetry_rate();
@@ -601,10 +611,6 @@ public class AltosConfigData implements Iterable<String> {
if (apogee_lockout >= 0)
link.printf("c L %d\n", apogee_lockout);
- /* Don't mess with radio calibration when remote */
- if (radio_calibration > 0 && !remote)
- link.printf("c f %d\n", radio_calibration);
-
/* HAS_RADIO */
if (has_frequency()) {
boolean has_frequency = radio_frequency >= 0;
diff --git a/altoslib/AltosConfigDataException.java b/altoslib/AltosConfigDataException.java
index d1d0d8d0..75cd1695 100644
--- a/altoslib/AltosConfigDataException.java
+++ b/altoslib/AltosConfigDataException.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosConfigDataException extends Exception {
diff --git a/altoslib/AltosConfigValues.java b/altoslib/AltosConfigValues.java
index 3306aa4b..aab0892a 100644
--- a/altoslib/AltosConfigValues.java
+++ b/altoslib/AltosConfigValues.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosConfigValues {
/* set and get all of the dialog values */
@@ -45,8 +45,6 @@ public interface AltosConfigValues {
public abstract void set_radio_calibration(int new_radio_calibration);
- public abstract int radio_calibration() throws AltosConfigDataException;
-
public abstract void set_radio_enable(int new_radio_enable);
public abstract int radio_enable();
diff --git a/altoslib/AltosConvert.java b/altoslib/AltosConvert.java
index 59092a6f..265b5f0f 100644
--- a/altoslib/AltosConvert.java
+++ b/altoslib/AltosConvert.java
@@ -18,7 +18,7 @@
/*
* Sensor data conversion functions
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosConvert {
/*
@@ -325,6 +325,14 @@ public class AltosConvert {
return miles_to_meters(mps) / 3600;
}
+ public static double mps_to_fps(double mps) {
+ return meters_to_miles(mps) * 5280;
+ }
+
+ public static double fps_to_mps(double mps) {
+ return miles_to_meters(mps) / 5280;
+ }
+
public static double meters_to_mach(double meters) {
return meters / 343; /* something close to mach at usual rocket sites */
}
diff --git a/altoslib/AltosDebug.java b/altoslib/AltosDebug.java
index 35f51dd4..e93c2d2d 100644
--- a/altoslib/AltosDebug.java
+++ b/altoslib/AltosDebug.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
diff --git a/altoslib/AltosDistance.java b/altoslib/AltosDistance.java
index fe18250e..b68a4525 100644
--- a/altoslib/AltosDistance.java
+++ b/altoslib/AltosDistance.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosDistance extends AltosUnits {
diff --git a/altoslib/AltosEeprom.java b/altoslib/AltosEeprom.java
index 7379b510..5f0a349f 100644
--- a/altoslib/AltosEeprom.java
+++ b/altoslib/AltosEeprom.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
diff --git a/altoslib/AltosEepromChunk.java b/altoslib/AltosEepromChunk.java
index b996eb00..7a80e294 100644
--- a/altoslib/AltosEepromChunk.java
+++ b/altoslib/AltosEepromChunk.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.text.*;
import java.util.concurrent.*;
@@ -69,7 +69,7 @@ public class AltosEepromChunk {
eeprom = new AltosEepromTM(this, offset);
break;
case AltosLib.AO_LOG_FORMAT_TINY:
- eeprom = new AltosEepromTm(this, offset, state);
+ eeprom = new AltosEepromTMini(this, offset, state);
break;
case AltosLib.AO_LOG_FORMAT_TELEMETRY:
case AltosLib.AO_LOG_FORMAT_TELESCIENCE:
diff --git a/altoslib/AltosEepromDownload.java b/altoslib/AltosEepromDownload.java
index 67f7fc57..1a02cb9c 100644
--- a/altoslib/AltosEepromDownload.java
+++ b/altoslib/AltosEepromDownload.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
diff --git a/altoslib/AltosEepromFile.java b/altoslib/AltosEepromFile.java
index d88aeab9..000bb1be 100644
--- a/altoslib/AltosEepromFile.java
+++ b/altoslib/AltosEepromFile.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
@@ -89,7 +89,7 @@ public class AltosEepromFile extends AltosStateIterable {
body = new AltosEepromIterable(AltosEepromTM.read(input));
break;
case AltosLib.AO_LOG_FORMAT_TINY:
- body = new AltosEepromIterable(AltosEepromTm.read(input));
+ body = new AltosEepromIterable(AltosEepromTMini.read(input));
break;
case AltosLib.AO_LOG_FORMAT_TELEMETRY:
case AltosLib.AO_LOG_FORMAT_TELESCIENCE:
diff --git a/altoslib/AltosEepromGPS.java b/altoslib/AltosEepromGPS.java
index 07ef2920..a0a074ee 100644
--- a/altoslib/AltosEepromGPS.java
+++ b/altoslib/AltosEepromGPS.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
diff --git a/altoslib/AltosEepromHeader.java b/altoslib/AltosEepromHeader.java
index e7ed93b0..6c8c56d4 100644
--- a/altoslib/AltosEepromHeader.java
+++ b/altoslib/AltosEepromHeader.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
diff --git a/altoslib/AltosEepromIterable.java b/altoslib/AltosEepromIterable.java
index f607fbd2..97bb9285 100644
--- a/altoslib/AltosEepromIterable.java
+++ b/altoslib/AltosEepromIterable.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
diff --git a/altoslib/AltosEepromList.java b/altoslib/AltosEepromList.java
index 12d10b6e..4d511ead 100644
--- a/altoslib/AltosEepromList.java
+++ b/altoslib/AltosEepromList.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
diff --git a/altoslib/AltosEepromLog.java b/altoslib/AltosEepromLog.java
index d1a1ab6c..f0ed2db4 100644
--- a/altoslib/AltosEepromLog.java
+++ b/altoslib/AltosEepromLog.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.text.*;
import java.util.concurrent.*;
diff --git a/altoslib/AltosEepromMega.java b/altoslib/AltosEepromMega.java
index db8ab3a8..29f0aa90 100644
--- a/altoslib/AltosEepromMega.java
+++ b/altoslib/AltosEepromMega.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
diff --git a/altoslib/AltosEepromMetrum2.java b/altoslib/AltosEepromMetrum2.java
index df0075b9..5662c8e5 100644
--- a/altoslib/AltosEepromMetrum2.java
+++ b/altoslib/AltosEepromMetrum2.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
diff --git a/altoslib/AltosEepromMini.java b/altoslib/AltosEepromMini.java
index 228145eb..f429a0e8 100644
--- a/altoslib/AltosEepromMini.java
+++ b/altoslib/AltosEepromMini.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
diff --git a/altoslib/AltosEepromMonitor.java b/altoslib/AltosEepromMonitor.java
index 800dc0b9..a966c631 100644
--- a/altoslib/AltosEepromMonitor.java
+++ b/altoslib/AltosEepromMonitor.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosEepromMonitor {
diff --git a/altoslib/AltosEepromTM.java b/altoslib/AltosEepromTM.java
index 316058e2..7a27a234 100644
--- a/altoslib/AltosEepromTM.java
+++ b/altoslib/AltosEepromTM.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
diff --git a/altoslib/AltosEepromTm.java b/altoslib/AltosEepromTMini.java
index 090b65e3..8f01c088 100644
--- a/altoslib/AltosEepromTm.java
+++ b/altoslib/AltosEepromTMini.java
@@ -15,13 +15,13 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
import java.text.*;
-public class AltosEepromTm extends AltosEeprom {
+public class AltosEepromTMini extends AltosEeprom {
public int i;
public int a;
public int b;
@@ -58,7 +58,7 @@ public class AltosEepromTm extends AltosEeprom {
}
}
- public AltosEepromTm (AltosEepromChunk chunk, int start, AltosState state) throws ParseException {
+ public AltosEepromTMini (AltosEepromChunk chunk, int start, AltosState state) throws ParseException {
int value = chunk.data16(start);
int i = (chunk.address + start) / record_length;
@@ -100,7 +100,7 @@ public class AltosEepromTm extends AltosEeprom {
}
}
- public AltosEepromTm (String line) {
+ public AltosEepromTMini (String line) {
valid = false;
tick = 0;
a = 0;
@@ -130,7 +130,7 @@ public class AltosEepromTm extends AltosEeprom {
}
}
- public AltosEepromTm(int in_cmd, int in_tick, int in_a, int in_b) {
+ public AltosEepromTMini(int in_cmd, int in_tick, int in_a, int in_b) {
valid = true;
cmd = in_cmd;
tick = in_tick;
@@ -146,7 +146,7 @@ public class AltosEepromTm extends AltosEeprom {
String line = AltosLib.gets(input);
if (line == null)
break;
- AltosEepromTm tm = new AltosEepromTm(line);
+ AltosEepromTMini tm = new AltosEepromTMini(line);
tms.add(tm);
} catch (IOException ie) {
break;
diff --git a/altoslib/AltosFile.java b/altoslib/AltosFile.java
index b8d62179..d1d17610 100644
--- a/altoslib/AltosFile.java
+++ b/altoslib/AltosFile.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.File;
import java.util.*;
diff --git a/altoslib/AltosFlash.java b/altoslib/AltosFlash.java
index 627b758b..d79edf68 100644
--- a/altoslib/AltosFlash.java
+++ b/altoslib/AltosFlash.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
diff --git a/altoslib/AltosFlashListener.java b/altoslib/AltosFlashListener.java
index e977c579..8d171baf 100644
--- a/altoslib/AltosFlashListener.java
+++ b/altoslib/AltosFlashListener.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosFlashListener {
public void position(String label, int percent);
diff --git a/altoslib/AltosFlightDisplay.java b/altoslib/AltosFlightDisplay.java
index 912f470f..4b57526a 100644
--- a/altoslib/AltosFlightDisplay.java
+++ b/altoslib/AltosFlightDisplay.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosFlightDisplay extends AltosUnitsListener, AltosFontListener {
void reset();
diff --git a/altoslib/AltosFlightReader.java b/altoslib/AltosFlightReader.java
index 84b2392b..62f24e9f 100644
--- a/altoslib/AltosFlightReader.java
+++ b/altoslib/AltosFlightReader.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.text.*;
import java.io.*;
diff --git a/altoslib/AltosFlightStats.java b/altoslib/AltosFlightStats.java
index 39e8cdae..1c7d67e0 100644
--- a/altoslib/AltosFlightStats.java
+++ b/altoslib/AltosFlightStats.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
@@ -57,7 +57,7 @@ public class AltosFlightStats {
}
if (state == null)
- return 0;
+ return AltosLib.MISSING;
double landed_height = state.height();
@@ -65,7 +65,7 @@ public class AltosFlightStats {
boolean above = true;
- double landed_time = -1000;
+ double landed_time = AltosLib.MISSING;
for (AltosState s : states) {
state = s;
@@ -73,14 +73,12 @@ public class AltosFlightStats {
if (state.height() > landed_height + 10) {
above = true;
} else {
- if (above && state.height() < landed_height + 2) {
+ if (above && Math.abs(state.height() - landed_height) < 2) {
above = false;
landed_time = state.time;
}
}
}
- if (landed_time == -1000)
- landed_time = state.time;
return landed_time;
}
@@ -96,10 +94,8 @@ public class AltosFlightStats {
break;
}
if (state == null)
- return 0;
+ return AltosLib.MISSING;
- if (boost_time == AltosLib.MISSING)
- boost_time = state.time;
return boost_time;
}
@@ -122,6 +118,13 @@ public class AltosFlightStats {
has_imu = false;
has_mag = false;
has_orient = false;
+
+ for (int s = AltosLib.ao_flight_startup; s <= AltosLib.ao_flight_landed; s++) {
+ state_count[s] = 0;
+ state_speed[s] = 0.0;
+ state_accel[s] = 0.0;
+ }
+
for (AltosState state : states) {
if (serial == AltosLib.MISSING && state.serial != AltosLib.MISSING)
serial = state.serial;
@@ -139,10 +142,13 @@ public class AltosFlightStats {
has_flight_data = true;
int state_id = state.state();
- if (state.time >= boost_time && state_id < AltosLib.ao_flight_boost)
+ if (boost_time != AltosLib.MISSING && state.time >= boost_time && state_id < AltosLib.ao_flight_boost) {
state_id = AltosLib.ao_flight_boost;
- if (state.time >= landed_time && state_id < AltosLib.ao_flight_landed)
+ }
+ if (landed_time != AltosLib.MISSING && state.time >= landed_time && state_id < AltosLib.ao_flight_landed) {
state_id = AltosLib.ao_flight_landed;
+ }
+
if (state.gps != null && state.gps.locked) {
year = state.gps.year;
month = state.gps.month;
diff --git a/altoslib/AltosFontListener.java b/altoslib/AltosFontListener.java
index ae23e13c..565f50e4 100644
--- a/altoslib/AltosFontListener.java
+++ b/altoslib/AltosFontListener.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosFontListener {
void font_size_changed(int font_size);
diff --git a/altoslib/AltosFrequency.java b/altoslib/AltosFrequency.java
index 7c6ffe61..9542fe33 100644
--- a/altoslib/AltosFrequency.java
+++ b/altoslib/AltosFrequency.java
@@ -15,9 +15,13 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
-public class AltosFrequency {
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
+public class AltosFrequency implements Serializable {
public double frequency;
public String description;
@@ -44,6 +48,10 @@ public class AltosFrequency {
frequency, description);
}
+ public String frequency_string() {
+ return String.format("%7.3f", frequency);
+ }
+
public boolean close(double f) {
double diff = Math.abs(frequency - f);
diff --git a/altoslib/AltosGPS.java b/altoslib/AltosGPS.java
index a4cd2061..c5290a3a 100644
--- a/altoslib/AltosGPS.java
+++ b/altoslib/AltosGPS.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.text.*;
import java.util.concurrent.*;
diff --git a/altoslib/AltosGPSSat.java b/altoslib/AltosGPSSat.java
index 3f9e479e..c853b634 100644
--- a/altoslib/AltosGPSSat.java
+++ b/altoslib/AltosGPSSat.java
@@ -15,9 +15,12 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
+import java.text.*;
+import java.util.concurrent.*;
+import java.io.*;
-public class AltosGPSSat {
+public class AltosGPSSat implements Serializable {
public int svid;
public int c_n0;
diff --git a/altoslib/AltosGreatCircle.java b/altoslib/AltosGreatCircle.java
index 9ced17e7..de3904bf 100644
--- a/altoslib/AltosGreatCircle.java
+++ b/altoslib/AltosGreatCircle.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.lang.Math;
import java.io.*;
diff --git a/altoslib/AltosHeight.java b/altoslib/AltosHeight.java
index 5cc3c20c..2bae2566 100644
--- a/altoslib/AltosHeight.java
+++ b/altoslib/AltosHeight.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosHeight extends AltosUnits {
diff --git a/altoslib/AltosHexfile.java b/altoslib/AltosHexfile.java
index fb036d0c..f72d4183 100644
--- a/altoslib/AltosHexfile.java
+++ b/altoslib/AltosHexfile.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.LinkedList;
diff --git a/altoslib/AltosHexsym.java b/altoslib/AltosHexsym.java
index 0149fde1..1d9cbb18 100644
--- a/altoslib/AltosHexsym.java
+++ b/altoslib/AltosHexsym.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosHexsym {
String name;
diff --git a/altoslib/AltosIMU.java b/altoslib/AltosIMU.java
index 285de8cc..62539e08 100644
--- a/altoslib/AltosIMU.java
+++ b/altoslib/AltosIMU.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.*;
import java.io.*;
diff --git a/altoslib/AltosIdle.java b/altoslib/AltosIdle.java
index 2e5981db..07a628c3 100644
--- a/altoslib/AltosIdle.java
+++ b/altoslib/AltosIdle.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
diff --git a/altoslib/AltosIdleFetch.java b/altoslib/AltosIdleFetch.java
index 48db6ab4..0095bb73 100644
--- a/altoslib/AltosIdleFetch.java
+++ b/altoslib/AltosIdleFetch.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
@@ -40,7 +40,7 @@ class AltosIdler {
static final int idle_sensor_tmini = 14;
static final int idle_sensor_tgps = 15;
- public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException, TimeoutException {
+ public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException, TimeoutException, AltosUnknownProduct {
for (int idler : idlers) {
AltosIdle idle = null;
switch (idler) {
@@ -137,8 +137,9 @@ public class AltosIdleFetch implements AltosStateUpdate {
double frequency;
String callsign;
- public void update_state(AltosState state) throws InterruptedException {
+ public void update_state(AltosState state) throws InterruptedException, AltosUnknownProduct {
try {
+ boolean matched = false;
/* Fetch config data from remote */
AltosConfigData config_data = new AltosConfigData(link);
state.set_state(AltosLib.ao_flight_stateless);
@@ -150,9 +151,12 @@ public class AltosIdleFetch implements AltosStateUpdate {
for (AltosIdler idler : idlers) {
if (idler.matches(config_data)) {
idler.update_state(state, link, config_data);
+ matched = true;
break;
}
}
+ if (!matched)
+ throw new AltosUnknownProduct(config_data.product);
state.set_received_time(System.currentTimeMillis());
} catch (TimeoutException te) {
}
diff --git a/altoslib/AltosIdleMonitor.java b/altoslib/AltosIdleMonitor.java
index d5c1a428..c67b4d8a 100644
--- a/altoslib/AltosIdleMonitor.java
+++ b/altoslib/AltosIdleMonitor.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.concurrent.*;
@@ -28,6 +28,7 @@ public class AltosIdleMonitor extends Thread {
AltosIdleFetch fetch;
boolean remote;
+ boolean close_on_exit;
double frequency;
String callsign;
@@ -50,7 +51,7 @@ public class AltosIdleMonitor extends Thread {
return link.reply_abort;
}
- boolean update_state(AltosState state) throws InterruptedException, TimeoutException {
+ boolean update_state(AltosState state) throws InterruptedException, TimeoutException, AltosUnknownProduct {
boolean worked = false;
boolean aborted = false;
@@ -98,6 +99,8 @@ public class AltosIdleMonitor extends Thread {
update_state(state);
listener.update(state, listener_state);
} catch (TimeoutException te) {
+ } catch (AltosUnknownProduct ae) {
+ listener.error(String.format("Unknown product \"%s\"", ae.product));
}
if (link.has_error || link.reply_abort) {
listener.failed();
@@ -107,18 +110,25 @@ public class AltosIdleMonitor extends Thread {
}
} catch (InterruptedException ie) {
}
- try {
- link.close();
- } catch (InterruptedException ie) {
+ if (close_on_exit) {
+ try {
+ link.close();
+ } catch (InterruptedException ie) {
+ }
}
}
- public AltosIdleMonitor(AltosIdleMonitorListener in_listener, AltosLink in_link, boolean in_remote)
- throws FileNotFoundException, InterruptedException, TimeoutException {
+ public AltosIdleMonitor(AltosIdleMonitorListener in_listener, AltosLink in_link, boolean in_remote, boolean in_close_on_exit) {
listener = in_listener;
link = in_link;
remote = in_remote;
+ close_on_exit = in_close_on_exit;
listener_state = new AltosListenerState();
fetch = new AltosIdleFetch(link);
}
+
+ public AltosIdleMonitor(AltosIdleMonitorListener in_listener, AltosLink in_link, boolean in_remote) {
+ this(in_listener, in_link, in_remote, true);
+ }
}
+
diff --git a/altoslib/AltosIdleMonitorListener.java b/altoslib/AltosIdleMonitorListener.java
index 5b751e52..36857f58 100644
--- a/altoslib/AltosIdleMonitorListener.java
+++ b/altoslib/AltosIdleMonitorListener.java
@@ -15,9 +15,10 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosIdleMonitorListener {
public void update(AltosState state, AltosListenerState listener_state);
+ public void error(String reason);
public void failed();
}
diff --git a/altoslib/AltosIgnite.java b/altoslib/AltosIgnite.java
index d5348628..ab9c2da6 100644
--- a/altoslib/AltosIgnite.java
+++ b/altoslib/AltosIgnite.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.*;
import java.io.*;
@@ -24,6 +24,7 @@ import java.util.concurrent.*;
public class AltosIgnite {
AltosLink link;
boolean remote;
+ boolean close_on_exit;
boolean link_started;
boolean have_npyro = false;
int npyro;
@@ -180,14 +181,18 @@ public class AltosIgnite {
public void close() throws InterruptedException {
stop_link();
- link.close();
+ if (close_on_exit)
+ link.close();
link = null;
}
- public AltosIgnite(AltosLink in_link, boolean in_remote)
- throws FileNotFoundException, TimeoutException, InterruptedException {
-
+ public AltosIgnite(AltosLink in_link, boolean in_remote, boolean in_close_on_exit) {
link = in_link;
remote = in_remote;
+ close_on_exit = in_close_on_exit;
+ }
+
+ public AltosIgnite(AltosLink in_link, boolean in_remote) {
+ this(in_link, in_remote, true);
}
-} \ No newline at end of file
+}
diff --git a/altoslib/AltosImage.java b/altoslib/AltosImage.java
index 7a0fe9dd..d54335c7 100644
--- a/altoslib/AltosImage.java
+++ b/altoslib/AltosImage.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
diff --git a/altoslib/AltosKML.java b/altoslib/AltosKML.java
index d302535f..ac5e0257 100644
--- a/altoslib/AltosKML.java
+++ b/altoslib/AltosKML.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
diff --git a/altoslib/AltosLatLon.java b/altoslib/AltosLatLon.java
index 8cd851e5..d39fe15f 100644
--- a/altoslib/AltosLatLon.java
+++ b/altoslib/AltosLatLon.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosLatLon {
public double lat;
diff --git a/altoslib/AltosLatitude.java b/altoslib/AltosLatitude.java
index 51d77785..e0deb504 100644
--- a/altoslib/AltosLatitude.java
+++ b/altoslib/AltosLatitude.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosLatitude extends AltosLocation {
public String pos() { return "N"; }
diff --git a/altoslib/AltosLaunchSite.java b/altoslib/AltosLaunchSite.java
index 7958d186..ee2a60e9 100644
--- a/altoslib/AltosLaunchSite.java
+++ b/altoslib/AltosLaunchSite.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.lang.*;
diff --git a/altoslib/AltosLaunchSiteListener.java b/altoslib/AltosLaunchSiteListener.java
index 4270dc4a..c77eadc5 100644
--- a/altoslib/AltosLaunchSiteListener.java
+++ b/altoslib/AltosLaunchSiteListener.java
@@ -14,7 +14,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.lang.*;
diff --git a/altoslib/AltosLaunchSites.java b/altoslib/AltosLaunchSites.java
index 4e843c10..3ebac601 100644
--- a/altoslib/AltosLaunchSites.java
+++ b/altoslib/AltosLaunchSites.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.lang.*;
@@ -47,7 +47,12 @@ public class AltosLaunchSites extends Thread {
public void run() {
try {
- url = new URL(AltosLib.launch_sites_url);
+ String path;
+
+ path = System.getenv(AltosLib.launch_sites_env);
+ if (path == null)
+ path = AltosLib.launch_sites_url;
+ url = new URL(path);
URLConnection uc = url.openConnection();
InputStreamReader in_stream = new InputStreamReader(uc.getInputStream(), AltosLib.unicode_set);
@@ -60,6 +65,7 @@ public class AltosLaunchSites extends Thread {
add(line);
}
} catch (Exception e) {
+ System.out.printf("file exception %s\n", e.toString());
} finally {
notify_complete();
}
diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java
index 575cfc1a..a73a7759 100644
--- a/altoslib/AltosLib.java
+++ b/altoslib/AltosLib.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.*;
import java.io.*;
@@ -198,6 +198,7 @@ public class AltosLib {
};
public static final String launch_sites_url = "http://www.altusmetrum.org/AltOS/launch-sites.txt";
+ public static final String launch_sites_env = "LAUNCH_SITES";
// public static final String launch_sites_url = "file:///home/keithp/misc/text/altusmetrum/AltOS/launch-sites.txt";
public static final int ao_telemetry_standard_len = 32;
diff --git a/altoslib/AltosLine.java b/altoslib/AltosLine.java
index cf3a1984..876cb7df 100644
--- a/altoslib/AltosLine.java
+++ b/altoslib/AltosLine.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosLine {
public String line;
diff --git a/altoslib/AltosLink.java b/altoslib/AltosLink.java
index 10967417..cd8609c0 100644
--- a/altoslib/AltosLink.java
+++ b/altoslib/AltosLink.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.concurrent.*;
@@ -170,8 +170,8 @@ public abstract class AltosLink implements Runnable {
boolean can_cancel = can_cancel_reply();
String reply = null;
- if (!can_cancel && remote)
- System.out.printf("Uh-oh, reading remote serial device from swing thread\n");
+// if (!can_cancel && remote)
+// System.out.printf("Uh-oh, reading remote serial device from swing thread\n");
if (remote && can_cancel) {
timeout = 500;
@@ -539,15 +539,15 @@ public abstract class AltosLink implements Runnable {
if (config_data.has_monitor_battery()) {
try {
- String[] items = adc();
- for (int i = 0; i < items.length;) {
- if (items[i].equals("batt")) {
- monitor_batt = Integer.parseInt(items[i+1]);
- i += 2;
- continue;
+ String[] items = adc();
+ for (int i = 0; i < items.length;) {
+ if (items[i].equals("batt")) {
+ monitor_batt = Integer.parseInt(items[i+1]);
+ i += 2;
+ continue;
+ }
+ i++;
}
- i++;
- }
} catch (TimeoutException te) {
}
}
diff --git a/altoslib/AltosListenerState.java b/altoslib/AltosListenerState.java
index 7df5c9bf..389e392f 100644
--- a/altoslib/AltosListenerState.java
+++ b/altoslib/AltosListenerState.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
diff --git a/altoslib/AltosLocation.java b/altoslib/AltosLocation.java
index 436e4b02..df1c9d63 100644
--- a/altoslib/AltosLocation.java
+++ b/altoslib/AltosLocation.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public abstract class AltosLocation extends AltosUnits {
diff --git a/altoslib/AltosLog.java b/altoslib/AltosLog.java
index 58306d55..a6e04215 100644
--- a/altoslib/AltosLog.java
+++ b/altoslib/AltosLog.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.text.*;
diff --git a/altoslib/AltosLongitude.java b/altoslib/AltosLongitude.java
index bc088602..61d74afc 100644
--- a/altoslib/AltosLongitude.java
+++ b/altoslib/AltosLongitude.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosLongitude extends AltosLocation {
public String pos() { return "E"; }
diff --git a/altoslib/AltosMag.java b/altoslib/AltosMag.java
index 3643ca9e..ce5a48c3 100644
--- a/altoslib/AltosMag.java
+++ b/altoslib/AltosMag.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.*;
import java.io.*;
diff --git a/altoslib/AltosMap.java b/altoslib/AltosMap.java
index 6c08f2d7..1841277f 100644
--- a/altoslib/AltosMap.java
+++ b/altoslib/AltosMap.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.lang.*;
@@ -308,7 +308,11 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener {
upper_left = floor(transform.screen_point(new AltosPointInt(0, 0)));
lower_right = floor(transform.screen_point(new AltosPointInt(width(), height())));
}
- for (AltosPointInt point : tiles.keySet()) {
+
+ Enumeration<AltosPointInt> keyEnumeration = tiles.keys();
+
+ while (keyEnumeration.hasMoreElements()) {
+ AltosPointInt point = keyEnumeration.nextElement();
if (point.x < upper_left.x || lower_right.x < point.x ||
point.y < upper_left.y || lower_right.y < point.y) {
tiles.remove(point);
@@ -324,7 +328,8 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener {
if (!tiles.containsKey(point)) {
AltosLatLon ul = transform.lat_lon(point);
AltosLatLon center = transform.lat_lon(new AltosPointDouble(x + AltosMap.px_size/2, y + AltosMap.px_size/2));
- AltosMapTile tile = map_interface.new_tile(this, ul, center, zoom, maptype, px_size);
+ AltosMapTile tile = map_interface.new_tile(cache, ul, center, zoom, maptype, px_size);
+ tile.add_listener(this);
tiles.put(point, tile);
}
}
@@ -341,11 +346,6 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener {
centre(lat, lon);
tiles.clear();
make_tiles();
- for (AltosMapTile tile : tiles.values()) {
- tile.add_store_listener(this);
- if (tile.store_status() != AltosMapTile.loading)
- listener.notify_tile(tile, tile.store_status());
- }
repaint();
}
@@ -377,7 +377,10 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener {
/* AltosMapTileListener methods */
public synchronized void notify_tile(AltosMapTile tile, int status) {
- for (AltosPointInt point : tiles.keySet()) {
+ Enumeration<AltosPointInt> keyEnumeration = tiles.keys();
+
+ while (keyEnumeration.hasMoreElements()) {
+ AltosPointInt point = keyEnumeration.nextElement();
if (tile == tiles.get(point)) {
AltosPointInt screen = transform.screen(point);
repaint(screen.x, screen.y, AltosMap.px_size, AltosMap.px_size);
@@ -414,10 +417,8 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener {
if (distance > drag_far)
dragged = true;
- if (transform == null) {
- debug("Transform not set in drag\n");
+ if (transform == null)
return;
- }
AltosLatLon new_centre = transform.screen_lat_lon(new AltosPointInt(width() / 2 - dx, height() / 2 - dy));
centre(new_centre);
@@ -432,7 +433,6 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener {
private void drag_stop(int x, int y) {
if (!dragged) {
if (transform == null) {
- debug("Transform not set in stop\n");
return;
}
map_interface.select_object (transform.screen_lat_lon(new AltosPointInt(x,y)));
@@ -440,14 +440,14 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener {
}
private void line_start(int x, int y) {
- if (line != null) {
+ if (line != null && transform != null) {
line.pressed(new AltosPointInt(x, y), transform);
repaint();
}
}
private void line(int x, int y) {
- if (line != null) {
+ if (line != null && transform != null) {
line.dragged(new AltosPointInt(x, y), transform);
repaint();
}
diff --git a/altoslib/AltosMapCache.java b/altoslib/AltosMapCache.java
index 744790c6..38e0f769 100644
--- a/altoslib/AltosMapCache.java
+++ b/altoslib/AltosMapCache.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.net.*;
@@ -23,25 +23,20 @@ import java.net.*;
public class AltosMapCache implements AltosMapCacheListener {
/* An entry in the MapCache */
- class MapCacheElement implements AltosMapStoreListener {
+ class MapCacheElement implements AltosMapTileListener {
AltosMapTile tile; /* Notify when image has been loaded */
AltosImage image;
- AltosMapStore store;
long used;
class loader implements Runnable {
public void run() {
- if (image != null)
- tile.notify_image(image);
- try {
- image = map_interface.load_image(store.file);
- } catch (Exception ex) {
+ if (image == null) {
+ try {
+ image = map_interface.load_image(tile.store.file);
+ } catch (Exception ex) {
+ }
}
- if (image == null)
- tile.set_status(AltosMapTile.failed);
- else
- tile.set_status(AltosMapTile.success);
tile.notify_image(image);
}
}
@@ -60,41 +55,21 @@ public class AltosMapCache implements AltosMapCacheListener {
}
public boolean has_map() {
- return store.status() == AltosMapTile.success;
+ return tile.status == AltosMapTile.loaded;
}
- public synchronized void notify_store(AltosMapStore store, int status) {
- switch (status) {
- case AltosMapTile.loading:
- break;
- case AltosMapTile.success:
+ public synchronized void notify_tile(AltosMapTile tile, int status) {
+ if (status == AltosMapTile.fetched) {
+ System.out.printf("tile fetched, loading image\n");
load();
- break;
- default:
- tile.set_status(status);
- tile.notify_image(null);
}
}
- public MapCacheElement(AltosMapTile tile, AltosMapStore store) throws IOException {
+ public MapCacheElement(AltosMapTile tile) {
this.tile = tile;
this.image = null;
- this.store = store;
this.used = 0;
-
- int status = store.status();
- switch (status) {
- case AltosMapTile.loading:
- store.add_listener(this);
- break;
- case AltosMapTile.success:
- load();
- break;
- default:
- tile.set_status(status);
- tile.notify_image(null);
- break;
- }
+ tile.add_listener(this);
}
}
@@ -135,7 +110,7 @@ public class AltosMapCache implements AltosMapCacheListener {
}
}
- public AltosImage get(AltosMapTile tile, AltosMapStore store, int width, int height) {
+ public AltosImage get(AltosMapTile tile) {
int oldest = -1;
long age = used;
@@ -148,7 +123,7 @@ public class AltosMapCache implements AltosMapCacheListener {
oldest = i;
break;
}
- if (store.equals(element.store)) {
+ if (tile.store.equals(element.tile.store)) {
element.used = used++;
return element.image;
}
@@ -158,24 +133,15 @@ public class AltosMapCache implements AltosMapCacheListener {
}
}
- try {
- element = new MapCacheElement(tile, store);
- element.used = used++;
- if (elements[oldest] != null)
- elements[oldest].flush();
+ element = new MapCacheElement(tile);
+ element.used = used++;
+ if (elements[oldest] != null)
+ elements[oldest].flush();
- elements[oldest] = element;
-
- if (element.image == null)
- tile.set_status(AltosMapTile.loading);
- else
- tile.set_status(AltosMapTile.success);
-
- return element.image;
- } catch (IOException e) {
- tile.set_status(AltosMapTile.failed);
- return null;
- }
+ elements[oldest] = element;
+ System.out.printf("AltosMapCache.get image ? %s\n",
+ element.image == null ? "false" : "true");
+ return element.image;
}
}
diff --git a/altoslib/AltosMapCacheListener.java b/altoslib/AltosMapCacheListener.java
index c0409630..4984d9e5 100644
--- a/altoslib/AltosMapCacheListener.java
+++ b/altoslib/AltosMapCacheListener.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosMapCacheListener {
public void map_cache_changed(int map_cache);
diff --git a/altoslib/AltosMapInterface.java b/altoslib/AltosMapInterface.java
index 0a59a808..756a78f2 100644
--- a/altoslib/AltosMapInterface.java
+++ b/altoslib/AltosMapInterface.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.net.*;
@@ -29,7 +29,7 @@ public interface AltosMapInterface {
public abstract AltosMapMark new_mark(double lat, double lon, int state);
- public abstract AltosMapTile new_tile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size);
+ public abstract AltosMapTile new_tile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size);
public abstract int width();
diff --git a/altoslib/AltosMapLine.java b/altoslib/AltosMapLine.java
index 061f226e..bd590136 100644
--- a/altoslib/AltosMapLine.java
+++ b/altoslib/AltosMapLine.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.lang.Math;
diff --git a/altoslib/AltosMapLoader.java b/altoslib/AltosMapLoader.java
index 9ed93a42..7112a1c4 100644
--- a/altoslib/AltosMapLoader.java
+++ b/altoslib/AltosMapLoader.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
@@ -24,7 +24,7 @@ import java.lang.Math;
import java.net.URL;
import java.net.URLConnection;
-public class AltosMapLoader implements AltosMapTileListener, AltosMapStoreListener {
+public class AltosMapLoader extends Thread implements AltosMapTileListener {
AltosMapLoaderListener listener;
double latitude, longitude;
@@ -88,14 +88,11 @@ public class AltosMapLoader implements AltosMapTileListener, AltosMapStoreListen
for (int y = (int) upper_left.y; y <= lower_right.y; y += AltosMap.px_size) {
for (int x = (int) upper_left.x; x <= lower_right.x; x += AltosMap.px_size) {
- listener.debug("Make tile at %d, %d\n", x, y);
AltosPointInt point = new AltosPointInt(x, y);
AltosLatLon ul = transform.lat_lon(point);
AltosLatLon center = transform.lat_lon(new AltosPointDouble(x + AltosMap.px_size/2, y + AltosMap.px_size/2));
- AltosMapTile tile = map.map_interface.new_tile(this, ul, center, zoom, maptype, AltosMap.px_size);
- tile.add_store_listener(this);
- if (tile.store_status() != AltosMapTile.loading)
- notify_tile(tile, tile.store_status());
+ AltosMapTile tile = map.map_interface.new_tile(null, ul, center, zoom, maptype, AltosMap.px_size);
+ tile.add_listener(this);
}
}
}
@@ -124,7 +121,7 @@ public class AltosMapLoader implements AltosMapTileListener, AltosMapStoreListen
do_load();
}
- private void start_load() {
+ public void run() {
cur_z = min_z;
int ntype = 0;
@@ -139,67 +136,64 @@ public class AltosMapLoader implements AltosMapTileListener, AltosMapStoreListen
cur_type = next_type(0);
+ tiles_total = 0;
for (int z = min_z; z <= max_z; z++)
- tiles_total += tiles_per_layer(z);
+ tiles_total += tiles_per_layer(z) * ntype;
layers_total = (max_z - min_z + 1) * ntype;
layers_loaded = 0;
tiles_loaded_total = 0;
- listener.debug("total tiles %d\n", tiles_total);
+ listener.debug("total tiles %d layers %d\n", tiles_total, layers_total);
listener.loader_start(tiles_total);
do_load();
}
- public void load(double latitude, double longitude, int min_z, int max_z, double radius, int all_types) {
- listener.debug("lat %f lon %f min_z %d max_z %d radius %f all_types %d\n",
- latitude, longitude, min_z, max_z, radius, all_types);
- this.latitude = latitude;
- this.longitude = longitude;
- this.min_z = min_z;
- this.max_z = max_z;
- this.radius = radius;
- this.all_types = all_types;
- start_load();
- }
-
- public synchronized void notify_store(AltosMapStore store, int status) {
+ public synchronized void notify_tile(AltosMapTile tile, int status) {
boolean do_next = false;
- if (status == AltosMapTile.loading)
+ if (status == AltosMapTile.fetching)
return;
+ tile.remove_listener(this);
+
if (layers_loaded >= layers_total)
return;
++tiles_loaded_total;
++tiles_loaded_layer;
- listener.debug("total %d layer %d\n", tiles_loaded_total, tiles_loaded_layer);
+
+ listener.debug("AltosMapLoader.notify_tile status %d total %d of %d layer %d of %d\n",
+ status, tiles_loaded_total, tiles_total, tiles_loaded_layer, tiles_this_layer);
if (tiles_loaded_layer == tiles_this_layer) {
++layers_loaded;
listener.debug("%d layers loaded\n", layers_loaded);
- if (layers_loaded == layers_total) {
- listener.loader_done(tiles_total);
- return;
- } else {
- do_next = true;
- }
+ do_next = true;
}
- listener.loader_notify(tiles_loaded_total,
- tiles_total, store.file.toString());
- if (do_next)
- next_load();
- }
- public synchronized void notify_tile(AltosMapTile tile, int status) {
- notify_store(tile.store, status);
+ if (tiles_loaded_total == tiles_total)
+ listener.loader_done(tiles_total);
+ else {
+ listener.loader_notify(tiles_loaded_total,
+ tiles_total, tile.store.file.toString());
+ if (do_next)
+ next_load();
+ }
}
- public AltosMapCache cache() { return map.cache(); }
-
- public AltosMapLoader(AltosMap map, AltosMapLoaderListener listener) {
+ public AltosMapLoader(AltosMap map, AltosMapLoaderListener listener,
+ double latitude, double longitude, int min_z, int max_z, double radius, int all_types) {
+ listener.debug("lat %f lon %f min_z %d max_z %d radius %f all_types %d\n",
+ latitude, longitude, min_z, max_z, radius, all_types);
this.map = map;
this.listener = listener;
+ this.latitude = latitude;
+ this.longitude = longitude;
+ this.min_z = min_z;
+ this.max_z = max_z;
+ this.radius = radius;
+ this.all_types = all_types;
+ start();
}
}
diff --git a/altoslib/AltosMapLoaderListener.java b/altoslib/AltosMapLoaderListener.java
index 798270cc..47d7b858 100644
--- a/altoslib/AltosMapLoaderListener.java
+++ b/altoslib/AltosMapLoaderListener.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosMapLoaderListener {
public abstract void loader_start(int max);
diff --git a/altoslib/AltosMapMark.java b/altoslib/AltosMapMark.java
index e87c168d..db714922 100644
--- a/altoslib/AltosMapMark.java
+++ b/altoslib/AltosMapMark.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.lang.Math;
diff --git a/altoslib/AltosMapPath.java b/altoslib/AltosMapPath.java
index 64be49be..6f6db4f4 100644
--- a/altoslib/AltosMapPath.java
+++ b/altoslib/AltosMapPath.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.lang.Math;
diff --git a/altoslib/AltosMapPathPoint.java b/altoslib/AltosMapPathPoint.java
index d500a7db..5b46cb19 100644
--- a/altoslib/AltosMapPathPoint.java
+++ b/altoslib/AltosMapPathPoint.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.lang.Math;
diff --git a/altoslib/AltosMapRectangle.java b/altoslib/AltosMapRectangle.java
index 9c116b82..b6294a4e 100644
--- a/altoslib/AltosMapRectangle.java
+++ b/altoslib/AltosMapRectangle.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosMapRectangle {
AltosLatLon ul, lr;
diff --git a/altoslib/AltosMapStore.java b/altoslib/AltosMapStore.java
index c0638433..aed365ca 100644
--- a/altoslib/AltosMapStore.java
+++ b/altoslib/AltosMapStore.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.net.*;
@@ -35,6 +35,7 @@ public class AltosMapStore {
public synchronized void add_listener(AltosMapStoreListener listener) {
if (!listeners.contains(listener))
listeners.add(listener);
+ listener.notify_store(this, status);
}
public synchronized void remove_listener(AltosMapStoreListener listener) {
@@ -110,7 +111,7 @@ public class AltosMapStore {
file.delete();
return AltosMapTile.bad_request;
}
- return AltosMapTile.success;
+ return AltosMapTile.fetched;
}
static Object fetch_lock = new Object();
@@ -118,42 +119,42 @@ public class AltosMapStore {
static final long forbidden_interval = 60l * 1000l * 1000l * 1000l;
static final long google_maps_ratelimit_ms = 1200;
- static Object loader_lock = new Object();
+ static Object fetcher_lock = new Object();
static LinkedList<AltosMapStore> waiting = new LinkedList<AltosMapStore>();
static LinkedList<AltosMapStore> running = new LinkedList<AltosMapStore>();
- static final int concurrent_loaders = 128;
+ static final int concurrent_fetchers = 128;
- static void start_loaders() {
- while (!waiting.isEmpty() && running.size() < concurrent_loaders) {
+ static void start_fetchers() {
+ while (!waiting.isEmpty() && running.size() < concurrent_fetchers) {
AltosMapStore s = waiting.remove();
running.add(s);
- Thread lt = s.make_loader_thread();
+ Thread lt = s.make_fetcher_thread();
lt.start();
}
}
- void finish_loader() {
- synchronized(loader_lock) {
+ void finish_fetcher() {
+ synchronized(fetcher_lock) {
running.remove(this);
- start_loaders();
+ start_fetchers();
}
}
- void add_loader() {
- synchronized(loader_lock) {
+ void add_fetcher() {
+ synchronized(fetcher_lock) {
waiting.add(this);
- start_loaders();
+ start_fetchers();
}
}
- class loader implements Runnable {
+ class fetcher implements Runnable {
public void run() {
try {
if (file.exists()) {
- notify_listeners(AltosMapTile.success);
+ notify_listeners(AltosMapTile.fetched);
return;
}
@@ -170,7 +171,7 @@ public class AltosMapStore {
synchronized (fetch_lock) {
long startTime = System.nanoTime();
new_status = fetch_url();
- if (new_status == AltosMapTile.success) {
+ if (new_status == AltosMapTile.fetched) {
long duration_ms = (System.nanoTime() - startTime) / 1000000;
if (duration_ms < google_maps_ratelimit_ms) {
try {
@@ -186,17 +187,17 @@ public class AltosMapStore {
}
notify_listeners(new_status);
} finally {
- finish_loader();
+ finish_fetcher();
}
}
}
- private Thread make_loader_thread() {
- return new Thread(new loader());
+ private Thread make_fetcher_thread() {
+ return new Thread(new fetcher());
}
- private void load() {
- add_loader();
+ private void fetch() {
+ add_fetcher();
}
private AltosMapStore (String url, File file) {
@@ -204,10 +205,10 @@ public class AltosMapStore {
this.file = file;
if (file.exists())
- status = AltosMapTile.success;
+ status = AltosMapTile.fetched;
else {
- status = AltosMapTile.loading;
- load();
+ status = AltosMapTile.fetching;
+ fetch();
}
}
diff --git a/altoslib/AltosMapStoreListener.java b/altoslib/AltosMapStoreListener.java
index 8912caf7..65bd6ef8 100644
--- a/altoslib/AltosMapStoreListener.java
+++ b/altoslib/AltosMapStoreListener.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosMapStoreListener {
abstract void notify_store(AltosMapStore store, int status);
diff --git a/altoslib/AltosMapTile.java b/altoslib/AltosMapTile.java
index 23ab64e4..fdc8ff65 100644
--- a/altoslib/AltosMapTile.java
+++ b/altoslib/AltosMapTile.java
@@ -15,27 +15,28 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
-public abstract class AltosMapTile implements AltosFontListener {
- AltosMapTileListener listener;
+public abstract class AltosMapTile implements AltosFontListener, AltosMapStoreListener {
+ LinkedList<AltosMapTileListener> listeners = new LinkedList<AltosMapTileListener>();
public AltosLatLon upper_left, center;
public int px_size;
int zoom;
int maptype;
int scale;
+ private AltosMapCache cache;
public AltosMapStore store;
- public AltosMapCache cache;
public int status;
- static public final int success = 0;
- static public final int loading = 1;
- static public final int failed = 2;
- static public final int bad_request = 3;
- static public final int forbidden = 4;
+ static public final int loaded = 0; /* loaded from file */
+ static public final int fetched = 1; /* downloaded to file */
+ static public final int fetching = 2; /* downloading from net */
+ static public final int failed = 3; /* loading from file failed */
+ static public final int bad_request = 4;/* downloading failed */
+ static public final int forbidden = 5; /* downloading failed */
private File map_file() {
double lat = center.lat;
@@ -79,33 +80,46 @@ public abstract class AltosMapTile implements AltosFontListener {
public void font_size_changed(int font_size) {
}
- public void set_status(int status) {
+ private synchronized void notify_listeners(int status) {
this.status = status;
- listener.notify_tile(this, status);
+ for (AltosMapTileListener listener : listeners)
+ listener.notify_tile(this, status);
}
- public void notify_image(AltosImage image) {
- listener.notify_tile(this, status);
+ public void notify_store(AltosMapStore store, int status) {
+// System.out.printf("AltosMapTile.notify_store %d\n", status);
+ notify_listeners(status);
}
- public int store_status() {
- return store.status();
+ public void notify_image(AltosImage image) {
+ if (image == null)
+ status = failed;
+ else
+ status = loaded;
+ notify_listeners(status);
}
- public void add_store_listener(AltosMapStoreListener listener) {
- store.add_listener(listener);
+ public abstract void paint(AltosMapTransform t);
+
+ public AltosImage get_image() {
+ if (cache == null)
+ return null;
+ return cache.get(this);
}
- public void remove_store_listener(AltosMapStoreListener listener) {
- store.remove_listener(listener);
+ public synchronized void add_listener(AltosMapTileListener listener) {
+ if (!listeners.contains(listener))
+ listeners.add(listener);
+ listener.notify_tile(this, status);
}
- public abstract void paint(AltosMapTransform t);
+ public synchronized void remove_listener(AltosMapTileListener listener) {
+ listeners.remove(listener);
+ }
- public AltosMapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size, int scale) {
- this.listener = listener;
+ public AltosMapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size, int scale) {
+ this.cache = cache;
this.upper_left = upper_left;
- this.cache = listener.cache();
while (center.lon < -180.0)
center.lon += 360.0;
@@ -118,11 +132,11 @@ public abstract class AltosMapTile implements AltosFontListener {
this.px_size = px_size;
this.scale = scale;
- status = AltosMapTile.loading;
store = AltosMapStore.get(map_url(), map_file());
+ store.add_listener(this);
}
- public AltosMapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
- this(listener, upper_left, center, zoom, maptype, px_size, 1);
+ public AltosMapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
+ this(cache, upper_left, center, zoom, maptype, px_size, 1);
}
}
diff --git a/altoslib/AltosMapTileListener.java b/altoslib/AltosMapTileListener.java
index 83c1eaed..6d78b205 100644
--- a/altoslib/AltosMapTileListener.java
+++ b/altoslib/AltosMapTileListener.java
@@ -15,10 +15,8 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosMapTileListener {
abstract public void notify_tile(AltosMapTile tile, int status);
-
- abstract public AltosMapCache cache();
}
diff --git a/altoslib/AltosMapTransform.java b/altoslib/AltosMapTransform.java
index ae78befa..b8901127 100644
--- a/altoslib/AltosMapTransform.java
+++ b/altoslib/AltosMapTransform.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.lang.Math;
diff --git a/altoslib/AltosMapTypeListener.java b/altoslib/AltosMapTypeListener.java
new file mode 100644
index 00000000..b82bda3f
--- /dev/null
+++ b/altoslib/AltosMapTypeListener.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altoslib_10;
+
+public interface AltosMapTypeListener {
+ public void map_type_changed(int map_type);
+}
diff --git a/altoslib/AltosMapZoomListener.java b/altoslib/AltosMapZoomListener.java
index 5067aaec..51f8c3c5 100644
--- a/altoslib/AltosMapZoomListener.java
+++ b/altoslib/AltosMapZoomListener.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosMapZoomListener {
abstract public void zoom_changed(int zoom);
diff --git a/altoslib/AltosMma655x.java b/altoslib/AltosMma655x.java
index 17aaa3f8..b09ec74b 100644
--- a/altoslib/AltosMma655x.java
+++ b/altoslib/AltosMma655x.java
@@ -15,13 +15,13 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.*;
public class AltosMma655x implements Cloneable {
- int accel;
+ private int accel;
public boolean parse_line(String line) throws NumberFormatException {
if (line.startsWith("MMA655X value")) {
@@ -45,12 +45,18 @@ public class AltosMma655x implements Cloneable {
return n;
}
- static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException {
+ static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException, AltosUnknownProduct {
try {
AltosMma655x mma655x = new AltosMma655x(link);
- if (mma655x != null)
- state.set_accel(mma655x.accel);
+ if (mma655x != null) {
+ int accel = mma655x.accel;
+ if (config_data.mma655x_inverted())
+ accel = 4095 - accel;
+ if (config_data.pad_orientation == 1)
+ accel = 4095 - accel;
+ state.set_accel(accel);
+ }
} catch (TimeoutException te) {
} catch (NumberFormatException ne) {
}
diff --git a/altoslib/AltosMs5607.java b/altoslib/AltosMs5607.java
index aa16e231..1277f267 100644
--- a/altoslib/AltosMs5607.java
+++ b/altoslib/AltosMs5607.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.*;
import java.io.*;
diff --git a/altoslib/AltosNoSymbol.java b/altoslib/AltosNoSymbol.java
index 51b48666..5451047e 100644
--- a/altoslib/AltosNoSymbol.java
+++ b/altoslib/AltosNoSymbol.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosNoSymbol extends Exception {
public AltosNoSymbol(String name) {
diff --git a/altoslib/AltosOrient.java b/altoslib/AltosOrient.java
index a2d501b2..8b22c131 100644
--- a/altoslib/AltosOrient.java
+++ b/altoslib/AltosOrient.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosOrient extends AltosUnits {
diff --git a/altoslib/AltosParse.java b/altoslib/AltosParse.java
index 18ef807b..1cbddcf9 100644
--- a/altoslib/AltosParse.java
+++ b/altoslib/AltosParse.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.*;
import java.text.*;
diff --git a/altoslib/AltosPointDouble.java b/altoslib/AltosPointDouble.java
index a358ea66..65bad427 100644
--- a/altoslib/AltosPointDouble.java
+++ b/altoslib/AltosPointDouble.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosPointDouble {
public double x, y;
diff --git a/altoslib/AltosPointInt.java b/altoslib/AltosPointInt.java
index 5f9591cc..34eb6fd3 100644
--- a/altoslib/AltosPointInt.java
+++ b/altoslib/AltosPointInt.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosPointInt {
public int x, y;
diff --git a/altoslib/AltosPreferences.java b/altoslib/AltosPreferences.java
index 91cfc6b6..fb3026a4 100644
--- a/altoslib/AltosPreferences.java
+++ b/altoslib/AltosPreferences.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
@@ -116,6 +116,7 @@ public class AltosPreferences {
public final static String frequency_count = "COUNT";
public final static String frequency_format = "FREQUENCY-%d";
public final static String description_format = "DESCRIPTION-%d";
+ public final static String frequenciesPreference = "FREQUENCIES";
/* Units preference */
@@ -128,25 +129,33 @@ public class AltosPreferences {
public static int map_cache = 9;
+ final static String mapTypePreference = "MAP-TYPE";
+ static int map_type;
+
public static AltosFrequency[] load_common_frequencies() {
+
AltosFrequency[] frequencies = null;
- boolean existing = false;
- existing = backend.nodeExists(common_frequencies_node_name);
- if (existing) {
- AltosPreferencesBackend node = backend.node(common_frequencies_node_name);
- int count = node.getInt(frequency_count, 0);
+ frequencies = (AltosFrequency[]) backend.getSerializable(frequenciesPreference, null);
+
+ if (frequencies == null) {
+ if (backend.nodeExists(common_frequencies_node_name)) {
+ AltosPreferencesBackend node = backend.node(common_frequencies_node_name);
+ int count = node.getInt(frequency_count, 0);
- frequencies = new AltosFrequency[count];
- for (int i = 0; i < count; i++) {
- double frequency;
- String description;
+ frequencies = new AltosFrequency[count];
+ for (int i = 0; i < count; i++) {
+ double frequency;
+ String description;
- frequency = node.getDouble(String.format(frequency_format, i), 0.0);
- description = node.getString(String.format(description_format, i), null);
- frequencies[i] = new AltosFrequency(frequency, description);
+ frequency = node.getDouble(String.format(frequency_format, i), 0.0);
+ description = node.getString(String.format(description_format, i), null);
+ frequencies[i] = new AltosFrequency(frequency, description);
+ }
}
- } else {
+ }
+
+ if (frequencies == null) {
frequencies = new AltosFrequency[10];
for (int i = 0; i < 10; i++) {
frequencies[i] = new AltosFrequency(434.550 + i * .1,
@@ -156,15 +165,6 @@ public class AltosPreferences {
return frequencies;
}
- public static void save_common_frequencies(AltosFrequency[] frequencies) {
- AltosPreferencesBackend node = backend.node(common_frequencies_node_name);
-
- node.putInt(frequency_count, frequencies.length);
- for (int i = 0; i < frequencies.length; i++) {
- node.putDouble(String.format(frequency_format, i), frequencies[i].frequency);
- node.putString(String.format(description_format, i), frequencies[i].description);
- }
- }
public static int launcher_serial;
public static int launcher_channel;
@@ -221,6 +221,7 @@ public class AltosPreferences {
map_cache = backend.getInt(mapCachePreference, 9);
map_cache_listeners = new LinkedList<AltosMapCacheListener>();
+ map_type = backend.getInt(mapTypePreference, AltosMap.maptype_hybrid);
}
public static void flush_preferences() {
@@ -349,24 +350,12 @@ public class AltosPreferences {
}
}
- public static void set_state(int serial, AltosState state, AltosListenerState listener_state) {
-
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
-
- try {
- ObjectOutputStream oos = new ObjectOutputStream(baos);
+ public static void set_state(AltosState state) {
- AltosSavedState saved_state = new AltosSavedState(state, listener_state);
- oos.writeObject(saved_state);
-
- byte[] bytes = baos.toByteArray();
-
- synchronized(backend) {
- backend.putBytes(String.format(statePreferenceFormat, serial), bytes);
- backend.putInt(statePreferenceLatest, serial);
- flush_preferences();
- }
- } catch (IOException ie) {
+ synchronized(backend) {
+ backend.putSerializable(String.format(statePreferenceFormat, state.serial), state);
+ backend.putInt(statePreferenceLatest, state.serial);
+ flush_preferences();
}
}
@@ -400,26 +389,14 @@ public class AltosPreferences {
return latest;
}
- public static AltosSavedState state(int serial) {
- byte[] bytes = null;
-
+ public static AltosState state(int serial) {
synchronized(backend) {
- bytes = backend.getBytes(String.format(statePreferenceFormat, serial), null);
- }
-
- if (bytes == null)
- return null;
-
- ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
-
- try {
- ObjectInputStream ois = new ObjectInputStream(bais);
- AltosSavedState saved_state = (AltosSavedState) ois.readObject();
- return saved_state;
- } catch (IOException ie) {
- } catch (ClassNotFoundException ce) {
+ try {
+ return (AltosState) backend.getSerializable(String.format(statePreferenceFormat, serial), null);
+ } catch (Exception e) {
+ return null;
+ }
}
- return null;
}
public static void set_scanning_telemetry(int new_scanning_telemetry) {
@@ -535,7 +512,7 @@ public class AltosPreferences {
public static void set_common_frequencies(AltosFrequency[] frequencies) {
synchronized(backend) {
common_frequencies = frequencies;
- save_common_frequencies(frequencies);
+ backend.putSerializable(frequenciesPreference, frequencies);
flush_preferences();
}
}
@@ -621,4 +598,39 @@ public class AltosPreferences {
return map_cache;
}
}
+
+ static LinkedList<AltosMapTypeListener> map_type_listeners;
+
+ public static void set_map_type(int map_type) {
+ synchronized(backend) {
+ AltosPreferences.map_type = map_type;
+ backend.putInt(mapTypePreference, map_type);
+ flush_preferences();
+ }
+ if (map_type_listeners != null) {
+ for (AltosMapTypeListener l : map_type_listeners) {
+ l.map_type_changed(map_type);
+ }
+ }
+ }
+
+ public static int map_type() {
+ synchronized(backend) {
+ return map_type;
+ }
+ }
+
+ public static void register_map_type_listener(AltosMapTypeListener l) {
+ synchronized(backend) {
+ if (map_type_listeners == null)
+ map_type_listeners = new LinkedList<AltosMapTypeListener>();
+ map_type_listeners.add(l);
+ }
+ }
+
+ public static void unregister_map_type_listener(AltosMapTypeListener l) {
+ synchronized(backend) {
+ map_type_listeners.remove(l);
+ }
+ }
}
diff --git a/altoslib/AltosPreferencesBackend.java b/altoslib/AltosPreferencesBackend.java
index f43c2ec9..6e1124e2 100644
--- a/altoslib/AltosPreferencesBackend.java
+++ b/altoslib/AltosPreferencesBackend.java
@@ -15,34 +15,74 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
-import java.io.File;
+import java.io.*;
+import java.util.*;
+import java.text.*;
-public interface AltosPreferencesBackend {
+public abstract class AltosPreferencesBackend {
- public String getString(String key, String def);
- public void putString(String key, String value);
+ public abstract String getString(String key, String def);
+ public abstract void putString(String key, String value);
- public int getInt(String key, int def);
- public void putInt(String key, int value);
+ public abstract int getInt(String key, int def);
+ public abstract void putInt(String key, int value);
- public double getDouble(String key, double def);
- public void putDouble(String key, double value);
+ public abstract double getDouble(String key, double def);
+ public abstract void putDouble(String key, double value);
- public boolean getBoolean(String key, boolean def);
- public void putBoolean(String key, boolean value);
+ public abstract boolean getBoolean(String key, boolean def);
+ public abstract void putBoolean(String key, boolean value);
- public byte[] getBytes(String key, byte[] def);
- public void putBytes(String key, byte[] value);
+ public abstract byte[] getBytes(String key, byte[] def);
+ public abstract void putBytes(String key, byte[] value);
- public boolean nodeExists(String key);
- public AltosPreferencesBackend node(String key);
+ public Serializable getSerializable(String key, Serializable def) {
+ byte[] bytes = null;
- public String[] keys();
- public void remove(String key);
+ bytes = getBytes(key, null);
+ if (bytes == null)
+ return def;
- public void flush();
+ ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
- public File homeDirectory();
+ try {
+ ObjectInputStream ois = new ObjectInputStream(bais);
+ Serializable object = (Serializable) ois.readObject();
+ return object;
+ } catch (IOException ie) {
+ debug("IO exception %s\n", ie.toString());
+ } catch (ClassNotFoundException ce) {
+ debug("ClassNotFoundException %s\n", ce.toString());
+ }
+ return def;
+ }
+
+ public void putSerializable(String key, Serializable object) {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ try {
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+
+ oos.writeObject(object);
+ byte[] bytes = baos.toByteArray();
+
+ putBytes(key, bytes);
+ } catch (IOException ie) {
+ debug("set_state failed %s\n", ie.toString());
+ }
+ }
+
+ public abstract boolean nodeExists(String key);
+ public abstract AltosPreferencesBackend node(String key);
+
+ public abstract String[] keys();
+ public abstract void remove(String key);
+
+ public abstract void flush();
+
+ public abstract File homeDirectory();
+
+ public abstract void debug(String format, Object ... arguments);
}
diff --git a/altoslib/AltosProgrammer.java b/altoslib/AltosProgrammer.java
index 7f9b277d..2f8e3bd0 100644
--- a/altoslib/AltosProgrammer.java
+++ b/altoslib/AltosProgrammer.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
diff --git a/altoslib/AltosPyro.java b/altoslib/AltosPyro.java
index 851e35fb..28e65bc2 100644
--- a/altoslib/AltosPyro.java
+++ b/altoslib/AltosPyro.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.*;
import java.text.*;
diff --git a/altoslib/AltosQuaternion.java b/altoslib/AltosQuaternion.java
index e96aa7db..bc471c9c 100644
--- a/altoslib/AltosQuaternion.java
+++ b/altoslib/AltosQuaternion.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosQuaternion {
double r; /* real bit */
diff --git a/altoslib/AltosRectangle.java b/altoslib/AltosRectangle.java
index 6933198a..4757687d 100644
--- a/altoslib/AltosRectangle.java
+++ b/altoslib/AltosRectangle.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosRectangle {
public int x, y, width, height;
diff --git a/altoslib/AltosReplayReader.java b/altoslib/AltosReplayReader.java
index 5dcb8702..0f77c979 100644
--- a/altoslib/AltosReplayReader.java
+++ b/altoslib/AltosReplayReader.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
diff --git a/altoslib/AltosRomconfig.java b/altoslib/AltosRomconfig.java
index 9c6bb668..af201939 100644
--- a/altoslib/AltosRomconfig.java
+++ b/altoslib/AltosRomconfig.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
diff --git a/altoslib/AltosRotation.java b/altoslib/AltosRotation.java
index e3c4dd56..e53a3a49 100644
--- a/altoslib/AltosRotation.java
+++ b/altoslib/AltosRotation.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosRotation {
private AltosQuaternion rotation;
diff --git a/altoslib/AltosSavedState.java b/altoslib/AltosSavedState.java
index a5a69c95..3dbf59a5 100644
--- a/altoslib/AltosSavedState.java
+++ b/altoslib/AltosSavedState.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
diff --git a/altoslib/AltosSelfFlash.java b/altoslib/AltosSelfFlash.java
index 3aa727b3..f996d7b1 100644
--- a/altoslib/AltosSelfFlash.java
+++ b/altoslib/AltosSelfFlash.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
diff --git a/altoslib/AltosSensorEMini.java b/altoslib/AltosSensorEMini.java
index 825cbd5d..884800f8 100644
--- a/altoslib/AltosSensorEMini.java
+++ b/altoslib/AltosSensorEMini.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.TimeoutException;
diff --git a/altoslib/AltosSensorMM.java b/altoslib/AltosSensorMM.java
index c0a92a18..99eca9d8 100644
--- a/altoslib/AltosSensorMM.java
+++ b/altoslib/AltosSensorMM.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.TimeoutException;
diff --git a/altoslib/AltosSensorMega.java b/altoslib/AltosSensorMega.java
index f38d7b44..a4224311 100644
--- a/altoslib/AltosSensorMega.java
+++ b/altoslib/AltosSensorMega.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.TimeoutException;
diff --git a/altoslib/AltosSensorMetrum.java b/altoslib/AltosSensorMetrum.java
index fbc10fdd..1b09647f 100644
--- a/altoslib/AltosSensorMetrum.java
+++ b/altoslib/AltosSensorMetrum.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.TimeoutException;
diff --git a/altoslib/AltosSensorTGPS.java b/altoslib/AltosSensorTGPS.java
index a2d22e9a..9f572eca 100644
--- a/altoslib/AltosSensorTGPS.java
+++ b/altoslib/AltosSensorTGPS.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.TimeoutException;
diff --git a/altoslib/AltosSensorTM.java b/altoslib/AltosSensorTM.java
index e0449568..bb842b52 100644
--- a/altoslib/AltosSensorTM.java
+++ b/altoslib/AltosSensorTM.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.TimeoutException;
diff --git a/altoslib/AltosSensorTMini.java b/altoslib/AltosSensorTMini.java
index 74ecacd6..9e01b50c 100644
--- a/altoslib/AltosSensorTMini.java
+++ b/altoslib/AltosSensorTMini.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.TimeoutException;
diff --git a/altoslib/AltosSpeed.java b/altoslib/AltosSpeed.java
index 45bd4c6a..e09bbb7a 100644
--- a/altoslib/AltosSpeed.java
+++ b/altoslib/AltosSpeed.java
@@ -15,35 +15,35 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosSpeed extends AltosUnits {
public double value(double v, boolean imperial_units) {
if (imperial_units)
- return AltosConvert.meters_to_mph(v);
+ return AltosConvert.mps_to_fps(v);
return v;
}
public double inverse(double v, boolean imperial_units) {
if (imperial_units)
- return AltosConvert.mph_to_meters(v);
+ return AltosConvert.fps_to_mps(v);
return v;
}
public String show_units(boolean imperial_units) {
if (imperial_units)
- return "mph";
+ return "fps";
return "m/s";
}
public String say_units(boolean imperial_units) {
if (imperial_units)
- return "miles per hour";
+ return "feet per second";
return "meters per second";
}
public int show_fraction(int width, boolean imperial_units) {
return width / 9;
}
-} \ No newline at end of file
+}
diff --git a/altoslib/AltosState.java b/altoslib/AltosState.java
index 523f5a70..7b41e98d 100644
--- a/altoslib/AltosState.java
+++ b/altoslib/AltosState.java
@@ -19,7 +19,7 @@
* Track flight state from telemetry or eeprom data stream
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
diff --git a/altoslib/AltosStateIterable.java b/altoslib/AltosStateIterable.java
index 13b8f4ca..a7baa85e 100644
--- a/altoslib/AltosStateIterable.java
+++ b/altoslib/AltosStateIterable.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
diff --git a/altoslib/AltosStateUpdate.java b/altoslib/AltosStateUpdate.java
index 68212846..12d4dd41 100644
--- a/altoslib/AltosStateUpdate.java
+++ b/altoslib/AltosStateUpdate.java
@@ -15,8 +15,8 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosStateUpdate {
- public void update_state(AltosState state) throws InterruptedException;
-} \ No newline at end of file
+ public void update_state(AltosState state) throws InterruptedException, AltosUnknownProduct;
+}
diff --git a/altoslib/AltosTelemetry.java b/altoslib/AltosTelemetry.java
index 0ba9849a..67caa60c 100644
--- a/altoslib/AltosTelemetry.java
+++ b/altoslib/AltosTelemetry.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.text.*;
diff --git a/altoslib/AltosTelemetryCompanion.java b/altoslib/AltosTelemetryCompanion.java
index c47f9486..b9d32f48 100644
--- a/altoslib/AltosTelemetryCompanion.java
+++ b/altoslib/AltosTelemetryCompanion.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetryCompanion extends AltosTelemetryStandard {
AltosCompanion companion;
diff --git a/altoslib/AltosTelemetryConfiguration.java b/altoslib/AltosTelemetryConfiguration.java
index 20381a53..cd2cb8ca 100644
--- a/altoslib/AltosTelemetryConfiguration.java
+++ b/altoslib/AltosTelemetryConfiguration.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetryConfiguration extends AltosTelemetryStandard {
diff --git a/altoslib/AltosTelemetryFile.java b/altoslib/AltosTelemetryFile.java
index a762f615..b80c2dc9 100644
--- a/altoslib/AltosTelemetryFile.java
+++ b/altoslib/AltosTelemetryFile.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
diff --git a/altoslib/AltosTelemetryIterable.java b/altoslib/AltosTelemetryIterable.java
index b29881e8..ff395868 100644
--- a/altoslib/AltosTelemetryIterable.java
+++ b/altoslib/AltosTelemetryIterable.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
diff --git a/altoslib/AltosTelemetryLegacy.java b/altoslib/AltosTelemetryLegacy.java
index b3071a4b..6c0fcfeb 100644
--- a/altoslib/AltosTelemetryLegacy.java
+++ b/altoslib/AltosTelemetryLegacy.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.text.*;
diff --git a/altoslib/AltosTelemetryLocation.java b/altoslib/AltosTelemetryLocation.java
index 6fbed4bc..33c36449 100644
--- a/altoslib/AltosTelemetryLocation.java
+++ b/altoslib/AltosTelemetryLocation.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetryLocation extends AltosTelemetryStandard {
diff --git a/altoslib/AltosTelemetryMap.java b/altoslib/AltosTelemetryMap.java
index 5aa0c41d..13b5dbea 100644
--- a/altoslib/AltosTelemetryMap.java
+++ b/altoslib/AltosTelemetryMap.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.text.*;
import java.util.HashMap;
diff --git a/altoslib/AltosTelemetryMegaData.java b/altoslib/AltosTelemetryMegaData.java
index 49657051..d71f2802 100644
--- a/altoslib/AltosTelemetryMegaData.java
+++ b/altoslib/AltosTelemetryMegaData.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetryMegaData extends AltosTelemetryStandard {
int state;
diff --git a/altoslib/AltosTelemetryMegaSensor.java b/altoslib/AltosTelemetryMegaSensor.java
index 2f6256fc..f0d16f19 100644
--- a/altoslib/AltosTelemetryMegaSensor.java
+++ b/altoslib/AltosTelemetryMegaSensor.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetryMegaSensor extends AltosTelemetryStandard {
int accel;
diff --git a/altoslib/AltosTelemetryMetrumData.java b/altoslib/AltosTelemetryMetrumData.java
index 4fbb9b86..a4e9116f 100644
--- a/altoslib/AltosTelemetryMetrumData.java
+++ b/altoslib/AltosTelemetryMetrumData.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetryMetrumData extends AltosTelemetryStandard {
diff --git a/altoslib/AltosTelemetryMetrumSensor.java b/altoslib/AltosTelemetryMetrumSensor.java
index 3769c129..1b405f2b 100644
--- a/altoslib/AltosTelemetryMetrumSensor.java
+++ b/altoslib/AltosTelemetryMetrumSensor.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetryMetrumSensor extends AltosTelemetryStandard {
diff --git a/altoslib/AltosTelemetryMini.java b/altoslib/AltosTelemetryMini.java
index 173fac42..8996d662 100644
--- a/altoslib/AltosTelemetryMini.java
+++ b/altoslib/AltosTelemetryMini.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetryMini extends AltosTelemetryStandard {
diff --git a/altoslib/AltosTelemetryRaw.java b/altoslib/AltosTelemetryRaw.java
index 7fa12f5e..8cf023a4 100644
--- a/altoslib/AltosTelemetryRaw.java
+++ b/altoslib/AltosTelemetryRaw.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetryRaw extends AltosTelemetryStandard {
public AltosTelemetryRaw(int[] bytes) {
diff --git a/altoslib/AltosTelemetryReader.java b/altoslib/AltosTelemetryReader.java
index 2d76f281..2b0a443c 100644
--- a/altoslib/AltosTelemetryReader.java
+++ b/altoslib/AltosTelemetryReader.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.text.*;
import java.io.*;
diff --git a/altoslib/AltosTelemetrySatellite.java b/altoslib/AltosTelemetrySatellite.java
index a3a8abfa..de60e63c 100644
--- a/altoslib/AltosTelemetrySatellite.java
+++ b/altoslib/AltosTelemetrySatellite.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetrySatellite extends AltosTelemetryStandard {
int channels;
diff --git a/altoslib/AltosTelemetrySensor.java b/altoslib/AltosTelemetrySensor.java
index 578ac2da..74b61d3c 100644
--- a/altoslib/AltosTelemetrySensor.java
+++ b/altoslib/AltosTelemetrySensor.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetrySensor extends AltosTelemetryStandard {
diff --git a/altoslib/AltosTelemetryStandard.java b/altoslib/AltosTelemetryStandard.java
index 5a147b2b..7086abfc 100644
--- a/altoslib/AltosTelemetryStandard.java
+++ b/altoslib/AltosTelemetryStandard.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public abstract class AltosTelemetryStandard extends AltosTelemetry {
int[] bytes;
diff --git a/altoslib/AltosTemperature.java b/altoslib/AltosTemperature.java
index 19e3393d..a1e485b3 100644
--- a/altoslib/AltosTemperature.java
+++ b/altoslib/AltosTemperature.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTemperature extends AltosUnits {
diff --git a/altoslib/AltosUnits.java b/altoslib/AltosUnits.java
index c211eb6d..13b9dbe6 100644
--- a/altoslib/AltosUnits.java
+++ b/altoslib/AltosUnits.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.text.*;
diff --git a/altoslib/AltosUnitsListener.java b/altoslib/AltosUnitsListener.java
index f71c4270..bb8451b7 100644
--- a/altoslib/AltosUnitsListener.java
+++ b/altoslib/AltosUnitsListener.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosUnitsListener {
public void units_changed(boolean imperial_units);
diff --git a/altoslib/AltosUnknownProduct.java b/altoslib/AltosUnknownProduct.java
new file mode 100644
index 00000000..ff536f57
--- /dev/null
+++ b/altoslib/AltosUnknownProduct.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altoslib_10;
+
+public class AltosUnknownProduct extends Exception {
+ public String product;
+
+ public AltosUnknownProduct (String in_product) {
+ product = in_product;
+ }
+}
diff --git a/altoslib/AltosVersion.java.in b/altoslib/AltosVersion.java.in
index 8c53ef0d..9ac94dcd 100644
--- a/altoslib/AltosVersion.java.in
+++ b/altoslib/AltosVersion.java.in
@@ -15,12 +15,12 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosVersion {
public final static String version = "@VERSION@";
- public final static String google_maps_api_key = @GOOGLEKEY@;
+ public final static String google_maps_api_key = "@GOOGLEKEY@";
public static boolean has_google_maps_api_key() {
return google_maps_api_key != null && google_maps_api_key.length() > 1;
diff --git a/altoslib/AltosVoltage.java b/altoslib/AltosVoltage.java
index 34f4620e..1738dd86 100644
--- a/altoslib/AltosVoltage.java
+++ b/altoslib/AltosVoltage.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosVoltage extends AltosUnits {
diff --git a/altoslib/AltosWriter.java b/altoslib/AltosWriter.java
index b5cc34f0..02b5d669 100644
--- a/altoslib/AltosWriter.java
+++ b/altoslib/AltosWriter.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosWriter {
diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am
index d1f8f265..dc9da8fd 100644
--- a/altoslib/Makefile.am
+++ b/altoslib/Makefile.am
@@ -39,7 +39,7 @@ altoslib_JAVA = \
AltosEepromDownload.java \
AltosEepromFile.java \
AltosEepromTM.java \
- AltosEepromTm.java \
+ AltosEepromTMini.java \
AltosEepromHeader.java \
AltosEepromIterable.java \
AltosEepromList.java \
@@ -113,6 +113,7 @@ altoslib_JAVA = \
AltosTelemetrySatellite.java \
AltosTelemetryStandard.java \
AltosUnitsListener.java \
+ AltosUnknownProduct.java \
AltosMs5607.java \
AltosIMU.java \
AltosMag.java \
@@ -157,6 +158,7 @@ altoslib_JAVA = \
AltosLaunchSites.java \
AltosMapLoaderListener.java \
AltosMapLoader.java \
+ AltosMapTypeListener.java \
AltosVersion.java
JAR=altoslib_$(ALTOSLIB_VERSION).jar
diff --git a/altosui/Altos.java b/altosui/Altos.java
index aae2a793..81bc8c28 100644
--- a/altosui/Altos.java
+++ b/altosui/Altos.java
@@ -20,8 +20,8 @@ package altosui;
import java.awt.*;
import libaltosJNI.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class Altos extends AltosUILib {
diff --git a/altosui/AltosAscent.java b/altosui/AltosAscent.java
index 2fed6e7c..85260a70 100644
--- a/altosui/AltosAscent.java
+++ b/altosui/AltosAscent.java
@@ -21,8 +21,8 @@ import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosAscent extends AltosUIFlightTab {
JLabel cur, max;
diff --git a/altosui/AltosCompanionInfo.java b/altosui/AltosCompanionInfo.java
index f5080f56..251982ad 100644
--- a/altosui/AltosCompanionInfo.java
+++ b/altosui/AltosCompanionInfo.java
@@ -19,8 +19,8 @@ package altosui;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosCompanionInfo extends JTable implements AltosFlightDisplay {
private AltosFlightInfoTableModel model;
diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java
index 50be7f8e..e47b0e22 100644
--- a/altosui/AltosConfig.java
+++ b/altosui/AltosConfig.java
@@ -22,8 +22,8 @@ import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
import java.text.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosConfig implements ActionListener {
diff --git a/altosui/AltosConfigPyroUI.java b/altosui/AltosConfigPyroUI.java
index 4ad62405..e0915a17 100644
--- a/altosui/AltosConfigPyroUI.java
+++ b/altosui/AltosConfigPyroUI.java
@@ -22,8 +22,8 @@ import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosConfigPyroUI
extends AltosUIDialog
diff --git a/altosui/AltosConfigTD.java b/altosui/AltosConfigTD.java
index 3958a013..eedc18c5 100644
--- a/altosui/AltosConfigTD.java
+++ b/altosui/AltosConfigTD.java
@@ -21,8 +21,8 @@ import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosConfigTD implements ActionListener {
diff --git a/altosui/AltosConfigTDUI.java b/altosui/AltosConfigTDUI.java
index 94416465..9a76fbe2 100644
--- a/altosui/AltosConfigTDUI.java
+++ b/altosui/AltosConfigTDUI.java
@@ -21,8 +21,8 @@ import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosConfigTDUI
extends AltosUIDialog
diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigUI.java
index a4216212..24167df3 100644
--- a/altosui/AltosConfigUI.java
+++ b/altosui/AltosConfigUI.java
@@ -22,8 +22,8 @@ import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.text.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosConfigUI
extends AltosUIDialog
@@ -63,7 +63,7 @@ public class AltosConfigUI
JComboBox<String> apogee_delay_value;
JComboBox<String> apogee_lockout_value;
AltosUIFreqList radio_frequency_value;
- JTextField radio_calibration_value;
+ JLabel radio_calibration_value;
JRadioButton radio_enable_value;
AltosUIRateList rate_value;
JComboBox<String> aprs_interval_value;
@@ -191,13 +191,6 @@ public class AltosConfigUI
return product != null && product.startsWith("TeleMetrum");
}
- void set_radio_calibration_tool_tip() {
- if (radio_calibration_value.isEnabled())
- radio_calibration_value.setToolTipText("Tune radio output to match desired frequency");
- else
- radio_calibration_value.setToolTipText("Cannot tune radio while connected over packet mode");
- }
-
void set_radio_enable_tool_tip() {
if (radio_enable_value.isEnabled())
radio_enable_value.setToolTipText("Enable/Disable telemetry and RDF transmissions");
@@ -478,12 +471,8 @@ public class AltosConfigUI
c.anchor = GridBagConstraints.LINE_START;
c.insets = ir;
c.ipady = 5;
- radio_calibration_value = new JTextField(String.format("%d", 1186611));
- radio_calibration_value.getDocument().addDocumentListener(this);
- if (remote)
- radio_calibration_value.setEnabled(false);
+ radio_calibration_value = new JLabel(String.format("%d", 1186611));
pane.add(radio_calibration_value, c);
- set_radio_calibration_tool_tip();
row++;
/* Radio Enable */
@@ -1087,10 +1076,6 @@ public class AltosConfigUI
radio_calibration_value.setText(String.format("%d", new_radio_calibration));
}
- public int radio_calibration() throws AltosConfigDataException {
- return parse_int("radio calibration", radio_calibration_value.getText(), false);
- }
-
public void set_radio_enable(int new_radio_enable) {
radio_enable_label.setVisible(new_radio_enable >= 0);
radio_enable_value.setVisible(new_radio_enable >= 0);
diff --git a/altosui/AltosConfigureUI.java b/altosui/AltosConfigureUI.java
index 3d8bb754..52c50352 100644
--- a/altosui/AltosConfigureUI.java
+++ b/altosui/AltosConfigureUI.java
@@ -22,7 +22,7 @@ import java.awt.event.*;
import java.beans.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosConfigureUI
extends AltosUIConfigure
diff --git a/altosui/AltosDescent.java b/altosui/AltosDescent.java
index 9257f069..eeaed19e 100644
--- a/altosui/AltosDescent.java
+++ b/altosui/AltosDescent.java
@@ -21,8 +21,8 @@ import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosDescent extends AltosUIFlightTab {
diff --git a/altosui/AltosFlightStatus.java b/altosui/AltosFlightStatus.java
index cffed41d..4229e4fc 100644
--- a/altosui/AltosFlightStatus.java
+++ b/altosui/AltosFlightStatus.java
@@ -19,8 +19,8 @@ package altosui;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosFlightStatus extends JComponent implements AltosFlightDisplay {
GridBagLayout layout;
diff --git a/altosui/AltosFlightStatusTableModel.java b/altosui/AltosFlightStatusTableModel.java
index f8a643fe..7bf2bb78 100644
--- a/altosui/AltosFlightStatusTableModel.java
+++ b/altosui/AltosFlightStatusTableModel.java
@@ -27,7 +27,7 @@ import java.util.*;
import java.text.*;
import java.util.prefs.*;
import java.util.concurrent.LinkedBlockingQueue;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosFlightStatusTableModel extends AbstractTableModel {
private String[] columnNames = {
diff --git a/altosui/AltosFlightStatusUpdate.java b/altosui/AltosFlightStatusUpdate.java
index 9fa813d2..d39366da 100644
--- a/altosui/AltosFlightStatusUpdate.java
+++ b/altosui/AltosFlightStatusUpdate.java
@@ -18,7 +18,7 @@
package altosui;
import java.awt.event.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosFlightStatusUpdate implements ActionListener {
diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java
index d7646a77..a1526cb5 100644
--- a/altosui/AltosFlightUI.java
+++ b/altosui/AltosFlightUI.java
@@ -22,8 +22,8 @@ import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay {
AltosVoice voice;
diff --git a/altosui/AltosGraphUI.java b/altosui/AltosGraphUI.java
index 8e12f229..34d56b24 100644
--- a/altosui/AltosGraphUI.java
+++ b/altosui/AltosGraphUI.java
@@ -23,8 +23,8 @@ import java.util.ArrayList;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java
index 565ab1b1..d789de77 100644
--- a/altosui/AltosIdleMonitorUI.java
+++ b/altosui/AltosIdleMonitorUI.java
@@ -24,8 +24,8 @@ import javax.swing.event.*;
import java.io.*;
import java.util.concurrent.*;
import java.util.Arrays;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDisplay, AltosIdleMonitorListener, DocumentListener {
AltosDevice device;
@@ -128,6 +128,19 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl
SwingUtilities.invokeLater(r);
}
+ public void error(final String reason) {
+ Runnable r = new Runnable() {
+ public void run() {
+ disconnect();
+ JOptionPane.showMessageDialog(AltosIdleMonitorUI.this,
+ reason,
+ "Error fetching data",
+ JOptionPane.ERROR_MESSAGE);
+ }
+ };
+ SwingUtilities.invokeLater(r);
+ }
+
Container bag;
AltosUIFreqList frequencies;
JTextField callsign_value;
diff --git a/altosui/AltosIgniteUI.java b/altosui/AltosIgniteUI.java
index 01d58b5e..eca2a668 100644
--- a/altosui/AltosIgniteUI.java
+++ b/altosui/AltosIgniteUI.java
@@ -24,8 +24,8 @@ import java.io.*;
import java.text.*;
import java.util.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosIgniteUI
extends AltosUIDialog
@@ -48,6 +48,8 @@ public class AltosIgniteUI
int time_remaining;
boolean timer_running;
+ int poll_remaining;
+
LinkedBlockingQueue<String> command_queue;
class Igniter {
@@ -256,6 +258,7 @@ public class AltosIgniteUI
void set_ignite_status() {
getting_status = false;
+ poll_remaining = 2;
if (!visible) {
visible = true;
setVisible(true);
@@ -263,6 +266,10 @@ public class AltosIgniteUI
}
void poll_ignite_status() {
+ if (poll_remaining > 0) {
+ --poll_remaining;
+ return;
+ }
if (!getting_status) {
getting_status = true;
send_command("get_status");
diff --git a/altosui/AltosIgnitor.java b/altosui/AltosIgnitor.java
index e0f9e921..903da5a9 100644
--- a/altosui/AltosIgnitor.java
+++ b/altosui/AltosIgnitor.java
@@ -20,8 +20,8 @@ package altosui;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosIgnitor extends AltosUIFlightTab {
diff --git a/altosui/AltosLanded.java b/altosui/AltosLanded.java
index 423e0e23..b704651d 100644
--- a/altosui/AltosLanded.java
+++ b/altosui/AltosLanded.java
@@ -21,8 +21,8 @@ import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosLanded extends AltosUIFlightTab implements ActionListener {
diff --git a/altosui/AltosLaunch.java b/altosui/AltosLaunch.java
index da0dfd92..503b0621 100644
--- a/altosui/AltosLaunch.java
+++ b/altosui/AltosLaunch.java
@@ -20,7 +20,7 @@ package altosui;
import java.io.*;
import java.util.concurrent.*;
import java.awt.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosLaunch {
AltosDevice device;
diff --git a/altosui/AltosLaunchUI.java b/altosui/AltosLaunchUI.java
index e6bc7929..127a33a3 100644
--- a/altosui/AltosLaunchUI.java
+++ b/altosui/AltosLaunchUI.java
@@ -23,7 +23,7 @@ import javax.swing.*;
import java.io.*;
import java.text.*;
import java.util.concurrent.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
class FireButton extends JButton {
protected void processMouseEvent(MouseEvent e) {
diff --git a/altosui/AltosPad.java b/altosui/AltosPad.java
index f984e908..4f55636d 100644
--- a/altosui/AltosPad.java
+++ b/altosui/AltosPad.java
@@ -18,8 +18,8 @@
package altosui;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosPad extends AltosUIFlightTab {
diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java
index de6aa34c..4a390ee6 100644
--- a/altosui/AltosUI.java
+++ b/altosui/AltosUI.java
@@ -22,8 +22,8 @@ import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosUI extends AltosUIFrame {
public AltosVoice voice = new AltosVoice();
diff --git a/altosui/Instdrv/NSIS/Includes/java.nsh b/altosui/Instdrv/NSIS/Includes/java.nsh
index d989ddd6..8e0e208a 100644
--- a/altosui/Instdrv/NSIS/Includes/java.nsh
+++ b/altosui/Instdrv/NSIS/Includes/java.nsh
@@ -2,153 +2,134 @@
; Definitions for Java Detection
-!define JRE_VERSION "1.6"
-!define JRE32_URL "http://javadl.sun.com/webapps/download/AutoDL?BundleId=52247&/jre-6u27-windows-i586.exe"
-!define JRE64_URL "http://javadl.sun.com/webapps/download/AutoDL?BundleId=52249&/jre-6u27-windows-x64.exe"
-
-Var JavaDownload
-Var JavaBits
+!define JAVA_VERSION "6.0"
+
+Function GetFileVersion
+ !define GetFileVersion `!insertmacro GetFileVersionCall`
+
+ !macro GetFileVersionCall _FILE _RESULT
+ Push `${_FILE}`
+ Call GetFileVersion
+ Pop ${_RESULT}
+ !macroend
+
+ Exch $0
+ Push $1
+ Push $2
+ Push $3
+ Push $4
+ Push $5
+ Push $6
+ ClearErrors
+
+ GetDllVersion '$0' $1 $2
+ IfErrors error
+ IntOp $3 $1 >> 16
+ IntOp $3 $3 & 0x0000FFFF
+ IntOp $4 $1 & 0x0000FFFF
+ IntOp $5 $2 >> 16
+ IntOp $5 $5 & 0x0000FFFF
+ IntOp $6 $2 & 0x0000FFFF
+ StrCpy $0 '$3.$4.$5.$6'
+ goto end
+
+ error:
+ SetErrors
+ StrCpy $0 ''
+
+ end:
+ Pop $6
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Exch $0
+FunctionEnd
-Function GetJRE
- ${If} ${RunningX64}
- StrCpy $JavaDownload ${JRE64_URL}
- StrCpy $JavaBits "64"
- ${Else}
- StrCpy $JavaDownload ${JRE32_URL}
- StrCpy $JavaBits "32"
- ${EndIf}
-
- MessageBox MB_OK "This product uses Java ${JRE_VERSION}, \
- $JavaBits bits, it will now \
- be downloaded and installed"
-
- StrCpy $2 "$TEMP\Java Runtime Environment.exe"
- nsisdl::download /TIMEOUT=30000 $JavaDownload $2
- Pop $R0 ;Get the return value
- StrCmp $R0 "success" +3
- MessageBox MB_OK "Download failed: $R0"
- Quit
- ExecWait $2
- Delete $2
+Function openLinkNewWindow
+ Push $3
+ Exch
+ Push $2
+ Exch
+ Push $1
+ Exch
+ Push $0
+ Exch
+
+ ReadRegStr $1 HKCU "Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.html\UserChoice" "Progid"
+ IfErrors iexplore
+
+ Goto foundbrowser
+iexplore:
+ StrCpy $1 "IE.AssocFile.HTM"
+
+foundbrowser:
+
+ StrCpy $2 "\shell\open\command"
+
+ StrCpy $3 $1$2
+
+ ReadRegStr $0 HKCR $3 ""
+
+# Get browser path
+ DetailPrint $0
+
+ StrCpy $2 '"'
+ StrCpy $1 $0 1
+ StrCmp $1 $2 +2 # if path is not enclosed in " look for space as final char
+ StrCpy $2 ' '
+ StrCpy $3 1
+ loop:
+ StrCpy $1 $0 1 $3
+ DetailPrint $1
+ StrCmp $1 $2 found
+ StrCmp $1 "" found
+ IntOp $3 $3 + 1
+ Goto loop
+
+ found:
+ StrCpy $1 $0 $3
+ StrCmp $2 " " +2
+ StrCpy $1 '$1"'
+
+ Pop $0
+ Exec '$1 $0'
+ Pop $0
+ Pop $1
+ Pop $2
+ Pop $3
FunctionEnd
+
+!macro _OpenURL URL
+Push "${URL}"
+Call openLinkNewWindow
+!macroend
+
+!define OpenURL '!insertmacro "_OpenURL"'
Function DoDetectJRE
- DetailPrint "Desired Java version ${JRE_VERSION}"
-
- ; Check in HKCU for CurrentVersion
-
- ClearErrors
- ReadRegStr $2 HKCU "SOFTWARE\JavaSoft\Java Runtime Environment" \
- "CurrentVersion"
-
- IfErrors hkcuwow_version
-
- DetailPrint "HKEY_CURRENT_USER Java version $2"
-
- ${VersionCompare} $2 ${JRE_VERSION} $3
-
- IntCmp $3 1 yes yes no
-
-hkcuwow_version:
-
- ; Check in HKCU Wow6432Node for CurrentVersion
-
- ClearErrors
- ReadRegStr $2 HKCU "SOFTWARE\Wow6432Node\JavaSoft\Java Runtime Environment" \
- "CurrentVersion"
-
- Iferrors hklm_version
-
- DetailPrint "HKEY_CURRENT_USER Wow6432Node Java version $2"
+ DetailPrint "Desired Java version ${JAVA_VERSION}"
- ${VersionCompare} $2 ${JRE_VERSION} $3
-
- IntCmp $3 1 yes yes no
-
-hklm_version:
-
- ; Check in HKLM for CurrentVersion
-
- ClearErrors
- ReadRegStr $2 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment" \
- "CurrentVersion"
+ SearchPath $0 javaw.exe
+ IfErrors no
- IfErrors hklmwow_version
-
- DetailPrint "HKEY_LOCAL_MACHINE Java version $2"
-
- ${VersionCompare} $2 ${JRE_VERSION} $3
-
- IntCmp $3 1 yes yes no
-
-hklmwow_version:
-
- ; Check in HKLM Wow6432Node for CurrentVersion
-
- ClearErrors
- ReadRegStr $2 HKLM "SOFTWARE\Wow6432Node\JavaSoft\Java Runtime Environment" \
- "CurrentVersion"
-
- Iferrors hkcu_any
-
- DetailPrint "HKEY_LOCAL_MACHINE Wow6432Node Java version $2"
-
- ${VersionCompare} $2 ${JRE_VERSION} $3
+ DetailPrint "Detected java in $0"
- IntCmp $3 1 yes yes no
+ ${GetFileVersion} "$0" $1
+ IfErrors no
-hkcu_any:
+ DetailPrint "Java version $1"
- ; Check in HKCU for any Java install
-
- StrCpy $0 0
-
-hkcu_any_loop:
- EnumRegKey $1 HKCU "SOFTWARE\JavaSoft" $0
-
- StrCmp $1 "Java Runtime Environment" found_hkcu
-
- StrCmp $1 "" hklm_any
-
- IntOp $0 $0 + 1
-
- Goto hkcu_any_loop
-
-found_hkcu:
-
- DetailPrint "HKEY_CURRENT_USER has SOFTWARE\JavaSoft\$1"
-
- Goto maybe
-
-hklm_any:
-
- ; Check in HKCU for any Java install
-
- StrCpy $0 0
-
-hklm_any_loop:
- EnumRegKey $1 HKLM "SOFTWARE\JavaSoft" $0
-
- StrCmp $1 "Java Runtime Environment" found_hklm
-
- StrCmp $1 "" no
-
- IntOp $0 $0 + 1
-
- Goto hklm_any_loop
-
-found_hklm:
-
- DetailPrint "HKEY_CURRENT_USER has SOFTWARE\JavaSoft\$1"
-
- Goto maybe
+ ${VersionCompare} $1 ${JAVA_VERSION} $2
+ IntCmp $2 1 yes yes old
yes:
StrCpy $0 2
Goto done
-maybe:
+old:
StrCpy $0 1
Goto done
@@ -168,26 +149,28 @@ var install
var quit
var skip
+Function GetJRE
+ ${OpenURL} "java.com"
+ MessageBox MB_OK "Click OK to continue after completing the Java Install."
+FunctionEnd
+
Function DetectJRE
Call DoDetectJRE
- IntCmp $0 1 ask_maybe ask_no yes
+ IntCmp $0 1 ask_old ask_no yes
ask_no:
- StrCpy $0 "No Java detected. Download and install?"
+ StrCpy $0 "Cannot find Java. Download and install?"
Goto ask
-ask_maybe:
- StrCpy $0 "Cannot determine installed Java version. Download and install?"
+ask_old:
+ StrCpy $0 "Java version appears to be too old. Download and install?"
Goto ask
ask:
MessageBox MB_YESNOCANCEL $0 IDYES do_java IDNO skip_java
-bail:
- Abort
-
do_java:
Call GetJRE
diff --git a/altosuilib/AltosBTDevice.java b/altosuilib/AltosBTDevice.java
index 01421071..8c2e0d75 100644
--- a/altosuilib/AltosBTDevice.java
+++ b/altosuilib/AltosBTDevice.java
@@ -15,10 +15,10 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import libaltosJNI.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosBTDevice extends altos_bt_device implements AltosDevice {
diff --git a/altosuilib/AltosBTDeviceIterator.java b/altosuilib/AltosBTDeviceIterator.java
index b8c4c6cf..ea29b055 100644
--- a/altosuilib/AltosBTDeviceIterator.java
+++ b/altosuilib/AltosBTDeviceIterator.java
@@ -15,11 +15,11 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.util.*;
import libaltosJNI.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosBTDeviceIterator implements Iterator<AltosBTDevice> {
AltosBTDevice current;
diff --git a/altosuilib/AltosBTKnown.java b/altosuilib/AltosBTKnown.java
index e444d310..8ae11f67 100644
--- a/altosuilib/AltosBTKnown.java
+++ b/altosuilib/AltosBTKnown.java
@@ -15,10 +15,10 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosBTKnown implements Iterable<AltosBTDevice> {
LinkedList<AltosBTDevice> devices = new LinkedList<AltosBTDevice>();
diff --git a/altosuilib/AltosBTManage.java b/altosuilib/AltosBTManage.java
index 65744141..e6a1ef64 100644
--- a/altosuilib/AltosBTManage.java
+++ b/altosuilib/AltosBTManage.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
@@ -23,7 +23,7 @@ import javax.swing.*;
import javax.swing.plaf.basic.*;
import java.util.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosBTManage extends AltosUIDialog implements ActionListener, Iterable<AltosBTDevice> {
LinkedBlockingQueue<AltosBTDevice> found_devices;
diff --git a/altosuilib/AltosCSVUI.java b/altosuilib/AltosCSVUI.java
index d5796cb1..3846d3fd 100644
--- a/altosuilib/AltosCSVUI.java
+++ b/altosuilib/AltosCSVUI.java
@@ -15,13 +15,13 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosCSVUI
extends AltosUIDialog
diff --git a/altosuilib/AltosConfigFreqUI.java b/altosuilib/AltosConfigFreqUI.java
index ccfdc1a3..5a689a39 100644
--- a/altosuilib/AltosConfigFreqUI.java
+++ b/altosuilib/AltosConfigFreqUI.java
@@ -15,14 +15,14 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.text.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
class AltosEditFreqUI extends AltosUIDialog implements ActionListener {
Frame frame;
diff --git a/altosuilib/AltosDataChooser.java b/altosuilib/AltosDataChooser.java
index f7bc516b..3dfadfe1 100644
--- a/altosuilib/AltosDataChooser.java
+++ b/altosuilib/AltosDataChooser.java
@@ -15,12 +15,12 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.io.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosDataChooser extends JFileChooser {
JFrame frame;
diff --git a/altosuilib/AltosDevice.java b/altosuilib/AltosDevice.java
index f78fc2d0..dbaf2e36 100644
--- a/altosuilib/AltosDevice.java
+++ b/altosuilib/AltosDevice.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import libaltosJNI.*;
diff --git a/altosuilib/AltosDeviceDialog.java b/altosuilib/AltosDeviceDialog.java
index 52083b60..21a8a23f 100644
--- a/altosuilib/AltosDeviceDialog.java
+++ b/altosuilib/AltosDeviceDialog.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import javax.swing.*;
import java.awt.*;
diff --git a/altosuilib/AltosDeviceUIDialog.java b/altosuilib/AltosDeviceUIDialog.java
index 908e74e7..75c3e691 100644
--- a/altosuilib/AltosDeviceUIDialog.java
+++ b/altosuilib/AltosDeviceUIDialog.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import javax.swing.*;
import java.awt.*;
diff --git a/altosuilib/AltosDisplayThread.java b/altosuilib/AltosDisplayThread.java
index 9aa31aa1..968a0b75 100644
--- a/altosuilib/AltosDisplayThread.java
+++ b/altosuilib/AltosDisplayThread.java
@@ -15,13 +15,13 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import javax.swing.*;
import java.io.*;
import java.text.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosDisplayThread extends Thread {
diff --git a/altosuilib/AltosEepromDelete.java b/altosuilib/AltosEepromDelete.java
index 270b0494..442cee88 100644
--- a/altosuilib/AltosEepromDelete.java
+++ b/altosuilib/AltosEepromDelete.java
@@ -15,13 +15,13 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosEepromDelete implements Runnable {
AltosEepromList flights;
diff --git a/altosuilib/AltosEepromManage.java b/altosuilib/AltosEepromManage.java
index 14cfb127..5f83e6f4 100644
--- a/altosuilib/AltosEepromManage.java
+++ b/altosuilib/AltosEepromManage.java
@@ -15,13 +15,13 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosEepromManage implements ActionListener {
diff --git a/altosuilib/AltosEepromMonitor.java b/altosuilib/AltosEepromMonitor.java
index 41d447bc..508e3e3f 100644
--- a/altosuilib/AltosEepromMonitor.java
+++ b/altosuilib/AltosEepromMonitor.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
diff --git a/altosuilib/AltosEepromMonitorUI.java b/altosuilib/AltosEepromMonitorUI.java
index 0c8083cd..905780a5 100644
--- a/altosuilib/AltosEepromMonitorUI.java
+++ b/altosuilib/AltosEepromMonitorUI.java
@@ -15,12 +15,12 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMonitor {
JFrame owner;
diff --git a/altosuilib/AltosEepromSelect.java b/altosuilib/AltosEepromSelect.java
index e5c45ca1..67bff710 100644
--- a/altosuilib/AltosEepromSelect.java
+++ b/altosuilib/AltosEepromSelect.java
@@ -15,13 +15,13 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
class AltosEepromItem implements ActionListener {
AltosEepromLog log;
diff --git a/altosuilib/AltosFlashUI.java b/altosuilib/AltosFlashUI.java
index 33d432c8..07f04c3e 100644
--- a/altosuilib/AltosFlashUI.java
+++ b/altosuilib/AltosFlashUI.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
@@ -23,7 +23,7 @@ import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.io.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosFlashUI
extends AltosUIDialog
diff --git a/altosuilib/AltosFlightInfoTableModel.java b/altosuilib/AltosFlightInfoTableModel.java
index 912fc716..9a430743 100644
--- a/altosuilib/AltosFlightInfoTableModel.java
+++ b/altosuilib/AltosFlightInfoTableModel.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import javax.swing.table.*;
diff --git a/altosuilib/AltosFlightStatsTable.java b/altosuilib/AltosFlightStatsTable.java
index c7461432..6171f61a 100644
--- a/altosuilib/AltosFlightStatsTable.java
+++ b/altosuilib/AltosFlightStatsTable.java
@@ -15,12 +15,12 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import javax.swing.*;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosFlightStatsTable extends JComponent implements AltosFontListener {
GridBagLayout layout;
@@ -117,18 +117,18 @@ public class AltosFlightStatsTable extends JComponent implements AltosFontListen
}
new FlightStat(layout, y++, "Maximum speed",
String.format("%5.0f m/s", stats.max_speed),
- String.format("%5.0f mph", AltosConvert.meters_to_mph(stats.max_speed)),
+ String.format("%5.0f fps", AltosConvert.mps_to_fps(stats.max_speed)),
String.format("Mach %4.1f", AltosConvert.meters_to_mach(stats.max_speed)));
- if (stats.max_acceleration != AltosLib.MISSING) {
+ if (stats.max_acceleration != AltosLib.MISSING)
new FlightStat(layout, y++, "Maximum boost acceleration",
String.format("%5.0f m/s²", stats.max_acceleration),
String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.max_acceleration)),
String.format("%5.0f G", AltosConvert.meters_to_g(stats.max_acceleration)));
+ if (stats.state_accel[AltosLib.ao_flight_boost] != AltosLib.MISSING)
new FlightStat(layout, y++, "Average boost acceleration",
String.format("%5.0f m/s²", stats.state_accel[AltosLib.ao_flight_boost]),
String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.state_accel[AltosLib.ao_flight_boost])),
String.format("%5.0f G", AltosConvert.meters_to_g(stats.state_accel[AltosLib.ao_flight_boost])));
- }
if (stats.state_speed[AltosLib.ao_flight_drogue] != AltosLib.MISSING)
new FlightStat(layout, y++, "Drogue descent rate",
String.format("%5.0f m/s", stats.state_speed[AltosLib.ao_flight_drogue]),
diff --git a/altosuilib/AltosGraph.java b/altosuilib/AltosGraph.java
index ceb730f9..a4334cc6 100644
--- a/altosuilib/AltosGraph.java
+++ b/altosuilib/AltosGraph.java
@@ -15,14 +15,14 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
diff --git a/altosuilib/AltosGraphDataPoint.java b/altosuilib/AltosGraphDataPoint.java
index 6a38f446..e4a065c6 100644
--- a/altosuilib/AltosGraphDataPoint.java
+++ b/altosuilib/AltosGraphDataPoint.java
@@ -15,9 +15,9 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosGraphDataPoint implements AltosUIDataPoint {
diff --git a/altosuilib/AltosGraphDataSet.java b/altosuilib/AltosGraphDataSet.java
index d7d07c83..673d1de9 100644
--- a/altosuilib/AltosGraphDataSet.java
+++ b/altosuilib/AltosGraphDataSet.java
@@ -15,12 +15,12 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.lang.*;
import java.io.*;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
class AltosGraphIterator implements Iterator<AltosUIDataPoint> {
AltosGraphDataSet dataSet;
diff --git a/altosuilib/AltosInfoTable.java b/altosuilib/AltosInfoTable.java
index 8e6558b1..3833b37a 100644
--- a/altosuilib/AltosInfoTable.java
+++ b/altosuilib/AltosInfoTable.java
@@ -15,13 +15,13 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosInfoTable extends JTable implements AltosFlightDisplay, HierarchyListener {
private AltosFlightInfoTableModel model;
diff --git a/altosuilib/AltosLed.java b/altosuilib/AltosLed.java
index fbe6b4ed..07485cc4 100644
--- a/altosuilib/AltosLed.java
+++ b/altosuilib/AltosLed.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import javax.swing.*;
diff --git a/altosuilib/AltosLights.java b/altosuilib/AltosLights.java
index 6ab50549..f445199c 100644
--- a/altosuilib/AltosLights.java
+++ b/altosuilib/AltosLights.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import javax.swing.*;
diff --git a/altosuilib/AltosPositionListener.java b/altosuilib/AltosPositionListener.java
index 0c4fb373..06ba4188 100644
--- a/altosuilib/AltosPositionListener.java
+++ b/altosuilib/AltosPositionListener.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
public interface AltosPositionListener {
public void position_changed(int position);
diff --git a/altosuilib/AltosRomconfigUI.java b/altosuilib/AltosRomconfigUI.java
index 275070ee..3a5188f8 100644
--- a/altosuilib/AltosRomconfigUI.java
+++ b/altosuilib/AltosRomconfigUI.java
@@ -15,12 +15,12 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosRomconfigUI
extends AltosUIDialog
diff --git a/altosuilib/AltosScanUI.java b/altosuilib/AltosScanUI.java
index bc647e8f..1d176e82 100644
--- a/altosuilib/AltosScanUI.java
+++ b/altosuilib/AltosScanUI.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
@@ -25,7 +25,7 @@ import java.io.*;
import java.util.*;
import java.text.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
class AltosScanResult {
String callsign;
diff --git a/altosuilib/AltosSerial.java b/altosuilib/AltosSerial.java
index a91740c5..85ab4654 100644
--- a/altosuilib/AltosSerial.java
+++ b/altosuilib/AltosSerial.java
@@ -19,13 +19,13 @@
* Deal with TeleDongle on a serial port
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.io.*;
import java.util.*;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import libaltosJNI.*;
/*
diff --git a/altosuilib/AltosSerialInUseException.java b/altosuilib/AltosSerialInUseException.java
index d1083098..af7edb65 100644
--- a/altosuilib/AltosSerialInUseException.java
+++ b/altosuilib/AltosSerialInUseException.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
public class AltosSerialInUseException extends Exception {
public AltosDevice device;
diff --git a/altosuilib/AltosUIAxis.java b/altosuilib/AltosUIAxis.java
index b4024a17..e307874a 100644
--- a/altosuilib/AltosUIAxis.java
+++ b/altosuilib/AltosUIAxis.java
@@ -15,14 +15,14 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
diff --git a/altosuilib/AltosUIConfigure.java b/altosuilib/AltosUIConfigure.java
index 03967d19..89114c7e 100644
--- a/altosuilib/AltosUIConfigure.java
+++ b/altosuilib/AltosUIConfigure.java
@@ -15,14 +15,14 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
class DelegatingRenderer implements ListCellRenderer<Object> {
diff --git a/altosuilib/AltosUIDataMissing.java b/altosuilib/AltosUIDataMissing.java
index 1a7e12bf..585289ed 100644
--- a/altosuilib/AltosUIDataMissing.java
+++ b/altosuilib/AltosUIDataMissing.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
public class AltosUIDataMissing extends Exception {
public int id;
diff --git a/altosuilib/AltosUIDataPoint.java b/altosuilib/AltosUIDataPoint.java
index cf320265..7feb6d8e 100644
--- a/altosuilib/AltosUIDataPoint.java
+++ b/altosuilib/AltosUIDataPoint.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
public interface AltosUIDataPoint {
public abstract double x() throws AltosUIDataMissing;
diff --git a/altosuilib/AltosUIDataSet.java b/altosuilib/AltosUIDataSet.java
index 29648dbf..82809aa5 100644
--- a/altosuilib/AltosUIDataSet.java
+++ b/altosuilib/AltosUIDataSet.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
public interface AltosUIDataSet {
public abstract String name();
diff --git a/altosuilib/AltosUIDialog.java b/altosuilib/AltosUIDialog.java
index 2d0bc3c9..a2625975 100644
--- a/altosuilib/AltosUIDialog.java
+++ b/altosuilib/AltosUIDialog.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
diff --git a/altosuilib/AltosUIEnable.java b/altosuilib/AltosUIEnable.java
index 42a09acf..7bb80bc1 100644
--- a/altosuilib/AltosUIEnable.java
+++ b/altosuilib/AltosUIEnable.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
@@ -23,7 +23,7 @@ import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
diff --git a/altosuilib/AltosUIFlightTab.java b/altosuilib/AltosUIFlightTab.java
index 0db1e5da..e098b76f 100644
--- a/altosuilib/AltosUIFlightTab.java
+++ b/altosuilib/AltosUIFlightTab.java
@@ -15,13 +15,13 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public abstract class AltosUIFlightTab extends JComponent implements AltosFlightDisplay, HierarchyListener {
public GridBagLayout layout;
diff --git a/altosuilib/AltosUIFrame.java b/altosuilib/AltosUIFrame.java
index b82f07f7..295225d6 100644
--- a/altosuilib/AltosUIFrame.java
+++ b/altosuilib/AltosUIFrame.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
diff --git a/altosuilib/AltosUIFreqList.java b/altosuilib/AltosUIFreqList.java
index e0e2ede7..7d49e692 100644
--- a/altosuilib/AltosUIFreqList.java
+++ b/altosuilib/AltosUIFreqList.java
@@ -15,10 +15,10 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosUIFreqList extends JComboBox<AltosFrequency> {
diff --git a/altosuilib/AltosUIGraph.java b/altosuilib/AltosUIGraph.java
index 9a669e32..dca12854 100644
--- a/altosuilib/AltosUIGraph.java
+++ b/altosuilib/AltosUIGraph.java
@@ -15,14 +15,14 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
diff --git a/altosuilib/AltosUIGrapher.java b/altosuilib/AltosUIGrapher.java
index 0df5c1a7..a30609fd 100644
--- a/altosuilib/AltosUIGrapher.java
+++ b/altosuilib/AltosUIGrapher.java
@@ -15,14 +15,14 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
diff --git a/altosuilib/AltosUIImage.java b/altosuilib/AltosUIImage.java
index 8c09b2e7..1907e155 100644
--- a/altosuilib/AltosUIImage.java
+++ b/altosuilib/AltosUIImage.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import javax.swing.*;
import javax.imageio.ImageIO;
diff --git a/altosuilib/AltosUIIndicator.java b/altosuilib/AltosUIIndicator.java
index 9bac992b..819123a7 100644
--- a/altosuilib/AltosUIIndicator.java
+++ b/altosuilib/AltosUIIndicator.java
@@ -15,11 +15,11 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public abstract class AltosUIIndicator implements AltosFontListener, AltosUnitsListener {
JLabel label;
diff --git a/altosuilib/AltosUILib.java b/altosuilib/AltosUILib.java
index 1f1ad23b..ff9fd72a 100644
--- a/altosuilib/AltosUILib.java
+++ b/altosuilib/AltosUILib.java
@@ -15,12 +15,12 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import libaltosJNI.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosUILib extends AltosLib {
@@ -112,9 +112,8 @@ public class AltosUILib extends AltosLib {
String OS = System.getProperty("os.name");
- if (OS.startsWith("Linux")) {
+ if (OS.startsWith("L") || OS.startsWith("W"))
has_bluetooth = true;
- }
initialized = true;
}
diff --git a/altosuilib/AltosUIListener.java b/altosuilib/AltosUIListener.java
index 8f758300..98d7452f 100644
--- a/altosuilib/AltosUIListener.java
+++ b/altosuilib/AltosUIListener.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
public interface AltosUIListener {
public void ui_changed(String look_and_feel);
diff --git a/altosuilib/AltosUIMapNew.java b/altosuilib/AltosUIMapNew.java
index 8de6bea2..a90e8c91 100644
--- a/altosuilib/AltosUIMapNew.java
+++ b/altosuilib/AltosUIMapNew.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
@@ -27,7 +27,7 @@ import java.awt.geom.*;
import java.util.*;
import java.util.concurrent.*;
import javax.imageio.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosUIMapNew extends JComponent implements AltosFlightDisplay, AltosMapInterface {
@@ -241,8 +241,8 @@ public class AltosUIMapNew extends JComponent implements AltosFlightDisplay, Alt
}
class MapTile extends AltosMapTile {
- public MapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
- super(listener, upper_left, center, zoom, maptype, px_size);
+ public MapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
+ super(cache, upper_left, center, zoom, maptype, px_size);
}
public void paint(AltosMapTransform t) {
@@ -254,11 +254,9 @@ public class AltosUIMapNew extends JComponent implements AltosFlightDisplay, Alt
if (!g.hitClip(point.x, point.y, px_size, px_size))
return;
- AltosImage altos_image = cache.get(this, store, px_size, px_size);
-
+ AltosImage altos_image = get_image();
AltosUIImage ui_image = (AltosUIImage) altos_image;
-
- Image image = null;
+ Image image = null;
if (ui_image != null)
image = ui_image.image;
@@ -272,8 +270,8 @@ public class AltosUIMapNew extends JComponent implements AltosFlightDisplay, Alt
if (t.has_location()) {
String message = null;
switch (status) {
- case AltosMapTile.loading:
- message = "Loading...";
+ case AltosMapTile.fetching:
+ message = "Fetching...";
break;
case AltosMapTile.bad_request:
message = "Internal error";
@@ -334,8 +332,8 @@ public class AltosUIMapNew extends JComponent implements AltosFlightDisplay, Alt
return new MapMark(lat, lon, state);
}
- public AltosMapTile new_tile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
- return new MapTile(listener, upper_left, center, zoom, maptype, px_size);
+ public AltosMapTile new_tile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
+ return new MapTile(cache, upper_left, center, zoom, maptype, px_size);
}
public int width() {
diff --git a/altosuilib/AltosUIMapPreloadNew.java b/altosuilib/AltosUIMapPreloadNew.java
index c1c3f8bb..3269bbdd 100644
--- a/altosuilib/AltosUIMapPreloadNew.java
+++ b/altosuilib/AltosUIMapPreloadNew.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
@@ -26,7 +26,7 @@ import java.text.*;
import java.lang.Math;
import java.net.URL;
import java.net.URLConnection;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
class AltosUIMapPos extends Box {
AltosUIFrame owner;
@@ -127,8 +127,6 @@ public class AltosUIMapPreloadNew extends AltosUIFrame implements ActionListener
JProgressBar pbar;
- AltosMapLoader loader;
-
JLabel site_list_label;
JComboBox<AltosLaunchSite> site_list;
@@ -189,7 +187,8 @@ public class AltosUIMapPreloadNew extends AltosUIFrame implements ActionListener
}
public void debug(String format, Object ... arguments) {
- System.out.printf(format, arguments);
+ if (AltosSerial.debug)
+ System.out.printf(format, arguments);
}
@@ -237,7 +236,10 @@ public class AltosUIMapPreloadNew extends AltosUIFrame implements ActionListener
r = r * 1000;
loading = true;
- loader.load(latitude, longitude, min_z, max_z, r, all_types());
+ new AltosMapLoader(map.map, this,
+ latitude, longitude,
+ min_z, max_z, r, all_types());
+
} catch (ParseException pe) {
load_button.setSelected(false);
}
@@ -270,8 +272,6 @@ public class AltosUIMapPreloadNew extends AltosUIFrame implements ActionListener
map = new AltosUIMapNew();
- loader = new AltosMapLoader(map.map, this);
-
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.CENTER;
c.insets = i;
diff --git a/altosuilib/AltosUIMarker.java b/altosuilib/AltosUIMarker.java
index 7c5a91b0..dc96357a 100644
--- a/altosuilib/AltosUIMarker.java
+++ b/altosuilib/AltosUIMarker.java
@@ -15,14 +15,14 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
diff --git a/altosuilib/AltosUIPreferences.java b/altosuilib/AltosUIPreferences.java
index 83099fa5..5fc5f15e 100644
--- a/altosuilib/AltosUIPreferences.java
+++ b/altosuilib/AltosUIPreferences.java
@@ -15,13 +15,13 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.io.*;
import java.util.*;
import java.awt.Component;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosUIPreferences extends AltosPreferences {
diff --git a/altosuilib/AltosUIPreferencesBackend.java b/altosuilib/AltosUIPreferencesBackend.java
index 6d7aa88b..d232edf7 100644
--- a/altosuilib/AltosUIPreferencesBackend.java
+++ b/altosuilib/AltosUIPreferencesBackend.java
@@ -15,14 +15,14 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.io.File;
import java.util.prefs.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import javax.swing.filechooser.FileSystemView;
-public class AltosUIPreferencesBackend implements AltosPreferencesBackend {
+public class AltosUIPreferencesBackend extends AltosPreferencesBackend {
private Preferences _preferences = null;
@@ -106,4 +106,8 @@ public class AltosUIPreferencesBackend implements AltosPreferencesBackend {
/* Use the file system view default directory */
return FileSystemView.getFileSystemView().getDefaultDirectory();
}
+
+ public void debug(String format, Object ... arguments) {
+ System.out.printf(format, arguments);
+ }
}
diff --git a/altosuilib/AltosUIRateList.java b/altosuilib/AltosUIRateList.java
index 8407f31d..5a18b32f 100644
--- a/altosuilib/AltosUIRateList.java
+++ b/altosuilib/AltosUIRateList.java
@@ -15,10 +15,10 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosUIRateList extends JComboBox<String> {
diff --git a/altosuilib/AltosUISeries.java b/altosuilib/AltosUISeries.java
index e2d19e47..b16f046b 100644
--- a/altosuilib/AltosUISeries.java
+++ b/altosuilib/AltosUISeries.java
@@ -15,14 +15,14 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
diff --git a/altosuilib/AltosUITelemetryList.java b/altosuilib/AltosUITelemetryList.java
index fbbd7c06..bba14678 100644
--- a/altosuilib/AltosUITelemetryList.java
+++ b/altosuilib/AltosUITelemetryList.java
@@ -15,11 +15,11 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.util.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosUITelemetryList extends JComboBox<String> {
diff --git a/altosuilib/AltosUIUnitsIndicator.java b/altosuilib/AltosUIUnitsIndicator.java
index 61e04b34..a84bd0b2 100644
--- a/altosuilib/AltosUIUnitsIndicator.java
+++ b/altosuilib/AltosUIUnitsIndicator.java
@@ -15,11 +15,11 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public abstract class AltosUIUnitsIndicator extends AltosUIIndicator {
diff --git a/altosuilib/AltosUIVoltageIndicator.java b/altosuilib/AltosUIVoltageIndicator.java
index 779098ce..d753b759 100644
--- a/altosuilib/AltosUIVoltageIndicator.java
+++ b/altosuilib/AltosUIVoltageIndicator.java
@@ -15,11 +15,11 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public abstract class AltosUIVoltageIndicator extends AltosUIUnitsIndicator {
diff --git a/altosuilib/AltosUSBDevice.java b/altosuilib/AltosUSBDevice.java
index 6da50deb..c93a3211 100644
--- a/altosuilib/AltosUSBDevice.java
+++ b/altosuilib/AltosUSBDevice.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.util.*;
import libaltosJNI.*;
diff --git a/altosuilib/AltosVoice.java b/altosuilib/AltosVoice.java
index e68c6d8b..1b65acdc 100644
--- a/altosuilib/AltosVoice.java
+++ b/altosuilib/AltosVoice.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import com.sun.speech.freetts.Voice;
import com.sun.speech.freetts.VoiceManager;
diff --git a/altosuilib/GrabNDrag.java b/altosuilib/GrabNDrag.java
index d9f0c7fd..725bbab6 100644
--- a/altosuilib/GrabNDrag.java
+++ b/altosuilib/GrabNDrag.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
diff --git a/altosuilib/OSXAdapter.java b/altosuilib/OSXAdapter.java
index 69cc3a55..c2915081 100755
--- a/altosuilib/OSXAdapter.java
+++ b/altosuilib/OSXAdapter.java
@@ -55,7 +55,7 @@ Copyright © 2003-2007 Apple, Inc., All Rights Reserved
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.lang.reflect.*;
import java.util.HashMap;
diff --git a/ao-bringup/cal-freq b/ao-bringup/cal-freq
index d3d9dc95..40c25ce8 100755
--- a/ao-bringup/cal-freq
+++ b/ao-bringup/cal-freq
@@ -10,7 +10,7 @@ case $# in
;;
esac
-../ao-tools/ao-cal-freq/ao-cal-freq --dev=$dev
+../ao-tools/ao-cal-freq/ao-cal-freq --tty=$dev
case $? in
0)
calline=`./get-radio-cal $dev`
diff --git a/ao-bringup/test-telemega b/ao-bringup/test-telemega
index b801b20c..0ac475a3 100755
--- a/ao-bringup/test-telemega
+++ b/ao-bringup/test-telemega
@@ -60,6 +60,7 @@ ao-list | while read product serial dev; do
echo""
echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
+ echo "\007"
ret=0
;;
esac
diff --git a/ao-bringup/turnon_chaoskey b/ao-bringup/turnon_chaoskey
new file mode 100755
index 00000000..8c20ebaa
--- /dev/null
+++ b/ao-bringup/turnon_chaoskey
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+if [ -x /usr/bin/dfu-util ]; then
+ DFU_UTIL=/usr/bin/dfu-util
+else
+ echo "Can't find dfu-util! Aborting."
+ exit 1
+fi
+
+if [ -x /usr/bin/ao-usbload ]; then
+ USBLOAD=/usr/bin/ao-usbload
+else
+ echo "Can't find ao-usbload! Aborting."
+ exit 1
+fi
+
+VERSION=1.0
+PRODUCT=ChaosKey
+
+echo "ChaosKey v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2015 by Keith Packard. Released under GPL v2"
+echo
+echo "Expectations:"
+echo "\tChaosKey v$VERSION powered from USB"
+echo
+
+$DFU_UTIL -a 0 -s 0x08000000:leave -D ../src/chaoskey-v$VERSION/flash-loader/chaoskey-v$VERSION*.bin || exit 1
+
+sleep 2
+
+$USBLOAD --serial=1 ../src/chaoskey-v$VERSION/chaoskey-v$VERSION*.ihx || exit 1
+
+exit $?
diff --git a/ao-tools/Makefile.am b/ao-tools/Makefile.am
index 66d2560e..fb554857 100644
--- a/ao-tools/Makefile.am
+++ b/ao-tools/Makefile.am
@@ -3,7 +3,7 @@ SUBDIRS=lib ao-rawload ao-dbg ao-bitbang ao-eeprom ao-list \
ao-dumpflash ao-edit-telem ao-dump-up ao-elftohex \
ao-flash ao-usbload ao-test-igniter ao-test-baro \
ao-test-flash ao-cal-accel ao-test-gps ao-usbtrng \
- ao-cal-freq
+ ao-cal-freq ao-chaosread ao-makebin
if LIBSTLINK
SUBDIRS += ao-stmload
endif
diff --git a/ao-tools/ao-chaosread/.gitignore b/ao-tools/ao-chaosread/.gitignore
new file mode 100644
index 00000000..b9443879
--- /dev/null
+++ b/ao-tools/ao-chaosread/.gitignore
@@ -0,0 +1 @@
+ao-chaosread
diff --git a/ao-tools/ao-chaosread/Makefile.am b/ao-tools/ao-chaosread/Makefile.am
new file mode 100644
index 00000000..581eb2d2
--- /dev/null
+++ b/ao-tools/ao-chaosread/Makefile.am
@@ -0,0 +1,9 @@
+bin_PROGRAMS=ao-chaosread
+
+AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+
+ao_chaosread_LDADD=$(LIBUSB_LIBS)
+
+ao_chaosread_SOURCES = ao-chaosread.c
+
+man_MANS = ao-chaosread.1
diff --git a/ao-tools/ao-chaosread/ao-chaosread.1 b/ao-tools/ao-chaosread/ao-chaosread.1
new file mode 100644
index 00000000..d8ed6cb3
--- /dev/null
+++ b/ao-tools/ao-chaosread/ao-chaosread.1
@@ -0,0 +1,36 @@
+.\"
+.\" Copyright © 2016 Keith Packard <keithp@keithp.com>
+.\"
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful, but
+.\" WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+.\" General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License along
+.\" with this program; if not, write to the Free Software Foundation, Inc.,
+.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+.\"
+.\"
+.TH AO-LOAD 1 "ao-chaosread" ""
+.SH NAME
+ao-chaosread \- read raw noise source from chaoskey
+.SH SYNOPSIS
+.B "ao-chaosread"
+.SH DESCRIPTION
+.I ao-chaosread
+reads ADC values from the noise source on the attached ChaosKey device.
+.SH OPTIONS
+.TP
+\-s serial | --serial serial
+This selects a ChaosKey by serial number instead of using the first
+one found.
+.SH USAGE
+.I ao-chaosread
+reads noise data.
+.SH AUTHOR
+Keith Packard
diff --git a/ao-tools/ao-chaosread/ao-chaosread.c b/ao-tools/ao-chaosread/ao-chaosread.c
new file mode 100644
index 00000000..806c2ef9
--- /dev/null
+++ b/ao-tools/ao-chaosread/ao-chaosread.c
@@ -0,0 +1,272 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <libusb.h>
+#include <getopt.h>
+#include <string.h>
+#include <strings.h>
+
+#define CHAOS_SIZE 64
+
+#define CHAOS_VENDOR 0x1d50
+#define CHAOS_PRODUCT 0x60c6
+
+struct chaoskey {
+ libusb_context *ctx;
+ libusb_device_handle *handle;
+ int kernel_active;
+};
+
+libusb_device_handle *
+chaoskey_match(libusb_device *dev, char *match_serial)
+{
+ struct libusb_device_descriptor desc;
+ int ret;
+ int match_len;
+ char *device_serial = NULL;
+ libusb_device_handle *handle = NULL;
+
+ ret = libusb_get_device_descriptor(dev, &desc);
+ if (ret < 0) {
+ fprintf(stderr, "failed to get device descriptor: %s\n", libusb_strerror(ret));
+ return 0;
+ }
+
+ if (desc.idVendor != CHAOS_VENDOR)
+ return NULL;
+ if (desc.idProduct != CHAOS_PRODUCT)
+ return NULL;
+
+ ret = libusb_open(dev, &handle);
+
+ if (match_serial == NULL)
+ return handle;
+
+ if (ret < 0) {
+ fprintf(stderr, "failed to open device: %s\n", libusb_strerror(ret));
+ return NULL;
+ }
+
+ match_len = strlen(match_serial);
+ device_serial = malloc(match_len + 2);
+
+ if (!device_serial) {
+ fprintf(stderr, "malloc failed\n");
+ goto out;
+ }
+
+ ret = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, device_serial, match_len + 1);
+
+ if (ret < 0) {
+ fprintf(stderr, "failed to get serial number: %s\n", libusb_strerror(ret));
+ goto out;
+ }
+
+ device_serial[ret] = '\0';
+
+ ret = strcmp(device_serial, match_serial);
+ free(device_serial);
+ if (ret)
+ goto out;
+
+ return handle;
+
+out:
+ free(device_serial);
+ if (handle)
+ libusb_close(handle);
+ return 0;
+}
+
+struct chaoskey *
+chaoskey_open(char *serial)
+{
+ struct chaoskey *ck;
+ int ret;
+ ssize_t num;
+ libusb_device **list;
+ libusb_device *device = NULL;
+ int d;
+
+ ck = calloc(sizeof (struct chaoskey), 1);
+ if (!ck)
+ goto out;
+ ret = libusb_init(&ck->ctx);
+ if (ret ) {
+ fprintf(stderr, "libusb_init failed: %s\n", libusb_strerror(ret));
+ goto out;
+ }
+
+ num = libusb_get_device_list(ck->ctx, &list);
+ if (num < 0) {
+ fprintf(stderr, "libusb_get_device_list failed: %s\n", libusb_strerror(num));
+ goto out;
+ }
+
+ for (d = 0; d < num; d++) {
+ libusb_device_handle *handle;
+
+ handle = chaoskey_match(list[d], serial);
+ if (handle) {
+ ck->handle = handle;
+ break;
+ }
+ }
+
+ libusb_free_device_list(list, 1);
+
+ if (!ck->handle) {
+ if (serial)
+ fprintf (stderr, "No chaoskey matching %s\n", serial);
+ else
+ fprintf (stderr, "No chaoskey\n");
+ goto out;
+ }
+
+ ck->kernel_active = libusb_kernel_driver_active(ck->handle, 0);
+ if (ck->kernel_active) {
+ ret = libusb_detach_kernel_driver(ck->handle, 0);
+ if (ret)
+ goto out;
+ }
+
+ ret = libusb_claim_interface(ck->handle, 0);
+ if (ret)
+ goto out;
+
+ return ck;
+out:
+ if (ck->kernel_active)
+ libusb_attach_kernel_driver(ck->handle, 0);
+ if (ck->ctx)
+ libusb_exit(ck->ctx);
+ free(ck);
+ return NULL;
+}
+
+void
+chaoskey_close(struct chaoskey *ck)
+{
+ libusb_release_interface(ck->handle, 0);
+ if (ck->kernel_active)
+ libusb_attach_kernel_driver(ck->handle, 0);
+ libusb_close(ck->handle);
+ libusb_exit(ck->ctx);
+ free(ck);
+}
+
+void
+chaoskey_transfer_callback(struct libusb_transfer *transfer)
+{
+ struct chaoskey *ck = transfer->user_data;
+}
+
+#define ENDPOINT 0x86
+
+int
+chaoskey_read(struct chaoskey *ck, uint8_t *buffer, int len)
+{
+ int total = 0;
+
+ while (len) {
+ int ret;
+ int transferred;
+
+ ret = libusb_bulk_transfer(ck->handle, ENDPOINT, buffer, len, &transferred, 10000);
+ if (ret) {
+ if (total)
+ return total;
+ else {
+ errno = EIO;
+ return -1;
+ }
+ }
+ len -= transferred;
+ buffer += transferred;
+ }
+}
+
+static const struct option options[] = {
+ { .name = "serial", .has_arg = 1, .val = 's' },
+ { .name = "length", .has_arg = 1, .val = 'l' },
+ { 0, 0, 0, 0},
+};
+
+static void usage(char *program)
+{
+ fprintf(stderr, "usage: %s [--serial=<serial>] [--length=<length>[kMG]]\n", program);
+ exit(1);
+}
+
+int
+main (int argc, char **argv)
+{
+ struct chaoskey *ck;
+ char buf[1024];
+ int got;
+ int c;
+ char *serial = NULL;
+ char *length_string;
+ char *length_end;
+ unsigned long length = sizeof(buf);
+ int this_time;
+
+ while ((c = getopt_long(argc, argv, "s:l:", options, NULL)) != -1) {
+ switch (c) {
+ case 's':
+ serial = optarg;
+ break;
+ case 'l':
+ length_string = optarg;
+ length = strtoul(length_string, &length_end, 10);
+ if (!strcasecmp(length_end, "k"))
+ length *= 1024;
+ else if (!strcasecmp(length_end, "m"))
+ length *= 1024 * 1024;
+ else if (!strcasecmp(length_end, "g"))
+ length *= 1024 * 1024 * 1024;
+ else if (strlen(length_end))
+ usage(argv[0]);
+ break;
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+
+ ck = chaoskey_open(serial);
+ if (!ck)
+ exit(1);
+
+ while (length) {
+ this_time = sizeof(buf);
+ if (length < sizeof(buf))
+ this_time = (int) length;
+ got = chaoskey_read(ck, buf, this_time);
+ if (got < 0) {
+ perror("read");
+ exit(1);
+ }
+ write(1, buf, got);
+ length -= got;
+ }
+ exit(0);
+}
diff --git a/ao-tools/ao-dump-up/ao-dump-up.c b/ao-tools/ao-dump-up/ao-dump-up.c
index b1f85af6..df05088c 100644
--- a/ao-tools/ao-dump-up/ao-dump-up.c
+++ b/ao-tools/ao-dump-up/ao-dump-up.c
@@ -140,20 +140,6 @@ static int find_header(struct cc_usb *cc)
}
}
-static const char *state_names[] = {
- "startup",
- "idle",
- "pad",
- "boost",
- "fast",
- "coast",
- "drogue",
- "main",
- "landed",
- "invalid"
-};
-
-
int
main (int argc, char **argv)
{
diff --git a/ao-tools/ao-makebin/Makefile.am b/ao-tools/ao-makebin/Makefile.am
new file mode 100644
index 00000000..758097a4
--- /dev/null
+++ b/ao-tools/ao-makebin/Makefile.am
@@ -0,0 +1,12 @@
+bin_PROGRAMS=ao-makebin
+
+AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AO_ELFTOHEX_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
+
+ao_makebin_DEPENDENCIES = $(AO_ELFTOHEX_LIBS)
+
+ao_makebin_LDADD=$(AO_ELFTOHEX_LIBS) -lelf
+
+ao_makebin_SOURCES=ao-makebin.c
+
+man_MANS = ao-makebin.1
diff --git a/ao-tools/ao-makebin/ao-makebin.1 b/ao-tools/ao-makebin/ao-makebin.1
new file mode 100644
index 00000000..e19ec2cc
--- /dev/null
+++ b/ao-tools/ao-makebin/ao-makebin.1
@@ -0,0 +1,47 @@
+.\"
+.\" Copyright © 2013 Keith Packard <keithp@keithp.com>
+.\"
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful, but
+.\" WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+.\" General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License along
+.\" with this program; if not, write to the Free Software Foundation, Inc.,
+.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+.\"
+.\"
+.TH AO-LOAD 1 "ao-makebin" ""
+.SH NAME
+ao-makebin \- construct raw binary file or DFU image from collection of ELF files
+.SH SYNOPSIS
+.B "ao-makebin"
+[\--base=\fIbase-address\fP]
+[\--output=\fIoutput.bin\fP]
+[\--dfu]
+[\--verbose]
+\fIinput.elf ...\fP
+.SH DESCRIPTION
+.I ao-makebin
+reads the specified .elf files and writes out a raw binary flash image
+.SH OPTIONS
+.TP
+\--base=\fIbase-address\fP
+This specifies the target address for the first byte of the file (default is 0)
+.TP
+\--output=\fIoutput.bin\fP
+This specifies the output file (default is stdout)
+.TP
+\--dfu
+Creates a DFU file (as documented by ST's UM0391 user manual) instead
+of a raw binary file.
+.TP
+\--verbose
+Dumps some debug information.
+.SH AUTHOR
+Keith Packard
diff --git a/ao-tools/ao-makebin/ao-makebin.c b/ao-tools/ao-makebin/ao-makebin.c
new file mode 100644
index 00000000..31ce1889
--- /dev/null
+++ b/ao-tools/ao-makebin/ao-makebin.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include "ao-hex.h"
+#include "ao-elf.h"
+#include "ao-dfu.h"
+
+static const struct option options[] = {
+ { .name = "verbose", .has_arg = 0, .val = 'v' },
+ { .name = "output", .has_arg = 1, .val = 'o' },
+ { .name = "base", .has_arg = 1, .val = 'b' },
+ { .name = "align", .has_arg = 1, .val = 'a' },
+ { .name = "dfu", .has_arg = 0, .val = 'd' },
+ { 0, 0, 0, 0},
+};
+
+static void usage(char *program)
+{
+ fprintf(stderr, "usage: %s [--verbose=<level>] [--output=<output.bin>] [--base=<base-address>] [--align=<align>] [--dfu] <input.elf> ...\n", program);
+ exit(1);
+}
+
+static int
+ends_with(char *whole, char *suffix)
+{
+ int whole_len = strlen(whole);
+ int suffix_len = strlen(suffix);
+
+ if (suffix_len > whole_len)
+ return 0;
+ return strcmp(whole + whole_len - suffix_len, suffix) == 0;
+}
+
+static struct ao_dfu_info dfu_info = {
+ .bcdDevice = 0x0000,
+ .idProduct = 0xdf11,
+ .idVendor = 0x0483,
+};
+
+int
+main (int argc, char **argv)
+{
+ char *output = NULL;
+ struct ao_hex_image *image = NULL;
+ struct ao_sym *file_symbols;
+ int num_file_symbols;
+ FILE *file;
+ int c;
+ uint32_t base = 0xffffffff;
+ uint32_t align = 0;
+ uint32_t length;
+ int verbose = 0;
+ int dfu = 0;
+
+ while ((c = getopt_long(argc, argv, "dvo:b:a:", options, NULL)) != -1) {
+ switch (c) {
+ case 'o':
+ output = optarg;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ case 'b':
+ base = strtoul(optarg, NULL, 0);
+ break;
+ case 'a':
+ align = strtoul(optarg, NULL, 0);
+ break;
+ case 'd':
+ dfu = 1;
+ break;
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+
+ while (argv[optind]) {
+ char *input = argv[optind];
+ struct ao_hex_image *tmp;
+
+ if (ends_with (input, ".ihx"))
+ tmp = ao_hex_load(input, &file_symbols, &num_file_symbols);
+ else
+ tmp = ao_load_elf(input, &file_symbols, &num_file_symbols);
+
+ if (!tmp)
+ usage(argv[0]);
+
+ if (verbose)
+ fprintf(stderr, "%s: 0x%x %d\n", input, tmp->address, tmp->length);
+
+ if (image) {
+ image = ao_hex_image_cat(image, tmp);
+ if (!image)
+ usage(argv[0]);
+ } else
+ image = tmp;
+ optind++;
+ }
+
+ if (base != 0xffffffff && base > image->address) {
+ fprintf(stderr, "requested base 0x%x is after image address 0x%x\n",
+ base, image->address);
+ usage(argv[0]);
+ }
+
+ if (verbose)
+ fprintf(stderr, "%s: base 0x%x length %d\n", output ? output : "<stdout>", image->address, image->length);
+
+ if (!output)
+ file = stdout;
+ else {
+ file = fopen(output, "w");
+ if (!file) {
+ perror(output);
+ exit(1);
+ }
+ }
+
+ if (dfu) {
+ if (!ao_dfu_write(file, &dfu_info, 1, image)) {
+ fprintf(stderr, "%s: dfu_write failed: %s\n", output, strerror(errno));
+ if (output)
+ unlink(output);
+ exit(1);
+ }
+ } else {
+ while (base < image->address) {
+ fputc(0xff, file);
+ base++;
+ }
+
+ if (fwrite(image->data, 1, image->length, file) != image->length) {
+ fprintf(stderr, "%s: failed to write bin file\n", output ? output : "<stdout>");
+ if (output)
+ unlink(output);
+ exit(1);
+ }
+
+ if (align) {
+ length = image->length;
+
+ while (length % align) {
+ fputc(0xff, file);
+ length++;
+ }
+ }
+ fflush(file);
+ }
+
+ exit(0);
+}
diff --git a/ao-tools/lib/Makefile.am b/ao-tools/lib/Makefile.am
index a03a976c..a33d682d 100644
--- a/ao-tools/lib/Makefile.am
+++ b/ao-tools/lib/Makefile.am
@@ -46,6 +46,8 @@ libao_tools_a_SOURCES = \
ao-editaltos.h \
ao-elf.c \
ao-elf.h \
+ ao-dfu.c \
+ ao-dfu.h \
ao-selfload.c \
ao-selfload.h \
ao-verbose.c \
diff --git a/ao-tools/lib/ao-dfu.c b/ao-tools/lib/ao-dfu.c
new file mode 100644
index 00000000..b6778495
--- /dev/null
+++ b/ao-tools/lib/ao-dfu.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <stdarg.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+#include "ao-hex.h"
+#include "ao-dfu.h"
+
+static uint32_t dfu_crc;
+static FILE *dfu_file;
+static int dfu_failed;
+static int dfu_error;
+
+static uint32_t update_crc(uint32_t crc, uint8_t byte)
+{
+ int j;
+ uint32_t mask;
+
+ crc = crc ^ byte;
+ for (j = 0; j < 8; j++) {
+ mask = -(crc & 1);
+ crc = (crc >> 1) ^ (0xEDB88320 & mask);
+ }
+ return crc;
+}
+
+static void dfu_init(FILE *file)
+{
+ dfu_crc = 0xffffffff;
+ dfu_file = file;
+ dfu_failed = 0;
+ dfu_error = 0;
+}
+
+static int dfu_fini(void)
+{
+ if (fflush(dfu_file) == EOF) {
+ if (!dfu_failed) {
+ dfu_failed = 1;
+ dfu_error = errno;
+ }
+ }
+ if (dfu_failed)
+ errno = dfu_error;
+ return !dfu_failed;
+}
+
+static void dfu_8(uint8_t byte) {
+ if (putc(byte, dfu_file) == EOF) {
+ if (!dfu_failed) {
+ dfu_failed = 1;
+ dfu_error = errno;
+ }
+ }
+ dfu_crc = update_crc(dfu_crc, byte);
+}
+
+static void dfu_pad(int len) {
+ while (len--)
+ dfu_8(0);
+}
+
+static void dfu_string(char *string) {
+ char c;
+
+ while ((c = *string++))
+ dfu_8((uint8_t) c);
+}
+
+static void dfu_string_pad(char *string, int len) {
+ char c;
+
+ while ((c = *string++)) {
+ dfu_8((uint8_t) c);
+ len--;
+ }
+ dfu_pad(len);
+}
+
+static void dfu_block(uint8_t *bytes, int len) {
+ while (len--)
+ dfu_8(*bytes++);
+}
+
+static void dfu_lsb16(uint16_t value) {
+ dfu_8(value);
+ dfu_8(value>>8);
+}
+
+static void dfu_lsb32(uint32_t value) {
+ dfu_8(value);
+ dfu_8(value >> 8);
+ dfu_8(value >> 16);
+ dfu_8(value >> 24);
+}
+
+static uint32_t dfu_image_size(struct ao_hex_image *image) {
+ return 8 + image->length;
+}
+
+static uint32_t dfu_images_size(int num_image, struct ao_hex_image images[])
+{
+ uint32_t size = 0;
+ int i;
+
+ for (i = 0; i < num_image; i++)
+ size += dfu_image_size(&images[i]);
+ return size;
+}
+
+static void dfu_image(struct ao_hex_image *image)
+{
+ dfu_lsb32(image->address);
+ dfu_lsb32(image->length);
+ dfu_block(image->data, image->length);
+}
+
+static void dfu_target(char *name, int num_image, struct ao_hex_image images[])
+{
+ uint32_t images_size = dfu_images_size(num_image, images);
+ int i;
+
+ dfu_string("Target");
+ dfu_8(0);
+ if (name) {
+ dfu_8(1);
+ dfu_pad(3);
+ dfu_string_pad(name, 255);
+ } else {
+ dfu_8(0);
+ dfu_pad(3);
+ dfu_pad(255);
+ }
+ dfu_lsb32(images_size);
+ dfu_lsb32(num_image);
+ for (i = 0; i < num_image; i++)
+ dfu_image(&images[i]);
+}
+
+static uint32_t dfu_target_size(int num_image, struct ao_hex_image images[])
+{
+ return 274 + dfu_images_size(num_image, images);
+}
+
+static uint32_t
+dfu_size(int num_image, struct ao_hex_image images[])
+{
+ uint32_t size = 0;
+ size += 11; /* DFU Prefix */
+
+ size += dfu_target_size(num_image, images);
+
+ return size;
+}
+
+int
+ao_dfu_write(FILE *file, struct ao_dfu_info *info, int num_image, struct ao_hex_image images[])
+{
+ uint32_t total_size;
+
+ total_size = dfu_size(num_image, images);
+
+ dfu_init(file);
+ /* DFU Prefix */
+ dfu_string(DFU_SIGNATURE);
+ dfu_8(0x01);
+ dfu_lsb32(total_size);
+ dfu_8(0x01);
+
+ dfu_target("ST...", num_image, images);
+
+ /* DFU Suffix */
+ dfu_lsb16(info->bcdDevice);
+ dfu_lsb16(info->idProduct);
+ dfu_lsb16(info->idVendor);
+ dfu_lsb16(DFU_SPEC_VERSION);
+ dfu_string("UFD");
+ dfu_8(16);
+ dfu_lsb32(dfu_crc);
+ return dfu_fini();
+}
+
diff --git a/ao-tools/lib/ao-dfu.h b/ao-tools/lib/ao-dfu.h
new file mode 100644
index 00000000..c3dfc496
--- /dev/null
+++ b/ao-tools/lib/ao-dfu.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_DFU_H_
+#define _AO_DFU_H_
+
+struct ao_dfu_info {
+ uint16_t bcdDevice;
+ uint16_t idProduct;
+ uint16_t idVendor;
+};
+
+#define DFU_SIGNATURE "DfuSe"
+#define DFU_SPEC_VERSION 0x011a
+
+#define DFU_TARGET_SIGNATURE "Target"
+
+int
+ao_dfu_write(FILE *file, struct ao_dfu_info *info, int num_image, struct ao_hex_image images[]);
+
+#endif /* _AO_DFU_H_ */
diff --git a/ao-tools/lib/ao-elf.c b/ao-tools/lib/ao-elf.c
index 99b37210..680a80f0 100644
--- a/ao-tools/lib/ao-elf.c
+++ b/ao-tools/lib/ao-elf.c
@@ -206,7 +206,7 @@ get_load(Elf *e)
#endif
size_t nshdr;
size_t s;
-
+
if (elf_getshdrstrndx(e, &shstrndx) < 0)
return 0;
@@ -238,7 +238,7 @@ get_load(Elf *e)
(uint32_t) phdr.p_filesz,
(uint32_t) phdr.p_memsz);
#endif
-
+
for (s = 0; s < nshdr; s++) {
scn = elf_getscn(e, s);
@@ -256,7 +256,7 @@ get_load(Elf *e)
#endif
if (phdr.p_offset <= shdr.sh_offset && shdr.sh_offset < phdr.p_offset + phdr.p_filesz) {
-
+
if (shdr.sh_size == 0)
continue;
diff --git a/ao-tools/lib/ao-hex.c b/ao-tools/lib/ao-hex.c
index 5cfc63c1..2ceed7ab 100644
--- a/ao-tools/lib/ao-hex.c
+++ b/ao-tools/lib/ao-hex.c
@@ -294,7 +294,7 @@ load_symbols(struct ao_hex_file *hex,
struct ao_sym *symbol;
int num_symbols = 0;
int size_symbols = 0;
-
+
extended_addr = 0;
for (i = 0; i < hex->nrecord; i++) {
record = hex->records[i];
@@ -451,6 +451,31 @@ ao_hex_image_free(struct ao_hex_image *image)
free(image);
}
+uint32_t min(uint32_t a, uint32_t b) { return a < b ? a : b; }
+uint32_t max(uint32_t a, uint32_t b) { return a > b ? a : b; }
+
+struct ao_hex_image *
+ao_hex_image_cat(struct ao_hex_image *a, struct ao_hex_image *b)
+{
+ struct ao_hex_image *n;
+ uint32_t base, bound;
+ uint32_t length;
+
+ base = min(a->address, b->address);
+ bound = max(a->address + a->length, b->address + b->length);
+ length = bound - base;
+
+ n = calloc (sizeof (struct ao_hex_image) + length, 1);
+ if (!n)
+ return NULL;
+ n->address = base;
+ n->length = length;
+ memset(n->data, 0xff, length);
+ memcpy(n->data + a->address - n->address, a->data, a->length);
+ memcpy(n->data + b->address - n->address, b->data, b->length);
+ return n;
+}
+
int
ao_hex_image_equal(struct ao_hex_image *a, struct ao_hex_image *b)
{
@@ -471,7 +496,7 @@ ao_hex_load(char *filename, struct ao_sym **symbols, int *num_symbolsp)
file = fopen (filename, "r");
if (!file)
return NULL;
-
+
hex_file = ao_hex_file_read(file, filename);
fclose(file);
if (!hex_file)
@@ -549,7 +574,7 @@ ao_hex_file_create(struct ao_hex_image *image, struct ao_sym *symbols, int num_s
ao_hex_record_set_checksum(record);
hex_file->records[nrecord++] = record;
-
+
/* Add the symbols
*/
@@ -616,7 +641,7 @@ ao_hex_save(FILE *file, struct ao_hex_image *image,
goto write_failed;
}
ret = true;
-
+
if (fflush(file) != 0)
ret = false;
write_failed:
diff --git a/ao-tools/lib/ao-hex.h b/ao-tools/lib/ao-hex.h
index eb510ba2..a1ab490c 100644
--- a/ao-tools/lib/ao-hex.h
+++ b/ao-tools/lib/ao-hex.h
@@ -71,6 +71,9 @@ ao_hex_image_free(struct ao_hex_image *image);
struct ao_hex_image *
ao_hex_load(char *filename, struct ao_sym **symbols, int *num_symbols);
+struct ao_hex_image *
+ao_hex_image_cat(struct ao_hex_image *a, struct ao_hex_image *b);
+
int
ao_hex_image_equal(struct ao_hex_image *a, struct ao_hex_image *b);
diff --git a/configure.ac b/configure.ac
index addaad0c..ee3d4225 100644
--- a/configure.ac
+++ b/configure.ac
@@ -18,8 +18,8 @@ dnl
dnl Process this file with autoconf to create configure.
AC_PREREQ(2.57)
-AC_INIT([altos], 1.6.2)
-ANDROID_VERSION=10
+AC_INIT([altos], 1.6.3)
+ANDROID_VERSION=11
AC_CONFIG_SRCDIR([src/kernel/ao.h])
AM_INIT_AUTOMAKE([foreign dist-bzip2])
AM_MAINTAINER_MODE
@@ -31,8 +31,8 @@ AC_SUBST(ANDROID_VERSION)
dnl ==========================================================================
dnl Java library versions
-ALTOSUILIB_VERSION=9
-ALTOSLIB_VERSION=9
+ALTOSUILIB_VERSION=10
+ALTOSLIB_VERSION=10
AC_SUBST(ALTOSLIB_VERSION)
AC_DEFINE(ALTOSLIB_VERSION,$ALTOSLIB_VERSION,[Version of the AltosLib package])
@@ -149,7 +149,7 @@ fi
ANDROID_RELEASE=no
if test "x$ANDROID_SDK" != "xno"; then
HAVE_ANDROID_SDK="yes"
- if test -f "$HOME/altusmetrumllc/release.keystore" -a -f "$HOME/altusmetrumllc/Passphrase"; then
+ if test -f "$HOME/altusmetrumllc/google-play-release.keystore" -a -f "$HOME/altusmetrumllc/google-play-passphrase"; then
ANDROID_RELEASE=yes
fi
else
@@ -174,7 +174,7 @@ AC_ARG_WITH(google-key, AS_HELP_STRING([--with-google-key=PATH],
[GOOGLEKEYFILE=$withval], [GOOGLEKEYFILE=$HOME/altusmetrumllc/google-maps-api-key])
if test -r "$GOOGLEKEYFILE" -a -s "$GOOGLEKEYFILE"; then
- GOOGLEKEY='"'`cat "$GOOGLEKEYFILE"`'"'
+ GOOGLEKEY=`cat "$GOOGLEKEYFILE"`
HAVE_GOOGLE_KEY="yes"
else
GOOGLEKEY='null'
@@ -557,6 +557,8 @@ ao-tools/ao-cal-accel/Makefile
ao-tools/ao-cal-freq/Makefile
ao-tools/ao-test-gps/Makefile
ao-tools/ao-usbtrng/Makefile
+ao-tools/ao-chaosread/Makefile
+ao-tools/ao-makebin/Makefile
ao-utils/Makefile
src/Version
])
diff --git a/doc/Makefile b/doc/Makefile
index 6a04a591..ed06006a 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -3,6 +3,7 @@
#
RELNOTES_INC=\
+ release-notes-1.6.3.inc \
release-notes-1.6.2.inc \
release-notes-1.6.1.inc \
release-notes-1.6.inc \
diff --git a/doc/altosdroid.inc b/doc/altosdroid.inc
index cdf7b96d..faaa13f9 100644
--- a/doc/altosdroid.inc
+++ b/doc/altosdroid.inc
@@ -58,35 +58,68 @@
doesn't, the most likely reason is that your Android
device doesn't support USB On-the-go.
- === Configuring AltosDroid
+ === AltosDroid Menu
+
+ The main AltosDroid menu has a selection of operation
+ and configuration options.
+
+ Connect a device::
+
+ Offers a menu of available TeleBT devices, and an
+ option to scan for additional devices.
+
+ Disconnect device::
+
+ Disconnects the current TeleBT or TeleDongle
+ device. You can reconnect TeleBT over bluetooth by
+ using Connect a Device. You can reconnect a USB device
+ by unplugging it and then plugging it back in.
- There are several configuration and operation
- parameters available in the AltosDroid menu.
-
Select radio frequency::
This selects which frequency to listen on by bringing
up a menu of pre-set radio frequencies. Pick the one
which matches your altimeter.
- Select data rate::
+ Select Tracker::
+
+ Switches the information displays to show data for a
+ different transmitting device. The map will always
+ show all of the devices in view. Trackers are shown
+ and selected by serial number, so make sure you note
+ the serial number of devices in each airframe.
+
+ Delete Track::
+
+ Deletes all information about a transmitting device.
+
+ Setup::
+
+ Offers additional configuration operations. See
+ <<_setup>>.
+
+ Idle Mode::
+
+ Communicate with an altimeter in Idle mode. See <<_idle_mode>>
+
+ Quit::
+
+ Shuts down AltosDroid.
+
+ === Setup
+
+ Telemetry Rate::
Altus Metrum transmitters can be configured to operate
at lower data rates to improve transmission range. If
you have configured your device to do this, this menu
item allows you to change the receiver to match.
- Change units::
-
- This toggles between metric and imperial units.
-
- Load maps::
+ Units::
- Brings up a dialog allowing you to download offline
- map tiles so that you can have maps available even if
- you have no network connectivity at the launch site.
+ Selects which units used to report values.
- Map type::
+ Map Type::
Displays a menu of map types and lets you select
one. Hybrid maps include satellite images with a
@@ -95,26 +128,58 @@
includes roads along with shadows indicating changes
in elevation, and other geographical features.
- Toggle Online/Offline maps::
+ Map Source::
- Switches between online and offline maps. Online maps
+ Select between online and offline maps. Online maps
will show a 'move to current position' icon in the
upper right corner, while offline maps will have
copyright information all over the map. Otherwise,
they're pretty similar.
- Select Tracker::
+ Preload Maps::
- Switches the information displays to show data for a
- different transmitting device. The map will always
- show all of the devices in view. Trackers are shown
- and selected by serial number, so make sure you note
- the serial number of devices in each airframe.
+ Brings up a dialog allowing you to download offline
+ map tiles so that you can have maps available even if
+ you have no network connectivity at the launch site.
+
+ Manage Frequencies::
- Delete Track::
+ This presents a dialog containing the current list of
+ frequencies that will be show in the 'Select radio
+ frequency' menu. You can change the label for existing
+ frequencies, delete or add new frequencies.
+
+ === Idle Mode
+
+ Callsign::
+
+ Lets you configure the callsign used by AltosDroid to
+ communicate with the flight computer. The callsign on
+ the two devices must match or the communication will
+ fail. This provides a modest amount of protection
+ against accidentally controlling another persons
+ flight computer.
+
+ Monitor::
+
+ This provides similar information to monitoring the
+ telemetry stream from a flight computer in flight
+ mode. The title of the application will change to
+ include (idle) so you can tell this mode is active.
+
+ Reboot::
+
+ Remotely reboots the flight computer. This is useful
+ when the flight computers turned on while the airframe
+ is horizontal and you want to restart the flight
+ computers in pad mode after raising the airframe to
+ vertical.
+
+ Fire Igniters::
+
+ Remotely control igniters for ground testing recovery
+ systems.
- Deletes all information about a transmitting device.
-
=== AltosDroid Flight Monitoring
AltosDroid is designed to mimic the AltosUI flight
@@ -253,7 +318,7 @@
Bearing::
- This is the aziumuth from true north for the rocket
+ This is the azimuth from true north for the rocket
from the android device. Use this in combination with
the Elevation value to help locate the rocket in the
sky, or at least to help point the antenna in the
@@ -300,7 +365,7 @@
Bearing::
- This is the aziumuth from true north for the rocket
+ This is the azimuth from true north for the rocket
from the android device. Use this in combination with
the Elevation value to help locate the rocket in the
sky, or at least to help point the antenna in the
@@ -328,7 +393,8 @@
Max Height::
- Shows the maximum height above launch pad.
+ Shows the maximum height above launch pad seen during
+ the flight.
Max Speed::
diff --git a/doc/altusmetrum-docinfo.xml b/doc/altusmetrum-docinfo.xml
index 63c1e035..5473dd66 100644
--- a/doc/altusmetrum-docinfo.xml
+++ b/doc/altusmetrum-docinfo.xml
@@ -47,6 +47,14 @@
<revhistory>
<?dbhtml filename="altusmetrum-revhistory.html"?>
<revision>
+ <revnumber>1.6.3</revnumber>
+ <date>21 April 2016</date>
+ <revremark>
+ Minor release adding idle mode to AltosDroid and fixing various
+ host software bugs.
+ </revremark>
+ </revision>
+ <revision>
<revnumber>1.6.2</revnumber>
<date>10 January 2016</date>
<revremark>
diff --git a/doc/easymini-docinfo.xml b/doc/easymini-docinfo.xml
index 7789d2f3..cf3f27d2 100644
--- a/doc/easymini-docinfo.xml
+++ b/doc/easymini-docinfo.xml
@@ -39,6 +39,13 @@
<revhistory>
<?dbhtml filename="easymini-revhistory.html"?>
<revision>
+ <revnumber>1.6.3</revnumber>
+ <date>21 April 2016</date>
+ <revremark>
+ Minor release fixing various host software bugs.
+ </revremark>
+ </revision>
+ <revision>
<revnumber>1.6.2</revnumber>
<date>10 January 2016</date>
<revremark>
diff --git a/doc/easymini-release-notes.inc b/doc/easymini-release-notes.inc
index 352a989b..7f578f71 100644
--- a/doc/easymini-release-notes.inc
+++ b/doc/easymini-release-notes.inc
@@ -2,6 +2,10 @@
== Release Notes
:leveloffset: 2
+ include::release-notes-1.6.3.raw[]
+
+ <<<<
+ :leveloffset: 2
include::release-notes-1.6.2.raw[]
:leveloffset: 0
diff --git a/doc/release-notes-1.6.3.inc b/doc/release-notes-1.6.3.inc
new file mode 100644
index 00000000..6aa77042
--- /dev/null
+++ b/doc/release-notes-1.6.3.inc
@@ -0,0 +1,92 @@
+= Release Notes for Version 1.6.3
+:toc!:
+:doctype: article
+
+ Version 1.6.3 adds idle mode to AltosDroid and has bug fixes
+ for our host software on desktops, laptops an android devices
+ along with BlueTooth support for Windows.
+
+ == AltOS
+
+ AltOS fixes:
+
+ * Fix hardware flow control on TeleBT v3.0. RTS/CTS is
+ wired backwards on this board, switch from using the
+ hardware to driving these pins with software.
+
+ == AltosUI and TeleGPS Applications
+
+ AltosUI and TeleGPS New Features:
+
+ * Add BlueTooth support for Windows operating system. This
+ supports connections to TeleBT over BlueTooth rather than
+ just USB.
+
+ AltosUI and TeleGPS Fixes:
+
+ * Change Java detection and install on Windows. Detection is
+ now done by looking for the 'javaw.exe' program, and
+ installation by opening a browser on the java.com web site.
+
+ * Delay polling while the Fire Igniters is visible to allow
+ for TeleMega to report back complete status over the radio.
+
+ * Disallow changing RF calibration numbers in the
+ configuration UI. There's no good reason to change this from
+ the field, and recovering is really hard if you haven't
+ written down the right number.
+
+ * Fix USB device discovery on Mac OS X El Capitan. This makes
+ the connected Altus Metrum USB devices appear again.
+
+ * Fix acceleration data presented in MonitorIdle mode for
+ TeleMetrum v2.0 flight computers.
+
+ == AltosDroid
+
+ AltosDroid new features:
+
+ * Monitor Idle mode. Check state of flight computer while in
+ idle mode over the radio link
+
+ * Fire Igniters. Remotely fire ignires for recovery system
+ ground tests.
+
+ * Remote reboot. Cause the flight computer to reboot over the
+ radio link. This provides a method for switching the flight
+ computer from idle to flight mode without needing to reach
+ the power switch.
+
+ * Configurable frequency menu. Change the set of available
+ frequencies and provide more descriptive names.
+
+ AltosDroid bug fixes:
+
+ * Don't set target location if GPS hasn't locked yet.
+
+ * Fix saving target states so they can be reloaded when the
+ application restarts. When the application is shut down and
+ restarted, all previous target state information will be
+ restored (including GPS position if available).
+
+ * Fix crash on some Android devices for offline maps when
+ changing the map scale or location.
+
+ * Don't require USB OTG support. This kept the latest
+ AltosDroid from being offered on devices without USB device
+ support, although it can work without that just fine using
+ BlueTooth.
+
+ * Don't require bluetooth to be enabled. This allows the
+ application to operate with USB devices or just show old
+ data without turning on the bluetooth radio.
+
+ * Recover old tracker positions when restarting
+ application. This finally allows you to safely stop and
+ restart the application without losing the last known
+ location of any tracker.
+
+ == Documentation
+
+ * Document TeleMega and EasyMega additional pyro channel
+ continuity audio alert pattern.
diff --git a/doc/release-notes.inc b/doc/release-notes.inc
index a6240d43..35ffa0d1 100644
--- a/doc/release-notes.inc
+++ b/doc/release-notes.inc
@@ -2,6 +2,10 @@
== Release Notes
:leveloffset: 2
+ include::release-notes-1.6.3.raw[]
+
+ <<<<
+ :leveloffset: 2
include::release-notes-1.6.2.raw[]
<<<<
diff --git a/doc/telegps-release-notes.inc b/doc/telegps-release-notes.inc
index dcdabc05..4123c783 100644
--- a/doc/telegps-release-notes.inc
+++ b/doc/telegps-release-notes.inc
@@ -2,6 +2,10 @@
== Release Notes
:leveloffset: 2
+ include::release-notes-1.6.3.raw[]
+
+ <<<<
+ :leveloffset: 2
include::release-notes-1.6.2.raw[]
<<<<
diff --git a/doc/usage.inc b/doc/usage.inc
index 8349f86c..25fdd6d3 100644
--- a/doc/usage.inc
+++ b/doc/usage.inc
@@ -166,6 +166,15 @@
controlling the flight or transmitting telemetry
signals, but no record of the flight will be
stored in on-board flash.
+
+ |Additional Igniters
+ |four very short beeps
+ |Continuity indication for the four additional pyro
+ |channels on TeleMega and EasyMega. One high tone for
+ |no continuity, one low tone for continuity. These are
+ |produced after the continuity indicators for the two
+ |primary igniter channels.
+
|====
ifdef::radio[]
diff --git a/icon/.gitignore b/icon/.gitignore
index 94c7c70c..3122511d 100644
--- a/icon/.gitignore
+++ b/icon/.gitignore
@@ -1,5 +1,7 @@
application-*.png
altusmetrum-*.png
+altusmetrum.xpm
+application-vnd.altusmetrum.micropeak.svg
*.rc
*.ico
*.icns
diff --git a/libaltos/Makefile-standalone b/libaltos/Makefile-standalone
index a1f9f5bc..1430aacb 100644
--- a/libaltos/Makefile-standalone
+++ b/libaltos/Makefile-standalone
@@ -5,9 +5,11 @@ OS:=$(shell uname)
#
ifeq ($(OS),Linux)
-JAVA_CFLAGS=-I/usr/lib/jvm/java-6-openjdk/include
+OS_SRCS=libaltos_posix.c libaltos_linux.c
-OS_LIB_CFLAGS=-DLINUX -DPOSIX_TTY $(JAVA_CFLAGS)
+JAVA_CFLAGS=-I/usr/lib/jvm/default-java/include -I/usr/lib/jvm/default-java/include/linux
+
+OS_LIB_CFLAGS=-DLINUX -DPOSIX_TTY $(JAVA_CFLAGS) -shared -fPIC
OS_APP_CFLAGS=$(OS_LIB_CFLAGS)
@@ -22,6 +24,8 @@ endif
#
ifeq ($(OS),Darwin)
+OS_SRCS=libaltos_posix.c libaltos_darwin.c
+
#OS_LIB_CFLAGS=\
# -DDARWIN -DPOSIX_TTY -arch i386 -arch x86_64 \
# --sysroot=/Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.5 \
@@ -29,8 +33,8 @@ ifeq ($(OS),Darwin)
# -iwithsysroot /System/Library/Frameworks/IOKit.framework/Headers \
# -iwithsysroot /System/Library/Frameworks/CoreFoundation.framework/Headers
-XCODE=/Applications/Xcode.app
-SDK=$(XCODE)/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk
+XCODE=/Applications/Xcode-beta.app
+SDK=$(XCODE)/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk
MINVERSION=10.5
OS_LIB_CFLAGS=\
@@ -39,7 +43,7 @@ OS_LIB_CFLAGS=\
-iwithsysroot /System/Library/Frameworks/JavaVM.framework/Headers \
-iwithsysroot /System/Library/Frameworks/IOKit.framework/Headers \
-iwithsysroot /System/Library/Frameworks/CoreFoundation.framework/Headers
-OS_APP_CFLAGS=$(OS_LIB_CFLAGS)
+OS_APP_CFLAGS=$(OS_LIB_CFLAGS) -O0 -g
OS_LDFLAGS =\
-framework IOKit -framework CoreFoundation
@@ -54,6 +58,8 @@ endif
#
ifneq (,$(findstring MINGW,$(OS)))
+OS_SRCS=libaltos_windows.c
+
CC=gcc
OS_LIB_CFLAGS = -DWINDOWS -mconsole -DBUILD_DLL
@@ -103,7 +109,7 @@ CFLAGS=$(OS_LIB_CFLAGS) -O -I.
LDFLAGS=$(OS_LDFLAGS)
HEADERS=libaltos.h
-SRCS = libaltos.c $(SWIG_WRAP)
+SRCS = libaltos_common.c $(OS_SRCS) $(SWIG_WRAP)
OBJS = $(SRCS:%.c=%.o)
LIBS = $(DARWIN_LIBS)
@@ -111,7 +117,7 @@ $(CJNITEST): cjnitest.c $(LIBNAME)
$(CC) -o $@ $(OS_APP_CFLAGS) cjnitest.c $(LIBNAME) $(LIBS) $(LDFLAGS)
$(LIBNAME): $(OBJS)
- $(CC) -shared $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(LDFLAGS)
+ $(CC) -shared -fPIC $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(LDFLAGS)
clean:
rm -f $(CLASSFILES) $(OBJS) $(LIBNAME) $(CJNITEST) cjnitest.o
diff --git a/libaltos/Makefile.am b/libaltos/Makefile.am
index 1db2d486..8f69c1ad 100644
--- a/libaltos/Makefile.am
+++ b/libaltos/Makefile.am
@@ -1,5 +1,5 @@
JAVAC=javac
-AM_CFLAGS=-DLINUX -DPOSIX_TTY -I$(JVM_INCLUDE)
+AM_CFLAGS=-DLINUX -DPOSIX_TTY -I$(JVM_INCLUDE) -I$(JVM_INCLUDE)/linux
AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -source 6
altoslibdir=$(libdir)/altos
@@ -8,9 +8,22 @@ altoslib_LTLIBRARIES=libaltos.la
libaltos_la_LDFLAGS=-version-info 1:0:1 -Wl,-znoexecstack
libaltos_la_SOURCES=\
- libaltos.c \
+ libaltos_common.c \
+ libaltos_posix.c \
+ libaltos_linux.c \
+ libaltos_wrap.c \
+ libaltos.h \
+ libaltos_posix.h \
+ libaltos_private.h
+
+WINDOWS_SRC=\
+ libaltos_common.c\
+ libaltos_windows.c\
libaltos_wrap.c
+WINDOWS_H=\
+ libaltos.h
+
noinst_PROGRAMS=cjnitest
cjnitest_SOURCES=cjnitest.c
@@ -64,16 +77,16 @@ classlibaltos.stamp: $(SWIG_FILE)
MINGCC32=i686-w64-mingw32-gcc
MINGCC64=x86_64-w64-mingw32-gcc
-MINGFLAGS=-Wall -DWINDOWS -DBUILD_DLL -I$(JVM_INCLUDE)
-MINGLIBS=-lsetupapi
+MINGFLAGS=-Wall -Wextra -DWINDOWS -DBUILD_DLL -mconsole -I$(JVM_INCLUDE) -I$(JVM_INCLUDE)/linux
+MINGLIBS=-lsetupapi -lws2_32
fat: all altos.dll altos64.dll
-altos.dll: $(libaltos_la_SOURCES)
- $(MINGCC32) -o $@ $(MINGFLAGS) -shared $(libaltos_la_SOURCES) $(MINGLIBS)
+altos.dll: $(WINDOWS_SRC) $(WINDOWS_H)
+ $(MINGCC32) -o $@ $(MINGFLAGS) -shared $(WINDOWS_SRC) $(MINGLIBS)
-altos64.dll: $(libaltos_la_SOURCES)
- $(MINGCC64) -o $@ $(MINGFLAGS) -shared $(libaltos_la_SOURCES) $(MINGLIBS)
+altos64.dll: $(WINDOWS_SRC) $(WINDOWS_H)
+ $(MINGCC64) -o $@ $(MINGFLAGS) -shared $(WINDOWS_SRC) $(MINGLIBS)
clean-local:
-rm -rf libaltosJNI *.class *.java classlibaltos.stamp $(SWIG_FILE) libaltos_wrap.c altos.dll altos64.dll
diff --git a/libaltos/libaltos.c b/libaltos/libaltos.c
deleted file mode 100644
index 97b7b3f9..00000000
--- a/libaltos/libaltos.c
+++ /dev/null
@@ -1,1535 +0,0 @@
-/*
- * Copyright © 2010 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "libaltos.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define BLUETOOTH_PRODUCT_TELEBT "TeleBT"
-
-#define USE_POLL
-
-PUBLIC int
-altos_init(void)
-{
- return LIBALTOS_SUCCESS;
-}
-
-PUBLIC void
-altos_fini(void)
-{
-}
-
-static struct altos_error last_error;
-
-static void
-altos_set_last_error(int code, char *string)
-{
- last_error.code = code;
- strncpy(last_error.string, string, sizeof (last_error.string) -1);
- last_error.string[sizeof(last_error.string)-1] = '\0';
-}
-
-PUBLIC void
-altos_get_last_error(struct altos_error *error)
-{
- *error = last_error;
-}
-
-#ifdef DARWIN
-
-#include <unistd.h>
-
-#undef USE_POLL
-
-/* Mac OS X don't have strndup even if _GNU_SOURCE is defined */
-static char *
-altos_strndup (const char *s, size_t n)
-{
- size_t len = strlen (s);
- char *ret;
-
- if (len <= n)
- return strdup (s);
- ret = malloc(n + 1);
- strncpy(ret, s, n);
- ret[n] = '\0';
- return ret;
-}
-
-#else
-#define altos_strndup strndup
-#endif
-
-#ifdef POSIX_TTY
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <termios.h>
-#include <errno.h>
-
-#define USB_BUF_SIZE 64
-
-struct altos_file {
- int fd;
-#ifdef USE_POLL
- int pipe[2];
-#else
- int out_fd;
-#endif
- unsigned char out_data[USB_BUF_SIZE];
- int out_used;
- unsigned char in_data[USB_BUF_SIZE];
- int in_used;
- int in_read;
-};
-
-static void
-altos_set_last_posix_error(void)
-{
- altos_set_last_error(errno, strerror(errno));
-}
-
-PUBLIC struct altos_file *
-altos_open(struct altos_device *device)
-{
- struct altos_file *file = calloc (sizeof (struct altos_file), 1);
- int ret;
- struct termios term;
-
- if (!file) {
- altos_set_last_posix_error();
- return NULL;
- }
-
-// altos_set_last_error(12, "yeah yeah, failed again");
-// free(file);
-// return NULL;
-
- file->fd = open(device->path, O_RDWR | O_NOCTTY);
- if (file->fd < 0) {
- altos_set_last_posix_error();
- free(file);
- return NULL;
- }
-#ifdef USE_POLL
- pipe(file->pipe);
-#else
- file->out_fd = open(device->path, O_RDWR | O_NOCTTY);
- if (file->out_fd < 0) {
- altos_set_last_posix_error();
- close(file->fd);
- free(file);
- return NULL;
- }
-#endif
- ret = tcgetattr(file->fd, &term);
- if (ret < 0) {
- altos_set_last_posix_error();
- close(file->fd);
-#ifndef USE_POLL
- close(file->out_fd);
-#endif
- free(file);
- return NULL;
- }
- cfmakeraw(&term);
- cfsetospeed(&term, B9600);
- cfsetispeed(&term, B9600);
-#ifdef USE_POLL
- term.c_cc[VMIN] = 1;
- term.c_cc[VTIME] = 0;
-#else
- term.c_cc[VMIN] = 0;
- term.c_cc[VTIME] = 1;
-#endif
- ret = tcsetattr(file->fd, TCSAFLUSH, &term);
- if (ret < 0) {
- altos_set_last_posix_error();
- close(file->fd);
-#ifndef USE_POLL
- close(file->out_fd);
-#endif
- free(file);
- return NULL;
- }
- return file;
-}
-
-PUBLIC void
-altos_close(struct altos_file *file)
-{
- if (file->fd != -1) {
- int fd = file->fd;
- file->fd = -1;
-#ifdef USE_POLL
- write(file->pipe[1], "\r", 1);
-#else
- close(file->out_fd);
- file->out_fd = -1;
-#endif
- close(fd);
- }
-}
-
-PUBLIC void
-altos_free(struct altos_file *file)
-{
- altos_close(file);
- free(file);
-}
-
-PUBLIC int
-altos_flush(struct altos_file *file)
-{
- if (file->out_used && 0) {
- printf ("flush \"");
- fwrite(file->out_data, 1, file->out_used, stdout);
- printf ("\"\n");
- }
- while (file->out_used) {
- int ret;
-
- if (file->fd < 0)
- return -EBADF;
-#ifdef USE_POLL
- ret = write (file->fd, file->out_data, file->out_used);
-#else
- ret = write (file->out_fd, file->out_data, file->out_used);
-#endif
- if (ret < 0) {
- altos_set_last_posix_error();
- return -last_error.code;
- }
- if (ret) {
- memmove(file->out_data, file->out_data + ret,
- file->out_used - ret);
- file->out_used -= ret;
- }
- }
- return 0;
-}
-
-PUBLIC int
-altos_putchar(struct altos_file *file, char c)
-{
- int ret;
-
- if (file->out_used == USB_BUF_SIZE) {
- ret = altos_flush(file);
- if (ret) {
- return ret;
- }
- }
- file->out_data[file->out_used++] = c;
- ret = 0;
- if (file->out_used == USB_BUF_SIZE)
- ret = altos_flush(file);
- return ret;
-}
-
-#ifdef USE_POLL
-#include <poll.h>
-#endif
-
-static int
-altos_fill(struct altos_file *file, int timeout)
-{
- int ret;
-#ifdef USE_POLL
- struct pollfd fd[2];
-#endif
-
- if (timeout == 0)
- timeout = -1;
- while (file->in_read == file->in_used) {
- if (file->fd < 0)
- return LIBALTOS_ERROR;
-#ifdef USE_POLL
- fd[0].fd = file->fd;
- fd[0].events = POLLIN|POLLERR|POLLHUP|POLLNVAL;
- fd[1].fd = file->pipe[0];
- fd[1].events = POLLIN;
- ret = poll(fd, 2, timeout);
- if (ret < 0) {
- altos_set_last_posix_error();
- return LIBALTOS_ERROR;
- }
- if (ret == 0)
- return LIBALTOS_TIMEOUT;
-
- if (fd[0].revents & (POLLHUP|POLLERR|POLLNVAL))
- return LIBALTOS_ERROR;
- if (fd[0].revents & POLLIN)
-#endif
- {
- ret = read(file->fd, file->in_data, USB_BUF_SIZE);
- if (ret < 0) {
- altos_set_last_posix_error();
- return LIBALTOS_ERROR;
- }
- file->in_read = 0;
- file->in_used = ret;
-#ifndef USE_POLL
- if (ret == 0 && timeout > 0)
- return LIBALTOS_TIMEOUT;
-#endif
- }
- }
- if (file->in_used && 0) {
- printf ("fill \"");
- fwrite(file->in_data, 1, file->in_used, stdout);
- printf ("\"\n");
- }
- return 0;
-}
-
-PUBLIC int
-altos_getchar(struct altos_file *file, int timeout)
-{
- int ret;
- while (file->in_read == file->in_used) {
- if (file->fd < 0)
- return LIBALTOS_ERROR;
- ret = altos_fill(file, timeout);
- if (ret)
- return ret;
- }
- return file->in_data[file->in_read++];
-}
-
-#endif /* POSIX_TTY */
-
-/*
- * Scan for Altus Metrum devices by looking through /sys
- */
-
-#ifdef LINUX
-
-#define _GNU_SOURCE
-#include <ctype.h>
-#include <dirent.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/hci.h>
-#include <bluetooth/hci_lib.h>
-#include <bluetooth/rfcomm.h>
-
-static char *
-cc_fullname (char *dir, char *file)
-{
- char *new;
- int dlen = strlen (dir);
- int flen = strlen (file);
- int slen = 0;
-
- if (dir[dlen-1] != '/')
- slen = 1;
- new = malloc (dlen + slen + flen + 1);
- if (!new)
- return 0;
- strcpy(new, dir);
- if (slen)
- strcat (new, "/");
- strcat(new, file);
- return new;
-}
-
-static char *
-cc_basename(char *file)
-{
- char *b;
-
- b = strrchr(file, '/');
- if (!b)
- return file;
- return b + 1;
-}
-
-static char *
-load_string(char *dir, char *file)
-{
- char *full = cc_fullname(dir, file);
- char line[4096];
- char *r;
- FILE *f;
- int rlen;
-
- f = fopen(full, "r");
- free(full);
- if (!f)
- return NULL;
- r = fgets(line, sizeof (line), f);
- fclose(f);
- if (!r)
- return NULL;
- rlen = strlen(r);
- if (r[rlen-1] == '\n')
- r[rlen-1] = '\0';
- return strdup(r);
-}
-
-static int
-load_hex(char *dir, char *file)
-{
- char *line;
- char *end;
- long i;
-
- line = load_string(dir, file);
- if (!line)
- return -1;
- i = strtol(line, &end, 16);
- free(line);
- if (end == line)
- return -1;
- return i;
-}
-
-static int
-load_dec(char *dir, char *file)
-{
- char *line;
- char *end;
- long i;
-
- line = load_string(dir, file);
- if (!line)
- return -1;
- i = strtol(line, &end, 10);
- free(line);
- if (end == line)
- return -1;
- return i;
-}
-
-static int
-dir_filter_tty_colon(const struct dirent *d)
-{
- return strncmp(d->d_name, "tty:", 4) == 0;
-}
-
-static int
-dir_filter_tty(const struct dirent *d)
-{
- return strncmp(d->d_name, "tty", 3) == 0;
-}
-
-struct altos_usbdev {
- char *sys;
- char *tty;
- char *manufacturer;
- char *product_name;
- int serial; /* AltOS always uses simple integer serial numbers */
- int idProduct;
- int idVendor;
-};
-
-static char *
-usb_tty(char *sys)
-{
- char *base;
- int num_configs;
- int config;
- struct dirent **namelist;
- int interface;
- int num_interfaces;
- char endpoint_base[20];
- char *endpoint_full;
- char *tty_dir;
- int ntty;
- char *tty;
-
- base = cc_basename(sys);
- num_configs = load_hex(sys, "bNumConfigurations");
- num_interfaces = load_hex(sys, "bNumInterfaces");
- for (config = 1; config <= num_configs; config++) {
- for (interface = 0; interface < num_interfaces; interface++) {
- sprintf(endpoint_base, "%s:%d.%d",
- base, config, interface);
- endpoint_full = cc_fullname(sys, endpoint_base);
-
-
- /* Check for tty:ttyACMx style names
- */
- ntty = scandir(endpoint_full, &namelist,
- dir_filter_tty_colon,
- alphasort);
- if (ntty > 0) {
- free(endpoint_full);
- tty = cc_fullname("/dev", namelist[0]->d_name + 4);
- free(namelist);
- return tty;
- }
-
- /* Check for tty/ttyACMx style names
- */
- tty_dir = cc_fullname(endpoint_full, "tty");
- ntty = scandir(tty_dir, &namelist,
- dir_filter_tty,
- alphasort);
- free (tty_dir);
- if (ntty > 0) {
- tty = cc_fullname("/dev", namelist[0]->d_name);
- free(endpoint_full);
- free(namelist);
- return tty;
- }
-
- /* Check for ttyACMx style names
- */
- ntty = scandir(endpoint_full, &namelist,
- dir_filter_tty,
- alphasort);
- free(endpoint_full);
- if (ntty > 0) {
- tty = cc_fullname("/dev", namelist[0]->d_name);
- free(namelist);
- return tty;
- }
-
- }
- }
- return NULL;
-}
-
-static struct altos_usbdev *
-usb_scan_device(char *sys)
-{
- struct altos_usbdev *usbdev;
- char *tty;
-
- tty = usb_tty(sys);
- if (!tty)
- return NULL;
- usbdev = calloc(1, sizeof (struct altos_usbdev));
- if (!usbdev)
- return NULL;
- usbdev->sys = strdup(sys);
- usbdev->manufacturer = load_string(sys, "manufacturer");
- usbdev->product_name = load_string(sys, "product");
- usbdev->serial = load_dec(sys, "serial");
- usbdev->idProduct = load_hex(sys, "idProduct");
- usbdev->idVendor = load_hex(sys, "idVendor");
- usbdev->tty = tty;
- return usbdev;
-}
-
-static void
-usbdev_free(struct altos_usbdev *usbdev)
-{
- free(usbdev->sys);
- free(usbdev->manufacturer);
- free(usbdev->product_name);
- /* this can get used as a return value */
- if (usbdev->tty)
- free(usbdev->tty);
- free(usbdev);
-}
-
-#define USB_DEVICES "/sys/bus/usb/devices"
-
-static int
-dir_filter_dev(const struct dirent *d)
-{
- const char *n = d->d_name;
- char c;
-
- while ((c = *n++)) {
- if (isdigit(c))
- continue;
- if (c == '-')
- continue;
- if (c == '.' && n != d->d_name + 1)
- continue;
- return 0;
- }
- return 1;
-}
-
-struct altos_list {
- struct altos_usbdev **dev;
- int current;
- int ndev;
-};
-
-struct altos_list *
-altos_list_start(void)
-{
- int e;
- struct dirent **ents;
- char *dir;
- struct altos_usbdev *dev;
- struct altos_list *devs;
- int n;
-
- devs = calloc(1, sizeof (struct altos_list));
- if (!devs)
- return NULL;
-
- n = scandir (USB_DEVICES, &ents,
- dir_filter_dev,
- alphasort);
- if (!n)
- return 0;
- for (e = 0; e < n; e++) {
- dir = cc_fullname(USB_DEVICES, ents[e]->d_name);
- dev = usb_scan_device(dir);
- if (!dev)
- continue;
- free(dir);
- if (devs->dev)
- devs->dev = realloc(devs->dev,
- (devs->ndev + 1) * sizeof (struct usbdev *));
- else
- devs->dev = malloc (sizeof (struct usbdev *));
- devs->dev[devs->ndev++] = dev;
- }
- free(ents);
- devs->current = 0;
- return devs;
-}
-
-PUBLIC struct altos_list *
-altos_ftdi_list_start(void)
-{
- return altos_list_start();
-}
-
-int
-altos_list_next(struct altos_list *list, struct altos_device *device)
-{
- struct altos_usbdev *dev;
- if (list->current >= list->ndev) {
- return 0;
- }
- dev = list->dev[list->current];
- strcpy(device->name, dev->product_name);
- device->vendor = dev->idVendor;
- device->product = dev->idProduct;
- strcpy(device->path, dev->tty);
- device->serial = dev->serial;
- list->current++;
- return 1;
-}
-
-void
-altos_list_finish(struct altos_list *usbdevs)
-{
- int i;
-
- if (!usbdevs)
- return;
- for (i = 0; i < usbdevs->ndev; i++)
- usbdev_free(usbdevs->dev[i]);
- free(usbdevs);
-}
-
-#include <dlfcn.h>
-
-static void *libbt;
-static int bt_initialized;
-
-static int init_bt(void) {
- if (!bt_initialized) {
- bt_initialized = 1;
- libbt = dlopen("libbluetooth.so.3", RTLD_LAZY);
- if (!libbt)
- printf("failed to find bluetooth library\n");
- }
- return libbt != NULL;
-}
-
-#define join(a,b) a ## b
-#define bt_func(name, ret, fail, formals, actuals) \
- static ret join(altos_, name) formals { \
- static ret (*name) formals; \
- if (!init_bt()) return fail; \
- name = dlsym(libbt, #name); \
- if (!name) return fail; \
- return name actuals; \
- }
-
-bt_func(ba2str, int, -1, (const bdaddr_t *ba, char *str), (ba, str))
-#define ba2str altos_ba2str
-
-bt_func(str2ba, int, -1, (const char *str, bdaddr_t *ba), (str, ba))
-#define str2ba altos_str2ba
-
-bt_func(hci_read_remote_name, int, -1, (int sock, const bdaddr_t *ba, int len, char *name, int timeout), (sock, ba, len, name, timeout))
-#define hci_read_remote_name altos_hci_read_remote_name
-
-bt_func(hci_open_dev, int, -1, (int dev_id), (dev_id))
-#define hci_open_dev altos_hci_open_dev
-
-bt_func(hci_get_route, int, -1, (bdaddr_t *bdaddr), (bdaddr))
-#define hci_get_route altos_hci_get_route
-
-bt_func(hci_inquiry, int, -1, (int adapter_id, int len, int max_rsp, const uint8_t *lap, inquiry_info **devs, long flags), (adapter_id, len, max_rsp, lap, devs, flags))
-#define hci_inquiry altos_hci_inquiry
-
-struct altos_bt_list {
- inquiry_info *ii;
- int sock;
- int dev_id;
- int rsp;
- int num_rsp;
-};
-
-#define INQUIRY_MAX_RSP 255
-
-struct altos_bt_list *
-altos_bt_list_start(int inquiry_time)
-{
- struct altos_bt_list *bt_list;
-
- bt_list = calloc(1, sizeof (struct altos_bt_list));
- if (!bt_list)
- goto no_bt_list;
-
- bt_list->ii = calloc(INQUIRY_MAX_RSP, sizeof (inquiry_info));
- if (!bt_list->ii)
- goto no_ii;
- bt_list->dev_id = hci_get_route(NULL);
- if (bt_list->dev_id < 0)
- goto no_dev_id;
-
- bt_list->sock = hci_open_dev(bt_list->dev_id);
- if (bt_list->sock < 0)
- goto no_sock;
-
- bt_list->num_rsp = hci_inquiry(bt_list->dev_id,
- inquiry_time,
- INQUIRY_MAX_RSP,
- NULL,
- &bt_list->ii,
- IREQ_CACHE_FLUSH);
- if (bt_list->num_rsp < 0)
- goto no_rsp;
-
- bt_list->rsp = 0;
- return bt_list;
-
-no_rsp:
- close(bt_list->sock);
-no_sock:
-no_dev_id:
- free(bt_list->ii);
-no_ii:
- free(bt_list);
-no_bt_list:
- return NULL;
-}
-
-int
-altos_bt_list_next(struct altos_bt_list *bt_list,
- struct altos_bt_device *device)
-{
- inquiry_info *ii;
-
- if (bt_list->rsp >= bt_list->num_rsp)
- return 0;
-
- ii = &bt_list->ii[bt_list->rsp];
- if (ba2str(&ii->bdaddr, device->addr) < 0)
- return 0;
- memset(&device->name, '\0', sizeof (device->name));
- if (hci_read_remote_name(bt_list->sock, &ii->bdaddr,
- sizeof (device->name),
- device->name, 0) < 0) {
- strcpy(device->name, "[unknown]");
- }
- bt_list->rsp++;
- return 1;
-}
-
-void
-altos_bt_list_finish(struct altos_bt_list *bt_list)
-{
- close(bt_list->sock);
- free(bt_list->ii);
- free(bt_list);
-}
-
-void
-altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device)
-{
- strncpy(device->name, name, sizeof (device->name));
- device->name[sizeof(device->name)-1] = '\0';
- strncpy(device->addr, addr, sizeof (device->addr));
- device->addr[sizeof(device->addr)-1] = '\0';
-}
-
-struct altos_file *
-altos_bt_open(struct altos_bt_device *device)
-{
- struct sockaddr_rc addr = { 0 };
- int status, i;
- struct altos_file *file;
-
- file = calloc(1, sizeof (struct altos_file));
- if (!file) {
- errno = ENOMEM;
- altos_set_last_posix_error();
- goto no_file;
- }
- addr.rc_family = AF_BLUETOOTH;
- addr.rc_channel = 1;
- if (str2ba(device->addr, &addr.rc_bdaddr) < 0) {
- altos_set_last_posix_error();
- goto no_sock;
- }
-
- for (i = 0; i < 5; i++) {
- file->fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
- if (file->fd < 0) {
- altos_set_last_posix_error();
- goto no_sock;
- }
-
- status = connect(file->fd,
- (struct sockaddr *)&addr,
- sizeof(addr));
- if (status >= 0 || errno != EBUSY)
- break;
- close(file->fd);
- usleep(100 * 1000);
- }
- if (status < 0) {
- altos_set_last_posix_error();
- goto no_link;
- }
- usleep(100 * 1000);
-
-#ifdef USE_POLL
- pipe(file->pipe);
-#else
- file->out_fd = dup(file->fd);
-#endif
- return file;
-no_link:
- close(file->fd);
-no_sock:
- free(file);
-no_file:
- return NULL;
-}
-
-#endif
-
-#ifdef DARWIN
-
-#include <IOKitLib.h>
-#include <IOKit/usb/USBspec.h>
-#include <sys/param.h>
-#include <paths.h>
-#include <CFNumber.h>
-#include <IOBSD.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-struct altos_list {
- io_iterator_t iterator;
- int ftdi;
-};
-
-static int
-get_string(io_object_t object, CFStringRef entry, char *result, int result_len)
-{
- CFTypeRef entry_as_string;
- Boolean got_string;
-
- entry_as_string = IORegistryEntrySearchCFProperty (object,
- kIOServicePlane,
- entry,
- kCFAllocatorDefault,
- kIORegistryIterateRecursively);
- if (entry_as_string) {
- got_string = CFStringGetCString(entry_as_string,
- result, result_len,
- kCFStringEncodingASCII);
-
- CFRelease(entry_as_string);
- if (got_string)
- return 1;
- }
- return 0;
-}
-
-static int
-get_number(io_object_t object, CFStringRef entry, int *result)
-{
- CFTypeRef entry_as_number;
- Boolean got_number;
-
- entry_as_number = IORegistryEntrySearchCFProperty (object,
- kIOServicePlane,
- entry,
- kCFAllocatorDefault,
- kIORegistryIterateRecursively);
- if (entry_as_number) {
- got_number = CFNumberGetValue(entry_as_number,
- kCFNumberIntType,
- result);
- if (got_number)
- return 1;
- }
- return 0;
-}
-
-PUBLIC struct altos_list *
-altos_list_start(void)
-{
- struct altos_list *list = calloc (sizeof (struct altos_list), 1);
- CFMutableDictionaryRef matching_dictionary = IOServiceMatching("IOUSBDevice");
- io_iterator_t tdIterator;
- io_object_t tdObject;
- kern_return_t ret;
- int i;
-
- ret = IOServiceGetMatchingServices(kIOMasterPortDefault, matching_dictionary, &list->iterator);
- if (ret != kIOReturnSuccess) {
- free(list);
- return NULL;
- }
- list->ftdi = 0;
- return list;
-}
-
-PUBLIC struct altos_list *
-altos_ftdi_list_start(void)
-{
- struct altos_list *list = altos_list_start();
-
- if (list)
- list->ftdi = 1;
- return list;
-}
-
-PUBLIC int
-altos_list_next(struct altos_list *list, struct altos_device *device)
-{
- io_object_t object;
- char serial_string[128];
-
- for (;;) {
- object = IOIteratorNext(list->iterator);
- if (!object)
- return 0;
-
- if (!get_number (object, CFSTR(kUSBVendorID), &device->vendor) ||
- !get_number (object, CFSTR(kUSBProductID), &device->product))
- continue;
- if (get_string (object, CFSTR("IOCalloutDevice"), device->path, sizeof (device->path)) &&
- get_string (object, CFSTR("USB Product Name"), device->name, sizeof (device->name)) &&
- get_string (object, CFSTR("USB Serial Number"), serial_string, sizeof (serial_string))) {
- device->serial = atoi(serial_string);
- return 1;
- }
- }
-}
-
-PUBLIC void
-altos_list_finish(struct altos_list *list)
-{
- IOObjectRelease (list->iterator);
- free(list);
-}
-
-struct altos_bt_list {
- int sock;
- int dev_id;
- int rsp;
- int num_rsp;
-};
-
-#define INQUIRY_MAX_RSP 255
-
-struct altos_bt_list *
-altos_bt_list_start(int inquiry_time)
-{
- return NULL;
-}
-
-int
-altos_bt_list_next(struct altos_bt_list *bt_list,
- struct altos_bt_device *device)
-{
- return 0;
-}
-
-void
-altos_bt_list_finish(struct altos_bt_list *bt_list)
-{
-}
-
-void
-altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device)
-{
- strncpy(device->name, name, sizeof (device->name));
- device->name[sizeof(device->name)-1] = '\0';
- strncpy(device->addr, addr, sizeof (device->addr));
- device->addr[sizeof(device->addr)-1] = '\0';
-}
-
-struct altos_file *
-altos_bt_open(struct altos_bt_device *device)
-{
- return NULL;
-}
-
-#endif
-
-
-#ifdef WINDOWS
-
-#include <stdlib.h>
-#include <windows.h>
-#include <setupapi.h>
-
-struct altos_list {
- HDEVINFO dev_info;
- int index;
- int ftdi;
-};
-
-#define USB_BUF_SIZE 64
-
-struct altos_file {
- HANDLE handle;
- unsigned char out_data[USB_BUF_SIZE];
- int out_used;
- unsigned char in_data[USB_BUF_SIZE];
- int in_used;
- int in_read;
- OVERLAPPED ov_read;
- BOOL pend_read;
- OVERLAPPED ov_write;
-};
-
-#include <stdarg.h>
-
-static void
-log_message(char *fmt, ...)
-{
- static FILE *log = NULL;
- va_list a;
-
- if (!log)
- log = fopen("\\temp\\altos.txt", "w");
- if (log) {
- SYSTEMTIME time;
- GetLocalTime(&time);
- fprintf (log, "%4d-%02d-%02d %2d:%02d:%02d. ",
- time.wYear, time.wMonth, time.wDay,
- time.wHour, time.wMinute, time.wSecond);
- va_start(a, fmt);
- vfprintf(log, fmt, a);
- va_end(a);
- fflush(log);
- }
-}
-
-static void
-_altos_set_last_windows_error(char *file, int line)
-{
- DWORD error = GetLastError();
- TCHAR message[1024];
- FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
- 0,
- error,
- 0,
- message,
- sizeof (message) / sizeof (TCHAR),
- NULL);
- if (error != ERROR_SUCCESS)
- log_message ("%s:%d %s\n", file, line, message);
- altos_set_last_error(error, message);
-}
-
-#define altos_set_last_windows_error() _altos_set_last_windows_error(__FILE__, __LINE__)
-
-PUBLIC struct altos_list *
-altos_list_start(void)
-{
- struct altos_list *list = calloc(1, sizeof (struct altos_list));
-
- if (!list)
- return NULL;
- list->dev_info = SetupDiGetClassDevs(NULL, "USB", NULL,
- DIGCF_ALLCLASSES|DIGCF_PRESENT);
- if (list->dev_info == INVALID_HANDLE_VALUE) {
- altos_set_last_windows_error();
- free(list);
- return NULL;
- }
- list->index = 0;
- list->ftdi = 0;
- return list;
-}
-
-PUBLIC struct altos_list *
-altos_ftdi_list_start(void)
-{
- struct altos_list *list = calloc(1, sizeof (struct altos_list));
-
- if (!list)
- return NULL;
- list->dev_info = SetupDiGetClassDevs(NULL, "FTDIBUS", NULL,
- DIGCF_ALLCLASSES|DIGCF_PRESENT);
- if (list->dev_info == INVALID_HANDLE_VALUE) {
- altos_set_last_windows_error();
- free(list);
- return NULL;
- }
- list->index = 0;
- list->ftdi = 1;
- return list;
-}
-
-PUBLIC int
-altos_list_next(struct altos_list *list, struct altos_device *device)
-{
- SP_DEVINFO_DATA dev_info_data;
- BYTE port[128];
- DWORD port_len;
- char friendlyname[256];
- BYTE symbolic[256];
- DWORD symbolic_len;
- HKEY dev_key;
- unsigned int vid, pid;
- int serial;
- HRESULT result;
- DWORD friendlyname_type;
- DWORD friendlyname_len;
- char instanceid[1024];
- DWORD instanceid_len;
-
- dev_info_data.cbSize = sizeof (SP_DEVINFO_DATA);
- while(SetupDiEnumDeviceInfo(list->dev_info, list->index,
- &dev_info_data))
- {
- list->index++;
-
- dev_key = SetupDiOpenDevRegKey(list->dev_info, &dev_info_data,
- DICS_FLAG_GLOBAL, 0, DIREG_DEV,
- KEY_READ);
- if (dev_key == INVALID_HANDLE_VALUE) {
- altos_set_last_windows_error();
- continue;
- }
-
- if (list->ftdi) {
- vid = 0x0403;
- pid = 0x6015;
- serial = 0;
- } else {
- vid = pid = serial = 0;
- /* Fetch symbolic name for this device and parse out
- * the vid/pid/serial info */
- symbolic_len = sizeof(symbolic);
- result = RegQueryValueEx(dev_key, "SymbolicName", NULL, NULL,
- symbolic, &symbolic_len);
- if (result != 0) {
- altos_set_last_windows_error();
- } else {
- sscanf((char *) symbolic + sizeof("\\??\\USB#VID_") - 1,
- "%04X", &vid);
- sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_") - 1,
- "%04X", &pid);
- sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_XXXX#") - 1,
- "%d", &serial);
- }
- if (vid == 0 || pid == 0 || serial == 0) {
- if (SetupDiGetDeviceInstanceId(list->dev_info,
- &dev_info_data,
- instanceid,
- sizeof (instanceid),
- &instanceid_len)) {
- sscanf((char *) instanceid + sizeof("USB\\VID_") - 1,
- "%04X", &vid);
- sscanf((char *) instanceid + sizeof("USB\\VID_XXXX&PID_") - 1,
- "%04X", &pid);
- sscanf((char *) instanceid + sizeof("USB\\VID_XXXX&PID_XXXX\\") - 1,
- "%d", &serial);
- } else {
- altos_set_last_windows_error();
- }
- }
- if (vid == 0 || pid == 0 || serial == 0) {
- RegCloseKey(dev_key);
- continue;
- }
- }
-
- /* Fetch the com port name */
- port_len = sizeof (port);
- result = RegQueryValueEx(dev_key, "PortName", NULL, NULL,
- port, &port_len);
- RegCloseKey(dev_key);
- if (result != 0) {
- altos_set_last_windows_error();
- continue;
- }
-
- /* Fetch the device description which is the device name,
- * with firmware that has unique USB ids */
- friendlyname_len = sizeof (friendlyname);
- if(!SetupDiGetDeviceRegistryProperty(list->dev_info,
- &dev_info_data,
- SPDRP_FRIENDLYNAME,
- &friendlyname_type,
- (BYTE *)friendlyname,
- sizeof(friendlyname),
- &friendlyname_len))
- {
- altos_set_last_windows_error();
- continue;
- }
- device->vendor = vid;
- device->product = pid;
- device->serial = serial;
- strcpy(device->name, friendlyname);
-
- strcpy(device->path, (char *) port);
- return 1;
- }
- result = GetLastError();
- if (result != ERROR_NO_MORE_ITEMS)
- altos_set_last_windows_error();
- return 0;
-}
-
-PUBLIC void
-altos_list_finish(struct altos_list *list)
-{
- SetupDiDestroyDeviceInfoList(list->dev_info);
- free(list);
-}
-
-static int
-altos_queue_read(struct altos_file *file)
-{
- DWORD got;
- if (file->pend_read)
- return LIBALTOS_SUCCESS;
-
- if (!ReadFile(file->handle, file->in_data, USB_BUF_SIZE, &got, &file->ov_read)) {
- if (GetLastError() != ERROR_IO_PENDING) {
- altos_set_last_windows_error();
- return LIBALTOS_ERROR;
- }
- file->pend_read = TRUE;
- } else {
- file->pend_read = FALSE;
- file->in_read = 0;
- file->in_used = got;
- }
- return LIBALTOS_SUCCESS;
-}
-
-static int
-altos_wait_read(struct altos_file *file, int timeout)
-{
- DWORD ret;
- DWORD got;
-
- if (!file->pend_read)
- return LIBALTOS_SUCCESS;
-
- if (!timeout)
- timeout = INFINITE;
-
- ret = WaitForSingleObject(file->ov_read.hEvent, timeout);
- switch (ret) {
- case WAIT_OBJECT_0:
- if (!GetOverlappedResult(file->handle, &file->ov_read, &got, FALSE)) {
- altos_set_last_windows_error();
- return LIBALTOS_ERROR;
- }
- file->pend_read = FALSE;
- file->in_read = 0;
- file->in_used = got;
- break;
- case WAIT_TIMEOUT:
- return LIBALTOS_TIMEOUT;
- break;
- default:
- altos_set_last_windows_error();
- return LIBALTOS_ERROR;
- }
- return LIBALTOS_SUCCESS;
-}
-
-static int
-altos_fill(struct altos_file *file, int timeout)
-{
- int ret;
-
- if (file->in_read < file->in_used)
- return LIBALTOS_SUCCESS;
-
- file->in_read = file->in_used = 0;
-
- ret = altos_queue_read(file);
- if (ret)
- return ret;
- ret = altos_wait_read(file, timeout);
- if (ret)
- return ret;
-
- return LIBALTOS_SUCCESS;
-}
-
-PUBLIC int
-altos_flush(struct altos_file *file)
-{
- DWORD put;
- unsigned char *data = file->out_data;
- int used = file->out_used;
- DWORD ret;
-
- while (used) {
- if (!WriteFile(file->handle, data, used, &put, &file->ov_write)) {
- if (GetLastError() != ERROR_IO_PENDING) {
- altos_set_last_windows_error();
- return LIBALTOS_ERROR;
- }
- ret = WaitForSingleObject(file->ov_write.hEvent, INFINITE);
- switch (ret) {
- case WAIT_OBJECT_0:
- if (!GetOverlappedResult(file->handle, &file->ov_write, &put, FALSE)) {
- altos_set_last_windows_error();
- return LIBALTOS_ERROR;
- }
- break;
- default:
- altos_set_last_windows_error();
- return LIBALTOS_ERROR;
- }
- }
- data += put;
- used -= put;
- }
- file->out_used = 0;
- return LIBALTOS_SUCCESS;
-}
-
-static HANDLE
-open_serial(char *full_name)
-{
- HANDLE handle;
- DCB dcb;
-
- handle = CreateFile(full_name, GENERIC_READ|GENERIC_WRITE,
- 0, NULL, OPEN_EXISTING,
- FILE_FLAG_OVERLAPPED, NULL);
-
- if (handle == INVALID_HANDLE_VALUE) {
- altos_set_last_windows_error();
- return INVALID_HANDLE_VALUE;
- }
-
- if (!GetCommState(handle, &dcb)) {
- altos_set_last_windows_error();
- CloseHandle(handle);
- return INVALID_HANDLE_VALUE;
- }
- dcb.BaudRate = CBR_9600;
- dcb.fBinary = TRUE;
- dcb.fParity = FALSE;
- dcb.fOutxCtsFlow = FALSE;
- dcb.fOutxDsrFlow = FALSE;
- dcb.fDtrControl = DTR_CONTROL_ENABLE;
- dcb.fDsrSensitivity = FALSE;
- dcb.fTXContinueOnXoff = FALSE;
- dcb.fOutX = FALSE;
- dcb.fInX = FALSE;
- dcb.fErrorChar = FALSE;
- dcb.fNull = FALSE;
- dcb.fRtsControl = RTS_CONTROL_ENABLE;
- dcb.fAbortOnError = FALSE;
- dcb.XonLim = 10;
- dcb.XoffLim = 10;
- dcb.ByteSize = 8;
- dcb.Parity = NOPARITY;
- dcb.StopBits = ONESTOPBIT;
- dcb.XonChar = 17;
- dcb.XoffChar = 19;
-#if 0
- dcb.ErrorChar = 0;
- dcb.EofChar = 0;
- dcb.EvtChar = 0;
-#endif
- if (!SetCommState(handle, &dcb)) {
- altos_set_last_windows_error();
- CloseHandle(handle);
- return INVALID_HANDLE_VALUE;
- }
- return handle;
-}
-
-PUBLIC struct altos_file *
-altos_open(struct altos_device *device)
-{
- struct altos_file *file = calloc (1, sizeof (struct altos_file));
- char full_name[64];
- COMMTIMEOUTS timeouts;
- int i;
-
- if (!file)
- return NULL;
-
- strcpy(full_name, "\\\\.\\");
- strcat(full_name, device->path);
-
- file->handle = INVALID_HANDLE_VALUE;
-
- for (i = 0; i < 5; i++) {
- file->handle = open_serial(full_name);
- if (file->handle != INVALID_HANDLE_VALUE)
- break;
- altos_set_last_windows_error();
- Sleep(100);
- }
-
- if (file->handle == INVALID_HANDLE_VALUE) {
- free(file);
- return NULL;
- }
-
- /* The FTDI driver doesn't appear to work right unless you open it twice */
- if (device->vendor == 0x0403) {
- CloseHandle(file->handle);
- file->handle = open_serial(full_name);
- if (file->handle == INVALID_HANDLE_VALUE) {
- free(file);
- return NULL;
- }
- }
-
- timeouts.ReadIntervalTimeout = MAXDWORD;
- timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
- timeouts.ReadTotalTimeoutConstant = 1 << 30; /* almost forever */
- timeouts.WriteTotalTimeoutMultiplier = 0;
- timeouts.WriteTotalTimeoutConstant = 0;
- SetCommTimeouts(file->handle, &timeouts);
-
- file->ov_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- file->ov_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
-
- return file;
-}
-
-PUBLIC void
-altos_close(struct altos_file *file)
-{
- HANDLE handle = file->handle;
- if (handle != INVALID_HANDLE_VALUE) {
- HANDLE ov_read = file->ov_read.hEvent;
- HANDLE ov_write = file->ov_write.hEvent;
- file->handle = INVALID_HANDLE_VALUE;
- file->ov_read.hEvent = INVALID_HANDLE_VALUE;
- file->ov_write.hEvent = INVALID_HANDLE_VALUE;
- PurgeComm(handle, PURGE_RXABORT|PURGE_RXCLEAR|PURGE_TXABORT|PURGE_TXCLEAR);
- Sleep(100);
- CloseHandle(handle);
- file->handle = INVALID_HANDLE_VALUE;
- CloseHandle(ov_read);
- CloseHandle(ov_write);
- }
-}
-
-PUBLIC void
-altos_free(struct altos_file *file)
-{
- altos_close(file);
- free(file);
-}
-
-PUBLIC int
-altos_putchar(struct altos_file *file, char c)
-{
- int ret;
-
- if (file->out_used == USB_BUF_SIZE) {
- ret = altos_flush(file);
- if (ret)
- return ret;
- }
- file->out_data[file->out_used++] = c;
- if (file->out_used == USB_BUF_SIZE)
- return altos_flush(file);
- return LIBALTOS_SUCCESS;
-}
-
-PUBLIC int
-altos_getchar(struct altos_file *file, int timeout)
-{
- int ret;
- while (file->in_read == file->in_used) {
- if (file->handle == INVALID_HANDLE_VALUE) {
- altos_set_last_windows_error();
- return LIBALTOS_ERROR;
- }
- ret = altos_fill(file, timeout);
- if (ret)
- return ret;
- }
- return file->in_data[file->in_read++];
-}
-
-struct altos_bt_list *
-altos_bt_list_start(int inquiry_time)
-{
- return NULL;
-}
-
-int
-altos_bt_list_next(struct altos_bt_list *bt_list,
- struct altos_bt_device *device)
-{
- return 0;
-}
-
-void
-altos_bt_list_finish(struct altos_bt_list *bt_list)
-{
- free(bt_list);
-}
-
-void
-altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device)
-{
- strncpy(device->name, name, sizeof (device->name));
- device->name[sizeof(device->name)-1] = '\0';
- strncpy(device->addr, addr, sizeof (device->addr));
- device->addr[sizeof(device->addr)-1] = '\0';
-}
-
-struct altos_file *
-altos_bt_open(struct altos_bt_device *device)
-{
- return NULL;
-}
-
-#endif
diff --git a/libaltos/libaltos.dylib b/libaltos/libaltos.dylib
index 8b491c58..c18493ea 100755
--- a/libaltos/libaltos.dylib
+++ b/libaltos/libaltos.dylib
Binary files differ
diff --git a/libaltos/libaltos_common.c b/libaltos/libaltos_common.c
new file mode 100644
index 00000000..090f03ad
--- /dev/null
+++ b/libaltos/libaltos_common.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "libaltos_private.h"
+
+PUBLIC int
+altos_init(void)
+{
+ return LIBALTOS_SUCCESS;
+}
+
+PUBLIC void
+altos_fini(void)
+{
+}
+
+struct altos_error altos_last_error;
+
+void
+altos_set_last_error(int code, char *string)
+{
+ altos_last_error.code = code;
+ strncpy(altos_last_error.string, string, sizeof (altos_last_error.string) -1);
+ altos_last_error.string[sizeof(altos_last_error.string)-1] = '\0';
+}
+
+PUBLIC void
+altos_get_last_error(struct altos_error *error)
+{
+ *error = altos_last_error;
+}
+
+PUBLIC int
+altos_getchar(struct altos_file *file, int timeout)
+{
+ int ret;
+ while (file->in_read == file->in_used) {
+ ret = altos_fill(file, timeout);
+ if (ret)
+ return ret;
+ }
+ return file->in_data[file->in_read++];
+}
+
+PUBLIC int
+altos_putchar(struct altos_file *file, char c)
+{
+ int ret;
+
+ if (file->out_used == USB_BUF_SIZE) {
+ ret = altos_flush(file);
+ if (ret) {
+ return ret;
+ }
+ }
+ file->out_data[file->out_used++] = c;
+ ret = 0;
+ if (file->out_used == USB_BUF_SIZE)
+ ret = altos_flush(file);
+ return ret;
+}
+
+
+PUBLIC void
+altos_free(struct altos_file *file)
+{
+ altos_close(file);
+ free(file);
+}
diff --git a/libaltos/libaltos_darwin.c b/libaltos/libaltos_darwin.c
new file mode 100644
index 00000000..04194d9a
--- /dev/null
+++ b/libaltos/libaltos_darwin.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "libaltos_private.h"
+#include "libaltos_posix.h"
+
+#include <IOKitLib.h>
+#include <IOKit/usb/USBspec.h>
+#include <IOKit/serial/IOSerialKeys.h>
+#include <usb/IOUSBLib.h>
+#include <usb/USBSpec.h>
+#include <sys/param.h>
+#include <paths.h>
+#include <CFNumber.h>
+#include <IOBSD.h>
+
+/* Mac OS X don't have strndup even if _GNU_SOURCE is defined */
+char *
+altos_strndup (const char *s, size_t n)
+{
+ size_t len = strlen (s);
+ char *ret;
+
+ if (len <= n)
+ return strdup (s);
+ ret = malloc(n + 1);
+ strncpy(ret, s, n);
+ ret[n] = '\0';
+ return ret;
+}
+
+struct altos_list {
+ io_iterator_t iterator;
+ int ftdi;
+};
+
+static char *
+get_cfstring(CFTypeRef string, char result[512])
+{
+ Boolean got_string;
+
+ got_string = CFStringGetCString(string, result, 512, kCFStringEncodingASCII);
+ if (!got_string)
+ strcpy(result, "CFStringGetCString failed");
+ return result;
+}
+
+static int
+get_string(io_object_t object, CFStringRef entry, char *result, int result_len)
+{
+ CFTypeRef entry_as_string;
+ Boolean got_string;
+ char entry_string[512];
+
+ entry_as_string = IORegistryEntrySearchCFProperty (object,
+ kIOServicePlane,
+ entry,
+ kCFAllocatorDefault,
+ kIORegistryIterateRecursively);
+ if (entry_as_string) {
+ got_string = CFStringGetCString(entry_as_string,
+ result, result_len,
+ kCFStringEncodingASCII);
+
+ CFRelease(entry_as_string);
+ if (got_string) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int
+get_number(io_object_t object, CFStringRef entry, int *result)
+{
+ CFTypeRef entry_as_number;
+ Boolean got_number;
+ char entry_string[512];
+
+ entry_as_number = IORegistryEntrySearchCFProperty (object,
+ kIOServicePlane,
+ entry,
+ kCFAllocatorDefault,
+ kIORegistryIterateRecursively);
+ if (entry_as_number) {
+ got_number = CFNumberGetValue(entry_as_number,
+ kCFNumberIntType,
+ result);
+ if (got_number) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+PUBLIC struct altos_list *
+altos_list_start(void)
+{
+ struct altos_list *list = calloc (sizeof (struct altos_list), 1);
+ CFMutableDictionaryRef matching_dictionary;
+ io_iterator_t tdIterator;
+ io_object_t tdObject;
+ kern_return_t ret;
+ int i;
+
+ matching_dictionary = IOServiceMatching(kIOSerialBSDServiceValue);
+ if (matching_dictionary) {
+ CFDictionarySetValue(matching_dictionary,
+ CFSTR(kIOSerialBSDTypeKey),
+ CFSTR(kIOSerialBSDAllTypes));
+ }
+
+ ret = IOServiceGetMatchingServices(kIOMasterPortDefault, matching_dictionary, &list->iterator);
+ if (ret != kIOReturnSuccess) {
+ free(list);
+ return NULL;
+ }
+ list->ftdi = 0;
+ return list;
+}
+
+PUBLIC struct altos_list *
+altos_ftdi_list_start(void)
+{
+ struct altos_list *list = altos_list_start();
+
+ if (list)
+ list->ftdi = 1;
+ return list;
+}
+
+static io_service_t get_usb_object(io_object_t serial_device)
+{
+ io_iterator_t iterator;
+ io_service_t usb_device;
+ io_service_t service;
+ IOReturn status;
+
+ status = IORegistryEntryCreateIterator(serial_device,
+ kIOServicePlane,
+ kIORegistryIterateParents | kIORegistryIterateRecursively,
+ &iterator);
+
+ if (status != kIOReturnSuccess)
+ return 0;
+
+ while((service = IOIteratorNext(iterator))) {
+ io_name_t servicename;
+ status = IORegistryEntryGetNameInPlane(service, kIOServicePlane, servicename);
+
+ if (status == kIOReturnSuccess && IOObjectConformsTo(service, kIOUSBDeviceClassName)) {
+ IOObjectRelease(iterator);
+ return service;
+ }
+ IOObjectRelease(service);
+ }
+ IOObjectRelease(iterator);
+ return 0;
+}
+
+PUBLIC int
+altos_list_next(struct altos_list *list, struct altos_device *device)
+{
+
+ io_object_t object;
+ io_service_t usb_device;
+ char serial_string[128];
+
+ for (;;) {
+ object = IOIteratorNext(list->iterator);
+ if (!object) {
+ return 0;
+ }
+
+ usb_device = get_usb_object(object);
+
+ if (get_number (usb_device, CFSTR(kUSBVendorID), &device->vendor) &&
+ get_number (usb_device, CFSTR(kUSBProductID), &device->product) &&
+ get_string (object, CFSTR(kIOCalloutDeviceKey), device->path, sizeof (device->path)) &&
+ get_string (usb_device, CFSTR(kUSBProductString), device->name, sizeof (device->name)) &&
+ get_string (usb_device, CFSTR(kUSBSerialNumberString), serial_string, sizeof (serial_string))) {
+ device->serial = atoi(serial_string);
+ IOObjectRelease(object);
+ IOObjectRelease(usb_device);
+ return 1;
+ }
+ IOObjectRelease(object);
+ IOObjectRelease(usb_device);
+ }
+}
+
+PUBLIC void
+altos_list_finish(struct altos_list *list)
+{
+ IOObjectRelease (list->iterator);
+ free(list);
+}
+
+struct altos_bt_list {
+ int sock;
+ int dev_id;
+ int rsp;
+ int num_rsp;
+};
+
+#define INQUIRY_MAX_RSP 255
+
+struct altos_bt_list *
+altos_bt_list_start(int inquiry_time)
+{
+ return NULL;
+}
+
+int
+altos_bt_list_next(struct altos_bt_list *bt_list,
+ struct altos_bt_device *device)
+{
+ return 0;
+}
+
+void
+altos_bt_list_finish(struct altos_bt_list *bt_list)
+{
+}
+
+void
+altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device)
+{
+ strncpy(device->name, name, sizeof (device->name));
+ device->name[sizeof(device->name)-1] = '\0';
+ strncpy(device->addr, addr, sizeof (device->addr));
+ device->addr[sizeof(device->addr)-1] = '\0';
+}
+
+struct altos_file *
+altos_bt_open(struct altos_bt_device *device)
+{
+ return NULL;
+}
diff --git a/libaltos/libaltos_linux.c b/libaltos/libaltos_linux.c
new file mode 100644
index 00000000..2065d74a
--- /dev/null
+++ b/libaltos/libaltos_linux.c
@@ -0,0 +1,528 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#define _GNU_SOURCE
+#include "libaltos_private.h"
+#include "libaltos_posix.h"
+
+#include <ctype.h>
+#include <dirent.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_lib.h>
+#include <bluetooth/rfcomm.h>
+
+static char *
+cc_fullname (char *dir, char *file)
+{
+ char *new;
+ int dlen = strlen (dir);
+ int flen = strlen (file);
+ int slen = 0;
+
+ if (dir[dlen-1] != '/')
+ slen = 1;
+ new = malloc (dlen + slen + flen + 1);
+ if (!new)
+ return 0;
+ strcpy(new, dir);
+ if (slen)
+ strcat (new, "/");
+ strcat(new, file);
+ return new;
+}
+
+static char *
+cc_basename(char *file)
+{
+ char *b;
+
+ b = strrchr(file, '/');
+ if (!b)
+ return file;
+ return b + 1;
+}
+
+static char *
+load_string(char *dir, char *file)
+{
+ char *full = cc_fullname(dir, file);
+ char line[4096];
+ char *r;
+ FILE *f;
+ int rlen;
+
+ f = fopen(full, "r");
+ free(full);
+ if (!f)
+ return NULL;
+ r = fgets(line, sizeof (line), f);
+ fclose(f);
+ if (!r)
+ return NULL;
+ rlen = strlen(r);
+ if (r[rlen-1] == '\n')
+ r[rlen-1] = '\0';
+ return strdup(r);
+}
+
+static int
+load_hex(char *dir, char *file)
+{
+ char *line;
+ char *end;
+ long i;
+
+ line = load_string(dir, file);
+ if (!line)
+ return -1;
+ i = strtol(line, &end, 16);
+ free(line);
+ if (end == line)
+ return -1;
+ return i;
+}
+
+static int
+load_dec(char *dir, char *file)
+{
+ char *line;
+ char *end;
+ long i;
+
+ line = load_string(dir, file);
+ if (!line)
+ return -1;
+ i = strtol(line, &end, 10);
+ free(line);
+ if (end == line)
+ return -1;
+ return i;
+}
+
+static int
+dir_filter_tty_colon(const struct dirent *d)
+{
+ return strncmp(d->d_name, "tty:", 4) == 0;
+}
+
+static int
+dir_filter_tty(const struct dirent *d)
+{
+ return strncmp(d->d_name, "tty", 3) == 0;
+}
+
+struct altos_usbdev {
+ char *sys;
+ char *tty;
+ char *manufacturer;
+ char *product_name;
+ int serial; /* AltOS always uses simple integer serial numbers */
+ int idProduct;
+ int idVendor;
+};
+
+static char *
+usb_tty(char *sys)
+{
+ char *base;
+ int num_configs;
+ int config;
+ struct dirent **namelist;
+ int interface;
+ int num_interfaces;
+ char endpoint_base[20];
+ char *endpoint_full;
+ char *tty_dir;
+ int ntty;
+ char *tty;
+
+ base = cc_basename(sys);
+ num_configs = load_hex(sys, "bNumConfigurations");
+ num_interfaces = load_hex(sys, "bNumInterfaces");
+ for (config = 1; config <= num_configs; config++) {
+ for (interface = 0; interface < num_interfaces; interface++) {
+ sprintf(endpoint_base, "%s:%d.%d",
+ base, config, interface);
+ endpoint_full = cc_fullname(sys, endpoint_base);
+
+
+ /* Check for tty:ttyACMx style names
+ */
+ ntty = scandir(endpoint_full, &namelist,
+ dir_filter_tty_colon,
+ alphasort);
+ if (ntty > 0) {
+ free(endpoint_full);
+ tty = cc_fullname("/dev", namelist[0]->d_name + 4);
+ free(namelist);
+ return tty;
+ }
+
+ /* Check for tty/ttyACMx style names
+ */
+ tty_dir = cc_fullname(endpoint_full, "tty");
+ ntty = scandir(tty_dir, &namelist,
+ dir_filter_tty,
+ alphasort);
+ free (tty_dir);
+ if (ntty > 0) {
+ tty = cc_fullname("/dev", namelist[0]->d_name);
+ free(endpoint_full);
+ free(namelist);
+ return tty;
+ }
+
+ /* Check for ttyACMx style names
+ */
+ ntty = scandir(endpoint_full, &namelist,
+ dir_filter_tty,
+ alphasort);
+ free(endpoint_full);
+ if (ntty > 0) {
+ tty = cc_fullname("/dev", namelist[0]->d_name);
+ free(namelist);
+ return tty;
+ }
+
+ }
+ }
+ return NULL;
+}
+
+static struct altos_usbdev *
+usb_scan_device(char *sys)
+{
+ struct altos_usbdev *usbdev;
+ char *tty;
+
+ tty = usb_tty(sys);
+ if (!tty)
+ return NULL;
+ usbdev = calloc(1, sizeof (struct altos_usbdev));
+ if (!usbdev)
+ return NULL;
+ usbdev->sys = strdup(sys);
+ usbdev->manufacturer = load_string(sys, "manufacturer");
+ usbdev->product_name = load_string(sys, "product");
+ usbdev->serial = load_dec(sys, "serial");
+ usbdev->idProduct = load_hex(sys, "idProduct");
+ usbdev->idVendor = load_hex(sys, "idVendor");
+ usbdev->tty = tty;
+ return usbdev;
+}
+
+static void
+usbdev_free(struct altos_usbdev *usbdev)
+{
+ free(usbdev->sys);
+ free(usbdev->manufacturer);
+ free(usbdev->product_name);
+ /* this can get used as a return value */
+ if (usbdev->tty)
+ free(usbdev->tty);
+ free(usbdev);
+}
+
+#define USB_DEVICES "/sys/bus/usb/devices"
+
+static int
+dir_filter_dev(const struct dirent *d)
+{
+ const char *n = d->d_name;
+ char c;
+
+ while ((c = *n++)) {
+ if (isdigit(c))
+ continue;
+ if (c == '-')
+ continue;
+ if (c == '.' && n != d->d_name + 1)
+ continue;
+ return 0;
+ }
+ return 1;
+}
+
+struct altos_list {
+ struct altos_usbdev **dev;
+ int current;
+ int ndev;
+};
+
+struct altos_list *
+altos_list_start(void)
+{
+ int e;
+ struct dirent **ents;
+ char *dir;
+ struct altos_usbdev *dev;
+ struct altos_list *devs;
+ int n;
+
+ devs = calloc(1, sizeof (struct altos_list));
+ if (!devs)
+ return NULL;
+
+ n = scandir (USB_DEVICES, &ents,
+ dir_filter_dev,
+ alphasort);
+ if (!n)
+ return 0;
+ for (e = 0; e < n; e++) {
+ dir = cc_fullname(USB_DEVICES, ents[e]->d_name);
+ dev = usb_scan_device(dir);
+ if (!dev)
+ continue;
+ free(dir);
+ if (devs->dev)
+ devs->dev = realloc(devs->dev,
+ (devs->ndev + 1) * sizeof (struct usbdev *));
+ else
+ devs->dev = malloc (sizeof (struct usbdev *));
+ devs->dev[devs->ndev++] = dev;
+ }
+ free(ents);
+ devs->current = 0;
+ return devs;
+}
+
+PUBLIC struct altos_list *
+altos_ftdi_list_start(void)
+{
+ return altos_list_start();
+}
+
+int
+altos_list_next(struct altos_list *list, struct altos_device *device)
+{
+ struct altos_usbdev *dev;
+ if (list->current >= list->ndev) {
+ return 0;
+ }
+ dev = list->dev[list->current];
+ strcpy(device->name, dev->product_name);
+ device->vendor = dev->idVendor;
+ device->product = dev->idProduct;
+ strcpy(device->path, dev->tty);
+ device->serial = dev->serial;
+ list->current++;
+ return 1;
+}
+
+void
+altos_list_finish(struct altos_list *usbdevs)
+{
+ int i;
+
+ if (!usbdevs)
+ return;
+ for (i = 0; i < usbdevs->ndev; i++)
+ usbdev_free(usbdevs->dev[i]);
+ free(usbdevs);
+}
+
+#include <dlfcn.h>
+
+static void *libbt;
+static int bt_initialized;
+
+static int init_bt(void) {
+ if (!bt_initialized) {
+ bt_initialized = 1;
+ libbt = dlopen("libbluetooth.so.3", RTLD_LAZY);
+ if (!libbt)
+ printf("failed to find bluetooth library\n");
+ }
+ return libbt != NULL;
+}
+
+#define join(a,b) a ## b
+#define bt_func(name, ret, fail, formals, actuals) \
+ static ret join(altos_, name) formals { \
+ static ret (*name) formals; \
+ if (!init_bt()) return fail; \
+ name = dlsym(libbt, #name); \
+ if (!name) return fail; \
+ return name actuals; \
+ }
+
+bt_func(ba2str, int, -1, (const bdaddr_t *ba, char *str), (ba, str))
+#define ba2str altos_ba2str
+
+bt_func(str2ba, int, -1, (const char *str, bdaddr_t *ba), (str, ba))
+#define str2ba altos_str2ba
+
+bt_func(hci_read_remote_name, int, -1, (int sock, const bdaddr_t *ba, int len, char *name, int timeout), (sock, ba, len, name, timeout))
+#define hci_read_remote_name altos_hci_read_remote_name
+
+bt_func(hci_open_dev, int, -1, (int dev_id), (dev_id))
+#define hci_open_dev altos_hci_open_dev
+
+bt_func(hci_get_route, int, -1, (bdaddr_t *bdaddr), (bdaddr))
+#define hci_get_route altos_hci_get_route
+
+bt_func(hci_inquiry, int, -1, (int adapter_id, int len, int max_rsp, const uint8_t *lap, inquiry_info **devs, long flags), (adapter_id, len, max_rsp, lap, devs, flags))
+#define hci_inquiry altos_hci_inquiry
+
+struct altos_bt_list {
+ inquiry_info *ii;
+ int sock;
+ int dev_id;
+ int rsp;
+ int num_rsp;
+};
+
+#define INQUIRY_MAX_RSP 255
+
+struct altos_bt_list *
+altos_bt_list_start(int inquiry_time)
+{
+ struct altos_bt_list *bt_list;
+
+ bt_list = calloc(1, sizeof (struct altos_bt_list));
+ if (!bt_list)
+ goto no_bt_list;
+
+ bt_list->ii = calloc(INQUIRY_MAX_RSP, sizeof (inquiry_info));
+ if (!bt_list->ii)
+ goto no_ii;
+ bt_list->dev_id = hci_get_route(NULL);
+ if (bt_list->dev_id < 0)
+ goto no_dev_id;
+
+ bt_list->sock = hci_open_dev(bt_list->dev_id);
+ if (bt_list->sock < 0)
+ goto no_sock;
+
+ bt_list->num_rsp = hci_inquiry(bt_list->dev_id,
+ inquiry_time,
+ INQUIRY_MAX_RSP,
+ NULL,
+ &bt_list->ii,
+ IREQ_CACHE_FLUSH);
+ if (bt_list->num_rsp < 0)
+ goto no_rsp;
+
+ bt_list->rsp = 0;
+ return bt_list;
+
+no_rsp:
+ close(bt_list->sock);
+no_sock:
+no_dev_id:
+ free(bt_list->ii);
+no_ii:
+ free(bt_list);
+no_bt_list:
+ return NULL;
+}
+
+int
+altos_bt_list_next(struct altos_bt_list *bt_list,
+ struct altos_bt_device *device)
+{
+ inquiry_info *ii;
+
+ if (bt_list->rsp >= bt_list->num_rsp)
+ return 0;
+
+ ii = &bt_list->ii[bt_list->rsp];
+ if (ba2str(&ii->bdaddr, device->addr) < 0)
+ return 0;
+ memset(&device->name, '\0', sizeof (device->name));
+ if (hci_read_remote_name(bt_list->sock, &ii->bdaddr,
+ sizeof (device->name),
+ device->name, 0) < 0) {
+ strcpy(device->name, "[unknown]");
+ }
+ bt_list->rsp++;
+ return 1;
+}
+
+void
+altos_bt_list_finish(struct altos_bt_list *bt_list)
+{
+ close(bt_list->sock);
+ free(bt_list->ii);
+ free(bt_list);
+}
+
+void
+altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device)
+{
+ strncpy(device->name, name, sizeof (device->name));
+ device->name[sizeof(device->name)-1] = '\0';
+ strncpy(device->addr, addr, sizeof (device->addr));
+ device->addr[sizeof(device->addr)-1] = '\0';
+}
+
+struct altos_file *
+altos_bt_open(struct altos_bt_device *device)
+{
+ struct sockaddr_rc addr = { 0 };
+ int status, i;
+ struct altos_file_posix *file;
+
+ file = calloc(1, sizeof (struct altos_file_posix));
+ if (!file) {
+ errno = ENOMEM;
+ altos_set_last_posix_error();
+ goto no_file;
+ }
+ addr.rc_family = AF_BLUETOOTH;
+ addr.rc_channel = 1;
+ if (str2ba(device->addr, &addr.rc_bdaddr) < 0) {
+ altos_set_last_posix_error();
+ goto no_sock;
+ }
+
+ for (i = 0; i < 5; i++) {
+ file->fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
+ if (file->fd < 0) {
+ altos_set_last_posix_error();
+ goto no_sock;
+ }
+
+ status = connect(file->fd,
+ (struct sockaddr *)&addr,
+ sizeof(addr));
+ if (status >= 0 || errno != EBUSY)
+ break;
+ close(file->fd);
+ usleep(100 * 1000);
+ }
+ if (status < 0) {
+ altos_set_last_posix_error();
+ goto no_link;
+ }
+ usleep(100 * 1000);
+
+#ifdef USE_POLL
+ pipe(file->pipe);
+#else
+ file->out_fd = dup(file->fd);
+#endif
+ return &file->file;
+no_link:
+ close(file->fd);
+no_sock:
+ free(file);
+no_file:
+ return NULL;
+}
+
diff --git a/libaltos/libaltos_posix.c b/libaltos/libaltos_posix.c
new file mode 100644
index 00000000..731e9aa1
--- /dev/null
+++ b/libaltos/libaltos_posix.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "libaltos_private.h"
+#include "libaltos_posix.h"
+
+void
+altos_set_last_posix_error(void)
+{
+ altos_set_last_error(errno, strerror(errno));
+}
+
+PUBLIC struct altos_file *
+altos_open(struct altos_device *device)
+{
+ struct altos_file_posix *file = calloc (sizeof (struct altos_file_posix), 1);
+ int ret;
+ struct termios term;
+
+ if (!file) {
+ altos_set_last_posix_error();
+ return NULL;
+ }
+
+// altos_set_last_error(12, "yeah yeah, failed again");
+// free(file);
+// return NULL;
+
+ file->fd = open(device->path, O_RDWR | O_NOCTTY);
+ if (file->fd < 0) {
+ altos_set_last_posix_error();
+ free(file);
+ return NULL;
+ }
+#ifdef USE_POLL
+ pipe(file->pipe);
+#else
+ file->out_fd = open(device->path, O_RDWR | O_NOCTTY);
+ if (file->out_fd < 0) {
+ altos_set_last_posix_error();
+ close(file->fd);
+ free(file);
+ return NULL;
+ }
+#endif
+ ret = tcgetattr(file->fd, &term);
+ if (ret < 0) {
+ altos_set_last_posix_error();
+ close(file->fd);
+#ifndef USE_POLL
+ close(file->out_fd);
+#endif
+ free(file);
+ return NULL;
+ }
+ cfmakeraw(&term);
+ cfsetospeed(&term, B9600);
+ cfsetispeed(&term, B9600);
+#ifdef USE_POLL
+ term.c_cc[VMIN] = 1;
+ term.c_cc[VTIME] = 0;
+#else
+ term.c_cc[VMIN] = 0;
+ term.c_cc[VTIME] = 1;
+#endif
+ ret = tcsetattr(file->fd, TCSAFLUSH, &term);
+ if (ret < 0) {
+ altos_set_last_posix_error();
+ close(file->fd);
+#ifndef USE_POLL
+ close(file->out_fd);
+#endif
+ free(file);
+ return NULL;
+ }
+ return &file->file;
+}
+
+PUBLIC void
+altos_close(struct altos_file *file_common)
+{
+ struct altos_file_posix *file = (struct altos_file_posix *) file_common;
+
+ if (file->fd != -1) {
+ int fd = file->fd;
+ file->fd = -1;
+#ifdef USE_POLL
+ write(file->pipe[1], "\r", 1);
+#else
+ close(file->out_fd);
+ file->out_fd = -1;
+#endif
+ close(fd);
+ }
+}
+
+PUBLIC int
+altos_flush(struct altos_file *file_common)
+{
+ struct altos_file_posix *file = (struct altos_file_posix *) file_common;
+
+ if (file->file.out_used && 0) {
+ printf ("flush \"");
+ fwrite(file->file.out_data, 1, file->file.out_used, stdout);
+ printf ("\"\n");
+ }
+ while (file->file.out_used) {
+ int ret;
+
+ if (file->fd < 0)
+ return -EBADF;
+#ifdef USE_POLL
+ ret = write (file->fd, file->file.out_data, file->file.out_used);
+#else
+ ret = write (file->out_fd, file->file.out_data, file->file.out_used);
+#endif
+ if (ret < 0) {
+ altos_set_last_posix_error();
+ return -altos_last_error.code;
+ }
+ if (ret) {
+ memmove(file->file.out_data, file->file.out_data + ret,
+ file->file.out_used - ret);
+ file->file.out_used -= ret;
+ }
+ }
+ return 0;
+}
+
+
+#ifdef USE_POLL
+#include <poll.h>
+#endif
+
+int
+altos_fill(struct altos_file *file_common, int timeout)
+{
+ struct altos_file_posix *file = (struct altos_file_posix *) file_common;
+
+ int ret;
+#ifdef USE_POLL
+ struct pollfd fd[2];
+#endif
+ if (timeout == 0)
+ timeout = -1;
+ while (file->file.in_read == file->file.in_used) {
+ if (file->fd < 0)
+ return LIBALTOS_ERROR;
+#ifdef USE_POLL
+ fd[0].fd = file->fd;
+ fd[0].events = POLLIN|POLLERR|POLLHUP|POLLNVAL;
+ fd[1].fd = file->pipe[0];
+ fd[1].events = POLLIN;
+ ret = poll(fd, 2, timeout);
+ if (ret < 0) {
+ altos_set_last_posix_error();
+ return LIBALTOS_ERROR;
+ }
+ if (ret == 0)
+ return LIBALTOS_TIMEOUT;
+
+ if (fd[0].revents & (POLLHUP|POLLERR|POLLNVAL))
+ return LIBALTOS_ERROR;
+ if (fd[0].revents & POLLIN)
+#endif
+ {
+ ret = read(file->fd, file->file.in_data, USB_BUF_SIZE);
+ if (ret < 0) {
+ altos_set_last_posix_error();
+ return LIBALTOS_ERROR;
+ }
+ file->file.in_read = 0;
+ file->file.in_used = ret;
+#ifndef USE_POLL
+ if (ret == 0 && timeout > 0)
+ return LIBALTOS_TIMEOUT;
+#endif
+ }
+ }
+ if (file->file.in_used && 0) {
+ printf ("fill \"");
+ fwrite(file->file.in_data, 1, file->file.in_used, stdout);
+ printf ("\"\n");
+ }
+ return 0;
+}
+
diff --git a/libaltos/libaltos_posix.h b/libaltos/libaltos_posix.h
new file mode 100644
index 00000000..dc9bfb62
--- /dev/null
+++ b/libaltos/libaltos_posix.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _LIBALTOS_POSIX_H_
+#define _LIBALTOS_POSIX_H_
+
+#include <fcntl.h>
+#include <termios.h>
+#include <errno.h>
+#include <unistd.h>
+
+struct altos_file_posix {
+ struct altos_file file;
+
+ int fd;
+#ifdef USE_POLL
+ int pipe[2];
+#else
+ int out_fd;
+#endif
+};
+
+void
+altos_set_last_posix_error(void);
+
+#endif /* _LIBALTOS_POSIX_H_ */
diff --git a/libaltos/libaltos_private.h b/libaltos/libaltos_private.h
new file mode 100644
index 00000000..56f6335b
--- /dev/null
+++ b/libaltos/libaltos_private.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _LIBALTOS_PRIVATE_H_
+#define _LIBALTOS_PRIVATE_H_
+
+#include "libaltos.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define BLUETOOTH_PRODUCT_TELEBT "TeleBT"
+
+#define USB_BUF_SIZE 64
+
+struct altos_file {
+ /* Shared data */
+ unsigned char out_data[USB_BUF_SIZE];
+ int out_used;
+ unsigned char in_data[USB_BUF_SIZE];
+ int in_used;
+ int in_read;
+};
+
+#ifdef LINUX
+#define USE_POLL
+#endif
+
+#ifdef DARWIN
+#include <unistd.h>
+
+#define strndup(s,n) altos_strndup(s,n)
+
+char *altos_strndup(const char *s, size_t n);
+
+#endif
+
+void
+altos_set_last_error(int code, char *string);
+
+extern struct altos_error altos_last_error;
+
+PUBLIC int
+altos_flush(struct altos_file *file);
+
+int
+altos_fill(struct altos_file *file, int timeout);
+
+#endif /* _LIBALTOS_PRIVATE_H_ */
diff --git a/libaltos/libaltos_windows.c b/libaltos/libaltos_windows.c
new file mode 100644
index 00000000..2c3f41e1
--- /dev/null
+++ b/libaltos/libaltos_windows.c
@@ -0,0 +1,761 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "libaltos_private.h"
+
+#include <winsock2.h>
+#include <windows.h>
+#include <setupapi.h>
+
+struct altos_list {
+ HDEVINFO dev_info;
+ int index;
+ int ftdi;
+};
+
+#define USB_BUF_SIZE 64
+
+struct altos_file_windows {
+ struct altos_file file;
+
+ BOOL is_winsock;
+ /* Data used by the regular I/O */
+ HANDLE handle;
+ OVERLAPPED ov_read;
+ BOOL pend_read;
+ OVERLAPPED ov_write;
+
+ /* Data used by winsock */
+ SOCKET socket;
+};
+
+#include <stdarg.h>
+
+static void
+log_message(char *fmt, ...)
+{
+ static FILE *log = NULL;
+ va_list a;
+
+ if (!log)
+ log = fopen("\\temp\\altos.txt", "w");
+ if (log) {
+ SYSTEMTIME time;
+ char buffer[4096];
+
+ GetLocalTime(&time);
+ sprintf (buffer, "%4d-%02d-%02d %2d:%02d:%02d. ",
+ time.wYear, time.wMonth, time.wDay,
+ time.wHour, time.wMinute, time.wSecond);
+ va_start(a, fmt);
+
+ vsprintf(buffer + strlen(buffer), fmt, a);
+ va_end(a);
+
+ fputs(buffer, log);
+ fflush(log);
+ fputs(buffer, stdout);
+ fflush(stdout);
+ }
+}
+
+static void
+_altos_set_last_windows_error(char *file, int line, DWORD error)
+{
+ TCHAR message[1024];
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
+ 0,
+ error,
+ 0,
+ message,
+ sizeof (message) / sizeof (TCHAR),
+ NULL);
+ if (error != ERROR_SUCCESS)
+ log_message ("%s:%d (%d) %s\n", file, line, error, message);
+ altos_set_last_error(error, message);
+}
+
+#define altos_set_last_windows_error() _altos_set_last_windows_error(__FILE__, __LINE__, GetLastError())
+#define altos_set_last_winsock_error() _altos_set_last_windows_error(__FILE__, __LINE__, WSAGetLastError())
+
+PUBLIC struct altos_list *
+altos_list_start(void)
+{
+ struct altos_list *list = calloc(1, sizeof (struct altos_list));
+
+ if (!list)
+ return NULL;
+ list->dev_info = SetupDiGetClassDevs(NULL, "USB", NULL,
+ DIGCF_ALLCLASSES|DIGCF_PRESENT);
+ if (list->dev_info == INVALID_HANDLE_VALUE) {
+ altos_set_last_windows_error();
+ free(list);
+ return NULL;
+ }
+ list->index = 0;
+ list->ftdi = 0;
+ return list;
+}
+
+PUBLIC struct altos_list *
+altos_ftdi_list_start(void)
+{
+ struct altos_list *list = calloc(1, sizeof (struct altos_list));
+
+ if (!list)
+ return NULL;
+ list->dev_info = SetupDiGetClassDevs(NULL, "FTDIBUS", NULL,
+ DIGCF_ALLCLASSES|DIGCF_PRESENT);
+ if (list->dev_info == INVALID_HANDLE_VALUE) {
+ altos_set_last_windows_error();
+ free(list);
+ return NULL;
+ }
+ list->index = 0;
+ list->ftdi = 1;
+ return list;
+}
+
+PUBLIC int
+altos_list_next(struct altos_list *list, struct altos_device *device)
+{
+ SP_DEVINFO_DATA dev_info_data;
+ BYTE port[128];
+ DWORD port_len;
+ char friendlyname[256];
+ BYTE symbolic[256];
+ DWORD symbolic_len;
+ HKEY dev_key;
+ unsigned int vid, pid;
+ int serial;
+ HRESULT result;
+ DWORD friendlyname_type;
+ DWORD friendlyname_len;
+ char instanceid[1024];
+ DWORD instanceid_len;
+
+ dev_info_data.cbSize = sizeof (SP_DEVINFO_DATA);
+ while(SetupDiEnumDeviceInfo(list->dev_info, list->index,
+ &dev_info_data))
+ {
+ list->index++;
+
+ dev_key = SetupDiOpenDevRegKey(list->dev_info, &dev_info_data,
+ DICS_FLAG_GLOBAL, 0, DIREG_DEV,
+ KEY_READ);
+ if (dev_key == INVALID_HANDLE_VALUE) {
+ altos_set_last_windows_error();
+ continue;
+ }
+
+ if (list->ftdi) {
+ vid = 0x0403;
+ pid = 0x6015;
+ serial = 0;
+ } else {
+ vid = pid = serial = 0;
+ /* Fetch symbolic name for this device and parse out
+ * the vid/pid/serial info */
+ symbolic_len = sizeof(symbolic);
+ result = RegQueryValueEx(dev_key, "SymbolicName", NULL, NULL,
+ symbolic, &symbolic_len);
+ if (result != 0) {
+ altos_set_last_windows_error();
+ } else {
+ sscanf((char *) symbolic + sizeof("\\??\\USB#VID_") - 1,
+ "%04X", &vid);
+ sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_") - 1,
+ "%04X", &pid);
+ sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_XXXX#") - 1,
+ "%d", &serial);
+ }
+ if (vid == 0 || pid == 0 || serial == 0) {
+ if (SetupDiGetDeviceInstanceId(list->dev_info,
+ &dev_info_data,
+ instanceid,
+ sizeof (instanceid),
+ &instanceid_len)) {
+ sscanf((char *) instanceid + sizeof("USB\\VID_") - 1,
+ "%04X", &vid);
+ sscanf((char *) instanceid + sizeof("USB\\VID_XXXX&PID_") - 1,
+ "%04X", &pid);
+ sscanf((char *) instanceid + sizeof("USB\\VID_XXXX&PID_XXXX\\") - 1,
+ "%d", &serial);
+ } else {
+ altos_set_last_windows_error();
+ }
+ }
+ if (vid == 0 || pid == 0 || serial == 0) {
+ RegCloseKey(dev_key);
+ continue;
+ }
+ }
+
+ /* Fetch the com port name */
+ port_len = sizeof (port);
+ result = RegQueryValueEx(dev_key, "PortName", NULL, NULL,
+ port, &port_len);
+ RegCloseKey(dev_key);
+ if (result != 0) {
+ altos_set_last_windows_error();
+ continue;
+ }
+
+ /* Fetch the device description which is the device name,
+ * with firmware that has unique USB ids */
+ friendlyname_len = sizeof (friendlyname);
+ if(!SetupDiGetDeviceRegistryProperty(list->dev_info,
+ &dev_info_data,
+ SPDRP_FRIENDLYNAME,
+ &friendlyname_type,
+ (BYTE *)friendlyname,
+ sizeof(friendlyname),
+ &friendlyname_len))
+ {
+ altos_set_last_windows_error();
+ continue;
+ }
+ device->vendor = vid;
+ device->product = pid;
+ device->serial = serial;
+ strcpy(device->name, friendlyname);
+
+ strcpy(device->path, (char *) port);
+ return 1;
+ }
+ result = GetLastError();
+ if (result != ERROR_NO_MORE_ITEMS)
+ altos_set_last_windows_error();
+ return 0;
+}
+
+PUBLIC void
+altos_list_finish(struct altos_list *list)
+{
+ SetupDiDestroyDeviceInfoList(list->dev_info);
+ free(list);
+}
+
+static int
+altos_queue_read(struct altos_file_windows *file)
+{
+ DWORD got;
+ if (file->pend_read)
+ return LIBALTOS_SUCCESS;
+
+ if (!ReadFile(file->handle, file->file.in_data, USB_BUF_SIZE, &got, &file->ov_read)) {
+ if (GetLastError() != ERROR_IO_PENDING) {
+ altos_set_last_windows_error();
+ return LIBALTOS_ERROR;
+ }
+ file->pend_read = TRUE;
+ } else {
+ file->pend_read = FALSE;
+ file->file.in_read = 0;
+ file->file.in_used = got;
+ }
+ return LIBALTOS_SUCCESS;
+}
+
+static int
+altos_wait_read(struct altos_file_windows *file, int timeout)
+{
+ DWORD ret;
+ DWORD got;
+
+ if (!file->pend_read)
+ return LIBALTOS_SUCCESS;
+
+ if (!timeout)
+ timeout = INFINITE;
+
+ ret = WaitForSingleObject(file->ov_read.hEvent, timeout);
+ switch (ret) {
+ case WAIT_OBJECT_0:
+ if (!GetOverlappedResult(file->handle, &file->ov_read, &got, FALSE)) {
+ if (GetLastError () != ERROR_OPERATION_ABORTED)
+ altos_set_last_windows_error();
+ return LIBALTOS_ERROR;
+ }
+ file->pend_read = FALSE;
+ file->file.in_read = 0;
+ file->file.in_used = got;
+ break;
+ case WAIT_TIMEOUT:
+ return LIBALTOS_TIMEOUT;
+ break;
+ default:
+ altos_set_last_windows_error();
+ return LIBALTOS_ERROR;
+ }
+ return LIBALTOS_SUCCESS;
+}
+
+int
+altos_fill(struct altos_file *file_common, int timeout)
+{
+ struct altos_file_windows *file = (struct altos_file_windows *) file_common;
+
+ int ret;
+
+ if (file->file.in_read < file->file.in_used)
+ return LIBALTOS_SUCCESS;
+
+ file->file.in_read = file->file.in_used = 0;
+
+ if (file->is_winsock) {
+
+ for (;;) {
+ fd_set readfds;
+ TIMEVAL timeval;
+ int thistimeout;
+
+ /* Check to see if the socket has been closed */
+ if (file->socket == INVALID_SOCKET)
+ return LIBALTOS_ERROR;
+
+#define POLL_TIMEOUT 10000
+
+ /* Poll to see if the socket has been closed
+ * as select doesn't abort when that happens
+ */
+ if (timeout) {
+ thistimeout = timeout;
+ if (thistimeout > POLL_TIMEOUT)
+ thistimeout = POLL_TIMEOUT;
+ } else {
+ thistimeout = POLL_TIMEOUT;
+ }
+
+ timeval.tv_sec = thistimeout / 1000;
+ timeval.tv_usec = (thistimeout % 1000) * 1000;
+
+ FD_ZERO(&readfds);
+ FD_SET(file->socket, &readfds);
+
+ ret = select(1, &readfds, NULL, NULL, &timeval);
+
+ if (ret == 0) {
+ if (timeout) {
+ timeout -= thistimeout;
+ if (timeout == 0)
+ return LIBALTOS_TIMEOUT;
+ }
+ } else {
+ if (ret > 0)
+ break;
+
+ if (ret < 0) {
+ altos_set_last_winsock_error();
+ return LIBALTOS_ERROR;
+ }
+ }
+ }
+
+ if (file->socket == INVALID_SOCKET) {
+ altos_set_last_winsock_error();
+ return LIBALTOS_ERROR;
+ }
+
+ ret = recv(file->socket, (char *) file->file.in_data, USB_BUF_SIZE, 0);
+
+ if (ret <= 0) {
+ altos_set_last_winsock_error();
+ return LIBALTOS_ERROR;
+ }
+ file->file.in_read = 0;
+ file->file.in_used = ret;
+ } else {
+ if (file->handle == INVALID_HANDLE_VALUE) {
+ altos_set_last_windows_error();
+ return LIBALTOS_ERROR;
+ }
+
+ ret = altos_queue_read(file);
+ if (ret)
+ return ret;
+ ret = altos_wait_read(file, timeout);
+ if (ret)
+ return ret;
+ }
+
+ return LIBALTOS_SUCCESS;
+}
+
+PUBLIC int
+altos_flush(struct altos_file *file_common)
+{
+ struct altos_file_windows *file = (struct altos_file_windows *) file_common;
+
+ unsigned char *data = file->file.out_data;
+ int used = file->file.out_used;
+
+ while (used) {
+ if (file->is_winsock) {
+ int put;
+
+ put = send(file->socket, (char *) data, used, 0);
+ if (put <= 0) {
+ altos_set_last_winsock_error();
+ return LIBALTOS_ERROR;
+ }
+ data += put;
+ used -= put;
+ } else {
+ DWORD put;
+ DWORD ret;
+ if (!WriteFile(file->handle, data, used, &put, &file->ov_write)) {
+ if (GetLastError() != ERROR_IO_PENDING) {
+ altos_set_last_windows_error();
+ return LIBALTOS_ERROR;
+ }
+ ret = WaitForSingleObject(file->ov_write.hEvent, INFINITE);
+ switch (ret) {
+ case WAIT_OBJECT_0:
+ if (!GetOverlappedResult(file->handle, &file->ov_write, &put, FALSE)) {
+ altos_set_last_windows_error();
+ return LIBALTOS_ERROR;
+ }
+ break;
+ default:
+ altos_set_last_windows_error();
+ return LIBALTOS_ERROR;
+ }
+ }
+ data += put;
+ used -= put;
+ }
+ }
+ file->file.out_used = 0;
+ return LIBALTOS_SUCCESS;
+}
+
+static HANDLE
+open_serial(char *full_name)
+{
+ HANDLE handle;
+ DCB dcb;
+
+ handle = CreateFile(full_name, GENERIC_READ|GENERIC_WRITE,
+ 0, NULL, OPEN_EXISTING,
+ FILE_FLAG_OVERLAPPED, NULL);
+
+ if (handle == INVALID_HANDLE_VALUE) {
+ altos_set_last_windows_error();
+ return INVALID_HANDLE_VALUE;
+ }
+
+ if (!GetCommState(handle, &dcb)) {
+ altos_set_last_windows_error();
+ CloseHandle(handle);
+ return INVALID_HANDLE_VALUE;
+ }
+ dcb.BaudRate = CBR_9600;
+ dcb.fBinary = TRUE;
+ dcb.fParity = FALSE;
+ dcb.fOutxCtsFlow = FALSE;
+ dcb.fOutxDsrFlow = FALSE;
+ dcb.fDtrControl = DTR_CONTROL_ENABLE;
+ dcb.fDsrSensitivity = FALSE;
+ dcb.fTXContinueOnXoff = FALSE;
+ dcb.fOutX = FALSE;
+ dcb.fInX = FALSE;
+ dcb.fErrorChar = FALSE;
+ dcb.fNull = FALSE;
+ dcb.fRtsControl = RTS_CONTROL_ENABLE;
+ dcb.fAbortOnError = FALSE;
+ dcb.XonLim = 10;
+ dcb.XoffLim = 10;
+ dcb.ByteSize = 8;
+ dcb.Parity = NOPARITY;
+ dcb.StopBits = ONESTOPBIT;
+ dcb.XonChar = 17;
+ dcb.XoffChar = 19;
+#if 0
+ dcb.ErrorChar = 0;
+ dcb.EofChar = 0;
+ dcb.EvtChar = 0;
+#endif
+ if (!SetCommState(handle, &dcb)) {
+ altos_set_last_windows_error();
+ CloseHandle(handle);
+ return INVALID_HANDLE_VALUE;
+ }
+ return handle;
+}
+
+PUBLIC struct altos_file *
+altos_open(struct altos_device *device)
+{
+ struct altos_file_windows *file = calloc (1, sizeof (struct altos_file_windows));
+ char full_name[64];
+ COMMTIMEOUTS timeouts;
+ int i;
+
+ if (!file)
+ return NULL;
+
+ strcpy(full_name, "\\\\.\\");
+ strcat(full_name, device->path);
+
+ file->handle = INVALID_HANDLE_VALUE;
+
+ for (i = 0; i < 5; i++) {
+ file->handle = open_serial(full_name);
+ if (file->handle != INVALID_HANDLE_VALUE)
+ break;
+ altos_set_last_windows_error();
+ Sleep(100);
+ }
+
+ if (file->handle == INVALID_HANDLE_VALUE) {
+ free(file);
+ return NULL;
+ }
+
+ /* The FTDI driver doesn't appear to work right unless you open it twice */
+ if (device->vendor == 0x0403) {
+ CloseHandle(file->handle);
+ file->handle = open_serial(full_name);
+ if (file->handle == INVALID_HANDLE_VALUE) {
+ free(file);
+ return NULL;
+ }
+ }
+
+ timeouts.ReadIntervalTimeout = MAXDWORD;
+ timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
+ timeouts.ReadTotalTimeoutConstant = 1 << 30; /* almost forever */
+ timeouts.WriteTotalTimeoutMultiplier = 0;
+ timeouts.WriteTotalTimeoutConstant = 0;
+ SetCommTimeouts(file->handle, &timeouts);
+
+ file->ov_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ file->ov_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ return &file->file;
+}
+
+PUBLIC void
+altos_close(struct altos_file *file_common)
+{
+ struct altos_file_windows *file = (struct altos_file_windows *) file_common;
+
+ if (file->is_winsock) {
+ SOCKET socket = file->socket;
+ if (socket != INVALID_SOCKET) {
+ file->socket = INVALID_SOCKET;
+ closesocket(socket);
+ }
+ } else {
+ HANDLE handle = file->handle;
+ if (handle != INVALID_HANDLE_VALUE) {
+ HANDLE ov_read = file->ov_read.hEvent;
+ HANDLE ov_write = file->ov_write.hEvent;
+ file->handle = INVALID_HANDLE_VALUE;
+ file->ov_read.hEvent = INVALID_HANDLE_VALUE;
+ file->ov_write.hEvent = INVALID_HANDLE_VALUE;
+ PurgeComm(handle, PURGE_RXABORT|PURGE_RXCLEAR|PURGE_TXABORT|PURGE_TXCLEAR);
+ Sleep(100);
+ CloseHandle(handle);
+ file->handle = INVALID_HANDLE_VALUE;
+ CloseHandle(ov_read);
+ CloseHandle(ov_write);
+ }
+ }
+}
+
+#include <ws2bth.h>
+
+#define LUP_SET (LUP_RETURN_NAME| LUP_CONTAINERS | LUP_RETURN_ADDR | LUP_FLUSHCACHE |\
+ LUP_RETURN_TYPE | LUP_RETURN_BLOB | LUP_RES_SERVICE)
+
+struct altos_bt_list {
+ WSADATA WSAData;
+ HANDLE lookup;
+};
+
+struct altos_bt_list *
+altos_bt_list_start(int inquiry_time)
+{
+ struct altos_bt_list *bt_list;
+ WSAQUERYSET query_set;
+ int retCode;
+
+ /* Windows provides no way to set the time */
+ (void) inquiry_time;
+ bt_list = calloc(1, sizeof (struct altos_bt_list));
+ if (!bt_list) {
+ altos_set_last_windows_error();
+ return NULL;
+ }
+
+ if ((retCode = WSAStartup(MAKEWORD(2,2),&bt_list->WSAData)) != 0) {
+ altos_set_last_winsock_error();
+ free(bt_list);
+ return NULL;
+ }
+
+ memset(&query_set, '\0', sizeof (query_set));
+ query_set.dwSize = sizeof(WSAQUERYSET);
+ query_set.dwNameSpace = NS_BTH;
+
+ retCode = WSALookupServiceBegin(&query_set, LUP_SET, &bt_list->lookup);
+
+ if (retCode != 0) {
+ altos_set_last_winsock_error();
+ free(bt_list);
+ return NULL;
+ }
+ return bt_list;
+}
+
+static unsigned char get_byte(BTH_ADDR ba, int shift)
+{
+ return (ba >> ((5 - shift) << 3)) & 0xff;
+}
+
+static BTH_ADDR put_byte(unsigned char c, int shift)
+{
+ return ((BTH_ADDR) c) << ((5 - shift) << 3);
+}
+
+static void
+ba2str(BTH_ADDR ba, char *str)
+{
+
+ sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
+ get_byte(ba, 0),
+ get_byte(ba, 1),
+ get_byte(ba, 2),
+ get_byte(ba, 3),
+ get_byte(ba, 4),
+ get_byte(ba, 5));
+}
+
+static BTH_ADDR
+str2ba(char *str)
+{
+ unsigned int bytes[6];
+
+ sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
+ &bytes[0],
+ &bytes[1],
+ &bytes[2],
+ &bytes[3],
+ &bytes[4],
+ &bytes[5]);
+ return (put_byte(bytes[0], 0) |
+ put_byte(bytes[1], 1) |
+ put_byte(bytes[2], 2) |
+ put_byte(bytes[3], 3) |
+ put_byte(bytes[4], 4) |
+ put_byte(bytes[5], 5));
+}
+
+int
+altos_bt_list_next(struct altos_bt_list *bt_list,
+ struct altos_bt_device *device)
+{
+ for (;;) {
+ BYTE buffer[4096];
+ DWORD length = sizeof (buffer);;
+ WSAQUERYSET *results = (WSAQUERYSET *)buffer;
+ CSADDR_INFO *addr_info;
+ int retCode;
+ SOCKADDR_BTH *sockaddr_bth;
+
+ memset(buffer, '\0', sizeof(buffer));
+
+ retCode = WSALookupServiceNext(bt_list->lookup, LUP_SET, &length, results);
+
+ if (retCode != 0) {
+ int error = WSAGetLastError();
+ if (error != WSAENOMORE && error != WSA_E_NO_MORE)
+ altos_set_last_winsock_error();
+ return 0;
+ }
+
+ if (results->dwNumberOfCsAddrs > 0) {
+
+ addr_info = results->lpcsaBuffer;
+
+ strncpy(device->name, results->lpszServiceInstanceName, sizeof(device->name));
+ device->name[sizeof(device->name)-1] = '\0';
+
+ sockaddr_bth = (SOCKADDR_BTH *) addr_info->RemoteAddr.lpSockaddr;
+
+ ba2str(sockaddr_bth->btAddr, device->addr);
+
+ return 1;
+ }
+ }
+}
+
+void
+altos_bt_list_finish(struct altos_bt_list *bt_list)
+{
+ WSALookupServiceEnd(bt_list->lookup);
+ free(bt_list);
+}
+
+void
+altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device)
+{
+ strncpy(device->name, name, sizeof (device->name));
+ device->name[sizeof(device->name)-1] = '\0';
+ strncpy(device->addr, addr, sizeof (device->addr));
+ device->addr[sizeof(device->addr)-1] = '\0';
+}
+
+struct altos_file *
+altos_bt_open(struct altos_bt_device *device)
+{
+ struct altos_file_windows *file;
+ SOCKADDR_BTH sockaddr_bth;
+ int ret;
+
+ file = calloc(1, sizeof (struct altos_file_windows));
+ if (!file) {
+ return NULL;
+ }
+
+ file->is_winsock = TRUE;
+ file->socket = WSASocket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM, NULL, 0, WSA_FLAG_OVERLAPPED);
+
+ if (file->socket == INVALID_SOCKET) {
+ altos_set_last_winsock_error();
+ free(file);
+ return NULL;
+ }
+
+ memset(&sockaddr_bth, '\0', sizeof (sockaddr_bth));
+ sockaddr_bth.addressFamily = AF_BTH;
+ sockaddr_bth.btAddr = str2ba(device->addr);
+ sockaddr_bth.port = 1;
+
+ ret = connect(file->socket, (SOCKADDR *) &sockaddr_bth, sizeof (sockaddr_bth));
+
+ if (ret != 0) {
+ altos_set_last_winsock_error();
+ closesocket(file->socket);
+ free(file);
+ return NULL;
+ }
+ return &file->file;
+}
+
diff --git a/micropeak/MicroData.java b/micropeak/MicroData.java
index 085b0131..60bf8ad7 100644
--- a/micropeak/MicroData.java
+++ b/micropeak/MicroData.java
@@ -20,8 +20,8 @@ package org.altusmetrum.micropeak;
import java.lang.*;
import java.io.*;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
class MicroIterator implements Iterator<MicroDataPoint> {
int i;
diff --git a/micropeak/MicroDataPoint.java b/micropeak/MicroDataPoint.java
index 0157f05d..2775165f 100644
--- a/micropeak/MicroDataPoint.java
+++ b/micropeak/MicroDataPoint.java
@@ -17,7 +17,7 @@
package org.altusmetrum.micropeak;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroDataPoint implements AltosUIDataPoint {
public double time;
diff --git a/micropeak/MicroDeviceDialog.java b/micropeak/MicroDeviceDialog.java
index 6e45359b..005e154e 100644
--- a/micropeak/MicroDeviceDialog.java
+++ b/micropeak/MicroDeviceDialog.java
@@ -21,7 +21,7 @@ import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroDeviceDialog extends AltosDeviceDialog {
diff --git a/micropeak/MicroDownload.java b/micropeak/MicroDownload.java
index 53d70b1b..49bcaf54 100644
--- a/micropeak/MicroDownload.java
+++ b/micropeak/MicroDownload.java
@@ -23,8 +23,8 @@ import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroDownload extends AltosUIDialog implements Runnable, ActionListener, MicroSerialLog, WindowListener {
MicroPeak owner;
diff --git a/micropeak/MicroExport.java b/micropeak/MicroExport.java
index c5b5d3d6..1c48a0d3 100644
--- a/micropeak/MicroExport.java
+++ b/micropeak/MicroExport.java
@@ -23,8 +23,8 @@ import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroExport extends JFileChooser {
diff --git a/micropeak/MicroFile.java b/micropeak/MicroFile.java
index 5712d6b6..0ef021a1 100644
--- a/micropeak/MicroFile.java
+++ b/micropeak/MicroFile.java
@@ -19,8 +19,8 @@ package org.altusmetrum.micropeak;
import java.io.*;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroFile {
diff --git a/micropeak/MicroFileChooser.java b/micropeak/MicroFileChooser.java
index 01ce284b..013d1128 100644
--- a/micropeak/MicroFileChooser.java
+++ b/micropeak/MicroFileChooser.java
@@ -20,8 +20,8 @@ package org.altusmetrum.micropeak;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.io.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroFileChooser extends JFileChooser {
JFrame frame;
diff --git a/micropeak/MicroFrame.java b/micropeak/MicroFrame.java
index 21f839b6..9f3c0426 100644
--- a/micropeak/MicroFrame.java
+++ b/micropeak/MicroFrame.java
@@ -21,7 +21,7 @@ import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroFrame extends AltosUIFrame {
static String[] micro_icon_names = {
diff --git a/micropeak/MicroGraph.java b/micropeak/MicroGraph.java
index c4dcb29c..4941070c 100644
--- a/micropeak/MicroGraph.java
+++ b/micropeak/MicroGraph.java
@@ -22,8 +22,8 @@ import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
diff --git a/micropeak/MicroPeak.java b/micropeak/MicroPeak.java
index 1b7327e4..fb4fe1cb 100644
--- a/micropeak/MicroPeak.java
+++ b/micropeak/MicroPeak.java
@@ -23,8 +23,8 @@ import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroPeak extends MicroFrame implements ActionListener, ItemListener {
diff --git a/micropeak/MicroRaw.java b/micropeak/MicroRaw.java
index c3504834..767ff9e1 100644
--- a/micropeak/MicroRaw.java
+++ b/micropeak/MicroRaw.java
@@ -20,8 +20,8 @@ package org.altusmetrum.micropeak;
import java.awt.*;
import java.io.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroRaw extends JTextArea {
diff --git a/micropeak/MicroSave.java b/micropeak/MicroSave.java
index e964ee9e..a38e2b46 100644
--- a/micropeak/MicroSave.java
+++ b/micropeak/MicroSave.java
@@ -24,8 +24,8 @@ import javax.swing.filechooser.FileNameExtensionFilter;
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroSave extends JFileChooser {
diff --git a/micropeak/MicroSerial.java b/micropeak/MicroSerial.java
index f5a98929..ea68aa1a 100644
--- a/micropeak/MicroSerial.java
+++ b/micropeak/MicroSerial.java
@@ -20,7 +20,7 @@ package org.altusmetrum.micropeak;
import java.util.*;
import java.io.*;
import libaltosJNI.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroSerial extends InputStream {
SWIGTYPE_p_altos_file file;
diff --git a/micropeak/MicroSerialLog.java b/micropeak/MicroSerialLog.java
index e808dee2..e8accaeb 100644
--- a/micropeak/MicroSerialLog.java
+++ b/micropeak/MicroSerialLog.java
@@ -20,7 +20,7 @@ package org.altusmetrum.micropeak;
import java.util.*;
import java.io.*;
import libaltosJNI.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
public interface MicroSerialLog {
diff --git a/micropeak/MicroStats.java b/micropeak/MicroStats.java
index 9e8f1938..d2f80a8f 100644
--- a/micropeak/MicroStats.java
+++ b/micropeak/MicroStats.java
@@ -18,8 +18,8 @@
package org.altusmetrum.micropeak;
import java.io.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroStats {
double coast_height;
diff --git a/micropeak/MicroStatsTable.java b/micropeak/MicroStatsTable.java
index ad7b206c..1adef54a 100644
--- a/micropeak/MicroStatsTable.java
+++ b/micropeak/MicroStatsTable.java
@@ -19,8 +19,8 @@ package org.altusmetrum.micropeak;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroStatsTable extends JComponent implements AltosFontListener {
GridBagLayout layout;
diff --git a/micropeak/MicroUSB.java b/micropeak/MicroUSB.java
index f6568d36..9ceae1cb 100644
--- a/micropeak/MicroUSB.java
+++ b/micropeak/MicroUSB.java
@@ -19,8 +19,8 @@ package org.altusmetrum.micropeak;
import java.util.*;
import libaltosJNI.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroUSB extends altos_device implements AltosDevice {
diff --git a/micropeak/micropeak-windows.nsi.in b/micropeak/micropeak-windows.nsi.in
index c3b63f7b..34f5908d 100644
--- a/micropeak/micropeak-windows.nsi.in
+++ b/micropeak/micropeak-windows.nsi.in
@@ -62,15 +62,6 @@ UninstPage instfiles
; And the stuff to install
-Section "FTDI USB Driver"
- SetOutPath $INSTDIR
-
- File "CDM_v2.12.00_WHQL_Certified.exe"
-
- StrCpy $2 "$INSTDIR\CDM_v2.12.00_WHQL_Certified.exe"
- ExecWait $2
-SectionEnd
-
Section "Install Driver" InstDriver
InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} AltusMetrumSerial
@@ -117,6 +108,15 @@ Section "${REG_NAME} Desktop Shortcut"
CreateShortCut "$DESKTOP\${REG_NAME}.lnk" "$INSTDIR\${WIN_APP_EXE}" "" "$INSTDIR\${WIN_APP_ICON}"
SectionEnd
+Section "FTDI USB Driver"
+ SetOutPath $INSTDIR
+
+ File "CDM_v2.12.00_WHQL_Certified.exe"
+
+ StrCpy $2 "$INSTDIR\CDM_v2.12.00_WHQL_Certified.exe"
+ ExecWait $2
+SectionEnd
+
Section "Documentation"
SetOutPath $INSTDIR
diff --git a/src/Makefile b/src/Makefile
index ebe1df9c..ecba2fbd 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -39,11 +39,14 @@ ARMM3DIRS=\
telescience-v0.2 telescience-v0.2/flash-loader \
teledongle-v3.0 teledongle-v3.0/flash-loader \
teleballoon-v2.0 \
- telebt-v3.0 telebt-v3.0/flash-loader
+ telebt-v3.0 telebt-v3.0/flash-loader \
+ telelcotwo-v0.1 telelcotwo-v0.1/flash-loader \
+ telefiretwo-v0.1 telefiretwo-v0.1/flash-loader \
ARMM0DIRS=\
easymini-v1.0 easymini-v1.0/flash-loader \
- chaoskey-v0.1 chaoskey-v0.1/flash-loader
+ chaoskey-v0.1 chaoskey-v0.1/flash-loader \
+ chaoskey-v1.0 chaoskey-v1.0/flash-loader
AVRDIRS=\
telescience-v0.1 telescience-pwm micropeak nanopeak-v0.1 microkite
diff --git a/src/cc1111/ao_arch_funcs.h b/src/cc1111/ao_arch_funcs.h
index ea340dfd..1eb506cd 100644
--- a/src/cc1111/ao_arch_funcs.h
+++ b/src/cc1111/ao_arch_funcs.h
@@ -146,4 +146,6 @@ ao_spi_init(void);
#define ao_enable_output(port,bit,pin,v) cc1111_enable_output(port,token_evaluator(port,DIR), token_evaluator(port,SEL), pin, bit, v)
#define ao_gpio_set(port, bit, pin, v) ((pin) = (v))
#define ao_gpio_get(port, bit, pin) (pin)
-
+#define ao_gpio_get_bits(port) (port)
+#define ao_gpio_set_bits(port, bits) ((port) |= bits)
+#define ao_gpio_clr_bits(port, bits) ((port) &= ~bits)
diff --git a/src/chaoskey-v0.1/Makefile b/src/chaoskey-v0.1/Makefile
index ac4a6788..85392280 100644
--- a/src/chaoskey-v0.1/Makefile
+++ b/src/chaoskey-v0.1/Makefile
@@ -13,6 +13,7 @@ INC = \
ao_product.h \
ao_task.h \
ao_adc_fast.h \
+ ao_power.h \
stm32f0.h
#
@@ -33,9 +34,11 @@ ALTOS_SRC = \
ao_usb_stm.c \
ao_trng_send.c \
ao_task.c \
+ ao_power.c \
+ ao_gpio.c \
ao_product.c
-PRODUCT=ChaosKey-v0.1
+PRODUCT=ChaosKey-hw-0.3-sw-$(VERSION)
PRODUCT_DEF=-DCHAOSKEY_V_0_1
IDVENDOR=0x1d50
IDPRODUCT=0x60c6
diff --git a/src/chaoskey-v0.1/ao_pins.h b/src/chaoskey-v0.1/ao_pins.h
index 72963dba..73f76307 100644
--- a/src/chaoskey-v0.1/ao_pins.h
+++ b/src/chaoskey-v0.1/ao_pins.h
@@ -27,6 +27,9 @@
#define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN)
+#define AO_POWER_MANAGEMENT 1
+#define AO_LED_POWER AO_LED_RED
+
#define HAS_BEEP 0
/* 48MHz clock based on USB */
@@ -40,10 +43,18 @@
#define AO_APB_PRESCALER 1
#define AO_RCC_CFGR_PPRE_DIV STM_RCC_CFGR_PPRE_DIV_1
-#define HAS_USB 1
-#define AO_USB_DIRECTIO 1
-#define AO_PA11_PA12_RMP 0
-#define AO_USB_INTERFACE_CLASS 0xff
+#define HAS_USB 1
+#define AO_USB_DIRECTIO 1
+#define AO_PA11_PA12_RMP 0
+#define AO_USB_DEVICE_CLASS 0xff
+#define AO_USB_INTERFACE_CLASS_DATA 0xff
+#define AO_USB_HAS_OUT 0
+#define AO_USB_HAS_IN 1
+#define AO_USB_HAS_IN2 1
+#define AO_USB_HAS_INT 0
+#define USE_USB_STDIO 0
+#define AO_USB_SELF_POWER 0
+#define AO_USB_DEVICE_ID_SERIAL 1
#define IS_FLASH_LOADER 0
@@ -57,11 +68,21 @@
#define AO_NUM_ADC 1
+/* TRNG enable */
+
+#define AO_TRNG_ENABLE_PORT (&stm_gpioa)
+#define AO_TRNG_ENABLE_BIT 8
+
/* CRC */
#define AO_CRC_WIDTH 32
#define AO_CRC_INIT 0xffffffff
/* TRNG */
-#define AO_LED_TRNG_ACTIVE AO_LED_GREEN
+#define AO_LED_TRNG_COOKED AO_LED_GREEN
+#define AO_LED_TRNG_RAW AO_LED_GREEN
+
+/* Mode pin */
+#define AO_RAW_PORT (&stm_gpioa)
+#define AO_RAW_BIT 15
#endif /* _AO_PINS_H_ */
diff --git a/src/chaoskey-v1.0/.gitignore b/src/chaoskey-v1.0/.gitignore
new file mode 100644
index 00000000..b0adba26
--- /dev/null
+++ b/src/chaoskey-v1.0/.gitignore
@@ -0,0 +1,2 @@
+ao_product.h
+chaoskey-*
diff --git a/src/chaoskey-v1.0/Makefile b/src/chaoskey-v1.0/Makefile
new file mode 100644
index 00000000..d9944a12
--- /dev/null
+++ b/src/chaoskey-v1.0/Makefile
@@ -0,0 +1,73 @@
+#
+# AltOS build
+#
+#
+
+include ../stmf0/Makefile.defs
+
+INC = \
+ ao.h \
+ ao_arch.h \
+ ao_arch_funcs.h \
+ ao_pins.h \
+ ao_product.h \
+ ao_task.h \
+ ao_adc_fast.h \
+ ao_power.h \
+ stm32f0.h
+
+#
+# Common AltOS sources
+#
+ALTOS_SRC = \
+ ao_interrupt.c \
+ ao_timer.c \
+ ao_panic.c \
+ ao_mutex.c \
+ ao_dma_stm.c \
+ ao_adc_fast.c \
+ ao_crc_stm.c \
+ ao_stdio.c \
+ ao_led.c \
+ ao_romconfig.c \
+ ao_boot_chain.c \
+ ao_usb_stm.c \
+ ao_trng_send.c \
+ ao_task.c \
+ ao_power.c \
+ ao_gpio.c \
+ ao_product.c
+
+PRODUCT=ChaosKey-hw-1.0-sw-$(VERSION)
+PRODUCT_DEF=-DCHAOSKEY_V_1_0
+IDVENDOR=0x1d50
+IDPRODUCT=0x60c6
+
+CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -g -Os
+
+PROGNAME=chaoskey-v1.0
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_chaoskey.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+ $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+ao_product.h: ao-make-product.5c ../Version
+ $(call quiet,NICKLE,$<) $< -m altusmetrum.org -V $(IDVENDOR) -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) -o $@
+
+$(OBJ): $(INC)
+
+distclean: clean
+
+clean:
+ rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+ rm -f ao_product.h
+
+install:
+
+uninstall:
diff --git a/src/chaoskey-v1.0/ao_chaoskey.c b/src/chaoskey-v1.0/ao_chaoskey.c
new file mode 100644
index 00000000..f887e601
--- /dev/null
+++ b/src/chaoskey-v1.0/ao_chaoskey.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2014 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_adc_fast.h>
+#include <ao_crc.h>
+#include <ao_trng_send.h>
+
+void main(void)
+{
+ ao_led_init(LEDS_AVAILABLE);
+ ao_clock_init();
+ ao_task_init();
+ ao_timer_init();
+ ao_dma_init();
+ ao_adc_init();
+ ao_crc_init();
+
+ ao_usb_init();
+
+ ao_trng_send_init();
+
+ ao_start_scheduler();
+}
diff --git a/src/chaoskey-v1.0/ao_pins.h b/src/chaoskey-v1.0/ao_pins.h
new file mode 100644
index 00000000..89a2cb08
--- /dev/null
+++ b/src/chaoskey-v1.0/ao_pins.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright © 2015 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define LED_PORT_ENABLE STM_RCC_AHBENR_IOPBEN
+#define LED_PORT (&stm_gpiob)
+#define LED_PIN_RED 4
+#define AO_LED_RED (1 << LED_PIN_RED)
+
+#define LEDS_AVAILABLE (AO_LED_RED)
+
+#define AO_POWER_MANAGEMENT 1
+#define AO_LED_POWER AO_LED_RED
+
+#define HAS_BEEP 0
+
+/* 48MHz clock based on USB */
+#define AO_HSI48 1
+
+/* HCLK = 48MHz */
+#define AO_AHB_PRESCALER 1
+#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1
+
+/* APB = 48MHz */
+#define AO_APB_PRESCALER 1
+#define AO_RCC_CFGR_PPRE_DIV STM_RCC_CFGR_PPRE_DIV_1
+
+#define HAS_USB 1
+#define AO_USB_DIRECTIO 1
+#define AO_PA11_PA12_RMP 1
+#define AO_USB_DEVICE_CLASS 0xff
+#define AO_USB_INTERFACE_CLASS_DATA 0xff
+#define AO_USB_HAS_OUT 0
+#define AO_USB_HAS_IN 1
+#define AO_USB_HAS_IN2 1
+#define AO_USB_HAS_INT 0
+#define AO_USB_SELF_POWER 0
+#define AO_USB_DEVICE_ID_SERIAL 1
+#define AO_USB_START_DISABLED 1
+#define USE_USB_STDIO 0
+
+#define IS_FLASH_LOADER 0
+
+/* ADC */
+
+#define AO_ADC_PIN0_PORT (&stm_gpioa)
+#define AO_ADC_PIN0_PIN 0
+#define AO_ADC_PIN0_CH 0
+
+#define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_IOPAEN))
+
+#define AO_NUM_ADC 1
+
+/* TRNG enable */
+
+#define AO_TRNG_ENABLE_PORT (&stm_gpioa)
+#define AO_TRNG_ENABLE_BIT 1
+
+/* CRC */
+#define AO_CRC_WIDTH 32
+#define AO_CRC_INIT 0xffffffff
+
+/* Mode pin */
+#define AO_RAW_PORT (&stm_gpioa)
+#define AO_RAW_BIT 15
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/chaoskey-v1.0/flash-loader/.gitignore b/src/chaoskey-v1.0/flash-loader/.gitignore
new file mode 100644
index 00000000..a60a4945
--- /dev/null
+++ b/src/chaoskey-v1.0/flash-loader/.gitignore
@@ -0,0 +1,2 @@
+ao_product.h
+chaoskey*
diff --git a/src/chaoskey-v1.0/flash-loader/Makefile b/src/chaoskey-v1.0/flash-loader/Makefile
new file mode 100644
index 00000000..4f84014a
--- /dev/null
+++ b/src/chaoskey-v1.0/flash-loader/Makefile
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=chaoskey-v1.0
+include $(TOPDIR)/stmf0/Makefile-flash.defs
diff --git a/src/chaoskey-v1.0/flash-loader/ao_pins.h b/src/chaoskey-v1.0/flash-loader/ao_pins.h
new file mode 100644
index 00000000..570800ca
--- /dev/null
+++ b/src/chaoskey-v1.0/flash-loader/ao_pins.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#include <ao_flash_stm_pins.h>
+
+/* Pin 5 on debug connector */
+
+#define AO_BOOT_PIN 1
+#define AO_BOOT_APPLICATION_GPIO stm_gpioa
+#define AO_BOOT_APPLICATION_PIN 15
+#define AO_BOOT_APPLICATION_VALUE 1
+#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP
+
+/* USB */
+#define HAS_USB 1
+#define AO_USB_DIRECTIO 0
+#define AO_PA11_PA12_RMP 1
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/detherm/.gitignore b/src/detherm/.gitignore
new file mode 100644
index 00000000..4f11d9a0
--- /dev/null
+++ b/src/detherm/.gitignore
@@ -0,0 +1,2 @@
+ao_product.h
+detherm-*
diff --git a/src/detherm/Makefile b/src/detherm/Makefile
new file mode 100644
index 00000000..6b0e0bf8
--- /dev/null
+++ b/src/detherm/Makefile
@@ -0,0 +1,82 @@
+#
+# AltOS build
+#
+#
+
+include ../stmf0/Makefile.defs
+
+INC = \
+ ao.h \
+ ao_arch.h \
+ ao_arch_funcs.h \
+ ao_pins.h \
+ ao_product.h \
+ ao_task.h \
+ stm32f0.h
+
+#
+# Common AltOS sources
+#
+ALTOS_SRC = \
+ ao_interrupt.c \
+ ao_timer.c \
+ ao_panic.c \
+ ao_mutex.c \
+ ao_dma_stm.c \
+ ao_usb_stm.c \
+ ao_spi_stm.c \
+ ao_exti_stm.c \
+ ao_stdio.c \
+ ao_led.c \
+ ao_log.c \
+ ao_log_mini.c \
+ ao_sample.c \
+ ao_data.c \
+ ao_kalman.c \
+ ao_flight.c \
+ ao_report.c \
+ ao_storage.c \
+ ao_m25.c \
+ ao_romconfig.c \
+ ao_boot_chain.c \
+ ao_ms5607.c \
+ ao_convert_pa.c \
+ ao_pwm.c \
+ ao_servo.c \
+ ao_task.c \
+ ao_config.c \
+ ao_cmd.c \
+ ao_product.c
+
+PRODUCT=Detherm-v1.0
+PRODUCT_DEF=-DDETHERM_V_1_0
+IDPRODUCT=0x0013
+
+CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -g -Os
+
+PROGNAME=detherm-v1.0
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_detherm.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+ $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+ao_product.h: ao-make-product.5c ../Version
+ $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) -o $@
+
+$(OBJ): $(INC)
+
+distclean: clean
+
+clean:
+ rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+ rm -f ao_product.h
+
+install:
+
+uninstall:
diff --git a/src/detherm/ao_detherm.c b/src/detherm/ao_detherm.c
new file mode 100644
index 00000000..fba9195e
--- /dev/null
+++ b/src/detherm/ao_detherm.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright © 2014 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_exti.h>
+#include <ao_pwm.h>
+#include <ao_servo.h>
+
+void main(void)
+{
+ ao_led_init(LEDS_AVAILABLE);
+
+ ao_led_on(AO_LED_RED);
+
+ ao_clock_init();
+ ao_task_init();
+ ao_timer_init();
+ ao_exti_init();
+
+ ao_dma_init();
+ ao_spi_init();
+ ao_usb_init();
+
+ ao_storage_init();
+ ao_ms5607_init();
+// ao_flight_init();
+ ao_pwm_init();
+ ao_servo_init();
+ ao_log_init();
+ ao_report_init();
+ ao_config_init();
+
+ ao_cmd_init();
+
+ ao_start_scheduler();
+}
diff --git a/src/detherm/ao_pins.h b/src/detherm/ao_pins.h
new file mode 100644
index 00000000..1c577b6e
--- /dev/null
+++ b/src/detherm/ao_pins.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright © 2015 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define LED_PORT_ENABLE STM_RCC_AHBENR_IOPAEN
+#define LED_PORT (&stm_gpioa)
+#define LED_PIN_RED 3
+#define AO_LED_RED (1 << LED_PIN_RED)
+
+#define LEDS_AVAILABLE (AO_LED_RED)
+
+#define HAS_BEEP 0
+
+/* 48MHz clock based on USB */
+//#define AO_HSI48 1
+#define AO_HSE 16000000
+#define AO_RCC_CFGR_PLLMUL STM_RCC_CFGR_PLLMUL_3
+#define AO_PLLMUL 3
+#define AO_PLLDIV 1
+
+/* HCLK = 48MHz */
+#define AO_AHB_PRESCALER 1
+#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1
+
+/* APB = 48MHz */
+#define AO_APB_PRESCALER 1
+#define AO_RCC_CFGR_PPRE_DIV STM_RCC_CFGR_PPRE_DIV_1
+
+#define HAS_USB 1
+#define AO_USB_DIRECTIO 0
+#define AO_PA11_PA12_RMP 1
+
+#define IS_FLASH_LOADER 0
+
+#define AO_DATA_RING 16
+
+#define HAS_ADC 0
+#define HAS_ACCEL 0
+#define HAS_GPS 0
+#define HAS_RADIO 0
+#define HAS_FLIGHT 1
+#define HAS_EEPROM 1
+#define HAS_LOG 1
+
+#define AO_LOG_FORMAT AO_LOG_FORMAT_DETHERM
+
+#define USE_INTERNAL_FLASH 0
+
+/* SPI */
+#define HAS_SPI_1 1
+#define HAS_SPI_2 0
+#define SPI_1_PA5_PA6_PA7 1
+#define SPI_1_PB3_PB4_PB5 1
+#define SPI_1_OSPEEDR STM_OSPEEDR_HIGH
+
+/* MS5607 */
+#define HAS_MS5607 1
+
+#define AO_MS5607_CS_PORT (&stm_gpioa)
+#define AO_MS5607_CS_PIN 0
+#define AO_MS5607_SPI_INDEX AO_SPI_1_PB3_PB4_PB5
+#define AO_MS5607_MISO_PORT (&stm_gpiob)
+#define AO_MS5607_MISO_PIN 4
+#define AO_MS5607_PRIVATE_PINS 1
+#define AO_MS5607_SPI_SPEED AO_SPI_SPEED_6MHz
+
+/* Flash */
+
+#define M25_MAX_CHIPS 1
+#define AO_M25_SPI_CS_PORT (&stm_gpioa)
+#define AO_M25_SPI_CS_MASK (1 << 4)
+#define AO_M25_SPI_BUS AO_SPI_1_PA5_PA6_PA7
+
+/* PWM */
+
+#define NUM_PWM 1
+#define AO_PWM_TIMER (&stm_tim3)
+#define AO_PWM_0_GPIO (&stm_gpiob)
+#define AO_PWM_0_PIN 1
+#define AO_PWM_0_CH 4
+#define PWM_MAX 20000
+#define AO_PWM_TIMER_ENABLE STM_RCC_APB1ENR_TIM3EN
+#define AO_PWM_TIMER_SCALE 32
+
+/* Servo */
+
+#define AO_SERVO_DIR_PORT (&stm_gpiob)
+#define AO_SERVO_DIR_BIT 0
+#define AO_SERVO_SPEED_PWM 0
+
+/* limit 2 */
+#define AO_SERVO_LIMIT_FORE_PORT (&stm_gpiob)
+#define AO_SERVO_LIMIT_FORE_BIT 6
+
+/* limit 1 */
+#define AO_SERVO_LIMIT_BACK_PORT (&stm_gpiob)
+#define AO_SERVO_LIMIT_BACK_BIT 7
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/detherm/flash-loader/.gitignore b/src/detherm/flash-loader/.gitignore
new file mode 100644
index 00000000..d0d4657e
--- /dev/null
+++ b/src/detherm/flash-loader/.gitignore
@@ -0,0 +1,2 @@
+ao_product.h
+detherm*
diff --git a/src/detherm/flash-loader/Makefile b/src/detherm/flash-loader/Makefile
new file mode 100644
index 00000000..5210aa09
--- /dev/null
+++ b/src/detherm/flash-loader/Makefile
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=detherm-v1.0
+include $(TOPDIR)/stmf0/Makefile-flash.defs
diff --git a/src/detherm/flash-loader/ao_pins.h b/src/detherm/flash-loader/ao_pins.h
new file mode 100644
index 00000000..570800ca
--- /dev/null
+++ b/src/detherm/flash-loader/ao_pins.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#include <ao_flash_stm_pins.h>
+
+/* Pin 5 on debug connector */
+
+#define AO_BOOT_PIN 1
+#define AO_BOOT_APPLICATION_GPIO stm_gpioa
+#define AO_BOOT_APPLICATION_PIN 15
+#define AO_BOOT_APPLICATION_VALUE 1
+#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP
+
+/* USB */
+#define HAS_USB 1
+#define AO_USB_DIRECTIO 0
+#define AO_PA11_PA12_RMP 1
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/drivers/ao_button.c b/src/drivers/ao_button.c
index cdf07352..8e7dead7 100644
--- a/src/drivers/ao_button.c
+++ b/src/drivers/ao_button.c
@@ -18,7 +18,6 @@
#include <ao.h>
#include <ao_button.h>
#include <ao_exti.h>
-#include <ao_debounce.h>
#if AO_EVENT
#include <ao_event.h>
#define ao_button_queue(b,v) ao_event_put_isr(AO_EVENT_BUTTON, b, v)
@@ -26,9 +25,14 @@
#define ao_button_queue(b,v)
#endif
-#define AO_BUTTON_DEBOUNCE_HOLD 10
+#define AO_BUTTON_DEBOUNCE_INTERVAL AO_MS_TO_TICKS(50)
-static struct ao_debounce ao_button_debounce[AO_BUTTON_COUNT];
+struct ao_button_state {
+ AO_TICK_TYPE time;
+ uint8_t value;
+};
+
+static struct ao_button_state ao_button_state[AO_BUTTON_COUNT];
#define port(q) AO_BUTTON_ ## q ## _PORT
#define bit(q) AO_BUTTON_ ## q
@@ -38,10 +42,8 @@ static struct ao_debounce ao_button_debounce[AO_BUTTON_COUNT];
#define ao_button_value(b) !ao_gpio_get(port(b), bit(b), pin(b))
static uint8_t
-_ao_button_get(struct ao_debounce *debounce)
+_ao_button_get(uint8_t b)
{
- uint8_t b = debounce - ao_button_debounce;
-
switch (b) {
#if AO_BUTTON_COUNT > 0
case 0: return ao_button_value(0);
@@ -63,22 +65,31 @@ _ao_button_get(struct ao_debounce *debounce)
}
static void
-_ao_button_set(struct ao_debounce *debounce, uint8_t value)
+_ao_button_check(uint8_t b)
{
- uint8_t b = debounce - ao_button_debounce;
-
- ao_button_queue(b, value);
-}
+ uint8_t value = _ao_button_get(b);
+ if (value != ao_button_state[b].value) {
+ AO_TICK_TYPE now = ao_time();
-#define ao_button_update(b) ao_button_do(b, ao_gpio_get(port(b), bit(b), pin(b)))
+ if ((now - ao_button_state[b].time) >= AO_BUTTON_DEBOUNCE_INTERVAL) {
+ ao_button_state[b].value = value;
+ ao_button_queue(b, value);
+ }
+ ao_button_state[b].time = now;
+ }
+}
static void
-ao_button_debounce_init(struct ao_debounce *debounce) {
- ao_debounce_config(debounce,
- _ao_button_get,
- _ao_button_set,
- AO_BUTTON_DEBOUNCE_HOLD);
+_ao_button_init(uint8_t b)
+{
+ uint8_t m = ao_arch_irqsave();
+ uint8_t value = _ao_button_get(b);
+ ao_button_state[b].value = value;
+ ao_button_state[b].time = ao_time();
+ ao_button_queue(b, value);
+ ao_arch_irqrestore(m);
+
}
static void
@@ -87,17 +98,17 @@ ao_button_isr(void)
uint8_t b;
for (b = 0; b < AO_BUTTON_COUNT; b++)
- _ao_debounce_start(&ao_button_debounce[b]);
+ _ao_button_check(b);
}
#define init(b) do { \
- ao_button_debounce_init(&ao_button_debounce[b]); \
ao_enable_port(port(b)); \
\
ao_exti_setup(port(b), bit(b), \
AO_BUTTON_MODE|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, \
- ao_button_isr); \
+ ao_button_isr); \
ao_exti_enable(port(b), bit(b)); \
+ _ao_button_init(b); \
} while (0)
void
@@ -118,5 +129,4 @@ ao_button_init(void)
#if AO_BUTTON_COUNT > 4
init(4);
#endif
- ao_debounce_init();
}
diff --git a/src/drivers/ao_cc1200.c b/src/drivers/ao_cc1200.c
index 6547be39..6bccb188 100644
--- a/src/drivers/ao_cc1200.c
+++ b/src/drivers/ao_cc1200.c
@@ -20,6 +20,9 @@
#include <ao_exti.h>
#include <ao_fec.h>
#include <ao_packet.h>
+#if HAS_PAD
+#include <ao_pad.h>
+#endif
static uint8_t ao_radio_mutex;
@@ -813,6 +816,9 @@ ao_radio_test_cmd(void)
#if PACKET_HAS_SLAVE
ao_packet_slave_stop();
#endif
+#if HAS_PAD
+ ao_pad_disable();
+#endif
ao_radio_get(0xff);
ao_radio_set_mode(AO_RADIO_MODE_TEST);
ao_radio_strobe(CC1200_STX);
@@ -838,6 +844,9 @@ ao_radio_test_cmd(void)
#if HAS_MONITOR
ao_monitor_enable();
#endif
+#if HAS_PAD
+ ao_pad_enable();
+#endif
}
}
diff --git a/src/drivers/ao_event.c b/src/drivers/ao_event.c
index 5c0d2863..8f88d778 100644
--- a/src/drivers/ao_event.c
+++ b/src/drivers/ao_event.c
@@ -41,6 +41,22 @@ ao_event_get(struct ao_event *ev)
);
}
+uint8_t
+ao_event_get_for(struct ao_event *ev, uint16_t timeout)
+{
+ uint8_t empty = 1;
+ ao_arch_critical(
+ while ((empty = ao_event_queue_empty()))
+ if (ao_sleep_for(&ao_event_queue, timeout))
+ break;
+ if (!empty) {
+ *ev = ao_event_queue[ao_event_queue_remove];
+ ao_event_queue_remove = ao_event_queue_next(ao_event_queue_remove);
+ }
+ );
+ return empty;
+}
+
/* called with interrupts disabled */
void
ao_event_put_isr(uint8_t type, uint8_t unit, int32_t value)
diff --git a/src/drivers/ao_event.h b/src/drivers/ao_event.h
index 584a845a..ea89da23 100644
--- a/src/drivers/ao_event.h
+++ b/src/drivers/ao_event.h
@@ -32,6 +32,9 @@ struct ao_event {
void
ao_event_get(struct ao_event *ev);
+uint8_t
+ao_event_get_for(struct ao_event *ev, uint16_t timeout);
+
void
ao_event_put_isr(uint8_t type, uint8_t unit, int32_t value);
diff --git a/src/drivers/ao_lco_two.c b/src/drivers/ao_lco_two.c
new file mode 100644
index 00000000..f53fef7d
--- /dev/null
+++ b/src/drivers/ao_lco_two.c
@@ -0,0 +1,314 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_lco.h>
+#include <ao_event.h>
+#include <ao_lco_func.h>
+#include <ao_radio_cmac.h>
+
+#define DEBUG 1
+
+#if DEBUG
+static uint8_t ao_lco_debug;
+#define DEBUG_EVENT 1
+#define DEBUG_STATUS 2
+#define PRINTD(l, ...) do { if (!(ao_lco_debug & l)) break; printf ("\r%5u %s: ", ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } while(0)
+#else
+#define PRINTD(l,...)
+#endif
+
+#define AO_LCO_VALID_LAST 1
+#define AO_LCO_VALID_EVER 2
+
+static uint8_t ao_lco_suspended;
+static uint8_t ao_lco_selected;
+static uint8_t ao_lco_valid;
+static uint8_t ao_lco_channels;
+static uint16_t ao_lco_tick_offset;
+
+/* UI values */
+static uint8_t ao_lco_armed;
+static uint8_t ao_lco_firing;
+
+#define ao_lco_box (ao_config.pad_box)
+
+static struct ao_pad_query ao_pad_query;
+
+#define MASK_SIZE(n) (((n) + 7) >> 3)
+#define MASK_ID(n) ((n) >> 3)
+#define MASK_SHIFT(n) ((n) & 7)
+
+static void
+ao_lco_set_armed(int pad, int armed)
+{
+ uint8_t bit = (1 << pad);
+
+ if (armed) {
+ ao_lco_selected |= bit;
+ ao_lco_armed |= bit;
+ } else {
+ ao_lco_selected &= ~bit;
+ ao_lco_armed &= ~bit;
+ }
+ PRINTD(DEBUG_EVENT, "pad %d bit 0x%x armed %d ao_lco_selected 0x%x ao_lco_armed 0x%x\n",
+ pad, bit, armed, ao_lco_selected, ao_lco_armed);
+ ao_wakeup(&ao_lco_armed);
+}
+
+static void
+ao_lco_suspend(void)
+{
+ if (!ao_lco_suspended) {
+ PRINTD(DEBUG_EVENT, "suspend\n");
+ ao_lco_suspended = 1;
+ ao_lco_selected = 0;
+ ao_lco_armed = 0;
+ ao_wakeup(&ao_pad_query);
+ }
+}
+
+static void
+ao_lco_wakeup(void)
+{
+ if (ao_lco_suspended) {
+ ao_lco_suspended = 0;
+ ao_wakeup(&ao_lco_suspended);
+ }
+}
+
+static void
+ao_lco_input(void)
+{
+ static struct ao_event event;
+ uint8_t timeout;
+
+ ao_config_get();
+ for (;;) {
+ if (ao_config.pad_idle && !ao_lco_suspended) {
+ timeout = ao_event_get_for(&event, AO_SEC_TO_TICKS(ao_config.pad_idle));
+ if (timeout) {
+ ao_lco_suspend();
+ continue;
+ }
+ } else {
+ ao_event_get(&event);
+ }
+ ao_lco_wakeup();
+ PRINTD(DEBUG_EVENT, "event type %d unit %d value %d\n",
+ event.type, event.unit, event.value);
+ switch (event.type) {
+ case AO_EVENT_BUTTON:
+ switch (event.unit) {
+ case AO_BUTTON_ARM_0:
+ ao_lco_set_armed(0, event.value);
+ break;
+#if AO_BUTTON_ARM_NUM > 1
+ case AO_BUTTON_ARM_1:
+ ao_lco_set_armed(1, event.value);
+ break;
+#endif
+ case AO_BUTTON_FIRE:
+ if (ao_lco_armed) {
+ ao_lco_firing = event.value;
+ PRINTD(DEBUG_EVENT, "Firing %d\n", ao_lco_firing);
+ ao_wakeup(&ao_lco_armed);
+ }
+ break;
+ }
+ break;
+ }
+ }
+}
+
+static AO_LED_TYPE continuity_led[AO_LED_CONTINUITY_NUM] = {
+#ifdef AO_LED_CONTINUITY_0
+ AO_LED_CONTINUITY_0,
+#endif
+#ifdef AO_LED_CONTINUITY_1
+ AO_LED_CONTINUITY_1,
+#endif
+#ifdef AO_LED_CONTINUITY_2
+ AO_LED_CONTINUITY_2,
+#endif
+#ifdef AO_LED_CONTINUITY_3
+ AO_LED_CONTINUITY_3,
+#endif
+#ifdef AO_LED_CONTINUITY_4
+ AO_LED_CONTINUITY_4,
+#endif
+#ifdef AO_LED_CONTINUITY_5
+ AO_LED_CONTINUITY_5,
+#endif
+#ifdef AO_LED_CONTINUITY_6
+ AO_LED_CONTINUITY_6,
+#endif
+#ifdef AO_LED_CONTINUITY_7
+ AO_LED_CONTINUITY_7,
+#endif
+};
+
+static uint8_t
+ao_lco_get_channels(void)
+{
+ int8_t r;
+
+ r = ao_lco_query(ao_lco_box, &ao_pad_query, &ao_lco_tick_offset);
+ if (r == AO_RADIO_CMAC_OK) {
+ ao_lco_channels = ao_pad_query.channels;
+ ao_lco_valid = AO_LCO_VALID_LAST | AO_LCO_VALID_EVER;
+ } else
+ ao_lco_valid &= ~AO_LCO_VALID_LAST;
+ PRINTD(DEBUG_STATUS, "ao_lco_get_channels() rssi %d valid %d ret %d offset %d\n", ao_radio_cmac_rssi, ao_lco_valid, r, ao_lco_tick_offset);
+ ao_wakeup(&ao_pad_query);
+ return ao_lco_valid;
+}
+
+static void
+ao_lco_igniter_status(void)
+{
+ uint8_t c;
+ uint8_t t = 0;
+
+ for (;;) {
+ ao_sleep(&ao_pad_query);
+ while (ao_lco_suspended) {
+ ao_led_off(AO_LED_GREEN|AO_LED_AMBER|AO_LED_RED|AO_LED_REMOTE_ARM);
+ for (c = 0; c < AO_LED_CONTINUITY_NUM; c++)
+ ao_led_off(continuity_led[c]);
+ ao_sleep(&ao_lco_suspended);
+ }
+ PRINTD(DEBUG_STATUS, "RSSI %d VALID %d\n", ao_radio_cmac_rssi, ao_lco_valid);
+ if (!(ao_lco_valid & AO_LCO_VALID_LAST)) {
+ ao_led_on(AO_LED_RED);
+ ao_led_off(AO_LED_GREEN|AO_LED_AMBER);
+ continue;
+ }
+ if (ao_radio_cmac_rssi < -90) {
+ ao_led_on(AO_LED_AMBER);
+ ao_led_off(AO_LED_RED|AO_LED_GREEN);
+ } else {
+ ao_led_on(AO_LED_GREEN);
+ ao_led_off(AO_LED_RED|AO_LED_AMBER);
+ }
+ if (ao_pad_query.arm_status)
+ ao_led_on(AO_LED_REMOTE_ARM);
+ else
+ ao_led_off(AO_LED_REMOTE_ARM);
+
+ for (c = 0; c < AO_LED_CONTINUITY_NUM; c++) {
+ uint8_t status;
+
+ if (ao_pad_query.channels & (1 << c))
+ status = ao_pad_query.igniter_status[c];
+ else
+ status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN;
+ PRINTD(DEBUG_STATUS, "\tchannel %d status %d\n", c, status);
+ if (status == AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN)
+ ao_led_on(continuity_led[c]);
+ else
+ ao_led_off(continuity_led[c]);
+ }
+ t = 1-t;
+ }
+}
+
+static void
+ao_lco_arm_warn(void)
+{
+ int i;
+ for (;;) {
+ while (ao_lco_suspended)
+ ao_sleep(&ao_lco_suspended);
+ while (!ao_lco_armed)
+ ao_sleep(&ao_lco_armed);
+ for (i = 0; i < ao_lco_armed; i++) {
+ ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(100));
+ ao_delay(AO_MS_TO_TICKS(100));
+ }
+ ao_delay(AO_MS_TO_TICKS(300));
+ }
+}
+
+static struct ao_task ao_lco_input_task;
+static struct ao_task ao_lco_monitor_task;
+static struct ao_task ao_lco_arm_warn_task;
+static struct ao_task ao_lco_igniter_status_task;
+
+static void
+ao_lco_monitor(void)
+{
+ uint16_t delay;
+
+ ao_add_task(&ao_lco_input_task, ao_lco_input, "lco input");
+ ao_add_task(&ao_lco_arm_warn_task, ao_lco_arm_warn, "lco arm warn");
+ ao_add_task(&ao_lco_igniter_status_task, ao_lco_igniter_status, "lco igniter status");
+ ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200));
+ for (;;) {
+ while (ao_lco_suspended)
+ ao_sleep(&ao_lco_suspended);
+
+ PRINTD(DEBUG_STATUS, "monitor armed %d firing %d\n",
+ ao_lco_armed, ao_lco_firing);
+
+ if (ao_lco_armed && ao_lco_firing) {
+ ao_lco_ignite();
+ } else {
+ ao_lco_get_channels();
+ if (ao_lco_armed) {
+ if (ao_lco_selected) {
+ PRINTD(DEBUG_STATUS, "Arming pads %x\n",
+ ao_lco_selected);
+ if (ao_lco_valid & AO_LCO_VALID_EVER) {
+ ao_lco_arm(ao_lco_box, ao_lco_selected, ao_lco_tick_offset);
+ ao_delay(AO_MS_TO_TICKS(10));
+ }
+ }
+ }
+ }
+ if (ao_lco_armed && ao_lco_firing)
+ delay = AO_MS_TO_TICKS(100);
+ else {
+ delay = AO_SEC_TO_TICKS(1);
+ }
+ ao_sleep_for(&ao_lco_armed, delay);
+ }
+}
+
+#if DEBUG
+void
+ao_lco_set_debug(void)
+{
+ ao_cmd_decimal();
+ if (ao_cmd_status == ao_cmd_success)
+ ao_lco_debug = ao_cmd_lex_i;
+}
+
+__code struct ao_cmds ao_lco_cmds[] = {
+ { ao_lco_set_debug, "D <0 off, 1 on>\0Debug" },
+ { 0, NULL }
+};
+#endif
+
+void
+ao_lco_init(void)
+{
+ ao_add_task(&ao_lco_monitor_task, ao_lco_monitor, "lco monitor");
+#if DEBUG
+ ao_cmd_register(&ao_lco_cmds[0]);
+#endif
+}
diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c
index 6098699e..ef31882e 100644
--- a/src/drivers/ao_ms5607.c
+++ b/src/drivers/ao_ms5607.c
@@ -24,9 +24,13 @@
__xdata struct ao_ms5607_prom ao_ms5607_prom;
static __xdata uint8_t ms5607_configured;
+#ifndef AO_MS5607_SPI_SPEED
+#define AO_MS5607_SPI_SPEED AO_SPI_SPEED_FAST
+#endif
+
static void
ao_ms5607_start(void) {
- ao_spi_get_bit(AO_MS5607_CS_PORT, AO_MS5607_CS_PIN, AO_MS5607_CS, AO_MS5607_SPI_INDEX, AO_SPI_SPEED_FAST);
+ ao_spi_get_bit(AO_MS5607_CS_PORT, AO_MS5607_CS_PIN, AO_MS5607_CS, AO_MS5607_SPI_INDEX, AO_MS5607_SPI_SPEED);
}
static void
diff --git a/src/drivers/ao_packet_master.c b/src/drivers/ao_packet_master.c
index 5e440db0..2beda4cb 100644
--- a/src/drivers/ao_packet_master.c
+++ b/src/drivers/ao_packet_master.c
@@ -117,6 +117,7 @@ ao_packet_forward(void) __reentrant
{
char c;
ao_packet_enable = 1;
+ ao_packet_tx_used = 0;
ao_cmd_white();
flush();
diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c
index 419ea8d3..99a90e77 100644
--- a/src/drivers/ao_pad.c
+++ b/src/drivers/ao_pad.c
@@ -50,7 +50,11 @@ ao_siren(uint8_t v)
#ifdef AO_SIREN
ao_gpio_set(AO_SIREN_PORT, AO_SIREN_PIN, AO_SIREN, v);
#else
+#if HAS_BEEP
ao_beep(v ? AO_BEEP_MID : 0);
+#else
+ (void) v;
+#endif
#endif
}
@@ -59,13 +63,15 @@ ao_strobe(uint8_t v)
{
#ifdef AO_STROBE
ao_gpio_set(AO_STROBE_PORT, AO_STROBE_PIN, AO_STROBE, v);
+#else
+ (void) v;
#endif
}
static void
ao_pad_run(void)
{
- uint8_t pins;
+ AO_PORT_TYPE pins;
for (;;) {
while (!ao_pad_ignite)
@@ -90,18 +96,28 @@ ao_pad_run(void)
if (ao_pad_ignite & (1 << 3))
pins |= (1 << AO_PAD_PIN_3);
#endif
- AO_PAD_PORT = (AO_PAD_PORT & (~AO_PAD_ALL_PINS)) | pins;
+ PRINTD("ignite pins 0x%x\n", pins);
+ ao_gpio_set_bits(AO_PAD_PORT, pins);
while (ao_pad_ignite) {
ao_pad_ignite = 0;
ao_delay(AO_PAD_FIRE_TIME);
}
- AO_PAD_PORT &= ~(AO_PAD_ALL_PINS);
+ ao_gpio_clr_bits(AO_PAD_PORT, pins);
+ PRINTD("turn off pins 0x%x\n", pins);
}
}
#define AO_PAD_ARM_SIREN_INTERVAL 200
+#ifndef AO_PYRO_R_PYRO_SENSE
+#define AO_PYRO_R_PYRO_SENSE 100
+#define AO_PYRO_R_SENSE_GND 27
+#define AO_FIRE_R_POWER_FET 100
+#define AO_FIRE_R_FET_SENSE 100
+#define AO_FIRE_R_SENSE_GND 27
+#endif
+
static void
ao_pad_monitor(void)
{
@@ -109,7 +125,7 @@ ao_pad_monitor(void)
uint8_t sample;
__pdata uint8_t prev = 0, cur = 0;
__pdata uint8_t beeping = 0;
- __xdata struct ao_data *packet;
+ __xdata volatile struct ao_data *packet;
__pdata uint16_t arm_beep_time = 0;
sample = ao_data_head;
@@ -120,12 +136,18 @@ ao_pad_monitor(void)
ao_sleep((void *) DATA_TO_XDATA(&ao_data_head));
);
+
packet = &ao_data_ring[sample];
sample = ao_data_ring_next(sample);
pyro = packet->adc.pyro;
-#define VOLTS_TO_PYRO(x) ((int16_t) ((x) * 27.0 / 127.0 / 3.3 * 32767.0))
+#define VOLTS_TO_PYRO(x) ((int16_t) ((x) * ((1.0 * AO_PYRO_R_SENSE_GND) / \
+ (1.0 * (AO_PYRO_R_SENSE_GND + AO_PYRO_R_PYRO_SENSE)) / 3.3 * AO_ADC_MAX)))
+
+
+#define VOLTS_TO_FIRE(x) ((int16_t) ((x) * ((1.0 * AO_FIRE_R_SENSE_GND) / \
+ (1.0 * (AO_FIRE_R_SENSE_GND + AO_FIRE_R_FET_SENSE)) / 3.3 * AO_ADC_MAX)))
/* convert ADC value to voltage in tenths, then add .2 for the diode drop */
query.battery = (packet->adc.batt + 96) / 192 + 2;
@@ -133,14 +155,16 @@ ao_pad_monitor(void)
if (pyro > VOLTS_TO_PYRO(10)) {
query.arm_status = AO_PAD_ARM_STATUS_ARMED;
cur |= AO_LED_ARMED;
- } else if (pyro < VOLTS_TO_PYRO(5)) {
- query.arm_status = AO_PAD_ARM_STATUS_DISARMED;
- arm_beep_time = 0;
- } else {
+#if AO_FIRE_R_POWER_FET
+ } else if (pyro > VOLTS_TO_PYRO(5)) {
if ((ao_time() % 100) < 50)
cur |= AO_LED_ARMED;
query.arm_status = AO_PAD_ARM_STATUS_UNKNOWN;
arm_beep_time = 0;
+#endif
+ } else {
+ query.arm_status = AO_PAD_ARM_STATUS_DISARMED;
+ arm_beep_time = 0;
}
if ((ao_time() - ao_pad_packet_time) > AO_SEC_TO_TICKS(2))
cur |= AO_LED_RED;
@@ -165,22 +189,39 @@ ao_pad_monitor(void)
* 27k /
* gnd ---
*
+ * v_pyro \
+ * 200k igniter
+ * output /
+ * 200k \
+ * sense relay
+ * 22k /
+ * gnd ---
+ *
* If the relay is closed, then sense will be 0
* If no igniter is present, then sense will be v_pyro * 27k/227k = pyro * 127 / 227 ~= pyro/2
* If igniter is present, then sense will be v_pyro * 27k/127k ~= v_pyro / 20 = pyro
*/
+#if AO_FIRE_R_POWER_FET
if (sense <= pyro / 8) {
status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED;
if ((ao_time() % 100) < 50)
cur |= AO_LED_CONTINUITY(c);
- }
- else if (pyro / 8 * 3 <= sense && sense <= pyro / 8 * 5)
+ } else
+ if (pyro / 8 * 3 <= sense && sense <= pyro / 8 * 5)
status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN;
else if (pyro / 8 * 7 <= sense) {
status = AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN;
cur |= AO_LED_CONTINUITY(c);
}
+#else
+ if (sense >= pyro / 8 * 5) {
+ status = AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN;
+ cur |= AO_LED_CONTINUITY(c);
+ } else {
+ status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN;
+ }
+#endif
query.igniter_status[c] = status;
}
if (cur != prev) {
@@ -240,8 +281,14 @@ ao_pad_read_box(void)
l = byte & 0xf;
return h * 10 + l;
}
-#else
-#define ao_pad_read_box() 0
+#endif
+
+#if HAS_FIXED_PAD_BOX
+#define ao_pad_read_box() ao_config.pad_box
+#endif
+
+#ifdef PAD_BOX
+#define ao_pad_read_box() PAD_BOX
#endif
static void
diff --git a/src/drivers/ao_servo.c b/src/drivers/ao_servo.c
new file mode 100644
index 00000000..b48a4112
--- /dev/null
+++ b/src/drivers/ao_servo.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+#include "ao_servo.h"
+#include "ao_pwm.h"
+#include "ao_exti.h"
+
+static uint8_t limit_wakeup;
+
+static void
+ao_limit_isr(void)
+{
+ ao_wakeup(&limit_wakeup);
+}
+
+static void
+ao_limit_enable(uint8_t dir)
+{
+ if (dir == AO_SERVO_FORE)
+ ao_exti_enable(AO_SERVO_LIMIT_FORE_PORT, AO_SERVO_LIMIT_FORE_BIT);
+ else
+ ao_exti_enable(AO_SERVO_LIMIT_BACK_PORT, AO_SERVO_LIMIT_BACK_BIT);
+}
+
+static void
+ao_limit_disable(uint8_t dir)
+{
+ if (dir == AO_SERVO_FORE)
+ ao_exti_disable(AO_SERVO_LIMIT_FORE_PORT, AO_SERVO_LIMIT_FORE_BIT);
+ else
+ ao_exti_disable(AO_SERVO_LIMIT_BACK_PORT, AO_SERVO_LIMIT_BACK_BIT);
+}
+
+static uint8_t
+ao_limit_get(uint8_t dir)
+{
+ if (dir == AO_SERVO_FORE)
+ return !ao_gpio_get(AO_SERVO_LIMIT_FORE_PORT, AO_SERVO_LIMIT_FORE_BIT, PIN);
+ else
+ return !ao_gpio_get(AO_SERVO_LIMIT_BACK_PORT, AO_SERVO_LIMIT_BACK_BIT, PIN);
+}
+
+void
+ao_servo_run(uint16_t speed, uint8_t dir, uint16_t timeout)
+{
+ printf ("speed %d dir %d\n", speed, dir);
+
+ /* Turn on the motor */
+ ao_gpio_set(AO_SERVO_DIR_PORT, AO_SERVO_DIR_BIT, AO_SERVO_DIR_PIN, dir);
+ ao_pwm_set(AO_SERVO_SPEED_PWM, speed);
+
+ /* Wait until the limit sensor is triggered */
+ ao_arch_block_interrupts();
+ ao_limit_enable(dir);
+ while (!ao_limit_get(dir))
+ if (ao_sleep_for(&limit_wakeup, timeout))
+ break;
+ ao_limit_disable(dir);
+ ao_arch_release_interrupts();
+
+ /* Turn off the motor */
+ ao_pwm_set(AO_SERVO_SPEED_PWM, 0);
+}
+
+#define init_limit(p,b) do { \
+ ao_enable_port(p); \
+ ao_exti_setup(p, b, \
+ AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED, \
+ ao_limit_isr); \
+ } while (0)
+
+
+static void
+ao_servo_cmd(void)
+{
+ uint8_t dir;
+ uint16_t speed;
+
+ ao_cmd_decimal();
+ dir = ao_cmd_lex_u32;
+ ao_cmd_decimal();
+ speed = ao_cmd_lex_u32;
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+
+ printf("Run servo %d\n", dir);
+ ao_servo_run(speed, dir, AO_MS_TO_TICKS(200));
+}
+
+static const struct ao_cmds ao_servo_cmds[] = {
+ { ao_servo_cmd, "S <dir> <speed>\0Run servo in indicated direction" },
+ { 0, NULL },
+};
+
+
+void
+ao_servo_init(void)
+{
+ init_limit(AO_SERVO_LIMIT_FORE_PORT, AO_SERVO_LIMIT_FORE_BIT);
+ init_limit(AO_SERVO_LIMIT_BACK_PORT, AO_SERVO_LIMIT_BACK_BIT);
+ ao_enable_output(AO_SERVO_DIR_PORT, AO_SERVO_DIR_BIT, AO_SERVO_DIR_PIN, 0);
+ ao_cmd_register(&ao_servo_cmds[0]);
+}
diff --git a/src/drivers/ao_servo.h b/src/drivers/ao_servo.h
new file mode 100644
index 00000000..e1df347a
--- /dev/null
+++ b/src/drivers/ao_servo.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_SERVO_H_
+#define _AO_SERVO_H_
+
+void
+ao_servo_run(uint16_t speed, uint8_t dir, uint16_t timeout);
+
+void
+ao_servo_init(void);
+
+#define AO_SERVO_FORE 0
+#define AO_SERVO_BACK 1
+
+/* To configure the servo:
+ *
+ * #define AO_SERVO_PWM <pwm index>
+ * #define AO_SERVO_DIR_PORT <gpio>
+ * #define AO_SERVO_DIR_PIN <pin>
+ * #define AO_SERVO_LIMIT_FORE_PORT <gpio>
+ * #define AO_SERVO_LIMIT_FORE_PIN <pin>
+ * #define AO_SERVO_LIMIT_BACK_PORT <gpio>
+ * #define AO_SERVO_LIMIT_BACK_PIN <pin>
+ */
+
+#endif /* _AO_SERVO_H_ */
diff --git a/src/drivers/ao_trng_send.c b/src/drivers/ao_trng_send.c
index bac6035c..171a345f 100644
--- a/src/drivers/ao_trng_send.c
+++ b/src/drivers/ao_trng_send.c
@@ -19,47 +19,247 @@
#include <ao_adc_fast.h>
#include <ao_crc.h>
#include <ao_trng_send.h>
+#include <ao_exti.h>
+#include <ao_power.h>
+
+static struct ao_task ao_trng_send_task, ao_trng_send_raw_task;
+static uint8_t trng_running;
+static AO_TICK_TYPE trng_power_time;
+
+#define TRNG_ENABLE_DELAY AO_MS_TO_TICKS(100)
+
+static uint8_t random_mutex;
static void
-ao_trng_send(void)
+ao_trng_get_raw(uint16_t *buf)
+{
+ uint16_t i;
+ uint16_t t;
+ uint16_t v;
+
+ t = ao_adc_get(AO_USB_IN_SIZE>>1); /* one 16-bit value per two output bytes */
+ for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) {
+ v = ao_adc_ring[t];
+ *buf++ = v;
+ t = (t + 1) & (AO_ADC_RING_SIZE - 1);
+ }
+ ao_adc_ack(AO_USB_IN_SIZE>>1);
+}
+
+static void
+ao_trng_send_raw(void)
{
static uint16_t *buffer[2];
int usb_buf_id;
+
+ if (!buffer[0]) {
+ buffer[0] = ao_usb_alloc();
+ buffer[1] = ao_usb_alloc();
+ if (!buffer[0])
+ ao_exit();
+ }
+
+ usb_buf_id = 0;
+
+ for (;;) {
+ ao_mutex_get(&random_mutex);
+ if (!trng_running) {
+ AO_TICK_TYPE delay;
+
+ delay = trng_power_time + TRNG_ENABLE_DELAY - ao_time();
+ if (delay > TRNG_ENABLE_DELAY)
+ delay = TRNG_ENABLE_DELAY;
+
+ /* Delay long enough for the HV power supply
+ * to stabilize so that the first bits we read
+ * aren't of poor quality
+ */
+ ao_delay(delay);
+ trng_running = TRUE;
+ }
+#ifdef AO_LED_TRNG_RAW
+ ao_led_on(AO_LED_TRNG_RAW);
+#endif
+ ao_trng_get_raw(buffer[usb_buf_id]);
+#ifdef AO_LED_TRNG_RAW
+ ao_led_off(AO_LED_TRNG_RAW);
+#endif
+ ao_mutex_put(&random_mutex);
+ ao_usb_write2(buffer[usb_buf_id], AO_USB_IN_SIZE);
+ usb_buf_id = 1-usb_buf_id;
+ }
+}
+
+/* Make sure there's at least 8 bits of variance in the samples */
+#define MIN_VARIANCE (128 * 128)
+
+/* Make sure the signal is spread around a bit */
+#define MAX_VARIANCE (512 * 512)
+
+#define ADD_STATS(value) do { \
+ sum += (value); \
+ sum2 += (value) * (value); \
+ } while(0)
+
+#define VARIANCE(n) ((sum2 - (sum / (n) * sum)) / (n))
+
+static int
+ao_trng_get_cooked(uint16_t *buf)
+{
uint16_t i;
- uint16_t *buf;
uint16_t t;
uint32_t *rnd = (uint32_t *) ao_adc_ring;
+ int32_t sum, sum2, var;
+
+ sum = sum2 = 0;
+ t = ao_adc_get(AO_USB_IN_SIZE) >> 1; /* one 16-bit value per output byte */
+ for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) {
+ uint32_t v;
+ uint16_t v1, v2;
+
+ /* Fetch two values in one operation */
+ v = rnd[t];
+ t = (t + 1) & ((AO_ADC_RING_SIZE >> 1) - 1);
+
+ *buf++ = ao_crc_in_32_out_16(v);
+
+ v1 = v;
+ v2 = v >> 16;
+
+ ADD_STATS(v1);
+ ADD_STATS(v2);
+ }
+ ao_adc_ack(AO_USB_IN_SIZE);
+ var = VARIANCE(2 * AO_USB_IN_SIZE / sizeof (uint16_t));
+ return var >= MIN_VARIANCE && var <= MAX_VARIANCE;
+}
+
+#define AO_TRNG_START_WAIT 1024
+#define AO_TRNG_START_CHECK 32
+
+static void
+ao_trng_send(void)
+{
+ static uint16_t *buffer[2];
+ int usb_buf_id;
+ int good_bits;
+ int failed;
+ int s;
if (!buffer[0]) {
buffer[0] = ao_usb_alloc();
buffer[1] = ao_usb_alloc();
if (!buffer[0])
- return;
+ ao_exit();
}
usb_buf_id = 0;
+#ifdef AO_TRNG_ENABLE_PORT
+ ao_gpio_set(AO_TRNG_ENABLE_PORT, AO_TRNG_ENABLE_BIT, AO_TRNG_ENABLE_PIN, 1);
+#endif
+ trng_power_time = ao_time();
+
ao_crc_reset();
+ ao_delay(TRNG_ENABLE_DELAY);
+
+ for (s = 0; s < AO_TRNG_START_WAIT; s++) {
+ if (ao_trng_get_cooked(buffer[0]))
+ break;
+ ao_delay(AO_MS_TO_TICKS(10));
+ }
+
+ /* Validate the hardware before enabling USB */
+ failed = 0;
+ for (s = 0; s < AO_TRNG_START_CHECK; s++) {
+ if (!ao_trng_get_cooked(buffer[0])) {
+ failed++;
+ ao_delay(AO_MS_TO_TICKS(10));
+ }
+ }
+ if (failed > AO_TRNG_START_CHECK / 4)
+ ao_panic(AO_PANIC_DMA);
+
+ ao_add_task(&ao_trng_send_raw_task, ao_trng_send_raw, "trng_send_raw");
+
+#ifdef AO_USB_START_DISABLED
+ ao_usb_enable();
+#endif
+
for (;;) {
- ao_led_on(AO_LED_TRNG_ACTIVE);
- t = ao_adc_get(AO_USB_IN_SIZE) >> 1; /* one 16-bit value per output byte */
- buf = buffer[usb_buf_id];
- for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) {
- *buf++ = ao_crc_in_32_out_16(rnd[t]);
- t = (t + 1) & ((AO_ADC_RING_SIZE>>1) - 1);
+ ao_mutex_get(&random_mutex);
+ if (!trng_running) {
+ AO_TICK_TYPE delay;
+
+ delay = trng_power_time + TRNG_ENABLE_DELAY - ao_time();
+ if (delay > TRNG_ENABLE_DELAY)
+ delay = TRNG_ENABLE_DELAY;
+
+ /* Delay long enough for the HV power supply
+ * to stabilize so that the first bits we read
+ * aren't of poor quality
+ */
+ ao_delay(delay);
+ trng_running = TRUE;
+ }
+#ifdef AO_LED_TRNG_COOKED
+ ao_led_on(AO_LED_TRNG_COOKED);
+#endif
+ good_bits = ao_trng_get_cooked(buffer[usb_buf_id]);
+#ifdef AO_LED_TRNG_COOKED
+ ao_led_off(AO_LED_TRNG_COOKED);
+#endif
+ ao_mutex_put(&random_mutex);
+ if (good_bits) {
+ ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE);
+ usb_buf_id = 1-usb_buf_id;
+ failed = 0;
+ } else {
+ failed++;
+ ao_delay(AO_MS_TO_TICKS(10));
+ if (failed > 10) {
+ ao_usb_disable();
+ ao_panic(AO_PANIC_DMA);
+ }
}
- ao_adc_ack(AO_USB_IN_SIZE);
- ao_led_off(AO_LED_TRNG_ACTIVE);
- ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE);
- usb_buf_id = 1-usb_buf_id;
}
}
-static struct ao_task ao_trng_send_task;
+#if AO_POWER_MANAGEMENT
+
+static void ao_trng_suspend(void *arg)
+{
+ (void) arg;
+#ifdef AO_TRNG_ENABLE_PORT
+ ao_gpio_set(AO_TRNG_ENABLE_PORT, AO_TRNG_ENABLE_BIT, AO_TRNG_ENABLE_PIN, 0);
+#endif
+ trng_running = FALSE;
+}
+
+static void ao_trng_resume(void *arg)
+{
+ (void) arg;
+#ifdef AO_TRNG_ENABLE_PORT
+ ao_gpio_set(AO_TRNG_ENABLE_PORT, AO_TRNG_ENABLE_BIT, AO_TRNG_ENABLE_PIN, 1);
+#endif
+ trng_power_time = ao_time();
+}
+
+static struct ao_power ao_trng_power = {
+ .suspend = ao_trng_suspend,
+ .resume = ao_trng_resume
+};
+
+#endif
void
ao_trng_send_init(void)
{
+#ifdef AO_TRNG_ENABLE_PORT
+ ao_enable_output(AO_TRNG_ENABLE_PORT, AO_TRNG_ENABLE_BIT, AO_TRNG_ENABLE_PIN, 0);
+ ao_power_register(&ao_trng_power);
+#endif
+ ao_enable_input(AO_RAW_PORT, AO_RAW_BIT, AO_EXTI_MODE_PULL_UP);
ao_add_task(&ao_trng_send_task, ao_trng_send, "trng_send");
}
diff --git a/src/easymega-v1.0/ao_pins.h b/src/easymega-v1.0/ao_pins.h
index a5e55638..773e58d9 100644
--- a/src/easymega-v1.0/ao_pins.h
+++ b/src/easymega-v1.0/ao_pins.h
@@ -321,6 +321,7 @@ struct ao_adc {
*/
#define HAS_MMA655X 1
+#define AO_MMA655X_INVERT 0
#define AO_MMA655X_SPI_INDEX AO_SPI_1_PB3_PB4_PB5
#define AO_MMA655X_CS_PORT (&stm_gpioc)
#define AO_MMA655X_CS_PIN 12
diff --git a/src/kernel/ao.h b/src/kernel/ao.h
index 59a469ae..6ed0299e 100644
--- a/src/kernel/ao.h
+++ b/src/kernel/ao.h
@@ -124,6 +124,16 @@ ao_timer_init(void);
void
ao_clock_init(void);
+#if AO_POWER_MANAGEMENT
+/* Go to low power clock */
+void
+ao_clock_suspend(void);
+
+/* Restart full-speed clock */
+void
+ao_clock_resume(void);
+#endif
+
/*
* ao_mutex.c
*/
@@ -810,6 +820,8 @@ struct ao_fifo {
} while(0)
#define ao_fifo_full(f) ((((f).insert + 1) & (AO_FIFO_SIZE-1)) == (f).remove)
+#define ao_fifo_mostly(f) ((((f).insert - (f).remove) & (AO_FIFO_SIZE-1)) >= (AO_FIFO_SIZE * 3 / 4))
+#define ao_fifo_barely(f) ((((f).insert - (f).remove) & (AO_FIFO_SIZE-1)) >= (AO_FIFO_SIZE * 1 / 4))
#define ao_fifo_empty(f) ((f).insert == (f).remove)
#if PACKET_HAS_MASTER || PACKET_HAS_SLAVE
diff --git a/src/kernel/ao_config.c b/src/kernel/ao_config.c
index b0d3e541..f95ca893 100644
--- a/src/kernel/ao_config.c
+++ b/src/kernel/ao_config.c
@@ -224,6 +224,12 @@ _ao_config_get(void)
if (minor < 22)
ao_config.aprs_format = AO_CONFIG_DEFAULT_APRS_FORMAT;
#endif
+#if HAS_FIXED_PAD_BOX
+ if (minor < 22)
+ ao_config.pad_box = 1;
+ if (minor < 23)
+ ao_config.pad_idle = 120;
+#endif
ao_config.minor = AO_CONFIG_MINOR;
ao_config_dirty = 1;
}
@@ -899,6 +905,42 @@ ao_config_aprs_format_show(void)
}
#endif /* HAS_APRS */
+#if HAS_FIXED_PAD_BOX
+void
+ao_config_pad_box_show(void)
+{
+ printf ("Pad box: %d\n", ao_config.pad_box);
+}
+
+void
+ao_config_pad_box_set(void)
+{
+ ao_cmd_decimal();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ _ao_config_edit_start();
+ ao_config.pad_box = ao_cmd_lex_i;
+ _ao_config_edit_finish();
+}
+
+void
+ao_config_pad_idle_show(void)
+{
+ printf ("Idle timeout: %d\n", ao_config.pad_idle);
+}
+
+void
+ao_config_pad_idle_set(void)
+{
+ ao_cmd_decimal();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ _ao_config_edit_start();
+ ao_config.pad_idle = ao_cmd_lex_i;
+ _ao_config_edit_finish();
+}
+#endif
+
struct ao_config_var {
__code char *str;
void (*set)(void) __reentrant;
@@ -993,6 +1035,12 @@ __code struct ao_config_var ao_config_vars[] = {
{ "C <0 compressed, 1 uncompressed>\0APRS format",
ao_config_aprs_format_set, ao_config_aprs_format_show },
#endif
+#if HAS_FIXED_PAD_BOX
+ { "B <box>\0Set pad box (1-99)",
+ ao_config_pad_box_set, ao_config_pad_box_show },
+ { "i <seconds>\0Set idle timeout (0 disable)",
+ ao_config_pad_idle_set, ao_config_pad_idle_show },
+#endif
{ "s\0Show",
ao_config_show, 0 },
#if HAS_EEPROM
diff --git a/src/kernel/ao_config.h b/src/kernel/ao_config.h
index cfe8555c..3c73ea49 100644
--- a/src/kernel/ao_config.h
+++ b/src/kernel/ao_config.h
@@ -57,7 +57,7 @@
#endif
#define AO_CONFIG_MAJOR 1
-#define AO_CONFIG_MINOR 22
+#define AO_CONFIG_MINOR 23
#define AO_AES_LEN 16
@@ -118,6 +118,10 @@ struct ao_config {
#if HAS_APRS
uint8_t aprs_format; /* minor version 22 */
#endif
+#if HAS_FIXED_PAD_BOX
+ uint8_t pad_box; /* minor version 22 */
+ uint8_t pad_idle; /* minor version 23 */
+#endif
};
#define AO_APRS_FORMAT_COMPRESSED 0
diff --git a/src/kernel/ao_data.h b/src/kernel/ao_data.h
index 8f75ad87..6ee0965d 100644
--- a/src/kernel/ao_data.h
+++ b/src/kernel/ao_data.h
@@ -269,6 +269,10 @@ typedef int16_t accel_t;
#define AO_ACCEL_INVERT 4095
+#ifndef AO_MMA655X_INVERT
+#error AO_MMA655X_INVERT not defined
+#endif
+
#define ao_data_accel(packet) ((packet)->mma655x)
#if AO_MMA655X_INVERT
#define ao_data_accel_cook(packet) (AO_ACCEL_INVERT - (packet)->mma655x)
diff --git a/src/stm/ao_fast_timer.h b/src/kernel/ao_fast_timer.h
index 90fb3930..90fb3930 100644
--- a/src/stm/ao_fast_timer.h
+++ b/src/kernel/ao_fast_timer.h
diff --git a/src/kernel/ao_flight.c b/src/kernel/ao_flight.c
index 251dbc02..9ba02bb8 100644
--- a/src/kernel/ao_flight.c
+++ b/src/kernel/ao_flight.c
@@ -370,8 +370,10 @@ ao_flight(void)
{
ao_flight_state = ao_flight_landed;
+#if HAS_ADC
/* turn off the ADC capture */
ao_timer_set_adc_interval(0);
+#endif
ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
}
diff --git a/src/kernel/ao_log.h b/src/kernel/ao_log.h
index f86fb359..fdd428c2 100644
--- a/src/kernel/ao_log.h
+++ b/src/kernel/ao_log.h
@@ -49,6 +49,7 @@ extern __pdata enum ao_flight_state ao_log_state;
#define AO_LOG_FORMAT_TELEMINI 8 /* 16-byte MS5607 baro only, 3.3V supply */
#define AO_LOG_FORMAT_TELEGPS 9 /* 32 byte telegps records */
#define AO_LOG_FORMAT_TELEMEGA 10 /* 32 byte typed telemega records with 32 bit gyro cal */
+#define AO_LOG_FORMAT_DETHERM 11 /* 16-byte MS5607 baro only, no ADC */
#define AO_LOG_FORMAT_NONE 127 /* No log at all */
extern __code uint8_t ao_log_format;
diff --git a/src/kernel/ao_log_mini.c b/src/kernel/ao_log_mini.c
index 0ca3ed06..844f38aa 100644
--- a/src/kernel/ao_log_mini.c
+++ b/src/kernel/ao_log_mini.c
@@ -110,9 +110,11 @@ ao_log(void)
ao_data_ring[ao_log_data_pos].ms5607_raw.pres);
ao_log_pack24(log.u.sensor.temp,
ao_data_ring[ao_log_data_pos].ms5607_raw.temp);
+#if AO_LOG_FORMAT != AO_LOG_FORMAT_DETHERM
log.u.sensor.sense_a = ao_data_ring[ao_log_data_pos].adc.sense_a;
log.u.sensor.sense_m = ao_data_ring[ao_log_data_pos].adc.sense_m;
log.u.sensor.v_batt = ao_data_ring[ao_log_data_pos].adc.v_batt;
+#endif
ao_log_mini(&log);
if (ao_log_state <= ao_flight_coast)
next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT;
diff --git a/src/kernel/ao_panic.c b/src/kernel/ao_panic.c
index c29cd8fe..e280f98c 100644
--- a/src/kernel/ao_panic.c
+++ b/src/kernel/ao_panic.c
@@ -38,10 +38,15 @@ ao_panic_delay(uint8_t n)
{
uint8_t i = 0, j = 0;
- while (n--)
+ while (n--) {
+#ifdef AO_PANIC_DELAY_SCALE
+ uint8_t s = AO_PANIC_DELAY_SCALE;
+ while (s--)
+#endif
while (--j)
while (--i)
ao_arch_nop();
+ }
}
void
@@ -56,16 +61,16 @@ ao_panic(uint8_t reason)
ao_arch_block_interrupts();
for (;;) {
ao_panic_delay(20);
+#if HAS_BEEP
for (n = 0; n < 5; n++) {
- ao_led_on(AO_LED_PANIC);
ao_beep(AO_BEEP_HIGH);
ao_panic_delay(1);
- ao_led_off(AO_LED_PANIC);
ao_beep(AO_BEEP_LOW);
ao_panic_delay(1);
}
ao_beep(AO_BEEP_OFF);
ao_panic_delay(2);
+#endif
#ifdef SDCC
#pragma disable_warning 126
diff --git a/src/kernel/ao_power.c b/src/kernel/ao_power.c
new file mode 100644
index 00000000..bead5944
--- /dev/null
+++ b/src/kernel/ao_power.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_power.h>
+
+static struct ao_power *head, *tail;
+
+void
+ao_power_register(struct ao_power *power)
+{
+ if (power->registered)
+ return;
+ power->registered = TRUE;
+ if (tail) {
+ tail->next = power;
+ power->prev = tail;
+ tail = power;
+ } else {
+ head = tail = power;
+ }
+#ifdef AO_LED_POWER
+ ao_led_on(AO_LED_POWER);
+#endif
+}
+
+void
+ao_power_unregister(struct ao_power *power)
+{
+ if (!power->registered)
+ return;
+ power->registered = FALSE;
+ if (power->prev)
+ power->prev->next = power->next;
+ else
+ head = power->next;
+ if (power->next)
+ power->next->prev = power->prev;
+ else
+ tail = power->prev;
+}
+
+void
+ao_power_suspend(void)
+{
+ struct ao_power *p;
+
+#ifdef AO_LED_POWER
+ ao_led_off(AO_LED_POWER);
+#endif
+ for (p = tail; p; p = p->prev)
+ p->suspend(p->arg);
+}
+
+void
+ao_power_resume(void)
+{
+ struct ao_power *p;
+
+ for (p = head; p; p = p->next)
+ p->resume(p->arg);
+#ifdef AO_LED_POWER
+ ao_led_on(AO_LED_POWER);
+#endif
+}
+
diff --git a/src/kernel/ao_power.h b/src/kernel/ao_power.h
new file mode 100644
index 00000000..98a8c1c7
--- /dev/null
+++ b/src/kernel/ao_power.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_POWER_H_
+#define _AO_POWER_H_
+
+#if AO_POWER_MANAGEMENT
+
+struct ao_power {
+ struct ao_power *prev, *next;
+
+ void (*suspend)(void *arg);
+ void (*resume)(void *arg);
+ void *arg;
+ uint8_t registered;
+};
+
+void
+ao_power_register(struct ao_power *power);
+
+void
+ao_power_unregister(struct ao_power *power);
+
+void
+ao_power_suspend(void);
+
+void
+ao_power_resume(void);
+
+#else /* AO_POWER_MANAGEMENT */
+
+#define ao_power_register(power)
+#define ao_power_unregister(power)
+#define ao_power_suspend()
+#define ao_power_resume()
+
+#endif /* else AO_POWER_MANAGEMENT */
+
+#endif /* _AO_POWER_H_ */
diff --git a/src/kernel/ao_product.c b/src/kernel/ao_product.c
index c711a4d2..3a829b3a 100644
--- a/src/kernel/ao_product.c
+++ b/src/kernel/ao_product.c
@@ -33,11 +33,32 @@ const char ao_product[] = AO_iProduct_STRING;
#define AO_USB_MAX_POWER 100
#endif
-#ifndef AO_USB_INTERFACE_CLASS
-#define AO_USB_INTERFACE_CLASS 0x02
+#ifndef AO_USB_SELF_POWER
+#define AO_USB_SELF_POWER 1
+#endif
+
+#define AO_USB_DEVICE_CLASS_COMMUNICATION 0x02
+#define AO_USB_INTERFACE_CLASS_CONTROL_CDC 0x02
+#define AO_USB_INTERFACE_CLASS_DATA_CDC 0x0A
+
+#ifndef AO_USB_DEVICE_CLASS
+#define AO_USB_DEVICE_CLASS AO_USB_DEVICE_CLASS_COMMUNICATION
+#endif
+
+#ifndef AO_USB_INTERFACE_CLASS_DATA
+#define AO_USB_INTERFACE_CLASS_CONTROL AO_USB_INTERFACE_CLASS_CONTROL_CDC
+#define AO_USB_INTERFACE_CLASS_DATA AO_USB_INTERFACE_CLASS_DATA_CDC
#endif
#include "ao_usb.h"
+
+#define HEADER_LEN 9
+#define CONTROL_CLASS_LEN 35
+#define DATA_LEN (9 + 7 * AO_USB_HAS_OUT + 7 * AO_USB_HAS_IN + 7 * AO_USB_HAS_IN2)
+
+#define TOTAL_LENGTH (HEADER_LEN + AO_USB_HAS_INT * CONTROL_CLASS_LEN + DATA_LEN)
+#define NUM_INTERFACES (AO_USB_HAS_INT + 1)
+
/* USB descriptors in one giant block of bytes */
AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] =
{
@@ -45,7 +66,7 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] =
0x12,
AO_USB_DESC_DEVICE,
LE_WORD(0x0110), /* bcdUSB */
- 0x02, /* bDeviceClass */
+ AO_USB_DEVICE_CLASS, /* bDeviceClass */
0x00, /* bDeviceSubClass */
0x00, /* bDeviceProtocol */
AO_USB_CONTROL_SIZE, /* bMaxPacketSize */
@@ -60,20 +81,21 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] =
/* Configuration descriptor */
0x09,
AO_USB_DESC_CONFIGURATION,
- LE_WORD(67), /* wTotalLength */
- 0x02, /* bNumInterfaces */
+ LE_WORD(TOTAL_LENGTH), /* wTotalLength */
+ NUM_INTERFACES, /* bNumInterfaces */
0x01, /* bConfigurationValue */
0x00, /* iConfiguration */
- 0xC0, /* bmAttributes */
+ 0x80 | (AO_USB_SELF_POWER << 6), /* bmAttributes */
AO_USB_MAX_POWER >> 1, /* bMaxPower, 2mA units */
+#if AO_USB_HAS_INT
/* Control class interface */
0x09,
AO_USB_DESC_INTERFACE,
0x00, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x01, /* bNumEndPoints */
- AO_USB_INTERFACE_CLASS, /* bInterfaceClass */
+ AO_USB_INTERFACE_CLASS_CONTROL, /* bInterfaceClass */
0x02, /* bInterfaceSubClass */
0x01, /* bInterfaceProtocol, linux requires value of 1 for the cdc_acm module */
0x00, /* iInterface */
@@ -111,18 +133,20 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] =
0x03, /* bmAttributes = intr */
LE_WORD(8), /* wMaxPacketSize */
0xff, /* bInterval */
+#endif
/* Data class interface descriptor */
0x09,
AO_USB_DESC_INTERFACE,
- 0x01, /* bInterfaceNumber */
- 0x00, /* bAlternateSetting */
- 0x02, /* bNumEndPoints */
- 0x0A, /* bInterfaceClass = data */
- 0x00, /* bInterfaceSubClass */
- 0x00, /* bInterfaceProtocol */
- 0x00, /* iInterface */
-
+ AO_USB_HAS_INT, /* bInterfaceNumber */
+ 0x00, /* bAlternateSetting */
+ AO_USB_HAS_OUT + AO_USB_HAS_IN + AO_USB_HAS_IN2, /* bNumEndPoints */
+ AO_USB_INTERFACE_CLASS_DATA, /* bInterfaceClass = data */
+ 0x00, /* bInterfaceSubClass */
+ 0x00, /* bInterfaceProtocol */
+ 0x00, /* iInterface */
+
+#if AO_USB_HAS_OUT
/* Data EP OUT */
0x07,
AO_USB_DESC_ENDPOINT,
@@ -130,7 +154,9 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] =
0x02, /* bmAttributes = bulk */
LE_WORD(AO_USB_OUT_SIZE),/* wMaxPacketSize */
0x00, /* bInterval */
+#endif
+#if AO_USB_HAS_IN
/* Data EP in */
0x07,
AO_USB_DESC_ENDPOINT,
@@ -138,6 +164,17 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] =
0x02, /* bmAttributes = bulk */
LE_WORD(AO_USB_IN_SIZE),/* wMaxPacketSize */
0x00, /* bInterval */
+#endif
+
+#if AO_USB_HAS_IN2
+ /* Data EP in 2 */
+ 0x07,
+ AO_USB_DESC_ENDPOINT,
+ AO_USB_IN2_EP|0x80, /* bEndpointAddress */
+ 0x02, /* bmAttributes = bulk */
+ LE_WORD(AO_USB_IN_SIZE),/* wMaxPacketSize */
+ 0x00, /* bInterval */
+#endif
/* String descriptors */
0x04,
diff --git a/src/kernel/ao_task.c b/src/kernel/ao_task.c
index 55e423bb..e430edc6 100644
--- a/src/kernel/ao_task.c
+++ b/src/kernel/ao_task.c
@@ -355,7 +355,6 @@ ao_yield(void) ao_arch_naked_define
*/
if (ao_cur_task->wchan == NULL)
ao_task_to_run_queue(ao_cur_task);
- ao_cur_task = NULL;
for (;;) {
ao_arch_memory_barrier();
if (!ao_list_is_empty(&run_queue))
@@ -425,6 +424,7 @@ ao_sleep(__xdata void *wchan)
void
ao_wakeup(__xdata void *wchan) __reentrant
{
+ ao_validate_cur_stack();
#if HAS_TASK_QUEUE
struct ao_task *sleep, *next;
struct ao_list *sleep_queue;
@@ -442,10 +442,12 @@ ao_wakeup(__xdata void *wchan) __reentrant
}
ao_arch_irqrestore(flags);
#else
+ {
uint8_t i;
for (i = 0; i < ao_num_tasks; i++)
if (ao_tasks[i]->wchan == wchan)
ao_tasks[i]->wchan = NULL;
+ }
#endif
ao_check_stack();
}
diff --git a/src/kernel/ao_task.h b/src/kernel/ao_task.h
index c6bec0e3..0e353fe8 100644
--- a/src/kernel/ao_task.h
+++ b/src/kernel/ao_task.h
@@ -56,6 +56,10 @@ extern __data uint8_t ao_num_tasks;
extern __xdata struct ao_task *__data ao_cur_task;
extern __data uint8_t ao_task_minimize_latency; /* Reduce IRQ latency */
+#ifndef HAS_ARCH_VALIDATE_CUR_STACK
+#define ao_validate_cur_stack()
+#endif
+
/*
ao_task.c
*/
diff --git a/src/kernel/ao_usb.h b/src/kernel/ao_usb.h
index 1ce4f82f..8f3e7813 100644
--- a/src/kernel/ao_usb.h
+++ b/src/kernel/ao_usb.h
@@ -105,6 +105,23 @@ extern __code __at (0x00aa) uint8_t ao_usb_descriptors [];
#ifndef AO_USB_OUT_EP
#define AO_USB_OUT_EP 4
#define AO_USB_IN_EP 5
+#define AO_USB_IN2_EP 6
+#endif
+
+#ifndef AO_USB_HAS_OUT
+#define AO_USB_HAS_OUT 1
+#endif
+
+#ifndef AO_USB_HAS_IN
+#define AO_USB_HAS_IN 1
+#endif
+
+#ifndef AO_USB_HAS_INT
+#define AO_USB_HAS_INT 1
+#endif
+
+#ifndef AO_USB_HAS_IN2
+#define AO_USB_HAS_IN2 0
#endif
/*
diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h
index fbe641d8..dbb41538 100644
--- a/src/lpc/ao_arch_funcs.h
+++ b/src/lpc/ao_arch_funcs.h
@@ -227,6 +227,28 @@ ao_spi_duplex(const void *out, void *in, uint16_t len, uint8_t spi_index);
void
ao_spi_init(void);
+static inline void
+ao_spi_send_sync(const void *block, uint16_t len, uint8_t spi_index)
+{
+ ao_spi_send(block, len, spi_index);
+}
+
+static inline void ao_spi_send_byte(uint8_t byte, uint8_t spi_index)
+{
+ struct lpc_ssp *lpc_ssp;
+ switch (spi_index) {
+ case 0:
+ lpc_ssp = &lpc_ssp0;
+ break;
+ case 1:
+ lpc_ssp = &lpc_ssp1;
+ break;
+ }
+ lpc_ssp->dr = byte;
+ while ((lpc_ssp->sr & (1 << LPC_SSP_SR_RNE)) == 0);
+ (void) lpc_ssp->dr;
+}
+
#define ao_spi_init_cs(port, mask) do { \
uint8_t __bit__; \
for (__bit__ = 0; __bit__ < 32; __bit__++) { \
diff --git a/src/lpc/ao_fast_timer_lpc.c b/src/lpc/ao_fast_timer_lpc.c
new file mode 100644
index 00000000..c4f26fc4
--- /dev/null
+++ b/src/lpc/ao_fast_timer_lpc.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_fast_timer.h>
+
+static void (*ao_fast_timer_callback[AO_FAST_TIMER_MAX])(void);
+static uint8_t ao_fast_timer_count;
+static uint8_t ao_fast_timer_users;
+
+static void
+ao_fast_timer_enable(void)
+{
+ lpc_ct16b0.tcr = ((1 << LPC_CT16B_TCR_CEN) |
+ (1 << LPC_CT16B_TCR_CRST));
+}
+
+static void
+ao_fast_timer_disable(void)
+{
+ lpc_ct16b0.tcr = ((0 << LPC_CT16B_TCR_CEN) |
+ (0 << LPC_CT16B_TCR_CRST));
+}
+
+void
+ao_fast_timer_on(void (*callback)(void))
+{
+ ao_fast_timer_callback[ao_fast_timer_count] = callback;
+ if (!ao_fast_timer_count++)
+ ao_fast_timer_enable();
+}
+
+void
+ao_fast_timer_off(void (*callback)(void))
+{
+ uint8_t n;
+
+ for (n = 0; n < ao_fast_timer_count; n++)
+ if (ao_fast_timer_callback[n] == callback) {
+ for (; n < ao_fast_timer_count-1; n++) {
+ ao_fast_timer_callback[n] = ao_fast_timer_callback[n+1];
+ }
+ if (!--ao_fast_timer_count)
+ ao_fast_timer_disable();
+ break;
+ }
+}
+
+void lpc_ct16b0_isr(void)
+{
+ uint32_t v = lpc_ct16b0.ir;
+ int i;
+
+ lpc_ct16b0.ir = v;
+ if (v & (1 << LPC_CT16B_IR_MR0INT)) {
+ for (i = 0; i < ao_fast_timer_count; i++)
+ (*ao_fast_timer_callback[i])();
+ }
+}
+
+#ifndef FAST_TIMER_FREQ
+#define FAST_TIMER_FREQ 10000
+#endif
+
+#define TIMER_FAST (AO_LPC_SYSCLK / FAST_TIMER_FREQ)
+
+void
+ao_fast_timer_init(void)
+{
+ if (!ao_fast_timer_users) {
+
+ lpc_nvic_set_enable(LPC_ISR_CT16B0_POS);
+ lpc_nvic_set_priority(LPC_ISR_CT16B0_POS, AO_LPC_NVIC_CLOCK_PRIORITY);
+ /* Turn on 16-bit timer CT16B0 */
+
+ lpc_scb.sysahbclkctrl |= 1 << LPC_SCB_SYSAHBCLKCTRL_CT16B0;
+
+ /* Disable timer */
+ lpc_ct16b0.tcr = 0;
+
+ /* scale factor 1 */
+ lpc_ct16b0.pr = 0;
+ lpc_ct16b0.pc = 0;
+
+ lpc_ct16b0.mcr = ((1 << LPC_CT16B_MCR_MR0I) |
+ (1 << LPC_CT16B_MCR_MR0R));
+
+ lpc_ct16b0.mr[0] = TIMER_FAST;
+
+ ao_fast_timer_disable();
+ }
+ if (ao_fast_timer_users == AO_FAST_TIMER_MAX)
+ ao_panic(AO_PANIC_FAST_TIMER);
+ ao_fast_timer_users++;
+}
+
diff --git a/src/lpc/ao_timer_lpc.c b/src/lpc/ao_timer_lpc.c
index 44fb410e..623559eb 100644
--- a/src/lpc/ao_timer_lpc.c
+++ b/src/lpc/ao_timer_lpc.c
@@ -99,7 +99,7 @@ ao_clock_init(void)
(1 << LPC_SCB_SYSAHBCLKCTRL_FLASHARRAY) |
(1 << LPC_SCB_SYSAHBCLKCTRL_GPIO) |
(1 << LPC_SCB_SYSAHBCLKCTRL_IOCON));
-
+
/* Enable the brown-out detection at the highest voltage to
* make sure the flash part remains happy
*/
@@ -112,21 +112,21 @@ ao_clock_init(void)
/* Turn the IRC clock back on */
lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_IRC_PD);
ao_clock_delay();
-
+
/* Switch to the IRC clock */
lpc_scb.mainclksel = LPC_SCB_MAINCLKSEL_SEL_IRC << LPC_SCB_MAINCLKSEL_SEL;
lpc_scb.mainclkuen = (0 << LPC_SCB_MAINCLKUEN_ENA);
lpc_scb.mainclkuen = (1 << LPC_SCB_MAINCLKUEN_ENA);
while (!(lpc_scb.mainclkuen & (1 << LPC_SCB_MAINCLKUEN_ENA)))
;
-
+
/* Switch USB to the main clock */
lpc_scb.usbclksel = (LPC_SCB_USBCLKSEL_SEL_MAIN_CLOCK << LPC_SCB_USBCLKSEL_SEL);
lpc_scb.usbclkuen = (0 << LPC_SCB_USBCLKUEN_ENA);
lpc_scb.usbclkuen = (1 << LPC_SCB_USBCLKUEN_ENA);
while (!(lpc_scb.usbclkuen & (1 << LPC_SCB_USBCLKUEN_ENA)))
;
-
+
/* Find a PLL post divider ratio that gets the FCCO in range */
for (p = 0; p < 4; p++)
if (AO_LPC_CLKOUT << (1 + p) >= AO_LPC_FCCO_MIN)
@@ -163,12 +163,12 @@ ao_clock_init(void)
lpc_scb.syspllclkuen = (1 << LPC_SCB_SYSPLLCLKUEN_ENA);
while (!(lpc_scb.syspllclkuen & (1 << LPC_SCB_SYSPLLCLKUEN_ENA)))
;
-
+
/* Turn on the PLL */
lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_SYSPLL_PD);
/* Wait for it to lock */
-
+
for (i = 0; i < 20000; i++)
if (lpc_scb.syspllstat & (1 << LPC_SCB_SYSPLLSTAT_LOCK))
break;
@@ -199,7 +199,7 @@ ao_clock_init(void)
lpc_scb.usbpllclkuen = (1 << LPC_SCB_USBPLLCLKUEN_ENA);
while (!(lpc_scb.usbpllclkuen & (1 << LPC_SCB_USBPLLCLKUEN_ENA)))
;
-
+
/* Power down everything we don't need */
lpc_scb.pdruncfg = ((1 << LPC_SCB_PDRUNCFG_IRCOUT_PD) |
(1 << LPC_SCB_PDRUNCFG_IRC_PD) |
diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h
index 9408ceab..40d412d0 100644
--- a/src/lpc/lpc.h
+++ b/src/lpc/lpc.h
@@ -411,7 +411,7 @@ struct lpc_scb {
vuint32_t mainclksel; /* 0x70 */
vuint32_t mainclkuen;
vuint32_t sysahbclkdiv;
- uint32_t r7c;
+ uint32_t r7c;
vuint32_t sysahbclkctrl; /* 0x80 */
uint32_t r84[3];
@@ -429,14 +429,14 @@ struct lpc_scb {
uint32_t rcc;
uint32_t rd0[4];
-
+
vuint32_t clkoutsel; /* 0xe0 */
vuint32_t clkoutuen;
vuint32_t clkoutdiv;
uint32_t rec;
-
+
uint32_t rf0[4]; /* 0xf0 */
-
+
vuint32_t pioporcap0; /* 0x100 */
vuint32_t pioporcap1;
uint32_t r102[2];
@@ -445,7 +445,7 @@ struct lpc_scb {
uint32_t r120[4]; /* 0x120 */
uint32_t r130[4]; /* 0x130 */
uint32_t r140[4]; /* 0x140 */
-
+
vuint32_t bodctrl; /* 0x150 */
vuint32_t systckcal;
uint32_t r158[2];
@@ -479,7 +479,7 @@ struct lpc_scb {
uint32_t r240[12 * 4]; /* 0x240 */
uint32_t r300[15 * 4]; /* 0x300 */
-
+
uint32_t r3f0; /* 0x3f0 */
vuint32_t device_id;
};
@@ -680,7 +680,7 @@ struct lpc_gpio {
vuint32_t word[0x40]; /* 0x1000 */
uint8_t r1100[0x2000 - 0x1100];
-
+
vuint32_t dir[2]; /* 0x2000 */
uint8_t r2008[0x2080 - 0x2008];
@@ -1032,7 +1032,7 @@ lpc_nvic_enabled(int irq) {
return (lpc_nvic.iser >> irq) & 1;
}
-
+
static inline void
lpc_nvic_set_pending(int irq) {
lpc_nvic.ispr = (1 << irq);
@@ -1201,18 +1201,118 @@ extern struct lpc_adc lpc_adc;
#define LPC_ADC_STAT_OVERRUN 8
#define LPC_ADC_STAT_ADINT 16
+struct lpc_ct16b {
+ vuint32_t ir; /* 0x00 */
+ vuint32_t tcr;
+ vuint32_t tc;
+ vuint32_t pr;
+
+ vuint32_t pc; /* 0x10 */
+ vuint32_t mcr;
+ vuint32_t mr[4]; /* 0x18 */
+ vuint32_t ccr; /* 0x28 */
+ vuint32_t cr0;
+
+ vuint32_t cr1_0; /* 0x30 (only for ct16b0 */
+ vuint32_t cr1_1; /* 0x34 (only for ct16b1 */
+ uint32_t r38;
+ vuint32_t emr;
+
+ uint8_t r40[0x70 - 0x40];
+
+ vuint32_t ctcr; /* 0x70 */
+ vuint32_t pwmc;
+};
+
+extern struct lpc_ct16b lpc_ct16b0, lpc_ct16b1;
+
+#define lpc_ct16b0 (*(struct lpc_ct16b *) 0x4000c000)
+#define lpc_ct16b1 (*(struct lpc_ct16b *) 0x40010000)
+
+#define LPC_CT16B_IR_MR0INT 0
+#define LPC_CT16B_IR_MR1INT 1
+#define LPC_CT16B_IR_MR2INT 2
+#define LPC_CT16B_IR_MR3INT 3
+#define LPC_CT16B_IR_CR0INT 4
+#define LPC_CT16B0_IR_CR1INT 6
+#define LPC_CT16B1_IR_CR1INT 5
+
+#define LPC_CT16B_TCR_CEN 0
+#define LPC_CT16B_TCR_CRST 1
+
+#define LPC_CT16B_MCR_MR0I 0
+#define LPC_CT16B_MCR_MR0R 1
+#define LPC_CT16B_MCR_MR0S 2
+#define LPC_CT16B_MCR_MR1I 3
+#define LPC_CT16B_MCR_MR1R 4
+#define LPC_CT16B_MCR_MR1S 5
+#define LPC_CT16B_MCR_MR2I 6
+#define LPC_CT16B_MCR_MR2R 7
+#define LPC_CT16B_MCR_MR2S 8
+#define LPC_CT16B_MCR_MR3I 9
+#define LPC_CT16B_MCR_MR3R 10
+#define LPC_CT16B_MCR_MR3S 11
+
+#define LPC_CT16B_CCR_CAP0RE 0
+#define LPC_CT16B_CCR_CAP0FE 1
+#define LPC_CT16B_CCR_CAP0I 2
+#define LPC_CT16B0_CCR_CAP1RE 6
+#define LPC_CT16B0_CCR_CAP1FE 7
+#define LPC_CT16B0_CCR_CAP1I 8
+#define LPC_CT16B1_CCR_CAP1RE 3
+#define LPC_CT16B1_CCR_CAP1FE 4
+#define LPC_CT16B1_CCR_CAP1I 5
+
+#define LPC_CT16B_EMR_EM0 0
+#define LPC_CT16B_EMR_EM1 1
+#define LPC_CT16B_EMR_EM2 2
+#define LPC_CT16B_EMR_EM3 3
+#define LPC_CT16B_EMR_EMC0 4
+#define LPC_CT16B_EMR_EMC1 6
+#define LPC_CT16B_EMR_EMC2 8
+#define LPC_CT16B_EMR_EMC3 10
+
+#define LPC_CT16B_EMR_EMC_NOTHING 0
+#define LPC_CT16B_EMR_EMC_CLEAR 1
+#define LPC_CT16B_EMR_EMC_SET 2
+#define LPC_CT16B_EMR_EMC_TOGGLE 3
+
+#define LPC_CT16B_CCR_CTM 0
+#define LPC_CT16B_CCR_CTM_TIMER 0
+#define LPC_CT16B_CCR_CTM_COUNTER_RISING 1
+#define LPC_CT16B_CCR_CTM_COUNTER_FALLING 2
+#define LPC_CT16B_CCR_CTM_COUNTER_BOTH 3
+#define LPC_CT16B_CCR_CIS 2
+#define LPC_CT16B_CCR_CIS_CAP0 0
+#define LPC_CT16B0_CCR_CIS_CAP1 2
+#define LPC_CT16B1_CCR_CIS_CAP1 1
+#define LPC_CT16B_CCR_ENCC 4
+#define LPC_CT16B_CCR_SELCC 5
+#define LPC_CT16B_CCR_SELCC_RISING_CAP0 0
+#define LPC_CT16B_CCR_SELCC_FALLING_CAP0 1
+#define LPC_CT16B0_CCR_SELCC_RISING_CAP1 4
+#define LPC_CT16B0_CCR_SELCC_FALLING_CAP1 5
+#define LPC_CT16B1_CCR_SELCC_RISING_CAP1 2
+#define LPC_CT16B1_CCR_SELCC_FALLING_CAP1 3
+#define LPC_CT16B_CCR_
+
+#define LPC_CT16B_PWMC_PWMEN0 0
+#define LPC_CT16B_PWMC_PWMEN1 1
+#define LPC_CT16B_PWMC_PWMEN2 2
+#define LPC_CT16B_PWMC_PWMEN3 3
+
struct lpc_ct32b {
vuint32_t ir; /* 0x00 */
vuint32_t tcr;
vuint32_t tc;
vuint32_t pr;
-
+
vuint32_t pc; /* 0x10 */
vuint32_t mcr;
vuint32_t mr[4]; /* 0x18 */
vuint32_t ccr; /* 0x28 */
vuint32_t cr0;
-
+
vuint32_t cr1_0; /* 0x30 (only for ct32b0 */
vuint32_t cr1_1; /* 0x34 (only for ct32b1 */
uint32_t r38;
diff --git a/src/lpc/registers.ld b/src/lpc/registers.ld
index a523c39c..61dd9e70 100644
--- a/src/lpc/registers.ld
+++ b/src/lpc/registers.ld
@@ -1,6 +1,8 @@
lpc_usb_sram = 0x20004000;
lpc_usb_endpoint = 0x20004700;
lpc_usart = 0x40008000;
+lpc_ct16b0 = 0x4000c000;
+lpc_ct16b1 = 0x40010000;
lpc_ct32b0 = 0x40014000;
lpc_ct32b1 = 0x40018000;
lpc_adc = 0x4001c000;
diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h
index a6276c5a..f9508b8f 100644
--- a/src/stm/ao_arch.h
+++ b/src/stm/ao_arch.h
@@ -25,7 +25,9 @@
* STM32L definitions and code fragments for AltOS
*/
+#ifndef AO_STACK_SIZE
#define AO_STACK_SIZE 512
+#endif
#define AO_LED_TYPE uint16_t
diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h
index 42f1a2e5..2c017c79 100644
--- a/src/stm/ao_arch_funcs.h
+++ b/src/stm/ao_arch_funcs.h
@@ -82,6 +82,34 @@ ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index);
void
ao_spi_send_sync(void *block, uint16_t len, uint8_t spi_index);
+static inline void
+ao_spi_send_byte(uint8_t byte, uint8_t spi_index)
+{
+ struct stm_spi *stm_spi;
+
+ switch (AO_SPI_INDEX(spi_index)) {
+ case 0:
+ stm_spi = &stm_spi1;
+ break;
+ case 1:
+ stm_spi = &stm_spi2;
+ break;
+ }
+
+ stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
+ (0 << STM_SPI_CR2_RXNEIE) |
+ (0 << STM_SPI_CR2_ERRIE) |
+ (0 << STM_SPI_CR2_SSOE) |
+ (0 << STM_SPI_CR2_TXDMAEN) |
+ (0 << STM_SPI_CR2_RXDMAEN));
+
+ /* Clear RXNE */
+ (void) stm_spi->dr;
+
+ while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE)));
+ stm_spi->dr = byte;
+}
+
void
ao_spi_recv(void *block, uint16_t len, uint8_t spi_index);
@@ -149,6 +177,11 @@ ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t s
#define ao_gpio_get(port, bit, pin) stm_gpio_get(port, bit)
+#define ao_gpio_set_bits(port, bits) stm_gpio_set_bits(port, bits)
+
+#define ao_gpio_clr_bits(port, bits) stm_gpio_clr_bits(port, bits);
+
+
#define ao_enable_output(port,bit,pin,v) do { \
ao_enable_port(port); \
ao_gpio_set(port, bit, pin, v); \
@@ -245,12 +278,35 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t i2c_index, uint8_t stop);
void
ao_i2c_init(void);
+#if USE_SERIAL_1_SW_FLOW || USE_SERIAL_2_SW_FLOW || USE_SERIAL_3_SW_FLOW
+#define HAS_SERIAL_SW_FLOW 1
+#else
+#define HAS_SERIAL_SW_FLOW 0
+#endif
+
+#if USE_SERIAL_1_FLOW && !USE_SERIAL_1_SW_FLOW || USE_SERIAL_2_FLOW && !USE_SERIAL_2_SW_FLOW || USE_SERIAL_3_FLOW && !USE_SERIAL_3_SW_FLOW
+#define HAS_SERIAL_HW_FLOW 1
+#else
+#define HAS_SERIAL_HW_FLOW 0
+#endif
+
/* ao_serial_stm.c */
struct ao_stm_usart {
struct ao_fifo rx_fifo;
struct ao_fifo tx_fifo;
struct stm_usart *reg;
- uint8_t tx_started;
+ uint8_t tx_running;
+ uint8_t draining;
+#if HAS_SERIAL_SW_FLOW
+ /* RTS - 0 if we have FIFO space, 1 if not
+ * CTS - 0 if we can send, 0 if not
+ */
+ struct stm_gpio *gpio_rts;
+ struct stm_gpio *gpio_cts;
+ uint8_t pin_rts;
+ uint8_t pin_cts;
+ uint8_t rts;
+#endif
};
#if HAS_SERIAL_1
@@ -359,6 +415,22 @@ static inline void ao_arch_restore_stack(void) {
#define HAS_SAMPLE_PROFILE 0
#endif
+#if DEBUG
+#define HAS_ARCH_VALIDATE_CUR_STACK 1
+
+static inline void
+ao_validate_cur_stack(void)
+{
+ uint8_t *psp;
+
+ asm("mrs %0,psp" : "=&r" (psp));
+ if (ao_cur_task &&
+ psp <= ao_cur_task->stack &&
+ psp >= ao_cur_task->stack - 256)
+ ao_panic(AO_PANIC_STACK);
+}
+#endif
+
#if !HAS_SAMPLE_PROFILE
#define HAS_ARCH_START_SCHEDULER 1
diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c
index 88f2d029..bf079060 100644
--- a/src/stm/ao_serial_stm.c
+++ b/src/stm/ao_serial_stm.c
@@ -16,6 +16,7 @@
*/
#include <ao.h>
+#include <ao_exti.h>
void
ao_debug_out(char c)
@@ -26,40 +27,80 @@ ao_debug_out(char c)
stm_usart1.dr = c;
}
-static void
+static int
_ao_usart_tx_start(struct ao_stm_usart *usart)
{
- if (!ao_fifo_empty(usart->tx_fifo) && !usart->tx_started)
- {
- usart->tx_started = 1;
- ao_fifo_remove(usart->tx_fifo, usart->reg->dr);
+ if (!ao_fifo_empty(usart->tx_fifo)) {
+#if HAS_SERIAL_SW_FLOW
+ if (usart->gpio_cts && ao_gpio_get(usart->gpio_cts, usart->pin_cts, foo) == 1) {
+ ao_exti_enable(usart->gpio_cts, usart->pin_cts);
+ return 0;
+ }
+#endif
+ if (usart->reg->sr & (1 << STM_USART_SR_TXE))
+ {
+ usart->tx_running = 1;
+ usart->reg->cr1 |= (1 << STM_USART_CR1_TXEIE) | (1 << STM_USART_CR1_TCIE);
+ ao_fifo_remove(usart->tx_fifo, usart->reg->dr);
+ ao_wakeup(&usart->tx_fifo);
+ return 1;
+ }
}
+ return 0;
}
+#if HAS_SERIAL_SW_FLOW
static void
-ao_usart_isr(struct ao_stm_usart *usart, int stdin)
+_ao_usart_cts(struct ao_stm_usart *usart)
{
- uint32_t sr;
-
- sr = usart->reg->sr;
- usart->reg->sr = 0;
+ if (_ao_usart_tx_start(usart))
+ ao_exti_disable(usart->gpio_cts, usart->pin_cts);
+}
+#endif
- if (sr & (1 << STM_USART_SR_RXNE)) {
- char c = usart->reg->dr;
- if (!ao_fifo_full(usart->rx_fifo))
- ao_fifo_insert(usart->rx_fifo, c);
- ao_wakeup(&usart->rx_fifo);
- if (stdin)
- ao_wakeup(&ao_stdin_ready);
+static void
+_ao_usart_rx(struct ao_stm_usart *usart, int stdin)
+{
+ if (usart->reg->sr & (1 << STM_USART_SR_RXNE)) {
+ if (!ao_fifo_full(usart->rx_fifo)) {
+ ao_fifo_insert(usart->rx_fifo, usart->reg->dr);
+ ao_wakeup(&usart->rx_fifo);
+ if (stdin)
+ ao_wakeup(&ao_stdin_ready);
+#if HAS_SERIAL_SW_FLOW
+ /* If the fifo is nearly full, turn off RTS and wait
+ * for it to drain a bunch
+ */
+ if (usart->gpio_rts && ao_fifo_mostly(usart->rx_fifo)) {
+ ao_gpio_set(usart->gpio_rts, usart->pin_rts, usart->pin_rts, 1);
+ usart->rts = 0;
+ }
+#endif
+ } else {
+ usart->reg->cr1 &= ~(1 << STM_USART_CR1_RXNEIE);
+ }
}
- if (sr & (1 << STM_USART_SR_TC)) {
- usart->tx_started = 0;
- _ao_usart_tx_start(usart);
- ao_wakeup(&usart->tx_fifo);
+}
+
+static void
+ao_usart_isr(struct ao_stm_usart *usart, int stdin)
+{
+ _ao_usart_rx(usart, stdin);
+
+ if (!_ao_usart_tx_start(usart))
+ usart->reg->cr1 &= ~(1<< STM_USART_CR1_TXEIE);
+
+ if (usart->reg->sr & (1 << STM_USART_SR_TC)) {
+ usart->tx_running = 0;
+ usart->reg->cr1 &= ~(1 << STM_USART_CR1_TCIE);
+ if (usart->draining) {
+ usart->draining = 0;
+ ao_wakeup(&usart->tx_fifo);
+ }
}
}
-int
+static int
_ao_usart_pollchar(struct ao_stm_usart *usart)
{
int c;
@@ -69,12 +110,23 @@ _ao_usart_pollchar(struct ao_stm_usart *usart)
else {
uint8_t u;
ao_fifo_remove(usart->rx_fifo,u);
+ if ((usart->reg->cr1 & (1 << STM_USART_CR1_RXNEIE)) == 0) {
+ if (ao_fifo_barely(usart->rx_fifo))
+ usart->reg->cr1 |= (1 << STM_USART_CR1_RXNEIE);
+ }
+#if HAS_SERIAL_SW_FLOW
+ /* If we've cleared RTS, check if there's space now and turn it back on */
+ if (usart->gpio_rts && usart->rts == 0 && ao_fifo_barely(usart->rx_fifo)) {
+ ao_gpio_set(usart->gpio_rts, usart->pin_rts, foo, 0);
+ usart->rts = 1;
+ }
+#endif
c = u;
}
return c;
}
-char
+static char
ao_usart_getchar(struct ao_stm_usart *usart)
{
int c;
@@ -91,7 +143,7 @@ _ao_usart_sleep_for(struct ao_stm_usart *usart, uint16_t timeout)
return ao_sleep_for(&usart->rx_fifo, timeout);
}
-void
+static void
ao_usart_putchar(struct ao_stm_usart *usart, char c)
{
ao_arch_block_interrupts();
@@ -102,12 +154,14 @@ ao_usart_putchar(struct ao_stm_usart *usart, char c)
ao_arch_release_interrupts();
}
-void
+static void
ao_usart_drain(struct ao_stm_usart *usart)
{
ao_arch_block_interrupts();
- while (!ao_fifo_empty(usart->tx_fifo))
+ while (!ao_fifo_empty(usart->tx_fifo) || usart->tx_running) {
+ usart->draining = 1;
ao_sleep(&usart->tx_fifo);
+ }
ao_arch_release_interrupts();
}
@@ -131,7 +185,7 @@ static const struct {
},
};
-void
+static void
ao_usart_set_speed(struct ao_stm_usart *usart, uint8_t speed)
{
if (speed > AO_SERIAL_SPEED_115200)
@@ -139,7 +193,7 @@ ao_usart_set_speed(struct ao_stm_usart *usart, uint8_t speed)
usart->reg->brr = ao_usart_speeds[speed].brr;
}
-void
+static void
ao_usart_init(struct ao_stm_usart *usart)
{
usart->reg->cr1 = ((0 << STM_USART_CR1_OVER8) |
@@ -150,7 +204,7 @@ ao_usart_init(struct ao_stm_usart *usart)
(0 << STM_USART_CR1_PS) |
(0 << STM_USART_CR1_PEIE) |
(0 << STM_USART_CR1_TXEIE) |
- (1 << STM_USART_CR1_TCIE) |
+ (0 << STM_USART_CR1_TCIE) |
(1 << STM_USART_CR1_RXNEIE) |
(0 << STM_USART_CR1_IDLEIE) |
(1 << STM_USART_CR1_TE) |
@@ -185,12 +239,14 @@ ao_usart_init(struct ao_stm_usart *usart)
ao_usart_set_speed(usart, AO_SERIAL_SPEED_9600);
}
-void
+#if HAS_SERIAL_HW_FLOW
+static void
ao_usart_set_flow(struct ao_stm_usart *usart)
{
usart->reg->cr3 |= ((1 << STM_USART_CR3_CTSE) |
(1 << STM_USART_CR3_RTSE));
}
+#endif
#if HAS_SERIAL_1
@@ -231,6 +287,7 @@ ao_serial1_drain(void)
void
ao_serial1_set_speed(uint8_t speed)
{
+ ao_usart_drain(&ao_stm_usart1);
ao_usart_set_speed(&ao_stm_usart1, speed);
}
#endif /* HAS_SERIAL_1 */
@@ -274,15 +331,25 @@ ao_serial2_drain(void)
void
ao_serial2_set_speed(uint8_t speed)
{
+ ao_usart_drain(&ao_stm_usart2);
ao_usart_set_speed(&ao_stm_usart2, speed);
}
+
+#if HAS_SERIAL_SW_FLOW
+void
+ao_serial2_cts(void)
+{
+ _ao_usart_cts(&ao_stm_usart2);
+}
+#endif
+
#endif /* HAS_SERIAL_2 */
#if HAS_SERIAL_3
struct ao_stm_usart ao_stm_usart3;
-void stm_usart3_isr(void) { ao_usart_isr(&ao_stm_usart3, USE_SERIAL_2_STDIN); }
+void stm_usart3_isr(void) { ao_usart_isr(&ao_stm_usart3, USE_SERIAL_3_STDIN); }
char
ao_serial3_getchar(void)
@@ -311,10 +378,39 @@ _ao_serial3_sleep_for(uint16_t timeout)
void
ao_serial3_set_speed(uint8_t speed)
{
+ ao_usart_drain(&ao_stm_usart3);
ao_usart_set_speed(&ao_stm_usart3, speed);
}
+
+void
+ao_serial3_drain(void)
+{
+ ao_usart_drain(&ao_stm_usart3);
+}
#endif /* HAS_SERIAL_3 */
+#if HAS_SERIAL_SW_FLOW
+static void
+ao_serial_set_sw_rts_cts(struct ao_stm_usart *usart,
+ void (*isr)(void),
+ struct stm_gpio *port_rts,
+ int pin_rts,
+ struct stm_gpio *port_cts,
+ int pin_cts)
+{
+ /* Pull RTS low to note that there's space in the FIFO
+ */
+ ao_enable_output(port_rts, pin_rts, foo, 0);
+ usart->gpio_rts = port_rts;
+ usart->pin_rts = pin_rts;
+ usart->rts = 1;
+
+ ao_exti_setup(port_cts, pin_cts, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED, isr);
+ usart->gpio_cts = port_cts;
+ usart->pin_cts = pin_cts;
+}
+#endif
+
void
ao_serial_init(void)
{
@@ -367,10 +463,19 @@ ao_serial_init(void)
stm_afr_set(&stm_gpioa, 2, STM_AFR_AF7);
stm_afr_set(&stm_gpioa, 3, STM_AFR_AF7);
-#if USE_SERIAL_2_FLOW
+# if USE_SERIAL_2_FLOW
+# if USE_SERIAL_2_SW_FLOW
+ ao_serial_set_sw_rts_cts(&ao_stm_usart2,
+ ao_serial2_cts,
+ SERIAL_2_PORT_RTS,
+ SERIAL_2_PIN_RTS,
+ SERIAL_2_PORT_CTS,
+ SERIAL_2_PIN_CTS);
+# else
stm_afr_set(&stm_gpioa, 0, STM_AFR_AF7);
stm_afr_set(&stm_gpioa, 1, STM_AFR_AF7);
-#endif
+# endif
+# endif
#else
#if SERIAL_2_PD5_PD6
stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN);
@@ -389,7 +494,7 @@ ao_serial_init(void)
ao_stm_usart2.reg = &stm_usart2;
ao_usart_init(&ao_stm_usart2);
-#if USE_SERIAL_2_FLOW
+#if USE_SERIAL_2_FLOW && !USE_SERIAL_2_SW_FLOW
ao_usart_set_flow(&ao_stm_usart2);
#endif
diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c
index 8db62e76..91ede84b 100644
--- a/src/stm/ao_timer.c
+++ b/src/stm/ao_timer.c
@@ -41,6 +41,7 @@ volatile __data uint8_t ao_data_count;
void stm_systick_isr(void)
{
+ ao_validate_cur_stack();
if (stm_systick.csr & (1 << STM_SYSTICK_CSR_COUNTFLAG)) {
++ao_tick_count;
#if HAS_TASK_QUEUE
diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h
index 01afedc6..0b6b2798 100644
--- a/src/stm/stm32l.h
+++ b/src/stm/stm32l.h
@@ -166,6 +166,16 @@ stm_gpio_set(struct stm_gpio *gpio, int pin, uint8_t value) {
gpio->bsrr = ((uint32_t) (value ^ 1) << (pin + 16)) | ((uint32_t) value << pin);
}
+static inline void
+stm_gpio_set_bits(struct stm_gpio *gpio, uint16_t bits) {
+ gpio->bsrr = bits;
+}
+
+static inline void
+stm_gpio_clr_bits(struct stm_gpio *gpio, uint16_t bits) {
+ gpio->bsrr = ((uint32_t) bits) << 16;
+}
+
static inline uint8_t
stm_gpio_get(struct stm_gpio *gpio, int pin) {
return (gpio->idr >> pin) & 1;
diff --git a/src/stmf0/Makefile-flash.defs b/src/stmf0/Makefile-flash.defs
index 706b93ee..29d6ae45 100644
--- a/src/stmf0/Makefile-flash.defs
+++ b/src/stmf0/Makefile-flash.defs
@@ -39,17 +39,24 @@ LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stmf0 -Wl,-Taltos-loader.ld
PROGNAME=altos-flash
PROG=$(HARDWARE)-$(PROGNAME)-$(VERSION).elf
+BIN=$(HARDWARE)-$(PROGNAME)-$(VERSION).bin
+
+MAKEBIN=$(TOPDIR)/../ao-tools/ao-makebin/ao-makebin
+FLASH_ADDR=0x08000000
+
+all: $(PROG) $(BIN)
$(PROG): Makefile $(OBJ) altos-loader.ld
$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+$(BIN): $(PROG)
+ $(MAKEBIN) --output=$@ --base=$(FLASH_ADDR) $(PROG)
+
ao_product.h: ao-make-product.5c $(TOPDIR)/Version
$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
$(OBJ): $(INC)
-all: $(PROG)
-
distclean: clean
clean:
diff --git a/src/stmf0/ao_adc_fast.c b/src/stmf0/ao_adc_fast.c
index 26e6691c..0a2e2c5c 100644
--- a/src/stmf0/ao_adc_fast.c
+++ b/src/stmf0/ao_adc_fast.c
@@ -72,7 +72,9 @@ _ao_adc_start(void)
(1 << STM_DMA_CCR_MINC) |
(0 << STM_DMA_CCR_PINC) |
(0 << STM_DMA_CCR_CIRC) |
- (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR));
+ (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR) |
+ (1 << STM_DMA_CCR_TCIE));
+
ao_dma_set_isr(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1), ao_adc_dma_done);
ao_dma_start(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1));
@@ -83,7 +85,6 @@ void
ao_adc_init(void)
{
uint32_t chselr;
- int i;
/* Reset ADC */
stm_rcc.apb2rstr |= (1 << STM_RCC_APB2RSTR_ADCRST);
@@ -157,12 +158,13 @@ ao_adc_init(void)
/* Shortest sample time */
stm_adc.smpr = STM_ADC_SMPR_SMP_1_5 << STM_ADC_SMPR_SMP;
+ /* Turn off enable and start */
+ stm_adc.cr &= ~((1 << STM_ADC_CR_ADEN) | (1 << STM_ADC_CR_ADSTART));
+
/* Calibrate */
stm_adc.cr |= (1 << STM_ADC_CR_ADCAL);
- for (i = 0; i < 0xf000; i++) {
- if ((stm_adc.cr & (1 << STM_ADC_CR_ADCAL)) == 0)
- break;
- }
+ while ((stm_adc.cr & (1 << STM_ADC_CR_ADCAL)) != 0)
+ ;
/* Enable */
stm_adc.cr |= (1 << STM_ADC_CR_ADEN);
diff --git a/src/stmf0/ao_arch.h b/src/stmf0/ao_arch.h
index 6ee71ef9..2597cadc 100644
--- a/src/stmf0/ao_arch.h
+++ b/src/stmf0/ao_arch.h
@@ -25,7 +25,9 @@
* STM32F0 definitions and code fragments for AltOS
*/
+#ifndef AO_STACK_SIZE
#define AO_STACK_SIZE 512
+#endif
#define AO_LED_TYPE uint16_t
@@ -115,6 +117,7 @@ extern const uint32_t ao_radio_cal;
#define AO_PCLK1 (AO_HCLK / AO_APB1_PRESCALER)
#define AO_PCLK2 (AO_HCLK / AO_APB2_PRESCALER)
#define AO_SYSTICK (AO_HCLK)
+#define AO_PANIC_DELAY_SCALE (AO_SYSCLK / 12000000)
#if AO_APB1_PRESCALER == 1
#define AO_TIM23467_CLK AO_PCLK1
@@ -128,10 +131,10 @@ extern const uint32_t ao_radio_cal;
#define AO_TIM91011_CLK (2 * AO_PCLK2)
#endif
-#define AO_STM_NVIC_HIGH_PRIORITY 4
-#define AO_STM_NVIC_CLOCK_PRIORITY 6
-#define AO_STM_NVIC_MED_PRIORITY 8
-#define AO_STM_NVIC_LOW_PRIORITY 10
+#define AO_STM_NVIC_HIGH_PRIORITY (0 << 6)
+#define AO_STM_NVIC_CLOCK_PRIORITY (1 << 6)
+#define AO_STM_NVIC_MED_PRIORITY (2 << 6)
+#define AO_STM_NVIC_LOW_PRIORITY (3 << 6)
void ao_lcd_stm_init(void);
diff --git a/src/stmf0/ao_arch_funcs.h b/src/stmf0/ao_arch_funcs.h
index 3db96be2..ccfa3fc7 100644
--- a/src/stmf0/ao_arch_funcs.h
+++ b/src/stmf0/ao_arch_funcs.h
@@ -18,25 +18,27 @@
#ifndef _AO_ARCH_FUNCS_H_
#define _AO_ARCH_FUNCS_H_
+#include <ao_power.h>
+
/* ao_spi_stm.c
*/
-/* PCLK is set to 16MHz (HCLK 32MHz, APB prescaler 2) */
+/* PCLK is set to 48MHz (HCLK 48MHz, HPRE 1, PPRE 1) */
-#define AO_SPI_SPEED_8MHz STM_SPI_CR1_BR_PCLK_2
-#define AO_SPI_SPEED_4MHz STM_SPI_CR1_BR_PCLK_4
-#define AO_SPI_SPEED_2MHz STM_SPI_CR1_BR_PCLK_8
-#define AO_SPI_SPEED_1MHz STM_SPI_CR1_BR_PCLK_16
-#define AO_SPI_SPEED_500kHz STM_SPI_CR1_BR_PCLK_32
-#define AO_SPI_SPEED_250kHz STM_SPI_CR1_BR_PCLK_64
-#define AO_SPI_SPEED_125kHz STM_SPI_CR1_BR_PCLK_128
-#define AO_SPI_SPEED_62500Hz STM_SPI_CR1_BR_PCLK_256
+#define AO_SPI_SPEED_24MHz STM_SPI_CR1_BR_PCLK_2
+#define AO_SPI_SPEED_12MHz STM_SPI_CR1_BR_PCLK_4
+#define AO_SPI_SPEED_6MHz STM_SPI_CR1_BR_PCLK_8
+#define AO_SPI_SPEED_3MHz STM_SPI_CR1_BR_PCLK_16
+#define AO_SPI_SPEED_1500kHz STM_SPI_CR1_BR_PCLK_32
+#define AO_SPI_SPEED_750kHz STM_SPI_CR1_BR_PCLK_64
+#define AO_SPI_SPEED_375kHz STM_SPI_CR1_BR_PCLK_128
+#define AO_SPI_SPEED_187500Hz STM_SPI_CR1_BR_PCLK_256
-#define AO_SPI_SPEED_FAST AO_SPI_SPEED_8MHz
+#define AO_SPI_SPEED_FAST AO_SPI_SPEED_24MHz
/* Companion bus wants something no faster than 200kHz */
-#define AO_SPI_SPEED_200kHz AO_SPI_SPEED_125kHz
+#define AO_SPI_SPEED_200kHz AO_SPI_SPEED_187500Hz
#define AO_SPI_CONFIG_1 0x00
#define AO_SPI_1_CONFIG_PA5_PA6_PA7 AO_SPI_CONFIG_1
@@ -118,27 +120,44 @@ ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t s
#define ao_spi_get_bit(reg,bit,pin,bus,speed) ao_spi_get_mask(reg,(1<<bit),bus,speed)
#define ao_spi_put_bit(reg,bit,pin,bus) ao_spi_put_mask(reg,(1<<bit),bus)
-#define ao_enable_port(port) do { \
- if ((port) == &stm_gpioa) \
- stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN); \
- else if ((port) == &stm_gpiob) \
- stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN); \
- else if ((port) == &stm_gpioc) \
- stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPCEN); \
- else if ((port) == &stm_gpiof) \
- stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPFEN); \
- } while (0)
+extern struct ao_power ao_power_gpioa;
+extern struct ao_power ao_power_gpiob;
+extern struct ao_power ao_power_gpioc;
+extern struct ao_power ao_power_gpiof;
-#define ao_disable_port(port) do { \
- if ((port) == &stm_gpioa) \
- stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPAEN); \
- else if ((port) == &stm_gpiob) \
- stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPBEN); \
- else if ((port) == &stm_gpioc) \
- stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPCEN); \
- else if ((port) == &stm_gpiof) \
- stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPFEN); \
- } while (0)
+static inline void ao_enable_port(struct stm_gpio *port)
+{
+ if ((port) == &stm_gpioa) {
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN);
+ ao_power_register(&ao_power_gpioa);
+ } else if ((port) == &stm_gpiob) {
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN);
+ ao_power_register(&ao_power_gpiob);
+ } else if ((port) == &stm_gpioc) {
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPCEN);
+ ao_power_register(&ao_power_gpioc);
+ } else if ((port) == &stm_gpiof) {
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPFEN);
+ ao_power_register(&ao_power_gpiof);
+ }
+}
+
+static inline void ao_disable_port(struct stm_gpio *port)
+{
+ if ((port) == &stm_gpioa) {
+ stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPAEN);
+ ao_power_unregister(&ao_power_gpioa);
+ } else if ((port) == &stm_gpiob) {
+ stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPBEN);
+ ao_power_unregister(&ao_power_gpiob);
+ } else if ((port) == &stm_gpioc) {
+ stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPCEN);
+ ao_power_unregister(&ao_power_gpioc);
+ } else if ((port) == &stm_gpiof) {
+ stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPFEN);
+ ao_power_unregister(&ao_power_gpiof);
+ }
+}
#define ao_gpio_set(port, bit, pin, v) stm_gpio_set(port, bit, v)
@@ -166,8 +185,7 @@ ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t s
} while (0)
#define ao_enable_cs(port,bit) do { \
- stm_gpio_set((port), bit, 1); \
- stm_moder_set((port), bit, STM_MODER_OUTPUT); \
+ ao_enable_output(port, bit, pin, 1); \
} while (0)
#define ao_spi_init_cs(port, mask) do { \
@@ -395,6 +413,9 @@ ao_usb_free(uint16_t *buffer);
void
ao_usb_write(uint16_t *buffer, uint16_t len);
+
+void
+ao_usb_write2(uint16_t *buffer, uint16_t len);
#endif /* AO_USB_DIRECTIO */
#endif /* _AO_ARCH_FUNCS_H_ */
diff --git a/src/stmf0/ao_dma_stm.c b/src/stmf0/ao_dma_stm.c
index 78fabe18..e90c6bf8 100644
--- a/src/stmf0/ao_dma_stm.c
+++ b/src/stmf0/ao_dma_stm.c
@@ -28,9 +28,7 @@ static uint8_t ao_dma_allocated[STM_NUM_DMA];
static uint8_t ao_dma_mutex[STM_NUM_DMA];
static uint8_t ao_dma_active;
-#define id(ch) STM_DMA_INDEX(ch)
-#define id_mask(id) (STM_DMA_ISR_MASK << (id))
-#define ch_mask(ch) id_mask(id(ch))
+#define ch_mask(id) (STM_DMA_ISR_MASK << STM_DMA_ISR(id))
static void
ao_dma_isr(uint8_t low_index, uint8_t high_index, uint32_t mask) {
@@ -41,7 +39,7 @@ ao_dma_isr(uint8_t low_index, uint8_t high_index, uint32_t mask) {
/* Ack them */
stm_dma.ifcr = isr;
for (index = low_index; index <= high_index; index++) {
- if (isr & id_mask(index)) {
+ if (isr & ch_mask(index)) {
if (ao_dma_config[index].isr)
(*ao_dma_config[index].isr)(index);
else {
@@ -52,9 +50,25 @@ ao_dma_isr(uint8_t low_index, uint8_t high_index, uint32_t mask) {
}
}
-void stm_dma_ch1_isr(void) { ao_dma_isr(id(1), id(1), ch_mask(1)); }
-void stm_dma_ch2_3_isr(void) { ao_dma_isr(id(2), id(3), ch_mask(2) | ch_mask(3)); }
-void stm_dma1_ch4_5_6_isr(void) { ao_dma_isr(id(4), id(6), ch_mask(4) | ch_mask(5) | ch_mask(6)); }
+void stm_dma_ch1_isr(void) {
+ ao_dma_isr(STM_DMA_INDEX(1),
+ STM_DMA_INDEX(1),
+ ch_mask(STM_DMA_INDEX(1)));
+}
+
+void stm_dma_ch2_3_isr(void) {
+ ao_dma_isr(STM_DMA_INDEX(2),
+ STM_DMA_INDEX(3),
+ ch_mask(STM_DMA_INDEX(2)) |
+ ch_mask(STM_DMA_INDEX(3)));
+}
+
+void stm_dma1_ch4_5_6_isr(void) {
+ ao_dma_isr(STM_DMA_INDEX(4), STM_DMA_INDEX(6),
+ ch_mask(STM_DMA_INDEX(4)) |
+ ch_mask(STM_DMA_INDEX(5)) |
+ ch_mask(STM_DMA_INDEX(6)));
+}
void
ao_dma_set_transfer(uint8_t index,
@@ -73,11 +87,12 @@ ao_dma_set_transfer(uint8_t index,
if (ao_dma_active++ == 0)
stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMAEN);
);
- stm_dma.channel[index].ccr = ccr | (1 << STM_DMA_CCR_TCIE);
+ ao_dma_config[index].isr = NULL;
+ ao_dma_done[index] = 0;
stm_dma.channel[index].cndtr = count;
stm_dma.channel[index].cpar = peripheral;
stm_dma.channel[index].cmar = memory;
- ao_dma_config[index].isr = NULL;
+ stm_dma.channel[index].ccr = ccr;
}
void
@@ -89,7 +104,6 @@ ao_dma_set_isr(uint8_t index, void (*isr)(int))
void
ao_dma_start(uint8_t index)
{
- ao_dma_done[index] = 0;
stm_dma.channel[index].ccr |= (1 << STM_DMA_CCR_EN);
}
diff --git a/src/stmf0/ao_exti.h b/src/stmf0/ao_exti.h
index ebea224d..192611bd 100644
--- a/src/stmf0/ao_exti.h
+++ b/src/stmf0/ao_exti.h
@@ -28,7 +28,7 @@
#define AO_EXTI_PIN_NOCONFIGURE 64
void
-ao_exti_setup(struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)());
+ao_exti_setup(struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)(void));
void
ao_exti_set_mode(struct stm_gpio *gpio, uint8_t pin, uint8_t mode);
diff --git a/src/stmf0/ao_exti_stm.c b/src/stmf0/ao_exti_stm.c
new file mode 100644
index 00000000..910afcf7
--- /dev/null
+++ b/src/stmf0/ao_exti_stm.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_exti.h>
+
+static void (*ao_exti_callback[16])(void);
+
+uint32_t ao_last_exti;
+
+static void ao_exti_range_isr(uint8_t first, uint8_t last, uint16_t mask) {
+ uint16_t pending = (ao_last_exti = stm_exti.pr) & mask;
+ uint8_t pin;
+ static uint16_t last_mask;
+ static uint8_t last_pin;
+
+ if (pending == last_mask) {
+ stm_exti.pr = last_mask;
+ (*ao_exti_callback[last_pin])();
+ return;
+ }
+ stm_exti.pr = pending;
+ for (pin = first; pin <= last; pin++)
+ if ((pending & ((uint32_t) 1 << pin)) && ao_exti_callback[pin]) {
+ last_mask = (1 << pin);
+ last_pin = pin;
+ (*ao_exti_callback[pin])();
+ }
+}
+
+void stm_exti0_1_isr(void) { ao_exti_range_isr(0, 1, 0x0003); }
+void stm_exti2_3_isr(void) { ao_exti_range_isr(2, 3, 0x000c); }
+void stm_exti4_15_isr(void) { ao_exti_range_isr(4, 15, 0xfff0); }
+
+void
+ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)(void)) {
+ uint32_t mask = 1 << pin;
+ uint32_t pupdr;
+ uint8_t irq;
+ uint8_t prio;
+
+ ao_exti_callback[pin] = callback;
+
+ /* configure gpio to interrupt routing */
+ stm_exticr_set(gpio, pin);
+
+ if (!(mode & AO_EXTI_PIN_NOCONFIGURE)) {
+ /* configure pin as input, setting selected pull-up/down mode */
+ stm_moder_set(gpio, pin, STM_MODER_INPUT);
+ switch (mode & (AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_PULL_DOWN)) {
+ case 0:
+ default:
+ pupdr = STM_PUPDR_NONE;
+ break;
+ case AO_EXTI_MODE_PULL_UP:
+ pupdr = STM_PUPDR_PULL_UP;
+ break;
+ case AO_EXTI_MODE_PULL_DOWN:
+ pupdr = STM_PUPDR_PULL_DOWN;
+ break;
+ }
+ stm_pupdr_set(gpio, pin, pupdr);
+ }
+
+ /* Set interrupt mask and rising/falling mode */
+ stm_exti.imr &= ~mask;
+ if (mode & AO_EXTI_MODE_RISING)
+ stm_exti.rtsr |= mask;
+ else
+ stm_exti.rtsr &= ~mask;
+ if (mode & AO_EXTI_MODE_FALLING)
+ stm_exti.ftsr |= mask;
+ else
+ stm_exti.ftsr &= ~mask;
+
+ if (pin <= 1)
+ irq = STM_ISR_EXTI0_1_POS;
+ else if (pin <= 3)
+ irq = STM_ISR_EXTI2_3_POS;
+ else
+ irq = STM_ISR_EXTI4_15_POS;
+
+ /* Set priority */
+ prio = AO_STM_NVIC_MED_PRIORITY;
+ if (mode & AO_EXTI_PRIORITY_LOW)
+ prio = AO_STM_NVIC_LOW_PRIORITY;
+ else if (mode & AO_EXTI_PRIORITY_HIGH)
+ prio = AO_STM_NVIC_HIGH_PRIORITY;
+
+ stm_nvic_set_priority(irq, prio);
+ stm_nvic_set_enable(irq);
+}
+
+void
+ao_exti_set_mode(struct stm_gpio *gpio, uint8_t pin, uint8_t mode) {
+ (void) gpio;
+
+ uint32_t mask = 1 << pin;
+
+ if (mode & AO_EXTI_MODE_RISING)
+ stm_exti.rtsr |= mask;
+ else
+ stm_exti.rtsr &= ~mask;
+ if (mode & AO_EXTI_MODE_FALLING)
+ stm_exti.ftsr |= mask;
+ else
+ stm_exti.ftsr &= ~mask;
+}
+
+void
+ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)()) {
+ (void) gpio;
+ ao_exti_callback[pin] = callback;
+}
+
+void
+ao_exti_enable(struct stm_gpio *gpio, uint8_t pin) {
+ uint32_t mask = (1 << pin);
+ (void) gpio;
+ stm_exti.pr = mask;
+ stm_exti.imr |= (1 << pin);
+}
+
+void
+ao_exti_disable(struct stm_gpio *gpio, uint8_t pin) {
+ uint32_t mask = (1 << pin);
+ (void) gpio;
+ stm_exti.imr &= ~mask;
+ stm_exti.pr = mask;
+}
+
+void
+ao_exti_init(void)
+{
+}
diff --git a/src/stmf0/ao_gpio.c b/src/stmf0/ao_gpio.c
new file mode 100644
index 00000000..c7bf0797
--- /dev/null
+++ b/src/stmf0/ao_gpio.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+
+static void
+ao_gpio_suspend(void *arg)
+{
+ struct stm_gpio *port = arg;
+ if (port == &stm_gpioa)
+ stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPAEN);
+ else if ((port) == &stm_gpiob)
+ stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPBEN);
+ else if ((port) == &stm_gpioc)
+ stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPCEN);
+ else if ((port) == &stm_gpiof)
+ stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPFEN);
+}
+
+static void
+ao_gpio_resume(void *arg)
+{
+ struct stm_gpio *port = arg;
+ if (port == &stm_gpioa)
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN);
+ else if ((port) == &stm_gpiob)
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN);
+ else if ((port) == &stm_gpioc)
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPCEN);
+ else if ((port) == &stm_gpiof)
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPFEN);
+}
+
+struct ao_power ao_power_gpioa = {
+ .suspend = ao_gpio_suspend,
+ .resume = ao_gpio_resume,
+ .arg = &stm_gpioa
+};
+
+struct ao_power ao_power_gpiob = {
+ .suspend = ao_gpio_suspend,
+ .resume = ao_gpio_resume,
+ .arg = &stm_gpiob
+};
+
+struct ao_power ao_power_gpioc = {
+ .suspend = ao_gpio_suspend,
+ .resume = ao_gpio_resume,
+ .arg = &stm_gpioc
+};
+
+struct ao_power ao_power_gpiof = {
+ .suspend = ao_gpio_suspend,
+ .resume = ao_gpio_resume,
+ .arg = &stm_gpiof
+};
+
diff --git a/src/stmf0/ao_pwm.c b/src/stmf0/ao_pwm.c
new file mode 100644
index 00000000..c1e157f5
--- /dev/null
+++ b/src/stmf0/ao_pwm.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+#include "ao_pwm.h"
+
+static uint8_t pwm_running;
+
+static uint16_t pwm_value[NUM_PWM];
+
+static void
+ao_pwm_up(void)
+{
+ if (pwm_running++ == 0) {
+ struct stm_tim23 *tim = AO_PWM_TIMER;
+
+ tim->ccr1 = 0;
+ tim->ccr2 = 0;
+ tim->ccr3 = 0;
+ tim->ccr4 = 0;
+ tim->arr = PWM_MAX - 1; /* turn on the timer */
+ tim->cr1 = ((STM_TIM23_CR1_CKD_1 << STM_TIM23_CR1_CKD) |
+ (0 << STM_TIM23_CR1_ARPE) |
+ (STM_TIM23_CR1_CMS_EDGE << STM_TIM23_CR1_CMS) |
+ (STM_TIM23_CR1_DIR_UP << STM_TIM23_CR1_DIR) |
+ (0 << STM_TIM23_CR1_OPM) |
+ (0 << STM_TIM23_CR1_URS) |
+ (0 << STM_TIM23_CR1_UDIS) |
+ (1 << STM_TIM23_CR1_CEN));
+
+ /* Set the timer running */
+ tim->egr = (1 << STM_TIM23_EGR_UG);
+ }
+}
+
+static void
+ao_pwm_down(void)
+{
+ if (--pwm_running == 0) {
+ struct stm_tim23 *tim = AO_PWM_TIMER;
+
+ tim->arr = 0;
+ tim->cr1 = ((STM_TIM23_CR1_CKD_1 << STM_TIM23_CR1_CKD) |
+ (0 << STM_TIM23_CR1_ARPE) |
+ (STM_TIM23_CR1_CMS_EDGE << STM_TIM23_CR1_CMS) |
+ (STM_TIM23_CR1_DIR_UP << STM_TIM23_CR1_DIR) |
+ (0 << STM_TIM23_CR1_OPM) |
+ (0 << STM_TIM23_CR1_URS) |
+ (0 << STM_TIM23_CR1_UDIS) |
+ (0 << STM_TIM23_CR1_CEN));
+
+ /* Stop the timer */
+ tim->egr = (1 << STM_TIM23_EGR_UG);
+ }
+}
+
+void
+ao_pwm_set(uint8_t pwm, uint16_t value)
+{
+ struct stm_tim23 *tim = AO_PWM_TIMER;
+ uint8_t ch = AO_PWM_0_CH;
+
+ if (value > PWM_MAX)
+ value = PWM_MAX;
+ if (value != 0) {
+ if (pwm_value[pwm] == 0)
+ ao_pwm_up();
+ }
+#if NUM_PWM > 1
+ switch (pwm) {
+ case 0:
+ ch = AO_PWM_0_CH;
+ break;
+ case 1:
+ ch = AO_PWM_0_CH;
+ break;
+#if NUM_PWM > 2
+ case 2:
+ ch = AO_PWM_0_CH;
+ break;
+#endif
+#if NUM_PWM > 3
+ case 3:
+ ch = AO_PWM_0_CH;
+ break;
+#endif
+ }
+#endif
+
+ switch (ch) {
+ case 1:
+ tim->ccr1 = value;
+ break;
+ case 2:
+ tim->ccr2 = value;
+ break;
+ case 3:
+ tim->ccr3 = value;
+ break;
+ case 4:
+ tim->ccr4 = value;
+ break;
+ }
+ if (value == 0) {
+ if (pwm_value[pwm] != 0)
+ ao_pwm_down();
+ }
+ pwm_value[pwm] = value;
+}
+
+static void
+ao_pwm_cmd(void)
+{
+ uint8_t ch;
+ uint16_t val;
+
+ ao_cmd_decimal();
+ ch = ao_cmd_lex_u32;
+ ao_cmd_decimal();
+ val = ao_cmd_lex_u32;
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+
+ printf("Set channel %d to %d\n", ch, val);
+ ao_pwm_set(ch, val);
+}
+
+static const struct ao_cmds ao_pwm_cmds[] = {
+ { ao_pwm_cmd, "P <ch> <val>\0Set PWM ch to val" },
+ { 0, NULL },
+};
+
+void
+ao_pwm_init(void)
+{
+ struct stm_tim23 *tim = AO_PWM_TIMER;
+
+ stm_rcc.apb1enr |= (1 << AO_PWM_TIMER_ENABLE);
+
+ tim->cr1 = 0;
+ tim->psc = AO_PWM_TIMER_SCALE - 1;
+ tim->cnt = 0;
+ tim->ccer = ((1 << STM_TIM23_CCER_CC1E) |
+ (0 << STM_TIM23_CCER_CC1P) |
+ (1 << STM_TIM23_CCER_CC2E) |
+ (0 << STM_TIM23_CCER_CC2P) |
+ (1 << STM_TIM23_CCER_CC3E) |
+ (0 << STM_TIM23_CCER_CC3P) |
+ (1 << STM_TIM23_CCER_CC4E) |
+ (0 << STM_TIM23_CCER_CC4P));
+
+ tim->ccmr1 = ((0 << STM_TIM23_CCMR1_OC2CE) |
+ (STM_TIM23_CCMR1_OC2M_PWM_MODE_1 << STM_TIM23_CCMR1_OC2M) |
+ (0 << STM_TIM23_CCMR1_OC2PE) |
+ (0 << STM_TIM23_CCMR1_OC2FE) |
+ (STM_TIM23_CCMR1_CC2S_OUTPUT << STM_TIM23_CCMR1_CC2S) |
+
+ (0 << STM_TIM23_CCMR1_OC1CE) |
+ (STM_TIM23_CCMR1_OC1M_PWM_MODE_1 << STM_TIM23_CCMR1_OC1M) |
+ (0 << STM_TIM23_CCMR1_OC1PE) |
+ (0 << STM_TIM23_CCMR1_OC1FE) |
+ (STM_TIM23_CCMR1_CC1S_OUTPUT << STM_TIM23_CCMR1_CC1S));
+
+
+ tim->ccmr2 = ((0 << STM_TIM23_CCMR2_OC4CE) |
+ (STM_TIM23_CCMR2_OC4M_PWM_MODE_1 << STM_TIM23_CCMR2_OC4M) |
+ (0 << STM_TIM23_CCMR2_OC4PE) |
+ (0 << STM_TIM23_CCMR2_OC4FE) |
+ (STM_TIM23_CCMR2_CC4S_OUTPUT << STM_TIM23_CCMR2_CC4S) |
+
+ (0 << STM_TIM23_CCMR2_OC3CE) |
+ (STM_TIM23_CCMR2_OC3M_PWM_MODE_1 << STM_TIM23_CCMR2_OC3M) |
+ (0 << STM_TIM23_CCMR2_OC3PE) |
+ (0 << STM_TIM23_CCMR2_OC3FE) |
+ (STM_TIM23_CCMR2_CC3S_OUTPUT << STM_TIM23_CCMR2_CC3S));
+ tim->egr = 0;
+
+ tim->sr = 0;
+ tim->dier = 0;
+ tim->smcr = 0;
+ tim->cr2 = ((0 << STM_TIM23_CR2_TI1S) |
+ (STM_TIM23_CR2_MMS_RESET<< STM_TIM23_CR2_MMS) |
+ (0 << STM_TIM23_CR2_CCDS));
+
+ stm_afr_set(AO_PWM_0_GPIO, AO_PWM_0_PIN, STM_AFR_AF1);
+ stm_ospeedr_set(AO_PWM_0_GPIO, AO_PWM_0_PIN, STM_OSPEEDR_MEDIUM);
+#if NUM_PWM > 1
+ stm_afr_set(AO_PWM_1_GPIO, AO_PWM_1_PIN, STM_AFR_AF1);
+ stm_ospeedr_set(AO_PWM_1_GPIO, AO_PWM_1_PIN, STM_OSPEEDR_MEDIUM);
+#endif
+#if NUM_PWM > 2
+ stm_afr_set(AO_PWM_2_GPIO, AO_PWM_2_PIN, STM_AFR_AF1);
+ stm_ospeedr_set(AO_PWM_2_GPIO, AO_PWM_2_PIN, STM_OSPEEDR_MEDIUM);
+#endif
+#if NUM_PWM > 3
+ stm_afr_set(AO_PWM_3_GPIO, AO_PWM_3_PIN, STM_AFR_AF1);
+ stm_ospeedr_set(AO_PWM_3_GPIO, AO_PWM_3_PIN, STM_OSPEEDR_MEDIUM);
+#endif
+ ao_cmd_register(&ao_pwm_cmds[0]);
+}
diff --git a/src/stmf0/ao_spi_stm.c b/src/stmf0/ao_spi_stm.c
new file mode 100644
index 00000000..55bf59d2
--- /dev/null
+++ b/src/stmf0/ao_spi_stm.c
@@ -0,0 +1,478 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+
+struct ao_spi_stm_info {
+ uint8_t miso_dma_index;
+ uint8_t mosi_dma_index;
+ struct stm_spi *stm_spi;
+};
+
+static uint8_t ao_spi_mutex[STM_NUM_SPI];
+static uint8_t ao_spi_index[STM_NUM_SPI];
+
+static const struct ao_spi_stm_info ao_spi_stm_info[STM_NUM_SPI] = {
+ {
+ .miso_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI1_RX),
+ .mosi_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI1_TX),
+ &stm_spi1
+ },
+ {
+ .miso_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI2_RX),
+ .mosi_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI2_TX),
+ &stm_spi2
+ }
+};
+
+static uint8_t spi_dev_null;
+
+
+
+#define SPI_CR2 ((0 << STM_SPI_CR2_LDMA_TX) | \
+ (0 << STM_SPI_CR2_LDMA_RX) | \
+ (1 << STM_SPI_CR2_FRXTH) | \
+ (STM_SPI_CR2_DS_8 << STM_SPI_CR2_DS) | \
+ (0 << STM_SPI_CR2_TXEIE) | \
+ (0 << STM_SPI_CR2_RXNEIE) | \
+ (0 << STM_SPI_CR2_ERRIE) | \
+ (STM_SPI_CR2_FRF_MOTOROLA << STM_SPI_CR2_FRF) | \
+ (0 << STM_SPI_CR2_NSSP) | \
+ (0 << STM_SPI_CR2_SSOE))
+
+#define SPI_CR2_DMA (SPI_CR2 | \
+ (1 << STM_SPI_CR2_TXDMAEN) | \
+ (1 << STM_SPI_CR2_RXDMAEN))
+
+#define SPI_CR2_SYNC (SPI_CR2 | \
+ (0 << STM_SPI_CR2_TXDMAEN) | \
+ (0 << STM_SPI_CR2_RXDMAEN))
+
+void
+ao_spi_send(const void *block, uint16_t len, uint8_t spi_index)
+{
+ struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
+ uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index;
+ uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index;
+
+ /* Set up the transmit DMA to deliver data */
+ ao_dma_set_transfer(mosi_dma_index,
+ &stm_spi->dr,
+ (void *) block,
+ len,
+ (0 << STM_DMA_CCR_MEM2MEM) |
+ (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+ (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+ (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+ (1 << STM_DMA_CCR_MINC) |
+ (0 << STM_DMA_CCR_PINC) |
+ (0 << STM_DMA_CCR_CIRC) |
+ (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR) |
+ (0 << STM_DMA_CCR_TCIE));
+
+ /* Clear RXNE */
+ (void) stm_spi->dr;
+
+ /* Set up the receive DMA -- when this is done, we know the SPI unit
+ * is idle. Without this, we'd have to poll waiting for the BSY bit to
+ * be cleared
+ */
+ ao_dma_set_transfer(miso_dma_index,
+ &stm_spi->dr,
+ &spi_dev_null,
+ len,
+ (0 << STM_DMA_CCR_MEM2MEM) |
+ (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+ (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+ (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+ (0 << STM_DMA_CCR_MINC) |
+ (0 << STM_DMA_CCR_PINC) |
+ (0 << STM_DMA_CCR_CIRC) |
+ (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR) |
+ (1 << STM_DMA_CCR_TCIE));
+
+ stm_spi->cr2 = SPI_CR2_DMA;
+
+ ao_dma_start(miso_dma_index);
+ ao_dma_start(mosi_dma_index);
+ ao_arch_critical(
+ while (!ao_dma_done[miso_dma_index])
+ ao_sleep(&ao_dma_done[miso_dma_index]);
+ );
+ ao_dma_done_transfer(mosi_dma_index);
+ ao_dma_done_transfer(miso_dma_index);
+}
+
+void
+ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index)
+{
+ struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
+ uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index;
+ uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index;
+
+ /* Set up the transmit DMA to deliver data */
+ ao_dma_set_transfer(mosi_dma_index,
+ &stm_spi->dr,
+ &value,
+ len,
+ (0 << STM_DMA_CCR_MEM2MEM) |
+ (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+ (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+ (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+ (0 << STM_DMA_CCR_MINC) |
+ (0 << STM_DMA_CCR_PINC) |
+ (0 << STM_DMA_CCR_CIRC) |
+ (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR) |
+ (0 << STM_DMA_CCR_TCIE));
+
+ /* Clear RXNE */
+ (void) stm_spi->dr;
+
+ /* Set up the receive DMA -- when this is done, we know the SPI unit
+ * is idle. Without this, we'd have to poll waiting for the BSY bit to
+ * be cleared
+ */
+ ao_dma_set_transfer(miso_dma_index,
+ &stm_spi->dr,
+ &spi_dev_null,
+ len,
+ (0 << STM_DMA_CCR_MEM2MEM) |
+ (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+ (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+ (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+ (0 << STM_DMA_CCR_MINC) |
+ (0 << STM_DMA_CCR_PINC) |
+ (0 << STM_DMA_CCR_CIRC) |
+ (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR) |
+ (1 << STM_DMA_CCR_TCIE));
+
+ stm_spi->cr2 = SPI_CR2_DMA;
+ ao_dma_start(miso_dma_index);
+ ao_dma_start(mosi_dma_index);
+ ao_arch_critical(
+ while (!ao_dma_done[miso_dma_index])
+ ao_sleep(&ao_dma_done[miso_dma_index]);
+ );
+ ao_dma_done_transfer(mosi_dma_index);
+ ao_dma_done_transfer(miso_dma_index);
+}
+
+void
+ao_spi_send_sync(void *block, uint16_t len, uint8_t spi_index)
+{
+ uint8_t *b = block;
+ struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
+
+ stm_spi->cr2 = SPI_CR2_SYNC;
+
+ /* Clear RXNE */
+ (void) stm_spi->dr;
+
+ while (len--) {
+ while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE)));
+ stm_spi->dr = *b++;
+ }
+}
+
+void
+ao_spi_recv(void *block, uint16_t len, uint8_t spi_index)
+{
+ struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
+ uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index;
+ uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index;
+
+ spi_dev_null = 0xff;
+
+ /* Set up transmit DMA to make the SPI hardware actually run */
+ ao_dma_set_transfer(mosi_dma_index,
+ &stm_spi->dr,
+ &spi_dev_null,
+ len,
+ (0 << STM_DMA_CCR_MEM2MEM) |
+ (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+ (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+ (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+ (0 << STM_DMA_CCR_MINC) |
+ (0 << STM_DMA_CCR_PINC) |
+ (0 << STM_DMA_CCR_CIRC) |
+ (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR) |
+ (0 << STM_DMA_CCR_TCIE));
+
+ /* Clear RXNE */
+ (void) stm_spi->dr;
+
+ /* Set up the receive DMA to capture data */
+ ao_dma_set_transfer(miso_dma_index,
+ &stm_spi->dr,
+ block,
+ len,
+ (0 << STM_DMA_CCR_MEM2MEM) |
+ (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+ (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+ (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+ (1 << STM_DMA_CCR_MINC) |
+ (0 << STM_DMA_CCR_PINC) |
+ (0 << STM_DMA_CCR_CIRC) |
+ (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR) |
+ (1 << STM_DMA_CCR_TCIE));
+
+ stm_spi->cr2 = SPI_CR2_DMA;
+ ao_dma_start(miso_dma_index);
+ ao_dma_start(mosi_dma_index);
+
+ /* Wait until the SPI unit is done */
+ ao_arch_critical(
+ while (!ao_dma_done[miso_dma_index])
+ ao_sleep(&ao_dma_done[miso_dma_index]);
+ );
+
+ ao_dma_done_transfer(mosi_dma_index);
+ ao_dma_done_transfer(miso_dma_index);
+}
+
+void
+ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index)
+{
+ struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
+ uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index;
+ uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index;
+
+ /* Set up transmit DMA to send data */
+ ao_dma_set_transfer(mosi_dma_index,
+ &stm_spi->dr,
+ out,
+ len,
+ (0 << STM_DMA_CCR_MEM2MEM) |
+ (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+ (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+ (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+ (1 << STM_DMA_CCR_MINC) |
+ (0 << STM_DMA_CCR_PINC) |
+ (0 << STM_DMA_CCR_CIRC) |
+ (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR) |
+ (0 << STM_DMA_CCR_TCIE));
+
+ /* Clear RXNE */
+ (void) stm_spi->dr;
+
+ /* Set up the receive DMA to capture data */
+ ao_dma_set_transfer(miso_dma_index,
+ &stm_spi->dr,
+ in,
+ len,
+ (0 << STM_DMA_CCR_MEM2MEM) |
+ (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+ (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+ (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+ (1 << STM_DMA_CCR_MINC) |
+ (0 << STM_DMA_CCR_PINC) |
+ (0 << STM_DMA_CCR_CIRC) |
+ (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR) |
+ (1 << STM_DMA_CCR_TCIE));
+
+ stm_spi->cr2 = SPI_CR2_DMA;
+ ao_dma_start(miso_dma_index);
+ ao_dma_start(mosi_dma_index);
+
+ /* Wait until the SPI unit is done */
+ ao_arch_critical(
+ while (!ao_dma_done[miso_dma_index])
+ ao_sleep(&ao_dma_done[miso_dma_index]);
+ );
+
+ ao_dma_done_transfer(mosi_dma_index);
+ ao_dma_done_transfer(miso_dma_index);
+}
+
+static void
+ao_spi_disable_index(uint8_t spi_index)
+{
+ /* Disable current config
+ */
+ switch (AO_SPI_INDEX(spi_index)) {
+ case STM_SPI_INDEX(1):
+ switch (spi_index) {
+ case AO_SPI_1_PA5_PA6_PA7:
+ stm_gpio_set(&stm_gpioa, 5, 1);
+ stm_moder_set(&stm_gpioa, 5, STM_MODER_OUTPUT);
+ stm_moder_set(&stm_gpioa, 6, STM_MODER_INPUT);
+ stm_moder_set(&stm_gpioa, 7, STM_MODER_OUTPUT);
+ break;
+ case AO_SPI_1_PB3_PB4_PB5:
+ stm_gpio_set(&stm_gpiob, 3, 1);
+ stm_moder_set(&stm_gpiob, 3, STM_MODER_OUTPUT);
+ stm_moder_set(&stm_gpiob, 4, STM_MODER_INPUT);
+ stm_moder_set(&stm_gpiob, 5, STM_MODER_OUTPUT);
+ break;
+ }
+ break;
+ case STM_SPI_INDEX(2):
+ switch (spi_index) {
+ case AO_SPI_2_PB13_PB14_PB15:
+ stm_gpio_set(&stm_gpiob, 13, 1);
+ stm_moder_set(&stm_gpiob, 13, STM_MODER_OUTPUT);
+ stm_moder_set(&stm_gpiob, 14, STM_MODER_INPUT);
+ stm_moder_set(&stm_gpiob, 15, STM_MODER_OUTPUT);
+ break;
+ }
+ break;
+ }
+}
+
+static void
+ao_spi_enable_index(uint8_t spi_index)
+{
+ switch (AO_SPI_INDEX(spi_index)) {
+ case STM_SPI_INDEX(1):
+ switch (spi_index) {
+ case AO_SPI_1_PA5_PA6_PA7:
+ stm_afr_set(&stm_gpioa, 5, STM_AFR_AF0);
+ stm_afr_set(&stm_gpioa, 6, STM_AFR_AF0);
+ stm_afr_set(&stm_gpioa, 7, STM_AFR_AF0);
+ break;
+ case AO_SPI_1_PB3_PB4_PB5:
+ stm_afr_set(&stm_gpiob, 3, STM_AFR_AF0);
+ stm_afr_set(&stm_gpiob, 4, STM_AFR_AF0);
+ stm_afr_set(&stm_gpiob, 5, STM_AFR_AF0);
+ break;
+ }
+ break;
+ case STM_SPI_INDEX(2):
+ switch (spi_index) {
+ case AO_SPI_2_PB13_PB14_PB15:
+ stm_afr_set(&stm_gpiob, 13, STM_AFR_AF0);
+ stm_afr_set(&stm_gpiob, 14, STM_AFR_AF0);
+ stm_afr_set(&stm_gpiob, 15, STM_AFR_AF0);
+ break;
+ }
+ break;
+ }
+}
+
+static void
+ao_spi_config(uint8_t spi_index, uint32_t speed)
+{
+ uint8_t id = AO_SPI_INDEX(spi_index);
+ struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi;
+
+ stm_spi->cr2 = SPI_CR2;
+ stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) | /* Three wire mode */
+ (0 << STM_SPI_CR1_BIDIOE) |
+ (0 << STM_SPI_CR1_CRCEN) | /* CRC disabled */
+ (0 << STM_SPI_CR1_CRCNEXT) |
+ (0 << STM_SPI_CR1_CRCL) |
+ (0 << STM_SPI_CR1_RXONLY) |
+ (1 << STM_SPI_CR1_SSM) | /* Software SS handling */
+ (1 << STM_SPI_CR1_SSI) | /* ... */
+ (0 << STM_SPI_CR1_LSBFIRST) | /* Big endian */
+ (1 << STM_SPI_CR1_SPE) | /* Enable SPI unit */
+ (speed << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */
+ (1 << STM_SPI_CR1_MSTR) |
+ (0 << STM_SPI_CR1_CPOL) | /* Format 0 */
+ (0 << STM_SPI_CR1_CPHA));
+
+ if (spi_index != ao_spi_index[id]) {
+
+ /* Disable old config
+ */
+ ao_spi_disable_index(ao_spi_index[id]);
+
+ /* Enable new config
+ */
+ ao_spi_enable_index(spi_index);
+
+ /* Remember current config
+ */
+ ao_spi_index[id] = spi_index;
+ }
+}
+
+uint8_t
+ao_spi_try_get(uint8_t spi_index, uint32_t speed, uint8_t task_id)
+{
+ uint8_t id = AO_SPI_INDEX(spi_index);
+
+ if (!ao_mutex_try(&ao_spi_mutex[id], task_id))
+ return 0;
+ ao_spi_config(spi_index, speed);
+ return 1;
+}
+
+void
+ao_spi_get(uint8_t spi_index, uint32_t speed)
+{
+ uint8_t id = AO_SPI_INDEX(spi_index);
+ ao_mutex_get(&ao_spi_mutex[id]);
+ ao_spi_config(spi_index, speed);
+}
+
+void
+ao_spi_put(uint8_t spi_index)
+{
+ uint8_t id = AO_SPI_INDEX(spi_index);
+ struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi;
+
+ stm_spi->cr1 = 0;
+ ao_mutex_put(&ao_spi_mutex[id]);
+}
+
+static void
+ao_spi_channel_init(uint8_t spi_index)
+{
+ uint8_t id = AO_SPI_INDEX(spi_index);
+ struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi;
+
+ ao_spi_disable_index(spi_index);
+
+ stm_spi->cr1 = 0;
+ (void) stm_spi->sr;
+ stm_spi->cr2 = SPI_CR2_SYNC;
+}
+
+void
+ao_spi_init(void)
+{
+#if HAS_SPI_1
+# if SPI_1_PA5_PA6_PA7
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN);
+ stm_ospeedr_set(&stm_gpioa, 5, SPI_1_OSPEEDR);
+ stm_ospeedr_set(&stm_gpioa, 6, SPI_1_OSPEEDR);
+ stm_ospeedr_set(&stm_gpioa, 7, SPI_1_OSPEEDR);
+# endif
+# if SPI_1_PB3_PB4_PB5
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN);
+ stm_ospeedr_set(&stm_gpiob, 3, SPI_1_OSPEEDR);
+ stm_ospeedr_set(&stm_gpiob, 4, SPI_1_OSPEEDR);
+ stm_ospeedr_set(&stm_gpiob, 5, SPI_1_OSPEEDR);
+# endif
+ stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SPI1EN);
+ ao_spi_index[0] = AO_SPI_CONFIG_NONE;
+ ao_spi_channel_init(STM_SPI_INDEX(1));
+#endif
+
+#if HAS_SPI_2
+# if SPI_2_PB10_PB13_PB14
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN);
+ stm_ospeedr_set(&stm_gpiob, 13, SPI_2_OSPEEDR);
+ stm_ospeedr_set(&stm_gpiob, 14, SPI_2_OSPEEDR);
+ stm_ospeedr_set(&stm_gpiob, 15, SPI_2_OSPEEDR);
+# endif
+ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_SPI2EN);
+ ao_spi_index[1] = AO_SPI_CONFIG_NONE;
+ ao_spi_channel_init(STM_SPI_INDEX(2));
+#endif
+}
diff --git a/src/stmf0/ao_timer.c b/src/stmf0/ao_timer.c
index 3aae7e55..e5bf04a3 100644
--- a/src/stmf0/ao_timer.c
+++ b/src/stmf0/ao_timer.c
@@ -50,12 +50,14 @@ void stm_systick_isr(void)
#if AO_DATA_ALL
if (++ao_data_count == ao_data_interval) {
ao_data_count = 0;
+#if HAS_ADC
#if HAS_FAKE_FLIGHT
if (ao_fake_flight_active)
ao_fake_flight_poll();
else
#endif
ao_adc_poll();
+#endif
#if (AO_DATA_ALL & ~(AO_DATA_ADC))
ao_wakeup((void *) &ao_data_count);
#endif
@@ -92,6 +94,7 @@ ao_timer_init(void)
#endif
+#if AO_HSI48
static void
ao_clock_enable_crs(void)
{
@@ -127,15 +130,12 @@ ao_clock_enable_crs(void)
(0 << STM_CRS_CR_ERRIE) |
(0 << STM_CRS_CR_SYNCWARNIE) |
(0 << STM_CRS_CR_SYNCOKIE));
-
}
+#endif
-void
-ao_clock_init(void)
+static void
+ao_clock_hsi(void)
{
- uint32_t cfgr;
-
- /* Switch to HSI while messing about */
stm_rcc.cr |= (1 << STM_RCC_CR_HSION);
while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY)))
ao_arch_nop();
@@ -153,15 +153,17 @@ ao_clock_init(void)
/* reset PLLON, CSSON, HSEBYP, HSEON */
stm_rcc.cr &= 0x0000ffff;
+}
- /* Disable all interrupts */
- stm_rcc.cir = 0;
-
+static void
+ao_clock_normal_start(void)
+{
#if AO_HSE
-#define STM_RCC_CFGR_SWS_TARGET_CLOCK STM_RCC_CFGR_SWS_HSE
-#define STM_RCC_CFGR_SW_TARGET_CLOCK STM_RCC_CFGR_SW_HSE
+ uint32_t cfgr;
+#define STM_RCC_CFGR_SWS_TARGET_CLOCK STM_RCC_CFGR_SWS_PLL
+#define STM_RCC_CFGR_SW_TARGET_CLOCK STM_RCC_CFGR_SW_PLL
#define STM_PLLSRC AO_HSE
-#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK 1
+#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK STM_RCC_CFGR_PLLSRC_HSE
#if AO_HSE_BYPASS
stm_rcc.cr |= (1 << STM_RCC_CR_HSEBYP);
@@ -172,6 +174,33 @@ ao_clock_init(void)
stm_rcc.cr |= (1 << STM_RCC_CR_HSEON);
while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSERDY)))
asm("nop");
+
+#ifdef STM_PLLSRC
+ /* Disable the PLL */
+ stm_rcc.cr &= ~(1 << STM_RCC_CR_PLLON);
+ while (stm_rcc.cr & (1 << STM_RCC_CR_PLLRDY))
+ asm("nop");
+
+ /* PLLVCO to 48MHz (for USB) -> PLLMUL = 3 */
+ cfgr = stm_rcc.cfgr;
+ cfgr &= ~(STM_RCC_CFGR_PLLMUL_MASK << STM_RCC_CFGR_PLLMUL);
+ cfgr |= (AO_RCC_CFGR_PLLMUL << STM_RCC_CFGR_PLLMUL);
+
+ /* PLL source */
+ cfgr &= ~(1 << STM_RCC_CFGR_PLLSRC);
+ cfgr |= (STM_RCC_CFGR_PLLSRC_TARGET_CLOCK << STM_RCC_CFGR_PLLSRC);
+ stm_rcc.cfgr = cfgr;
+
+ /* Disable pre divider */
+ stm_rcc.cfgr2 = (STM_RCC_CFGR2_PREDIV_1 << STM_RCC_CFGR2_PREDIV);
+
+ /* Enable the PLL and wait for it */
+ stm_rcc.cr |= (1 << STM_RCC_CR_PLLON);
+ while (!(stm_rcc.cr & (1 << STM_RCC_CR_PLLRDY)))
+ asm("nop");
+
+#endif
+
#endif
@@ -196,10 +225,50 @@ ao_clock_init(void)
#define STM_PLLSRC STM_HSI
#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK 0
#endif
+}
+
+static void
+ao_clock_normal_switch(void)
+{
+ uint32_t cfgr;
+ cfgr = stm_rcc.cfgr;
+ cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW);
+ cfgr |= (STM_RCC_CFGR_SW_TARGET_CLOCK << STM_RCC_CFGR_SW);
+ stm_rcc.cfgr = cfgr;
+ for (;;) {
+ uint32_t c, part, mask, val;
+
+ c = stm_rcc.cfgr;
+ mask = (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS);
+ val = (STM_RCC_CFGR_SWS_TARGET_CLOCK << STM_RCC_CFGR_SWS);
+ part = c & mask;
+ if (part == val)
+ break;
+ }
+#if !AO_HSI && !AO_NEED_HSI
+ /* Turn off the HSI clock */
+ stm_rcc.cr &= ~(1 << STM_RCC_CR_HSION);
+#endif
#ifdef STM_PLLSRC
-#error No code for PLL initialization yet
+ /* USB PLL source */
+ stm_rcc.cfgr3 |= (1 << STM_RCC_CFGR3_USBSW);
#endif
+}
+
+void
+ao_clock_init(void)
+{
+ uint32_t cfgr;
+
+ /* Switch to HSI while messing about */
+ ao_clock_hsi();
+
+ /* Disable all interrupts */
+ stm_rcc.cir = 0;
+
+ /* Start high speed clock */
+ ao_clock_normal_start();
/* Set flash latency to tolerate 48MHz SYSCLK -> 1 wait state */
@@ -228,29 +297,11 @@ ao_clock_init(void)
stm_rcc.cfgr = cfgr;
/* Switch to the desired system clock */
-
- cfgr = stm_rcc.cfgr;
- cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW);
- cfgr |= (STM_RCC_CFGR_SW_TARGET_CLOCK << STM_RCC_CFGR_SW);
- stm_rcc.cfgr = cfgr;
- for (;;) {
- uint32_t c, part, mask, val;
-
- c = stm_rcc.cfgr;
- mask = (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS);
- val = (STM_RCC_CFGR_SWS_TARGET_CLOCK << STM_RCC_CFGR_SWS);
- part = c & mask;
- if (part == val)
- break;
- }
+ ao_clock_normal_switch();
/* Clear reset flags */
stm_rcc.csr |= (1 << STM_RCC_CSR_RMVF);
-#if !AO_HSI && !AO_NEED_HSI
- /* Turn off the HSI clock */
- stm_rcc.cr &= ~(1 << STM_RCC_CR_HSION);
-#endif
#if DEBUG_THE_CLOCK
/* Output SYSCLK on PA8 for measurments */
@@ -264,3 +315,18 @@ ao_clock_init(void)
stm_rcc.cfgr |= (STM_RCC_CFGR_MCOSEL_HSE << STM_RCC_CFGR_MCOSEL);
#endif
}
+
+#if AO_POWER_MANAGEMENT
+void
+ao_clock_suspend(void)
+{
+ ao_clock_hsi();
+}
+
+void
+ao_clock_resume(void)
+{
+ ao_clock_normal_start();
+ ao_clock_normal_switch();
+}
+#endif
diff --git a/src/stmf0/ao_usb_stm.c b/src/stmf0/ao_usb_stm.c
index b8146c21..253506d5 100644
--- a/src/stmf0/ao_usb_stm.c
+++ b/src/stmf0/ao_usb_stm.c
@@ -18,8 +18,10 @@
#include "ao.h"
#include "ao_usb.h"
#include "ao_product.h"
+#include "ao_power.h"
#define USB_DEBUG 0
+#define USB_STATUS 0
#define USB_DEBUG_DATA 0
#define USB_ECHO 0
@@ -27,6 +29,10 @@
#error "must define AO_PA11_PA12_RMP"
#endif
+#ifndef AO_POWER_MANAGEMENT
+#define AO_POWER_MANAGEMENT 0
+#endif
+
#ifndef USE_USB_STDIO
#define USE_USB_STDIO 1
#endif
@@ -83,23 +89,42 @@ static uint16_t ao_usb_sram_addr;
static uint16_t *ao_usb_ep0_tx_buffer;
static uint16_t *ao_usb_ep0_rx_buffer;
+#if AO_USB_HAS_INT
/* Pointer to interrupt buffer in USB memory */
static uint16_t ao_usb_int_tx_offset;
+#endif
/* Pointer to bulk data tx/rx buffers in USB memory */
+#if AO_USB_HAS_IN
static uint16_t ao_usb_in_tx_offset;
static uint16_t *ao_usb_in_tx_buffer;
-static uint16_t ao_usb_out_rx_offset;
-static uint16_t *ao_usb_out_rx_buffer;
/* System ram shadow of USB buffer; writing individual bytes is
* too much of a pain (sigh) */
static uint8_t ao_usb_tx_buffer[AO_USB_IN_SIZE];
static uint8_t ao_usb_tx_count;
+#endif
+#if AO_USB_HAS_OUT
+static uint16_t ao_usb_out_rx_offset;
+static uint16_t *ao_usb_out_rx_buffer;
+
+/* System ram shadow of USB buffer; writing individual bytes is
+ * too much of a pain (sigh) */
static uint8_t ao_usb_rx_buffer[AO_USB_OUT_SIZE];
static uint8_t ao_usb_rx_count, ao_usb_rx_pos;
+#endif
+#if AO_USB_HAS_IN2
+static uint16_t ao_usb_in2_tx_offset;
+static uint16_t *ao_usb_in2_tx_buffer;
+
+/* System ram shadow of USB buffer; writing individual bytes is
+ * too much of a pain (sigh) */
+static uint8_t ao_usb_tx2_buffer[AO_USB_IN_SIZE];
+static uint8_t ao_usb_tx2_count;
+#endif
+
/*
* End point register indices
*/
@@ -108,6 +133,7 @@ static uint8_t ao_usb_rx_count, ao_usb_rx_pos;
#define AO_USB_INT_EPR 1
#define AO_USB_OUT_EPR 2
#define AO_USB_IN_EPR 3
+#define AO_USB_IN2_EPR 4
/* Marks when we don't need to send an IN packet.
* This happens only when the last IN packet is not full,
@@ -122,6 +148,16 @@ static uint8_t ao_usb_in_flushed;
*/
static uint8_t ao_usb_in_pending;
+#if AO_USB_HAS_IN2
+/* Marks when we have delivered an IN packet to the hardware
+ * and it has not been received yet. ao_sleep on this address
+ * to wait for it to be delivered.
+ */
+static uint8_t ao_usb_in2_pending;
+static uint16_t in2_count;
+static uint8_t ao_usb_in2_flushed;
+#endif
+
/* Marks when an OUT packet has been received by the hardware
* but not pulled to the shadow buffer.
*/
@@ -129,10 +165,9 @@ static uint8_t ao_usb_out_avail;
uint8_t ao_usb_running;
static uint8_t ao_usb_configuration;
-#define AO_USB_EP0_GOT_RESET 1
-#define AO_USB_EP0_GOT_SETUP 2
-#define AO_USB_EP0_GOT_RX_DATA 4
-#define AO_USB_EP0_GOT_TX_ACK 8
+#define AO_USB_EP0_GOT_SETUP 1
+#define AO_USB_EP0_GOT_RX_DATA 2
+#define AO_USB_EP0_GOT_TX_ACK 4
static uint8_t ao_usb_ep0_receive;
static uint8_t ao_usb_address;
@@ -338,16 +373,29 @@ ao_usb_alloc_buffers(void)
ao_usb_ep0_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr);
ao_usb_sram_addr += AO_USB_CONTROL_SIZE;
+
+#if AO_USB_HAS_INT
ao_usb_int_tx_offset = ao_usb_sram_addr;
ao_usb_sram_addr += AO_USB_INT_SIZE;
+#endif
+#if AO_USB_HAS_OUT
ao_usb_out_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr);
ao_usb_out_rx_offset = ao_usb_sram_addr;
ao_usb_sram_addr += AO_USB_OUT_SIZE;
+#endif
+#if AO_USB_HAS_IN
ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr);
ao_usb_in_tx_offset = ao_usb_sram_addr;
ao_usb_sram_addr += AO_USB_IN_SIZE;
+#endif
+
+#if AO_USB_HAS_IN2
+ ao_usb_in2_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr);
+ ao_usb_in2_tx_offset = ao_usb_sram_addr;
+ ao_usb_sram_addr += AO_USB_IN_SIZE;
+#endif
}
static void
@@ -396,6 +444,7 @@ ao_usb_set_configuration(void)
{
debug ("ao_usb_set_configuration\n");
+#if AO_USB_HAS_INT
/* Set up the INT end point */
ao_usb_bdt[AO_USB_INT_EPR].single.addr_tx = ao_usb_int_tx_offset;
ao_usb_bdt[AO_USB_INT_EPR].single.count_tx = 0;
@@ -405,7 +454,9 @@ ao_usb_set_configuration(void)
STM_USB_EPR_EP_TYPE_INTERRUPT,
STM_USB_EPR_STAT_RX_DISABLED,
STM_USB_EPR_STAT_TX_NAK);
+#endif
+#if AO_USB_HAS_OUT
/* Set up the OUT end point */
ao_usb_bdt[AO_USB_OUT_EPR].single.addr_rx = ao_usb_out_rx_offset;
ao_usb_bdt[AO_USB_OUT_EPR].single.count_rx = ((1 << STM_USB_BDT_COUNT_RX_BL_SIZE) |
@@ -416,7 +467,9 @@ ao_usb_set_configuration(void)
STM_USB_EPR_EP_TYPE_BULK,
STM_USB_EPR_STAT_RX_VALID,
STM_USB_EPR_STAT_TX_DISABLED);
+#endif
+#if AO_USB_HAS_IN
/* Set up the IN end point */
ao_usb_bdt[AO_USB_IN_EPR].single.addr_tx = ao_usb_in_tx_offset;
ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = 0;
@@ -426,6 +479,19 @@ ao_usb_set_configuration(void)
STM_USB_EPR_EP_TYPE_BULK,
STM_USB_EPR_STAT_RX_DISABLED,
STM_USB_EPR_STAT_TX_NAK);
+#endif
+
+#if AO_USB_HAS_IN2
+ /* Set up the IN2 end point */
+ ao_usb_bdt[AO_USB_IN2_EPR].single.addr_tx = ao_usb_in2_tx_offset;
+ ao_usb_bdt[AO_USB_IN2_EPR].single.count_tx = 0;
+
+ ao_usb_init_ep(AO_USB_IN2_EPR,
+ AO_USB_IN2_EP,
+ STM_USB_EPR_EP_TYPE_BULK,
+ STM_USB_EPR_STAT_RX_DISABLED,
+ STM_USB_EPR_STAT_TX_NAK);
+#endif
ao_usb_running = 1;
#if AO_USB_DIRECTIO
@@ -559,6 +625,36 @@ ao_usb_ep0_in_start(uint16_t max)
static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8};
+#if AO_USB_DEVICE_ID_SERIAL
+static uint8_t ao_usb_serial[2 + 48];
+
+/* Convert a 32-bit value to 8 hexidecimal UCS2 characters */
+static void
+hex_to_ucs2(uint32_t in, uint8_t *out)
+{
+ int i;
+
+ for (i = 28; i >= 0; i -= 4) {
+ uint8_t bits = (in >> i) & 0xf;
+ *out++ = ((bits < 10) ? '0' : ('a' - 10)) + bits;
+ *out++ = 0;
+ }
+}
+
+/* Encode the device ID (96 bits) in hexidecimal to use as a device
+ * serial number
+ */
+static void
+ao_usb_serial_init(void)
+{
+ ao_usb_serial[0] = 50; /* length */
+ ao_usb_serial[1] = AO_USB_DESC_STRING;
+ hex_to_ucs2(stm_device_id.u_id0, ao_usb_serial + 2 + 0);
+ hex_to_ucs2(stm_device_id.u_id1, ao_usb_serial + 2 + 16);
+ hex_to_ucs2(stm_device_id.u_id2, ao_usb_serial + 2 + 32);
+}
+#endif
+
/* Walk through the list of descriptors and find a match
*/
static void
@@ -576,6 +672,13 @@ ao_usb_get_descriptor(uint16_t value)
len = descriptor[2];
else
len = descriptor[0];
+#if AO_USB_DEVICE_ID_SERIAL
+ /* Slightly hacky - the serial number is string 3 */
+ if (type == AO_USB_DESC_STRING && (value & 0xff) == 3) {
+ descriptor = ao_usb_serial;
+ len = sizeof (ao_usb_serial);
+ }
+#endif
ao_usb_ep0_in_set(descriptor, len);
break;
}
@@ -686,11 +789,6 @@ static void
ao_usb_ep0_handle(uint8_t receive)
{
ao_usb_ep0_receive = 0;
- if (receive & AO_USB_EP0_GOT_RESET) {
- debug ("\treset\n");
- ao_usb_set_ep0();
- return;
- }
if (receive & AO_USB_EP0_GOT_SETUP) {
debug ("\tsetup\n");
ao_usb_ep0_setup();
@@ -721,6 +819,25 @@ ao_usb_ep0_handle(uint8_t receive)
}
}
+#if AO_POWER_MANAGEMENT
+void
+ao_usb_suspend(void)
+{
+ stm_usb.cntr |= (1 << STM_USB_CNTR_FSUSP);
+ ao_power_suspend();
+ stm_usb.cntr |= (1 << STM_USB_CNTR_LP_MODE);
+ ao_clock_suspend();
+}
+
+void
+ao_usb_wakeup(void)
+{
+ ao_clock_resume();
+ stm_usb.cntr &= ~(1 << STM_USB_CNTR_FSUSP);
+ ao_power_resume();
+}
+#endif
+
void
stm_usb_isr(void)
{
@@ -773,6 +890,16 @@ stm_usb_isr(void)
ao_wakeup(&ao_usb_in_pending);
}
break;
+#if AO_USB_HAS_IN2
+ case AO_USB_IN2_EPR:
+ ++in2_count;
+ _tx_dbg1("TX2 ISR", epr);
+ if (ao_usb_epr_ctr_tx(epr)) {
+ ao_usb_in2_pending = 0;
+ ao_wakeup(&ao_usb_in2_pending);
+ }
+ break;
+#endif
case AO_USB_INT_EPR:
++int_count;
if (ao_usb_epr_ctr_tx(epr))
@@ -784,12 +911,22 @@ stm_usb_isr(void)
if (istr & (1 << STM_USB_ISTR_RESET)) {
++reset_count;
- ao_usb_ep0_receive |= AO_USB_EP0_GOT_RESET;
- ao_usb_ep0_handle(ao_usb_ep0_receive);
+ debug ("\treset\n");
+ ao_usb_set_ep0();
}
-
+#if AO_POWER_MANAGEMENT
+ if (istr & (1 << STM_USB_ISTR_SUSP)) {
+ debug ("\tsuspend\n");
+ ao_usb_suspend();
+ }
+ if (istr & (1 << STM_USB_ISTR_WKUP)) {
+ debug ("\twakeup\n");
+ ao_usb_wakeup();
+ }
+#endif
}
+#if AO_USB_HAS_IN
/* Queue the current IN buffer for transmission */
static void
_ao_usb_in_send(void)
@@ -868,7 +1005,90 @@ ao_usb_putchar(char c)
}
ao_arch_release_interrupts();
}
+#endif
+
+#if AO_USB_HAS_IN2
+/* Queue the current IN buffer for transmission */
+static void
+_ao_usb_in2_send(void)
+{
+ _tx_dbg0("in2_send start");
+ debug ("send2 %d\n", ao_usb_tx_count);
+ while (ao_usb_in2_pending)
+ ao_sleep(&ao_usb_in2_pending);
+ ao_usb_in2_pending = 1;
+ if (ao_usb_tx2_count != AO_USB_IN_SIZE)
+ ao_usb_in2_flushed = 1;
+ ao_usb_copy_tx(ao_usb_tx2_buffer, ao_usb_in2_tx_buffer, ao_usb_tx2_count);
+ ao_usb_bdt[AO_USB_IN2_EPR].single.addr_tx = ao_usb_in_tx_offset;
+ ao_usb_bdt[AO_USB_IN2_EPR].single.count_tx = ao_usb_tx_count;
+ ao_usb_tx2_count = 0;
+ _ao_usb_set_stat_tx(AO_USB_IN2_EPR, STM_USB_EPR_STAT_TX_VALID);
+ _tx_dbg0("in2_send end");
+}
+
+/* Wait for a free IN buffer. Interrupts are blocked */
+static void
+_ao_usb_in2_wait(void)
+{
+ for (;;) {
+ /* Check if the current buffer is writable */
+ if (ao_usb_tx2_count < AO_USB_IN_SIZE)
+ break;
+
+ _tx_dbg0("in2_wait top");
+ /* Wait for an IN buffer to be ready */
+ while (ao_usb_in2_pending)
+ ao_sleep(&ao_usb_in2_pending);
+ _tx_dbg0("in_wait bottom");
+ }
+}
+
+void
+ao_usb_flush2(void)
+{
+ if (!ao_usb_running)
+ return;
+
+ /* Anytime we've sent a character since
+ * the last time we flushed, we'll need
+ * to send a packet -- the only other time
+ * we would send a packet is when that
+ * packet was full, in which case we now
+ * want to send an empty packet
+ */
+ ao_arch_block_interrupts();
+ while (!ao_usb_in2_flushed) {
+ _tx_dbg0("flush2 top");
+ _ao_usb_in2_send();
+ _tx_dbg0("flush2 end");
+ }
+ ao_arch_release_interrupts();
+}
+
+void
+ao_usb_putchar2(char c)
+{
+ if (!ao_usb_running)
+ return;
+
+ ao_arch_block_interrupts();
+ _ao_usb_in2_wait();
+ ao_usb_in2_flushed = 0;
+ ao_usb_tx2_buffer[ao_usb_tx2_count++] = (uint8_t) c;
+
+ /* Send the packet when full */
+ if (ao_usb_tx2_count == AO_USB_IN_SIZE) {
+ _tx_dbg0("putchar2 full");
+ _ao_usb_in2_send();
+ _tx_dbg0("putchar2 flushed");
+ }
+ ao_arch_release_interrupts();
+}
+#endif
+
+#if AO_USB_HAS_OUT
static void
_ao_usb_out_recv(void)
{
@@ -925,6 +1145,7 @@ ao_usb_getchar(void)
ao_arch_release_interrupts();
return c;
}
+#endif
#if AO_USB_DIRECTIO
uint16_t *
@@ -979,6 +1200,43 @@ ao_usb_write(uint16_t *buffer, uint16_t len)
_ao_usb_set_stat_tx(AO_USB_IN_EPR, STM_USB_EPR_STAT_TX_VALID);
ao_arch_release_interrupts();
}
+
+#if AO_USB_HAS_IN2
+void
+ao_usb_write2(uint16_t *buffer, uint16_t len)
+{
+ ao_arch_block_interrupts();
+
+ /* Wait for everything to be ready at the same time */
+ for (;;) {
+ /* Make sure USB is connected */
+ if (!ao_usb_running) {
+ ao_sleep(&ao_usb_running);
+ continue;
+ }
+
+ /* Flush any pending regular I/O */
+ if (ao_usb_tx2_count) {
+ _ao_usb_in2_send();
+ continue;
+ }
+
+ /* Wait for an idle IN buffer */
+ if (ao_usb_in2_pending) {
+ ao_sleep(&ao_usb_in2_pending);
+ continue;
+ }
+ break;
+ }
+
+ ao_usb_in2_pending = 1;
+ ao_usb_in2_flushed = (len != AO_USB_IN_SIZE);
+ ao_usb_bdt[AO_USB_IN2_EPR].single.addr_tx = ao_usb_packet_buffer_offset(buffer);
+ ao_usb_bdt[AO_USB_IN2_EPR].single.count_tx = len;
+ _ao_usb_set_stat_tx(AO_USB_IN2_EPR, STM_USB_EPR_STAT_TX_VALID);
+ ao_arch_release_interrupts();
+}
+#endif
#endif
void
@@ -1050,8 +1308,8 @@ ao_usb_enable(void)
stm_usb.cntr = ((1 << STM_USB_CNTR_CTRM) |
(0 << STM_USB_CNTR_PMAOVRM) |
(0 << STM_USB_CNTR_ERRM) |
- (0 << STM_USB_CNTR_WKUPM) |
- (0 << STM_USB_CNTR_SUSPM) |
+ (AO_POWER_MANAGEMENT << STM_USB_CNTR_WKUPM) |
+ (AO_POWER_MANAGEMENT << STM_USB_CNTR_SUSPM) |
(1 << STM_USB_CNTR_RESETM) |
(0 << STM_USB_CNTR_SOFM) |
(0 << STM_USB_CNTR_ESOFM) |
@@ -1086,7 +1344,7 @@ ao_usb_echo(void)
}
#endif
-#if USB_DEBUG
+#if USB_STATUS
static void
ao_usb_irq(void)
{
@@ -1109,7 +1367,13 @@ ao_usb_init(void)
/* Set PA11/PA12 remapping bit */
stm_syscfg.cfgr1 |= (AO_PA11_PA12_RMP << STM_SYSCFG_CFGR1_PA11_PA12_RMP);
+#ifndef AO_USB_START_DISABLED
ao_usb_enable();
+#endif
+
+#if AO_USB_DEVICE_ID_SERIAL
+ ao_usb_serial_init();
+#endif
debug ("ao_usb_init\n");
ao_usb_ep0_state = AO_USB_EP0_IDLE;
@@ -1119,7 +1383,7 @@ ao_usb_init(void)
#if USB_ECHO
ao_add_task(&ao_usb_echo_task, ao_usb_echo, "usb echo");
#endif
-#if USB_DEBUG
+#if USB_STATUS
ao_cmd_register(&ao_usb_cmds[0]);
#endif
#if !USB_ECHO
diff --git a/src/stmf0/registers.ld b/src/stmf0/registers.ld
index 598fc1af..1f9862b1 100644
--- a/src/stmf0/registers.ld
+++ b/src/stmf0/registers.ld
@@ -54,4 +54,4 @@ stm_mpu = 0xe000ed90;
/* calibration data in system memory */
stm_cal = 0x1ffff7b8;
stm_flash_size_04x = 0x1ffff7cc;
-stm_device_id = 0x1ff80050;
+stm_device_id = 0x1ffff7ac;
diff --git a/src/stmf0/stm32f0.h b/src/stmf0/stm32f0.h
index ce8ca456..33eb9c88 100644
--- a/src/stmf0/stm32f0.h
+++ b/src/stmf0/stm32f0.h
@@ -475,6 +475,24 @@ extern struct stm_rcc stm_rcc;
#define STM_RCC_CR2_HSI14RDY 1
#define STM_RCC_CR2_HSI14ON 0
+#define STM_RCC_CFGR2_PREDIV 0
+#define STM_RCC_CFGR2_PREDIV_1 0x0
+#define STM_RCC_CFGR2_PREDIV_2 0x1
+#define STM_RCC_CFGR2_PREDIV_3 0x2
+#define STM_RCC_CFGR2_PREDIV_4 0x3
+#define STM_RCC_CFGR2_PREDIV_5 0x4
+#define STM_RCC_CFGR2_PREDIV_6 0x5
+#define STM_RCC_CFGR2_PREDIV_7 0x6
+#define STM_RCC_CFGR2_PREDIV_8 0x7
+#define STM_RCC_CFGR2_PREDIV_9 0x8
+#define STM_RCC_CFGR2_PREDIV_10 0x9
+#define STM_RCC_CFGR2_PREDIV_11 0xa
+#define STM_RCC_CFGR2_PREDIV_12 0xb
+#define STM_RCC_CFGR2_PREDIV_13 0xc
+#define STM_RCC_CFGR2_PREDIV_14 0xd
+#define STM_RCC_CFGR2_PREDIV_15 0xe
+#define STM_RCC_CFGR2_PREDIV_16 0xf
+
#define STM_RCC_CFGR3_USART3SW 18
#define STM_RCC_CFGR3_USART2SW 16
#define STM_RCC_CFGR3_ADCSW 8
@@ -795,7 +813,7 @@ isr(tim7)
#define STM_ISR_TSC_POS 8
#define STM_ISR_DMA_CH1_POS 9
#define STM_ISR_DMA_CH2_3_DMA2_CH1_2_POS 10
-#define STM_ISR_DMA_CH44_5_6_7_DMA2_CH3_4_5_POS 11
+#define STM_ISR_DMA_CH4_5_6_7_DMA2_CH3_4_5_POS 11
#define STM_ISR_ADC_COMP_POS 12
#define STM_ISR_TIM1_BRK_UP_TRG_COM_POS 13
#define STM_ISR_TIM1_CC_POS 14
@@ -819,8 +837,11 @@ isr(tim7)
struct stm_syscfg {
vuint32_t cfgr1;
+ uint32_t reserved_04;
vuint32_t exticr[4];
vuint32_t cfgr2;
+ uint8_t reserved_1c[0x80-0x1c];
+ vuint32_t itline[31];
};
extern struct stm_syscfg stm_syscfg;
@@ -858,7 +879,13 @@ extern struct stm_syscfg stm_syscfg;
#define STM_SYSCFG_CFGR1_MEM_MODE_SRAM 3
#define STM_SYSCFG_CFGR1_MEM_MODE_MASK 3
-#if 0
+#define STM_SYSCFG_EXTICR_PA 0
+#define STM_SYSCFG_EXTICR_PB 1
+#define STM_SYSCFG_EXTICR_PC 2
+#define STM_SYSCFG_EXTICR_PD 3
+#define STM_SYSCFG_EXTICR_PE 4
+#define STM_SYSCFG_EXTICR_PF 5
+
static inline void
stm_exticr_set(struct stm_gpio *gpio, int pin) {
uint8_t reg = pin >> 2;
@@ -879,8 +906,6 @@ stm_exticr_set(struct stm_gpio *gpio, int pin) {
stm_syscfg.exticr[reg] = (stm_syscfg.exticr[reg] & ~(0xf << shift)) | val << shift;
}
-#endif
-
struct stm_dma_channel {
vuint32_t ccr;
@@ -890,7 +915,7 @@ struct stm_dma_channel {
vuint32_t reserved;
};
-#define STM_NUM_DMA 6
+#define STM_NUM_DMA 5
struct stm_dma {
vuint32_t isr;
@@ -900,7 +925,7 @@ struct stm_dma {
extern struct stm_dma stm_dma;
-/* DMA channels go from 1 to 6, instead of 0 to 5 (sigh)
+/* DMA channels go from 1 to 5, instead of 0 to 4 (sigh)
*/
#define STM_DMA_INDEX(channel) ((channel) - 1)
@@ -1042,7 +1067,7 @@ extern struct stm_spi stm_spi1, stm_spi2, stm_spi3;
#define STM_SPI_CR1_BIDIOE 14
#define STM_SPI_CR1_CRCEN 13
#define STM_SPI_CR1_CRCNEXT 12
-#define STM_SPI_CR1_DFF 11
+#define STM_SPI_CR1_CRCL 11
#define STM_SPI_CR1_RXONLY 10
#define STM_SPI_CR1_SSM 9
#define STM_SPI_CR1_SSI 8
@@ -1063,17 +1088,43 @@ extern struct stm_spi stm_spi1, stm_spi2, stm_spi3;
#define STM_SPI_CR1_CPOL 1
#define STM_SPI_CR1_CPHA 0
+#define STM_SPI_CR2_LDMA_TX 14
+#define STM_SPI_CR2_LDMA_RX 13
+#define STM_SPI_CR2_FRXTH 12
+#define STM_SPI_CR2_DS 8
+#define STM_SPI_CR2_DS_4 0x3
+#define STM_SPI_CR2_DS_5 0x4
+#define STM_SPI_CR2_DS_6 0x5
+#define STM_SPI_CR2_DS_7 0x6
+#define STM_SPI_CR2_DS_8 0x7
+#define STM_SPI_CR2_DS_9 0x8
+#define STM_SPI_CR2_DS_10 0x9
+#define STM_SPI_CR2_DS_11 0xa
+#define STM_SPI_CR2_DS_12 0xb
+#define STM_SPI_CR2_DS_13 0xc
+#define STM_SPI_CR2_DS_14 0xd
+#define STM_SPI_CR2_DS_15 0xe
+#define STM_SPI_CR2_DS_16 0xf
#define STM_SPI_CR2_TXEIE 7
#define STM_SPI_CR2_RXNEIE 6
#define STM_SPI_CR2_ERRIE 5
+#define STM_SPI_CR2_FRF 4
+# define STM_SPI_CR2_FRF_MOTOROLA 0
+# define STM_SPI_CR2_FRF_TI 1
+#define STM_SPI_CR2_NSSP 3
#define STM_SPI_CR2_SSOE 2
#define STM_SPI_CR2_TXDMAEN 1
#define STM_SPI_CR2_RXDMAEN 0
+#define STM_SPI_SR_FTLVL 11
+#define STM_SPI_SR_FRLVL 9
+#define STM_SPI_SR_FRE 8
#define STM_SPI_SR_BSY 7
#define STM_SPI_SR_OVR 6
#define STM_SPI_SR_MODF 5
#define STM_SPI_SR_CRCERR 4
+#define STM_SPI_SR_UDR 3
+#define STM_SPI_SR_CHSIDE 2
#define STM_SPI_SR_TXE 1
#define STM_SPI_SR_RXNE 0
@@ -1293,7 +1344,7 @@ extern struct stm_i2c stm_i2c1, stm_i2c2;
#define STM_I2C_CCR_CCR 0
#define STM_I2C_CCR_MASK 0x7ff
-struct stm_tim234 {
+struct stm_tim23 {
vuint32_t cr1;
vuint32_t cr2;
vuint32_t smcr;
@@ -1318,204 +1369,205 @@ struct stm_tim234 {
uint32_t reserved_44;
vuint32_t dcr;
vuint32_t dmar;
-
- uint32_t reserved_50;
};
-extern struct stm_tim234 stm_tim2, stm_tim3, stm_tim4;
-
-#define STM_TIM234_CR1_CKD 8
-#define STM_TIM234_CR1_CKD_1 0
-#define STM_TIM234_CR1_CKD_2 1
-#define STM_TIM234_CR1_CKD_4 2
-#define STM_TIM234_CR1_CKD_MASK 3
-#define STM_TIM234_CR1_ARPE 7
-#define STM_TIM234_CR1_CMS 5
-#define STM_TIM234_CR1_CMS_EDGE 0
-#define STM_TIM234_CR1_CMS_CENTER_1 1
-#define STM_TIM234_CR1_CMS_CENTER_2 2
-#define STM_TIM234_CR1_CMS_CENTER_3 3
-#define STM_TIM234_CR1_CMS_MASK 3
-#define STM_TIM234_CR1_DIR 4
-#define STM_TIM234_CR1_DIR_UP 0
-#define STM_TIM234_CR1_DIR_DOWN 1
-#define STM_TIM234_CR1_OPM 3
-#define STM_TIM234_CR1_URS 2
-#define STM_TIM234_CR1_UDIS 1
-#define STM_TIM234_CR1_CEN 0
-
-#define STM_TIM234_CR2_TI1S 7
-#define STM_TIM234_CR2_MMS 4
-#define STM_TIM234_CR2_MMS_RESET 0
-#define STM_TIM234_CR2_MMS_ENABLE 1
-#define STM_TIM234_CR2_MMS_UPDATE 2
-#define STM_TIM234_CR2_MMS_COMPARE_PULSE 3
-#define STM_TIM234_CR2_MMS_COMPARE_OC1REF 4
-#define STM_TIM234_CR2_MMS_COMPARE_OC2REF 5
-#define STM_TIM234_CR2_MMS_COMPARE_OC3REF 6
-#define STM_TIM234_CR2_MMS_COMPARE_OC4REF 7
-#define STM_TIM234_CR2_MMS_MASK 7
-#define STM_TIM234_CR2_CCDS 3
-
-#define STM_TIM234_SMCR_ETP 15
-#define STM_TIM234_SMCR_ECE 14
-#define STM_TIM234_SMCR_ETPS 12
-#define STM_TIM234_SMCR_ETPS_OFF 0
-#define STM_TIM234_SMCR_ETPS_DIV_2 1
-#define STM_TIM234_SMCR_ETPS_DIV_4 2
-#define STM_TIM234_SMCR_ETPS_DIV_8 3
-#define STM_TIM234_SMCR_ETPS_MASK 3
-#define STM_TIM234_SMCR_ETF 8
-#define STM_TIM234_SMCR_ETF_NONE 0
-#define STM_TIM234_SMCR_ETF_INT_N_2 1
-#define STM_TIM234_SMCR_ETF_INT_N_4 2
-#define STM_TIM234_SMCR_ETF_INT_N_8 3
-#define STM_TIM234_SMCR_ETF_DTS_2_N_6 4
-#define STM_TIM234_SMCR_ETF_DTS_2_N_8 5
-#define STM_TIM234_SMCR_ETF_DTS_4_N_6 6
-#define STM_TIM234_SMCR_ETF_DTS_4_N_8 7
-#define STM_TIM234_SMCR_ETF_DTS_8_N_6 8
-#define STM_TIM234_SMCR_ETF_DTS_8_N_8 9
-#define STM_TIM234_SMCR_ETF_DTS_16_N_5 10
-#define STM_TIM234_SMCR_ETF_DTS_16_N_6 11
-#define STM_TIM234_SMCR_ETF_DTS_16_N_8 12
-#define STM_TIM234_SMCR_ETF_DTS_32_N_5 13
-#define STM_TIM234_SMCR_ETF_DTS_32_N_6 14
-#define STM_TIM234_SMCR_ETF_DTS_32_N_8 15
-#define STM_TIM234_SMCR_ETF_MASK 15
-#define STM_TIM234_SMCR_MSM 7
-#define STM_TIM234_SMCR_TS 4
-#define STM_TIM234_SMCR_TS_ITR0 0
-#define STM_TIM234_SMCR_TS_ITR1 1
-#define STM_TIM234_SMCR_TS_ITR2 2
-#define STM_TIM234_SMCR_TS_ITR3 3
-#define STM_TIM234_SMCR_TS_TI1F_ED 4
-#define STM_TIM234_SMCR_TS_TI1FP1 5
-#define STM_TIM234_SMCR_TS_TI2FP2 6
-#define STM_TIM234_SMCR_TS_ETRF 7
-#define STM_TIM234_SMCR_TS_MASK 7
-#define STM_TIM234_SMCR_OCCS 3
-#define STM_TIM234_SMCR_SMS 0
-#define STM_TIM234_SMCR_SMS_DISABLE 0
-#define STM_TIM234_SMCR_SMS_ENCODER_MODE_1 1
-#define STM_TIM234_SMCR_SMS_ENCODER_MODE_2 2
-#define STM_TIM234_SMCR_SMS_ENCODER_MODE_3 3
-#define STM_TIM234_SMCR_SMS_RESET_MODE 4
-#define STM_TIM234_SMCR_SMS_GATED_MODE 5
-#define STM_TIM234_SMCR_SMS_TRIGGER_MODE 6
-#define STM_TIM234_SMCR_SMS_EXTERNAL_CLOCK 7
-#define STM_TIM234_SMCR_SMS_MASK 7
-
-#define STM_TIM234_SR_CC4OF 12
-#define STM_TIM234_SR_CC3OF 11
-#define STM_TIM234_SR_CC2OF 10
-#define STM_TIM234_SR_CC1OF 9
-#define STM_TIM234_SR_TIF 6
-#define STM_TIM234_SR_CC4IF 4
-#define STM_TIM234_SR_CC3IF 3
-#define STM_TIM234_SR_CC2IF 2
-#define STM_TIM234_SR_CC1IF 1
-#define STM_TIM234_SR_UIF 0
-
-#define STM_TIM234_EGR_TG 6
-#define STM_TIM234_EGR_CC4G 4
-#define STM_TIM234_EGR_CC3G 3
-#define STM_TIM234_EGR_CC2G 2
-#define STM_TIM234_EGR_CC1G 1
-#define STM_TIM234_EGR_UG 0
-
-#define STM_TIM234_CCMR1_OC2CE 15
-#define STM_TIM234_CCMR1_OC2M 12
-#define STM_TIM234_CCMR1_OC2M_FROZEN 0
-#define STM_TIM234_CCMR1_OC2M_SET_HIGH_ON_MATCH 1
-#define STM_TIM234_CCMR1_OC2M_SET_LOW_ON_MATCH 2
-#define STM_TIM234_CCMR1_OC2M_TOGGLE 3
-#define STM_TIM234_CCMR1_OC2M_FORCE_LOW 4
-#define STM_TIM234_CCMR1_OC2M_FORCE_HIGH 5
-#define STM_TIM234_CCMR1_OC2M_PWM_MODE_1 6
-#define STM_TIM234_CCMR1_OC2M_PWM_MODE_2 7
-#define STM_TIM234_CCMR1_OC2M_MASK 7
-#define STM_TIM234_CCMR1_OC2PE 11
-#define STM_TIM234_CCMR1_OC2FE 10
-#define STM_TIM234_CCMR1_CC2S 8
-#define STM_TIM234_CCMR1_CC2S_OUTPUT 0
-#define STM_TIM234_CCMR1_CC2S_INPUT_TI2 1
-#define STM_TIM234_CCMR1_CC2S_INPUT_TI1 2
-#define STM_TIM234_CCMR1_CC2S_INPUT_TRC 3
-#define STM_TIM234_CCMR1_CC2S_MASK 3
-
-#define STM_TIM234_CCMR1_OC1CE 7
-#define STM_TIM234_CCMR1_OC1M 4
-#define STM_TIM234_CCMR1_OC1M_FROZEN 0
-#define STM_TIM234_CCMR1_OC1M_SET_HIGH_ON_MATCH 1
-#define STM_TIM234_CCMR1_OC1M_SET_LOW_ON_MATCH 2
-#define STM_TIM234_CCMR1_OC1M_TOGGLE 3
-#define STM_TIM234_CCMR1_OC1M_FORCE_LOW 4
-#define STM_TIM234_CCMR1_OC1M_FORCE_HIGH 5
-#define STM_TIM234_CCMR1_OC1M_PWM_MODE_1 6
-#define STM_TIM234_CCMR1_OC1M_PWM_MODE_2 7
-#define STM_TIM234_CCMR1_OC1M_MASK 7
-#define STM_TIM234_CCMR1_OC1PE 11
-#define STM_TIM234_CCMR1_OC1FE 2
-#define STM_TIM234_CCMR1_CC1S 0
-#define STM_TIM234_CCMR1_CC1S_OUTPUT 0
-#define STM_TIM234_CCMR1_CC1S_INPUT_TI1 1
-#define STM_TIM234_CCMR1_CC1S_INPUT_TI2 2
-#define STM_TIM234_CCMR1_CC1S_INPUT_TRC 3
-#define STM_TIM234_CCMR1_CC1S_MASK 3
-
-#define STM_TIM234_CCMR2_OC4CE 15
-#define STM_TIM234_CCMR2_OC4M 12
-#define STM_TIM234_CCMR2_OC4M_FROZEN 0
-#define STM_TIM234_CCMR2_OC4M_SET_HIGH_ON_MATCH 1
-#define STM_TIM234_CCMR2_OC4M_SET_LOW_ON_MATCH 2
-#define STM_TIM234_CCMR2_OC4M_TOGGLE 3
-#define STM_TIM234_CCMR2_OC4M_FORCE_LOW 4
-#define STM_TIM234_CCMR2_OC4M_FORCE_HIGH 5
-#define STM_TIM234_CCMR2_OC4M_PWM_MODE_1 6
-#define STM_TIM234_CCMR2_OC4M_PWM_MODE_2 7
-#define STM_TIM234_CCMR2_OC4M_MASK 7
-#define STM_TIM234_CCMR2_OC4PE 11
-#define STM_TIM234_CCMR2_OC4FE 10
-#define STM_TIM234_CCMR2_CC4S 8
-#define STM_TIM234_CCMR2_CC4S_OUTPUT 0
-#define STM_TIM234_CCMR2_CC4S_INPUT_TI4 1
-#define STM_TIM234_CCMR2_CC4S_INPUT_TI3 2
-#define STM_TIM234_CCMR2_CC4S_INPUT_TRC 3
-#define STM_TIM234_CCMR2_CC4S_MASK 3
-
-#define STM_TIM234_CCMR2_OC3CE 7
-#define STM_TIM234_CCMR2_OC3M 4
-#define STM_TIM234_CCMR2_OC3M_FROZEN 0
-#define STM_TIM234_CCMR2_OC3M_SET_HIGH_ON_MATCH 1
-#define STM_TIM234_CCMR2_OC3M_SET_LOW_ON_MATCH 2
-#define STM_TIM234_CCMR2_OC3M_TOGGLE 3
-#define STM_TIM234_CCMR2_OC3M_FORCE_LOW 4
-#define STM_TIM234_CCMR2_OC3M_FORCE_HIGH 5
-#define STM_TIM234_CCMR2_OC3M_PWM_MODE_1 6
-#define STM_TIM234_CCMR2_OC3M_PWM_MODE_2 7
-#define STM_TIM234_CCMR2_OC3M_MASK 7
-#define STM_TIM234_CCMR2_OC3PE 11
-#define STM_TIM234_CCMR2_OC3FE 2
-#define STM_TIM234_CCMR2_CC3S 0
-#define STM_TIM234_CCMR2_CC3S_OUTPUT 0
-#define STM_TIM234_CCMR2_CC3S_INPUT_TI3 1
-#define STM_TIM234_CCMR2_CC3S_INPUT_TI4 2
-#define STM_TIM234_CCMR2_CC3S_INPUT_TRC 3
-#define STM_TIM234_CCMR2_CC3S_MASK 3
-
-#define STM_TIM234_CCER_CC4NP 15
-#define STM_TIM234_CCER_CC4P 13
-#define STM_TIM234_CCER_CC4E 12
-#define STM_TIM234_CCER_CC3NP 11
-#define STM_TIM234_CCER_CC3P 9
-#define STM_TIM234_CCER_CC3E 8
-#define STM_TIM234_CCER_CC2NP 7
-#define STM_TIM234_CCER_CC2P 5
-#define STM_TIM234_CCER_CC2E 4
-#define STM_TIM234_CCER_CC1NP 3
-#define STM_TIM234_CCER_CC1P 1
-#define STM_TIM234_CCER_CC1E 0
+extern struct stm_tim23 stm_tim2, stm_tim3;
+
+#define stm_tim3 (*(struct stm_tim23 *) 0x40000400)
+#define stm_tim2 (*(struct stm_tim23 *) 0x40000000)
+
+#define STM_TIM23_CR1_CKD 8
+#define STM_TIM23_CR1_CKD_1 0
+#define STM_TIM23_CR1_CKD_2 1
+#define STM_TIM23_CR1_CKD_4 2
+#define STM_TIM23_CR1_CKD_MASK 3
+#define STM_TIM23_CR1_ARPE 7
+#define STM_TIM23_CR1_CMS 5
+#define STM_TIM23_CR1_CMS_EDGE 0
+#define STM_TIM23_CR1_CMS_CENTER_1 1
+#define STM_TIM23_CR1_CMS_CENTER_2 2
+#define STM_TIM23_CR1_CMS_CENTER_3 3
+#define STM_TIM23_CR1_CMS_MASK 3
+#define STM_TIM23_CR1_DIR 4
+#define STM_TIM23_CR1_DIR_UP 0
+#define STM_TIM23_CR1_DIR_DOWN 1
+#define STM_TIM23_CR1_OPM 3
+#define STM_TIM23_CR1_URS 2
+#define STM_TIM23_CR1_UDIS 1
+#define STM_TIM23_CR1_CEN 0
+
+#define STM_TIM23_CR2_TI1S 7
+#define STM_TIM23_CR2_MMS 4
+#define STM_TIM23_CR2_MMS_RESET 0
+#define STM_TIM23_CR2_MMS_ENABLE 1
+#define STM_TIM23_CR2_MMS_UPDATE 2
+#define STM_TIM23_CR2_MMS_COMPARE_PULSE 3
+#define STM_TIM23_CR2_MMS_COMPARE_OC1REF 4
+#define STM_TIM23_CR2_MMS_COMPARE_OC2REF 5
+#define STM_TIM23_CR2_MMS_COMPARE_OC3REF 6
+#define STM_TIM23_CR2_MMS_COMPARE_OC4REF 7
+#define STM_TIM23_CR2_MMS_MASK 7
+#define STM_TIM23_CR2_CCDS 3
+
+#define STM_TIM23_SMCR_ETP 15
+#define STM_TIM23_SMCR_ECE 14
+#define STM_TIM23_SMCR_ETPS 12
+#define STM_TIM23_SMCR_ETPS_OFF 0
+#define STM_TIM23_SMCR_ETPS_DIV_2 1
+#define STM_TIM23_SMCR_ETPS_DIV_4 2
+#define STM_TIM23_SMCR_ETPS_DIV_8 3
+#define STM_TIM23_SMCR_ETPS_MASK 3
+#define STM_TIM23_SMCR_ETF 8
+#define STM_TIM23_SMCR_ETF_NONE 0
+#define STM_TIM23_SMCR_ETF_INT_N_2 1
+#define STM_TIM23_SMCR_ETF_INT_N_4 2
+#define STM_TIM23_SMCR_ETF_INT_N_8 3
+#define STM_TIM23_SMCR_ETF_DTS_2_N_6 4
+#define STM_TIM23_SMCR_ETF_DTS_2_N_8 5
+#define STM_TIM23_SMCR_ETF_DTS_4_N_6 6
+#define STM_TIM23_SMCR_ETF_DTS_4_N_8 7
+#define STM_TIM23_SMCR_ETF_DTS_8_N_6 8
+#define STM_TIM23_SMCR_ETF_DTS_8_N_8 9
+#define STM_TIM23_SMCR_ETF_DTS_16_N_5 10
+#define STM_TIM23_SMCR_ETF_DTS_16_N_6 11
+#define STM_TIM23_SMCR_ETF_DTS_16_N_8 12
+#define STM_TIM23_SMCR_ETF_DTS_32_N_5 13
+#define STM_TIM23_SMCR_ETF_DTS_32_N_6 14
+#define STM_TIM23_SMCR_ETF_DTS_32_N_8 15
+#define STM_TIM23_SMCR_ETF_MASK 15
+#define STM_TIM23_SMCR_MSM 7
+#define STM_TIM23_SMCR_TS 4
+#define STM_TIM23_SMCR_TS_ITR0 0
+#define STM_TIM23_SMCR_TS_ITR1 1
+#define STM_TIM23_SMCR_TS_ITR2 2
+#define STM_TIM23_SMCR_TS_ITR3 3
+#define STM_TIM23_SMCR_TS_TI1F_ED 4
+#define STM_TIM23_SMCR_TS_TI1FP1 5
+#define STM_TIM23_SMCR_TS_TI2FP2 6
+#define STM_TIM23_SMCR_TS_ETRF 7
+#define STM_TIM23_SMCR_TS_MASK 7
+#define STM_TIM23_SMCR_OCCS 3
+#define STM_TIM23_SMCR_SMS 0
+#define STM_TIM23_SMCR_SMS_DISABLE 0
+#define STM_TIM23_SMCR_SMS_ENCODER_MODE_1 1
+#define STM_TIM23_SMCR_SMS_ENCODER_MODE_2 2
+#define STM_TIM23_SMCR_SMS_ENCODER_MODE_3 3
+#define STM_TIM23_SMCR_SMS_RESET_MODE 4
+#define STM_TIM23_SMCR_SMS_GATED_MODE 5
+#define STM_TIM23_SMCR_SMS_TRIGGER_MODE 6
+#define STM_TIM23_SMCR_SMS_EXTERNAL_CLOCK 7
+#define STM_TIM23_SMCR_SMS_MASK 7
+
+#define STM_TIM23_SR_CC4OF 12
+#define STM_TIM23_SR_CC3OF 11
+#define STM_TIM23_SR_CC2OF 10
+#define STM_TIM23_SR_CC1OF 9
+#define STM_TIM23_SR_TIF 6
+#define STM_TIM23_SR_CC4IF 4
+#define STM_TIM23_SR_CC3IF 3
+#define STM_TIM23_SR_CC2IF 2
+#define STM_TIM23_SR_CC1IF 1
+#define STM_TIM23_SR_UIF 0
+
+#define STM_TIM23_EGR_TG 6
+#define STM_TIM23_EGR_CC4G 4
+#define STM_TIM23_EGR_CC3G 3
+#define STM_TIM23_EGR_CC2G 2
+#define STM_TIM23_EGR_CC1G 1
+#define STM_TIM23_EGR_UG 0
+
+#define STM_TIM23_CCMR1_OC2CE 15
+#define STM_TIM23_CCMR1_OC2M 12
+#define STM_TIM23_CCMR1_OC2M_FROZEN 0
+#define STM_TIM23_CCMR1_OC2M_SET_HIGH_ON_MATCH 1
+#define STM_TIM23_CCMR1_OC2M_SET_LOW_ON_MATCH 2
+#define STM_TIM23_CCMR1_OC2M_TOGGLE 3
+#define STM_TIM23_CCMR1_OC2M_FORCE_LOW 4
+#define STM_TIM23_CCMR1_OC2M_FORCE_HIGH 5
+#define STM_TIM23_CCMR1_OC2M_PWM_MODE_1 6
+#define STM_TIM23_CCMR1_OC2M_PWM_MODE_2 7
+#define STM_TIM23_CCMR1_OC2M_MASK 7
+#define STM_TIM23_CCMR1_OC2PE 11
+#define STM_TIM23_CCMR1_OC2FE 10
+#define STM_TIM23_CCMR1_CC2S 8
+#define STM_TIM23_CCMR1_CC2S_OUTPUT 0
+#define STM_TIM23_CCMR1_CC2S_INPUT_TI2 1
+#define STM_TIM23_CCMR1_CC2S_INPUT_TI1 2
+#define STM_TIM23_CCMR1_CC2S_INPUT_TRC 3
+#define STM_TIM23_CCMR1_CC2S_MASK 3
+
+#define STM_TIM23_CCMR1_OC1CE 7
+#define STM_TIM23_CCMR1_OC1M 4
+#define STM_TIM23_CCMR1_OC1M_FROZEN 0
+#define STM_TIM23_CCMR1_OC1M_SET_HIGH_ON_MATCH 1
+#define STM_TIM23_CCMR1_OC1M_SET_LOW_ON_MATCH 2
+#define STM_TIM23_CCMR1_OC1M_TOGGLE 3
+#define STM_TIM23_CCMR1_OC1M_FORCE_LOW 4
+#define STM_TIM23_CCMR1_OC1M_FORCE_HIGH 5
+#define STM_TIM23_CCMR1_OC1M_PWM_MODE_1 6
+#define STM_TIM23_CCMR1_OC1M_PWM_MODE_2 7
+#define STM_TIM23_CCMR1_OC1M_MASK 7
+#define STM_TIM23_CCMR1_OC1PE 11
+#define STM_TIM23_CCMR1_OC1FE 2
+#define STM_TIM23_CCMR1_CC1S 0
+#define STM_TIM23_CCMR1_CC1S_OUTPUT 0
+#define STM_TIM23_CCMR1_CC1S_INPUT_TI1 1
+#define STM_TIM23_CCMR1_CC1S_INPUT_TI2 2
+#define STM_TIM23_CCMR1_CC1S_INPUT_TRC 3
+#define STM_TIM23_CCMR1_CC1S_MASK 3
+
+#define STM_TIM23_CCMR2_OC4CE 15
+#define STM_TIM23_CCMR2_OC4M 12
+#define STM_TIM23_CCMR2_OC4M_FROZEN 0
+#define STM_TIM23_CCMR2_OC4M_SET_HIGH_ON_MATCH 1
+#define STM_TIM23_CCMR2_OC4M_SET_LOW_ON_MATCH 2
+#define STM_TIM23_CCMR2_OC4M_TOGGLE 3
+#define STM_TIM23_CCMR2_OC4M_FORCE_LOW 4
+#define STM_TIM23_CCMR2_OC4M_FORCE_HIGH 5
+#define STM_TIM23_CCMR2_OC4M_PWM_MODE_1 6
+#define STM_TIM23_CCMR2_OC4M_PWM_MODE_2 7
+#define STM_TIM23_CCMR2_OC4M_MASK 7
+#define STM_TIM23_CCMR2_OC4PE 11
+#define STM_TIM23_CCMR2_OC4FE 10
+#define STM_TIM23_CCMR2_CC4S 8
+#define STM_TIM23_CCMR2_CC4S_OUTPUT 0
+#define STM_TIM23_CCMR2_CC4S_INPUT_TI4 1
+#define STM_TIM23_CCMR2_CC4S_INPUT_TI3 2
+#define STM_TIM23_CCMR2_CC4S_INPUT_TRC 3
+#define STM_TIM23_CCMR2_CC4S_MASK 3
+
+#define STM_TIM23_CCMR2_OC3CE 7
+#define STM_TIM23_CCMR2_OC3M 4
+#define STM_TIM23_CCMR2_OC3M_FROZEN 0
+#define STM_TIM23_CCMR2_OC3M_SET_HIGH_ON_MATCH 1
+#define STM_TIM23_CCMR2_OC3M_SET_LOW_ON_MATCH 2
+#define STM_TIM23_CCMR2_OC3M_TOGGLE 3
+#define STM_TIM23_CCMR2_OC3M_FORCE_LOW 4
+#define STM_TIM23_CCMR2_OC3M_FORCE_HIGH 5
+#define STM_TIM23_CCMR2_OC3M_PWM_MODE_1 6
+#define STM_TIM23_CCMR2_OC3M_PWM_MODE_2 7
+#define STM_TIM23_CCMR2_OC3M_MASK 7
+#define STM_TIM23_CCMR2_OC3PE 11
+#define STM_TIM23_CCMR2_OC3FE 2
+#define STM_TIM23_CCMR2_CC3S 0
+#define STM_TIM23_CCMR2_CC3S_OUTPUT 0
+#define STM_TIM23_CCMR2_CC3S_INPUT_TI3 1
+#define STM_TIM23_CCMR2_CC3S_INPUT_TI4 2
+#define STM_TIM23_CCMR2_CC3S_INPUT_TRC 3
+#define STM_TIM23_CCMR2_CC3S_MASK 3
+
+#define STM_TIM23_CCER_CC4NP 15
+#define STM_TIM23_CCER_CC4P 13
+#define STM_TIM23_CCER_CC4E 12
+#define STM_TIM23_CCER_CC3NP 11
+#define STM_TIM23_CCER_CC3P 9
+#define STM_TIM23_CCER_CC3E 8
+#define STM_TIM23_CCER_CC2NP 7
+#define STM_TIM23_CCER_CC2P 5
+#define STM_TIM23_CCER_CC2E 4
+#define STM_TIM23_CCER_CC1NP 3
+#define STM_TIM23_CCER_CC1P 1
+#define STM_TIM23_CCER_CC1E 0
struct stm_usb {
struct {
diff --git a/src/telebt-v3.0/.gitignore b/src/telebt-v3.0/.gitignore
new file mode 100644
index 00000000..a7d61147
--- /dev/null
+++ b/src/telebt-v3.0/.gitignore
@@ -0,0 +1,2 @@
+ao_product.h
+telebt-*.elf
diff --git a/src/telebt-v3.0/ao_pins.h b/src/telebt-v3.0/ao_pins.h
index a6a01662..50584940 100644
--- a/src/telebt-v3.0/ao_pins.h
+++ b/src/telebt-v3.0/ao_pins.h
@@ -52,8 +52,13 @@
#define USE_SERIAL_2_STDIN 1
#define DELAY_SERIAL_2_STDIN 1
#define USE_SERIAL_2_FLOW 1
+#define USE_SERIAL_2_SW_FLOW 1
#define SERIAL_2_PA2_PA3 1
#define SERIAL_2_PD5_PD6 0
+#define SERIAL_2_PORT_RTS (&stm_gpioa)
+#define SERIAL_2_PIN_RTS 0
+#define SERIAL_2_PORT_CTS (&stm_gpioa)
+#define SERIAL_2_PIN_CTS 1
#define HAS_SERIAL_3 0
#define USE_SERIAL_3_STDIN 0
diff --git a/src/telebt-v3.0/ao_telebt.c b/src/telebt-v3.0/ao_telebt.c
index 44ee4f3d..1fe06b1a 100644
--- a/src/telebt-v3.0/ao_telebt.c
+++ b/src/telebt-v3.0/ao_telebt.c
@@ -31,7 +31,6 @@ main(void)
ao_clock_init();
ao_task_init();
- ao_serial_init();
ao_led_init(LEDS_AVAILABLE);
ao_led_on(AO_LED_RED);
ao_timer_init();
diff --git a/src/telefire-v0.1/ao_pins.h b/src/telefire-v0.1/ao_pins.h
index 47ae663f..1087c7c9 100644
--- a/src/telefire-v0.1/ao_pins.h
+++ b/src/telefire-v0.1/ao_pins.h
@@ -39,6 +39,8 @@
#define PACKET_HAS_MASTER 0
#define PACKET_HAS_SLAVE 0
+#define PAD_BOX 0
+
#define AO_LED_CONTINUITY(c) (1 << ((c) + 2))
#define AO_LED_CONTINUITY_MASK (0xc)
#define AO_LED_ARMED 0x10
diff --git a/src/telefiretwo-v0.1/.gitignore b/src/telefiretwo-v0.1/.gitignore
new file mode 100644
index 00000000..e89f9fd7
--- /dev/null
+++ b/src/telefiretwo-v0.1/.gitignore
@@ -0,0 +1,2 @@
+telefiretwo-*
+ao_product.h
diff --git a/src/telefiretwo-v0.1/Makefile b/src/telefiretwo-v0.1/Makefile
new file mode 100644
index 00000000..6454d6fd
--- /dev/null
+++ b/src/telefiretwo-v0.1/Makefile
@@ -0,0 +1,89 @@
+#
+# TeleFire build file
+#
+
+include ../stm/Makefile.defs
+
+INC = \
+ ao.h \
+ ao_pins.h \
+ ao_arch.h \
+ ao_arch_funcs.h \
+ ao_pad.h \
+ ao_product.h \
+ ao_radio_spi.h \
+ ao_radio_cmac.h \
+ ao_cc1200_CC1200.h \
+ ao_cc1200.h \
+ stm32l.h
+#
+# Common AltOS sources
+#
+
+#PROFILE=ao_profile.c
+#PROFILE_DEF=-DAO_PROFILE=1
+
+ALTOS_SRC = \
+ ao_boot_chain.c \
+ ao_interrupt.c \
+ ao_product.c \
+ ao_romconfig.c \
+ ao_cmd.c \
+ ao_adc_stm.c \
+ ao_data.c \
+ ao_config.c \
+ ao_task.c \
+ ao_led.c \
+ ao_stdio.c \
+ ao_panic.c \
+ ao_timer.c \
+ ao_mutex.c \
+ ao_freq.c \
+ ao_dma_stm.c \
+ ao_spi_stm.c \
+ ao_eeprom_stm.c \
+ ao_usb_stm.c \
+ ao_exti_stm.c \
+ ao_cc1200.c \
+ ao_radio_cmac.c \
+ ao_aes.c \
+ ao_aes_tables.c \
+ ao_pad.c \
+ ao_radio_cmac_cmd.c
+
+PRODUCT_SRC = \
+ ao_telefiretwo.c
+
+PRODUCT=TeleFire-v0.1
+PRODUCT_DEF=-DTELEFIRETWO_V_0_1
+IDPRODUCT=0x000f
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g
+
+PROGNAME = telefiretwo-v0.1
+PROG = $(PROGNAME)-$(VERSION).elf
+HEX = $(PROGNAME)-$(VERSION).ihx
+
+SRC = $(ALTOS_SRC) $(PRODUCT_SRC)
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+ $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+$(OBJ): $(INC)
+
+ao_product.h: ao-make-product.5c ../Version
+ $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+distclean: clean
+
+clean:
+ rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+ rm -f ao_product.h
+
+install:
+
+uninstall:
+
diff --git a/src/telefiretwo-v0.1/ao_pins.h b/src/telefiretwo-v0.1/ao_pins.h
new file mode 100644
index 00000000..fd840f47
--- /dev/null
+++ b/src/telefiretwo-v0.1/ao_pins.h
@@ -0,0 +1,211 @@
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define HAS_RADIO 1
+#define HAS_RADIO_RATE 1
+#define HAS_TELEMETRY 0
+
+#define HAS_FLIGHT 0
+#define HAS_USB 1
+#define HAS_BEEP 0
+#define HAS_GPS 0
+#define HAS_SERIAL_1 0
+#define HAS_ADC 1
+#define HAS_DBG 0
+#define HAS_EEPROM 1
+#define HAS_LOG 0
+#define HAS_PAD 1
+#define USE_INTERNAL_FLASH 1
+#define IGNITE_ON_P0 0
+#define PACKET_HAS_MASTER 0
+#define PACKET_HAS_SLAVE 0
+#define AO_DATA_RING 32
+#define HAS_FIXED_PAD_BOX 1
+
+/* 8MHz High speed external crystal */
+#define AO_HSE 8000000
+
+/* PLLVCO = 96MHz (so that USB will work) */
+#define AO_PLLMUL 12
+#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12)
+
+#define AO_CC1200_FOSC 40000000
+
+/* SYSCLK = 32MHz (no need to go faster than CPU) */
+#define AO_PLLDIV 3
+#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_3)
+
+/* HCLK = 32MHz (CPU clock) */
+#define AO_AHB_PRESCALER 1
+#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1
+
+/* Run APB1 at 16MHz (HCLK/2) */
+#define AO_APB1_PRESCALER 2
+#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2
+
+/* Run APB2 at 16MHz (HCLK/2) */
+#define AO_APB2_PRESCALER 2
+#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2
+
+#define HAS_EEPROM 1
+#define USE_INTERNAL_FLASH 1
+#define USE_EEPROM_CONFIG 1
+#define USE_STORAGE_CONFIG 0
+#define HAS_USB 1
+#define HAS_BEEP 0
+#define HAS_RADIO 1
+#define HAS_RADIO_RATE 1
+#define HAS_TELEMETRY 0
+#define HAS_AES 1
+
+#define HAS_SPI_1 0
+#define SPI_1_PA5_PA6_PA7 0
+#define SPI_1_PB3_PB4_PB5 0
+#define SPI_1_PE13_PE14_PE15 0
+
+#define HAS_SPI_2 1 /* CC1200 */
+#define SPI_2_PB13_PB14_PB15 1
+#define SPI_2_PD1_PD3_PD4 0
+#define SPI_2_GPIO (&stm_gpiob)
+#define SPI_2_SCK 13
+#define SPI_2_MISO 14
+#define SPI_2_MOSI 15
+#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz
+
+#define HAS_I2C_1 0
+
+#define HAS_I2C_2 0
+
+#define PACKET_HAS_SLAVE 0
+#define PACKET_HAS_MASTER 0
+
+#define FAST_TIMER_FREQ 10000 /* .1ms for debouncing */
+
+/*
+ * Radio is a cc1200 connected via SPI
+ */
+
+#define AO_RADIO_CAL_DEFAULT 5695733
+
+#define AO_FEC_DEBUG 0
+#define AO_CC1200_SPI_CS_PORT (&stm_gpioa)
+#define AO_CC1200_SPI_CS_PIN 7
+#define AO_CC1200_SPI_BUS AO_SPI_2_PB13_PB14_PB15
+#define AO_CC1200_SPI stm_spi2
+
+#define AO_CC1200_INT_PORT (&stm_gpiob)
+#define AO_CC1200_INT_PIN (11)
+
+#define AO_CC1200_INT_GPIO 2
+#define AO_CC1200_INT_GPIO_IOCFG CC1200_IOCFG2
+
+#define LED_PORT_0 (&stm_gpioa)
+#define LED_PORT_1 (&stm_gpiob)
+
+#define LED_PORT_0_ENABLE STM_RCC_AHBENR_GPIOAEN
+#define LED_PORT_1_ENABLE STM_RCC_AHBENR_GPIOBEN
+
+/* Port A, pins 4-6 */
+#define LED_PORT_0_SHIFT 4
+#define LED_PORT_0_MASK 0x7
+#define LED_PIN_GREEN 0
+#define LED_PIN_AMBER 1
+#define LED_PIN_RED 2
+#define AO_LED_RED (1 << LED_PIN_RED)
+#define AO_LED_AMBER (1 << LED_PIN_AMBER)
+#define AO_LED_GREEN (1 << LED_PIN_GREEN)
+
+/* Port B, pins 3-5 */
+#define LED_PORT_1_SHIFT 0
+#define LED_PORT_1_MASK (0x7 << 3)
+#define LED_PIN_CONT_1 3
+#define LED_PIN_CONT_0 4
+#define LED_PIN_ARMED 5
+
+#define AO_LED_ARMED (1 << LED_PIN_ARMED)
+#define AO_LED_CONTINUITY(c) (1 << (4 - (c)))
+#define AO_LED_CONTINUITY_MASK (0x3 << 3)
+
+#define LEDS_AVAILABLE (LED_PORT_0_MASK|LED_PORT_1_MASK)
+
+#define SPI_CS_PORT P1
+#define SPI_CS_SEL P1SEL
+#define SPI_CS_DIR P1DIR
+
+#define SPI_CONST 0x00
+
+#define AO_PAD_NUM 2
+#define AO_PAD_PORT (&stm_gpiob)
+
+#define AO_PAD_PIN_0 9
+#define AO_PAD_ADC_0 0
+
+#define AO_PAD_PIN_1 8
+#define AO_PAD_ADC_1 1
+
+#define AO_PAD_ALL_PINS ((1 << AO_PAD_PIN_0) | (1 << AO_PAD_PIN_1))
+#define AO_PAD_ALL_CHANNELS ((1 << 0) | (1 << 1))
+
+/* test these values with real igniters */
+#define AO_PAD_RELAY_CLOSED 3524
+#define AO_PAD_NO_IGNITER 16904
+#define AO_PAD_GOOD_IGNITER 22514
+
+#define AO_PAD_ADC_PYRO 8
+#define AO_PAD_ADC_BATT 2
+
+#define AO_ADC_FIRST_PIN 0
+
+#define AO_NUM_ADC 4
+
+#define AO_ADC_SQ1 AO_PAD_ADC_0
+#define AO_ADC_SQ2 AO_PAD_ADC_1
+#define AO_ADC_SQ3 AO_PAD_ADC_PYRO
+#define AO_ADC_SQ4 AO_PAD_ADC_BATT
+
+#define AO_PYRO_R_PYRO_SENSE 200
+#define AO_PYRO_R_SENSE_GND 22
+
+#define AO_FIRE_R_POWER_FET 0
+#define AO_FIRE_R_FET_SENSE 200
+#define AO_FIRE_R_SENSE_GND 22
+
+#define HAS_ADC_TEMP 0
+
+struct ao_adc {
+ int16_t sense[AO_PAD_NUM];
+ int16_t pyro;
+ int16_t batt;
+};
+
+#define AO_ADC_DUMP(p) \
+ printf ("tick: %5u 0: %5d 1: %5d pyro: %5d batt %5d\n", \
+ (p)->tick, \
+ (p)->adc.sense[0], \
+ (p)->adc.sense[1], \
+ (p)->adc.pyro, \
+ (p)->adc.batt)
+
+#define AO_ADC_PINS ((1 << AO_PAD_ADC_0) | \
+ (1 << AO_PAD_ADC_1) | \
+ (1 << AO_PAD_ADC_PYRO) | \
+ (1 << AO_PAD_ADC_BATT))
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/telefiretwo-v0.1/ao_telefiretwo.c b/src/telefiretwo-v0.1/ao_telefiretwo.c
new file mode 100644
index 00000000..38629d86
--- /dev/null
+++ b/src/telefiretwo-v0.1/ao_telefiretwo.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_pad.h>
+#include <ao_exti.h>
+#include <ao_radio_cmac_cmd.h>
+
+void
+main(void)
+{
+ ao_clock_init();
+
+ ao_led_init(LEDS_AVAILABLE);
+
+ ao_task_init();
+
+ ao_timer_init();
+ ao_spi_init();
+ ao_dma_init();
+ ao_exti_init();
+
+ ao_cmd_init();
+
+ ao_adc_init();
+
+ ao_eeprom_init();
+
+ ao_radio_init();
+
+ ao_usb_init();
+
+ ao_config_init();
+
+ ao_pad_init();
+
+// ao_radio_cmac_cmd_init();
+
+ ao_start_scheduler();
+}
diff --git a/src/telefiretwo-v0.1/flash-loader/.gitignore b/src/telefiretwo-v0.1/flash-loader/.gitignore
new file mode 100644
index 00000000..65fe7eab
--- /dev/null
+++ b/src/telefiretwo-v0.1/flash-loader/.gitignore
@@ -0,0 +1,2 @@
+*.elf
+*.ihx
diff --git a/src/telefiretwo-v0.1/flash-loader/Makefile b/src/telefiretwo-v0.1/flash-loader/Makefile
new file mode 100644
index 00000000..108cd554
--- /dev/null
+++ b/src/telefiretwo-v0.1/flash-loader/Makefile
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=telefiretwo-v0.1
+include $(TOPDIR)/stm/Makefile-flash.defs
diff --git a/src/telefiretwo-v0.1/flash-loader/ao_pins.h b/src/telefiretwo-v0.1/flash-loader/ao_pins.h
new file mode 100644
index 00000000..daa9048d
--- /dev/null
+++ b/src/telefiretwo-v0.1/flash-loader/ao_pins.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+/* External crystal at 8MHz */
+#define AO_HSE 8000000
+
+#include <ao_flash_stm_pins.h>
+
+#define AO_BOOT_PIN 1
+#define AO_BOOT_APPLICATION_GPIO stm_gpiob
+#define AO_BOOT_APPLICATION_PIN 6
+#define AO_BOOT_APPLICATION_VALUE 1
+#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/telefiretwo-v0.2/.gitignore b/src/telefiretwo-v0.2/.gitignore
new file mode 100644
index 00000000..e89f9fd7
--- /dev/null
+++ b/src/telefiretwo-v0.2/.gitignore
@@ -0,0 +1,2 @@
+telefiretwo-*
+ao_product.h
diff --git a/src/telefiretwo-v0.2/Makefile b/src/telefiretwo-v0.2/Makefile
new file mode 100644
index 00000000..30985f9c
--- /dev/null
+++ b/src/telefiretwo-v0.2/Makefile
@@ -0,0 +1,90 @@
+#
+# TeleFire build file
+#
+
+include ../stm/Makefile.defs
+
+INC = \
+ ao.h \
+ ao_pins.h \
+ ao_arch.h \
+ ao_arch_funcs.h \
+ ao_pad.h \
+ ao_product.h \
+ ao_radio_spi.h \
+ ao_radio_cmac.h \
+ ao_cc1200_CC1200.h \
+ ao_cc1200.h \
+ stm32l.h
+#
+# Common AltOS sources
+#
+
+#PROFILE=ao_profile.c
+#PROFILE_DEF=-DAO_PROFILE=1
+
+ALTOS_SRC = \
+ ao_boot_chain.c \
+ ao_interrupt.c \
+ ao_product.c \
+ ao_romconfig.c \
+ ao_cmd.c \
+ ao_adc_stm.c \
+ ao_data.c \
+ ao_config.c \
+ ao_task.c \
+ ao_led.c \
+ ao_stdio.c \
+ ao_panic.c \
+ ao_timer.c \
+ ao_mutex.c \
+ ao_freq.c \
+ ao_dma_stm.c \
+ ao_spi_stm.c \
+ ao_beep_stm.c \
+ ao_eeprom_stm.c \
+ ao_usb_stm.c \
+ ao_exti_stm.c \
+ ao_cc1200.c \
+ ao_radio_cmac.c \
+ ao_aes.c \
+ ao_aes_tables.c \
+ ao_pad.c \
+ ao_radio_cmac_cmd.c
+
+PRODUCT_SRC = \
+ ao_telefiretwo.c
+
+PRODUCT=TeleFire-v0.2
+PRODUCT_DEF=-DTELEFIRETWO_V_0_2
+IDPRODUCT=0x000f
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g
+
+PROGNAME = telefiretwo-v0.2
+PROG = $(PROGNAME)-$(VERSION).elf
+HEX = $(PROGNAME)-$(VERSION).ihx
+
+SRC = $(ALTOS_SRC) $(PRODUCT_SRC)
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+ $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+$(OBJ): $(INC)
+
+ao_product.h: ao-make-product.5c ../Version
+ $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+distclean: clean
+
+clean:
+ rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+ rm -f ao_product.h
+
+install:
+
+uninstall:
+
diff --git a/src/telefiretwo-v0.2/ao_pins.h b/src/telefiretwo-v0.2/ao_pins.h
new file mode 100644
index 00000000..0fddc6df
--- /dev/null
+++ b/src/telefiretwo-v0.2/ao_pins.h
@@ -0,0 +1,210 @@
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define HAS_RADIO 1
+#define HAS_RADIO_RATE 1
+#define HAS_TELEMETRY 0
+
+#define HAS_FLIGHT 0
+#define HAS_USB 1
+#define HAS_BEEP 1
+#define BEEPER_CHANNEL 4
+#define HAS_GPS 0
+#define HAS_SERIAL_1 0
+#define HAS_ADC 1
+#define HAS_DBG 0
+#define HAS_EEPROM 1
+#define HAS_LOG 0
+#define HAS_PAD 1
+#define USE_INTERNAL_FLASH 1
+#define IGNITE_ON_P0 0
+#define PACKET_HAS_MASTER 0
+#define PACKET_HAS_SLAVE 0
+#define AO_DATA_RING 32
+#define HAS_FIXED_PAD_BOX 1
+
+/* 8MHz High speed external crystal */
+#define AO_HSE 8000000
+
+/* PLLVCO = 96MHz (so that USB will work) */
+#define AO_PLLMUL 12
+#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12)
+
+#define AO_CC1200_FOSC 40000000
+
+/* SYSCLK = 32MHz (no need to go faster than CPU) */
+#define AO_PLLDIV 3
+#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_3)
+
+/* HCLK = 32MHz (CPU clock) */
+#define AO_AHB_PRESCALER 1
+#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1
+
+/* Run APB1 at 16MHz (HCLK/2) */
+#define AO_APB1_PRESCALER 2
+#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2
+
+/* Run APB2 at 16MHz (HCLK/2) */
+#define AO_APB2_PRESCALER 2
+#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2
+
+#define HAS_EEPROM 1
+#define USE_INTERNAL_FLASH 1
+#define USE_EEPROM_CONFIG 1
+#define USE_STORAGE_CONFIG 0
+#define HAS_USB 1
+#define HAS_RADIO 1
+#define HAS_RADIO_RATE 1
+#define HAS_TELEMETRY 0
+#define HAS_AES 1
+
+#define HAS_SPI_1 0
+#define SPI_1_PA5_PA6_PA7 0
+#define SPI_1_PB3_PB4_PB5 0
+#define SPI_1_PE13_PE14_PE15 0
+
+#define HAS_SPI_2 1 /* CC1200 */
+#define SPI_2_PB13_PB14_PB15 1
+#define SPI_2_PD1_PD3_PD4 0
+#define SPI_2_GPIO (&stm_gpiob)
+#define SPI_2_SCK 13
+#define SPI_2_MISO 14
+#define SPI_2_MOSI 15
+#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz
+
+#define HAS_I2C_1 0
+
+#define HAS_I2C_2 0
+
+#define PACKET_HAS_SLAVE 0
+#define PACKET_HAS_MASTER 0
+
+#define FAST_TIMER_FREQ 10000 /* .1ms for debouncing */
+
+/*
+ * Radio is a cc1200 connected via SPI
+ */
+
+#define AO_RADIO_CAL_DEFAULT 5695733
+
+#define AO_FEC_DEBUG 0
+#define AO_CC1200_SPI_CS_PORT (&stm_gpioa)
+#define AO_CC1200_SPI_CS_PIN 7
+#define AO_CC1200_SPI_BUS AO_SPI_2_PB13_PB14_PB15
+#define AO_CC1200_SPI stm_spi2
+
+#define AO_CC1200_INT_PORT (&stm_gpiob)
+#define AO_CC1200_INT_PIN (11)
+
+#define AO_CC1200_INT_GPIO 2
+#define AO_CC1200_INT_GPIO_IOCFG CC1200_IOCFG2
+
+#define LED_PORT_0 (&stm_gpioa)
+#define LED_PORT_1 (&stm_gpiob)
+
+#define LED_PORT_0_ENABLE STM_RCC_AHBENR_GPIOAEN
+#define LED_PORT_1_ENABLE STM_RCC_AHBENR_GPIOBEN
+
+/* Port A, pins 4-6 */
+#define LED_PORT_0_SHIFT 4
+#define LED_PORT_0_MASK 0x7
+#define LED_PIN_GREEN 0
+#define LED_PIN_AMBER 1
+#define LED_PIN_RED 2
+#define AO_LED_RED (1 << LED_PIN_RED)
+#define AO_LED_AMBER (1 << LED_PIN_AMBER)
+#define AO_LED_GREEN (1 << LED_PIN_GREEN)
+
+/* Port B, pins 4-5 */
+#define LED_PORT_1_SHIFT 0
+#define LED_PORT_1_MASK (0x3 << 4)
+#define LED_PIN_CONT_0 4
+#define LED_PIN_ARMED 5
+
+#define AO_LED_ARMED (1 << LED_PIN_ARMED)
+#define AO_LED_CONTINUITY(c) (1 << (4 - (c)))
+#define AO_LED_CONTINUITY_MASK (0x1 << 4)
+
+#define LEDS_AVAILABLE (LED_PORT_0_MASK|LED_PORT_1_MASK)
+
+/* Alarm A */
+#define AO_SIREN
+#define AO_SIREN_PORT (&stm_gpiob)
+#define AO_SIREN_PIN 8
+
+/* Alarm B */
+#define AO_STROBE
+#define AO_STROBE_PORT (&stm_gpiob)
+#define AO_STROBE_PIN 9
+
+#define SPI_CONST 0x00
+
+#define AO_PAD_NUM 1
+#define AO_PAD_PORT (&stm_gpioa)
+
+#define AO_PAD_PIN_0 1
+#define AO_PAD_ADC_0 0
+
+#define AO_PAD_ALL_PINS ((1 << AO_PAD_PIN_0))
+#define AO_PAD_ALL_CHANNELS ((1 << 0))
+
+/* test these values with real igniters */
+#define AO_PAD_RELAY_CLOSED 3524
+#define AO_PAD_NO_IGNITER 16904
+#define AO_PAD_GOOD_IGNITER 22514
+
+#define AO_PAD_ADC_PYRO 2
+#define AO_PAD_ADC_BATT 8
+
+#define AO_ADC_FIRST_PIN 0
+
+#define AO_NUM_ADC 3
+
+#define AO_ADC_SQ1 AO_PAD_ADC_0
+#define AO_ADC_SQ2 AO_PAD_ADC_PYRO
+#define AO_ADC_SQ3 AO_PAD_ADC_BATT
+
+#define AO_PYRO_R_PYRO_SENSE 200
+#define AO_PYRO_R_SENSE_GND 22
+
+#define AO_FIRE_R_POWER_FET 0
+#define AO_FIRE_R_FET_SENSE 200
+#define AO_FIRE_R_SENSE_GND 22
+
+#define HAS_ADC_TEMP 0
+
+struct ao_adc {
+ int16_t sense[AO_PAD_NUM];
+ int16_t pyro;
+ int16_t batt;
+};
+
+#define AO_ADC_DUMP(p) \
+ printf ("tick: %5u 0: %5d pyro: %5d batt %5d\n", \
+ (p)->tick, \
+ (p)->adc.sense[0], \
+ (p)->adc.pyro, \
+ (p)->adc.batt)
+
+#define AO_ADC_PINS ((1 << AO_PAD_ADC_0) | \
+ (1 << AO_PAD_ADC_PYRO) | \
+ (1 << AO_PAD_ADC_BATT))
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/telefiretwo-v0.2/ao_telefiretwo.c b/src/telefiretwo-v0.2/ao_telefiretwo.c
new file mode 100644
index 00000000..38629d86
--- /dev/null
+++ b/src/telefiretwo-v0.2/ao_telefiretwo.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_pad.h>
+#include <ao_exti.h>
+#include <ao_radio_cmac_cmd.h>
+
+void
+main(void)
+{
+ ao_clock_init();
+
+ ao_led_init(LEDS_AVAILABLE);
+
+ ao_task_init();
+
+ ao_timer_init();
+ ao_spi_init();
+ ao_dma_init();
+ ao_exti_init();
+
+ ao_cmd_init();
+
+ ao_adc_init();
+
+ ao_eeprom_init();
+
+ ao_radio_init();
+
+ ao_usb_init();
+
+ ao_config_init();
+
+ ao_pad_init();
+
+// ao_radio_cmac_cmd_init();
+
+ ao_start_scheduler();
+}
diff --git a/src/telefiretwo-v0.2/flash-loader/.gitignore b/src/telefiretwo-v0.2/flash-loader/.gitignore
new file mode 100644
index 00000000..65fe7eab
--- /dev/null
+++ b/src/telefiretwo-v0.2/flash-loader/.gitignore
@@ -0,0 +1,2 @@
+*.elf
+*.ihx
diff --git a/src/telefiretwo-v0.2/flash-loader/Makefile b/src/telefiretwo-v0.2/flash-loader/Makefile
new file mode 100644
index 00000000..2b029ee0
--- /dev/null
+++ b/src/telefiretwo-v0.2/flash-loader/Makefile
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=telefiretwo-v0.2
+include $(TOPDIR)/stm/Makefile-flash.defs
diff --git a/src/telefiretwo-v0.2/flash-loader/ao_pins.h b/src/telefiretwo-v0.2/flash-loader/ao_pins.h
new file mode 100644
index 00000000..daa9048d
--- /dev/null
+++ b/src/telefiretwo-v0.2/flash-loader/ao_pins.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+/* External crystal at 8MHz */
+#define AO_HSE 8000000
+
+#include <ao_flash_stm_pins.h>
+
+#define AO_BOOT_PIN 1
+#define AO_BOOT_APPLICATION_GPIO stm_gpiob
+#define AO_BOOT_APPLICATION_PIN 6
+#define AO_BOOT_APPLICATION_VALUE 1
+#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/telelco-v0.2/Makefile b/src/telelco-v0.2/Makefile
index 7a21f099..8c1ced6c 100644
--- a/src/telelco-v0.2/Makefile
+++ b/src/telelco-v0.2/Makefile
@@ -22,7 +22,6 @@ INC = \
ao_radio_spi.h \
ao_radio_cmac.h \
ao_cc1120_CC1120.h \
- ao_debounce.h \
stm32l.h
#
@@ -61,7 +60,6 @@ ALTOS_SRC = \
ao_fec_tx.c \
ao_fec_rx.c \
ao_seven_segment.c \
- ao_debounce.c \
ao_quadrature.c \
ao_button.c \
ao_event.c \
diff --git a/src/telelco-v0.3/Makefile b/src/telelco-v0.3/Makefile
index 83d3fc43..0bb0f9dc 100644
--- a/src/telelco-v0.3/Makefile
+++ b/src/telelco-v0.3/Makefile
@@ -23,7 +23,6 @@ INC = \
ao_radio_cmac.h \
ao_cc1200_CC1200.h \
ao_cc1200.h \
- ao_debounce.h \
stm32l.h
#
@@ -62,7 +61,6 @@ ALTOS_SRC = \
ao_fec_tx.c \
ao_fec_rx.c \
ao_seven_segment.c \
- ao_debounce.c \
ao_quadrature.c \
ao_button.c \
ao_event.c \
diff --git a/src/telelcotwo-v0.1/.gitignore b/src/telelcotwo-v0.1/.gitignore
new file mode 100644
index 00000000..a32ec26e
--- /dev/null
+++ b/src/telelcotwo-v0.1/.gitignore
@@ -0,0 +1,2 @@
+ao_product.h
+telelco*.elf
diff --git a/src/telelcotwo-v0.1/Makefile b/src/telelcotwo-v0.1/Makefile
new file mode 100644
index 00000000..42188bb2
--- /dev/null
+++ b/src/telelcotwo-v0.1/Makefile
@@ -0,0 +1,96 @@
+#
+# AltOS build for TeleLCO
+#
+#
+
+include ../stm/Makefile.defs
+
+INC = \
+ ao.h \
+ ao_arch.h \
+ ao_arch_funcs.h \
+ ao_boot.h \
+ ao_companion.h \
+ ao_data.h \
+ ao_sample.h \
+ ao_pins.h \
+ ao_product.h \
+ ao_radio_spi.h \
+ ao_radio_cmac.h \
+ ao_cc1200_CC1200.h \
+ ao_cc1200.h \
+ stm32l.h
+
+#
+# Common AltOS sources
+#
+
+#PROFILE=ao_profile.c
+#PROFILE_DEF=-DAO_PROFILE=1
+
+ALTOS_SRC = \
+ ao_boot_chain.c \
+ ao_interrupt.c \
+ ao_product.c \
+ ao_romconfig.c \
+ ao_cmd.c \
+ ao_config.c \
+ ao_task.c \
+ ao_led.c \
+ ao_stdio.c \
+ ao_panic.c \
+ ao_timer.c \
+ ao_mutex.c \
+ ao_freq.c \
+ ao_dma_stm.c \
+ ao_spi_stm.c \
+ ao_beep_stm.c \
+ ao_eeprom_stm.c \
+ ao_fast_timer.c \
+ ao_usb_stm.c \
+ ao_exti_stm.c \
+ ao_cc1200.c \
+ ao_radio_cmac.c \
+ ao_aes.c \
+ ao_aes_tables.c \
+ ao_fec_tx.c \
+ ao_fec_rx.c \
+ ao_button.c \
+ ao_event.c \
+ ao_lco_two.c \
+ ao_lco_func.c \
+ ao_lco_cmd.c \
+ ao_radio_cmac_cmd.c
+
+PRODUCT=TeleLCOTwo-v0.1
+PRODUCT_DEF=-DTELELCOTWO
+IDPRODUCT=0x0023
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g
+
+PROGNAME=telelcotwo-v0.1
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_telelcotwo.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+ $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+$(OBJ): $(INC)
+
+ao_product.h: ao-make-product.5c ../Version
+ $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+distclean: clean
+
+clean:
+ rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+ rm -f ao_product.h
+
+install:
+
+uninstall:
diff --git a/src/telelcotwo-v0.1/ao_pins.h b/src/telelcotwo-v0.1/ao_pins.h
new file mode 100644
index 00000000..ce797a38
--- /dev/null
+++ b/src/telelcotwo-v0.1/ao_pins.h
@@ -0,0 +1,172 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+/* 8MHz High speed external crystal */
+#define AO_HSE 8000000
+
+/* PLLVCO = 96MHz (so that USB will work) */
+#define AO_PLLMUL 12
+#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12)
+
+#define AO_CC1200_FOSC 40000000
+
+/* SYSCLK = 32MHz (no need to go faster than CPU) */
+#define AO_PLLDIV 3
+#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_3)
+
+/* HCLK = 32MHz (CPU clock) */
+#define AO_AHB_PRESCALER 1
+#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1
+
+/* Run APB1 at 16MHz (HCLK/2) */
+#define AO_APB1_PRESCALER 2
+#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2
+
+/* Run APB2 at 16MHz (HCLK/2) */
+#define AO_APB2_PRESCALER 2
+#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2
+
+#define HAS_EEPROM 1
+#define USE_INTERNAL_FLASH 1
+#define USE_EEPROM_CONFIG 1
+#define USE_STORAGE_CONFIG 0
+#define HAS_USB 1
+#define HAS_BEEP 1
+#define BEEPER_CHANNEL 4
+#define HAS_RADIO 1
+#define HAS_RADIO_RATE 1
+#define HAS_TELEMETRY 0
+#define HAS_AES 1
+#define HAS_FIXED_PAD_BOX 1
+
+#define HAS_SPI_1 0
+#define SPI_1_PA5_PA6_PA7 0
+#define SPI_1_PB3_PB4_PB5 0
+#define SPI_1_PE13_PE14_PE15 0
+
+#define HAS_SPI_2 1 /* CC1200 */
+#define SPI_2_PB13_PB14_PB15 1
+#define SPI_2_PD1_PD3_PD4 0
+#define SPI_2_GPIO (&stm_gpiod)
+#define SPI_2_SCK 13
+#define SPI_2_MISO 14
+#define SPI_2_MOSI 15
+#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz
+
+#define HAS_I2C_1 0
+
+#define HAS_I2C_2 0
+
+#define PACKET_HAS_SLAVE 0
+#define PACKET_HAS_MASTER 0
+
+#define FAST_TIMER_FREQ 10000 /* .1ms for debouncing */
+
+/*
+ * Radio is a cc1200 connected via SPI
+ */
+
+#define AO_RADIO_CAL_DEFAULT 5695733
+
+#define AO_FEC_DEBUG 0
+#define AO_CC1200_SPI_CS_PORT (&stm_gpioa)
+#define AO_CC1200_SPI_CS_PIN 7
+#define AO_CC1200_SPI_BUS AO_SPI_2_PB13_PB14_PB15
+#define AO_CC1200_SPI stm_spi2
+
+#define AO_CC1200_INT_PORT (&stm_gpiob)
+#define AO_CC1200_INT_PIN (11)
+
+#define AO_CC1200_INT_GPIO 2
+#define AO_CC1200_INT_GPIO_IOCFG CC1200_IOCFG2
+
+#define LOW_LEVEL_DEBUG 0
+
+#define LED_PORT_0 (&stm_gpioa)
+#define LED_PORT_1 (&stm_gpiob)
+
+#define LED_PORT_0_ENABLE STM_RCC_AHBENR_GPIOAEN
+#define LED_PORT_1_ENABLE STM_RCC_AHBENR_GPIOBEN
+
+/* Port A, pins 4-6 */
+#define LED_PORT_0_SHIFT 4
+#define LED_PORT_0_MASK 0x7
+
+#define LED_PIN_GREEN 0
+#define LED_PIN_AMBER 1
+#define LED_PIN_RED 2
+
+#define AO_LED_RED (1 << LED_PIN_RED)
+#define AO_LED_AMBER (1 << LED_PIN_AMBER)
+#define AO_LED_GREEN (1 << LED_PIN_GREEN)
+
+/* Port B, pins 3-5 */
+#define LED_PORT_1_SHIFT 0
+#define LED_PORT_1_MASK (0x7 << 3)
+
+#define LED_PIN_CONTINUITY_1 3
+#define LED_PIN_CONTINUITY_0 4
+#define LED_PIN_REMOTE_ARM 5
+
+#define AO_LED_CONTINUITY_1 (1 << LED_PIN_CONTINUITY_1)
+#define AO_LED_CONTINUITY_0 (1 << LED_PIN_CONTINUITY_0)
+
+#define AO_LED_CONTINUITY_NUM 2
+
+#define AO_LED_REMOTE_ARM (1 << LED_PIN_REMOTE_ARM)
+
+#define LEDS_AVAILABLE (AO_LED_RED | \
+ AO_LED_AMBER | \
+ AO_LED_GREEN | \
+ AO_LED_CONTINUITY_1 | \
+ AO_LED_CONTINUITY_0 | \
+ AO_LED_REMOTE_ARM)
+
+/*
+ * Use event queue for input devices
+ */
+
+#define AO_EVENT 1
+
+/*
+ * Buttons
+ */
+
+#define AO_BUTTON_COUNT 3
+#define AO_BUTTON_MODE AO_EXTI_MODE_PULL_UP
+
+#define AO_BUTTON_0_PORT &stm_gpioa
+#define AO_BUTTON_0 0
+
+#define AO_BUTTON_ARM_0 0
+
+#define AO_BUTTON_1_PORT &stm_gpioa
+#define AO_BUTTON_1 1
+
+#define AO_BUTTON_ARM_1 1
+
+#define AO_BUTTON_ARM_NUM 2
+
+#define AO_BUTTON_2_PORT &stm_gpioa
+#define AO_BUTTON_2 2
+
+#define AO_BUTTON_FIRE 2
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/telelcotwo-v0.1/ao_telelcotwo.c b/src/telelcotwo-v0.1/ao_telelcotwo.c
new file mode 100644
index 00000000..318875e3
--- /dev/null
+++ b/src/telelcotwo-v0.1/ao_telelcotwo.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_exti.h>
+#include <ao_packet.h>
+#include <ao_companion.h>
+#include <ao_profile.h>
+#include <ao_pyro.h>
+#include <ao_aes.h>
+#include <ao_button.h>
+#include <ao_lco.h>
+#include <ao_lco_cmd.h>
+#include <ao_radio_cmac_cmd.h>
+#include <ao_eeprom.h>
+
+int
+main(void)
+{
+ ao_clock_init();
+
+ ao_led_init(LEDS_AVAILABLE);
+ ao_led_on(AO_LED_GREEN);
+ ao_beep_init();
+ ao_task_init();
+
+ ao_timer_init();
+
+ ao_spi_init();
+ ao_dma_init();
+ ao_exti_init();
+
+ ao_cmd_init();
+
+ ao_button_init();
+
+ ao_eeprom_init();
+
+ ao_radio_init();
+
+ ao_usb_init();
+
+ ao_config_init();
+
+ ao_lco_init();
+ ao_lco_cmd_init();
+// ao_radio_cmac_cmd_init();
+
+ ao_start_scheduler();
+ return 0;
+}
diff --git a/src/telelcotwo-v0.1/flash-loader/Makefile b/src/telelcotwo-v0.1/flash-loader/Makefile
new file mode 100644
index 00000000..69833314
--- /dev/null
+++ b/src/telelcotwo-v0.1/flash-loader/Makefile
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=telelcotwo-v0.1
+include $(TOPDIR)/stm/Makefile-flash.defs
diff --git a/src/telelcotwo-v0.1/flash-loader/ao_pins.h b/src/telelcotwo-v0.1/flash-loader/ao_pins.h
new file mode 100644
index 00000000..266bff6c
--- /dev/null
+++ b/src/telelcotwo-v0.1/flash-loader/ao_pins.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+/* External crystal at 8MHz */
+#define AO_HSE 8000000
+
+#include <ao_flash_stm_pins.h>
+
+/* Fire switch. Press at power on to get boot loader */
+
+#define AO_BOOT_PIN 1
+#define AO_BOOT_APPLICATION_GPIO stm_gpioa
+#define AO_BOOT_APPLICATION_PIN 2
+#define AO_BOOT_APPLICATION_VALUE 1
+#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/telemega-v0.1/ao_pins.h b/src/telemega-v0.1/ao_pins.h
index 7ccc6085..1815ef54 100644
--- a/src/telemega-v0.1/ao_pins.h
+++ b/src/telemega-v0.1/ao_pins.h
@@ -346,6 +346,7 @@ struct ao_adc {
*/
#define HAS_MMA655X 1
+#define AO_MMA655X_INVERT 0
#define AO_MMA655X_SPI_INDEX AO_SPI_1_PE13_PE14_PE15
#define AO_MMA655X_CS_PORT (&stm_gpiod)
#define AO_MMA655X_CS_PIN 4
diff --git a/src/telemega-v1.0/ao_pins.h b/src/telemega-v1.0/ao_pins.h
index 664546c2..b81e59a9 100644
--- a/src/telemega-v1.0/ao_pins.h
+++ b/src/telemega-v1.0/ao_pins.h
@@ -348,6 +348,7 @@ struct ao_adc {
*/
#define HAS_MMA655X 1
+#define AO_MMA655X_INVERT 0
#define AO_MMA655X_SPI_INDEX AO_SPI_1_PE13_PE14_PE15
#define AO_MMA655X_CS_PORT (&stm_gpiod)
#define AO_MMA655X_CS_PIN 4
diff --git a/src/telemega-v2.0/ao_pins.h b/src/telemega-v2.0/ao_pins.h
index 9095a350..242f0ab2 100644
--- a/src/telemega-v2.0/ao_pins.h
+++ b/src/telemega-v2.0/ao_pins.h
@@ -348,6 +348,7 @@ struct ao_adc {
*/
#define HAS_MMA655X 1
+#define AO_MMA655X_INVERT 0
#define AO_MMA655X_SPI_INDEX AO_SPI_1_PE13_PE14_PE15
#define AO_MMA655X_CS_PORT (&stm_gpiod)
#define AO_MMA655X_CS_PIN 4
diff --git a/src/telerepeat-v1.0/.gitignore b/src/telerepeat-v1.0/.gitignore
new file mode 100644
index 00000000..4bb125bc
--- /dev/null
+++ b/src/telerepeat-v1.0/.gitignore
@@ -0,0 +1,2 @@
+telerepeat-*
+ao_product.h
diff --git a/src/telerepeat-v1.0/.sdcdbrc b/src/telerepeat-v1.0/.sdcdbrc
new file mode 100644
index 00000000..2c77e32b
--- /dev/null
+++ b/src/telerepeat-v1.0/.sdcdbrc
@@ -0,0 +1,2 @@
+--directory=../cc1111:../product:../kernel:../drivers:.
+
diff --git a/src/test/plotem b/src/test/plotem
new file mode 100755
index 00000000..8bc392cf
--- /dev/null
+++ b/src/test/plotem
@@ -0,0 +1,10 @@
+gnuplot -persist << EOF
+set ylabel "altitude (m)"
+set y2label "error"
+set xlabel "time (s)"
+set xtics border out nomirror
+set ytics border out nomirror
+set y2tics border out nomirror
+plot "$1" using 1:3 with lines axes x1y1 title "raw height",\
+"$1" using 1:21 with lines axes x1y2 title "error"
+EOF
diff --git a/telegps/TeleGPS.java b/telegps/TeleGPS.java
index 0250a38e..122b1182 100644
--- a/telegps/TeleGPS.java
+++ b/telegps/TeleGPS.java
@@ -24,8 +24,8 @@ import java.io.*;
import java.util.concurrent.*;
import java.util.*;
import java.text.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class TeleGPS
extends AltosUIFrame
diff --git a/telegps/TeleGPSConfig.java b/telegps/TeleGPSConfig.java
index 165981f9..daef1cac 100644
--- a/telegps/TeleGPSConfig.java
+++ b/telegps/TeleGPSConfig.java
@@ -22,8 +22,8 @@ import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
import java.text.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class TeleGPSConfig implements ActionListener {
diff --git a/telegps/TeleGPSConfigUI.java b/telegps/TeleGPSConfigUI.java
index 5a3a05eb..0f8a3d25 100644
--- a/telegps/TeleGPSConfigUI.java
+++ b/telegps/TeleGPSConfigUI.java
@@ -22,8 +22,8 @@ import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class TeleGPSConfigUI
extends AltosUIDialog
@@ -54,7 +54,7 @@ public class TeleGPSConfigUI
JLabel version_value;
JLabel serial_value;
AltosUIFreqList radio_frequency_value;
- JTextField radio_calibration_value;
+ JLabel radio_calibration_value;
JRadioButton radio_enable_value;
AltosUIRateList rate_value;
JComboBox<String> aprs_interval_value;
@@ -138,13 +138,6 @@ public class TeleGPSConfigUI
return product != null && product.startsWith("TeleGPS");
}
- void set_radio_calibration_tool_tip() {
- if (radio_calibration_value.isEnabled())
- radio_calibration_value.setToolTipText("Tune radio output to match desired frequency");
- else
- radio_calibration_value.setToolTipText("Cannot tune radio while connected over packet mode");
- }
-
void set_radio_enable_tool_tip() {
if (radio_enable_value.isEnabled())
radio_enable_value.setToolTipText("Enable/Disable telemetry and RDF transmissions");
@@ -316,10 +309,8 @@ public class TeleGPSConfigUI
c.anchor = GridBagConstraints.LINE_START;
c.insets = ir;
c.ipady = 5;
- radio_calibration_value = new JTextField(String.format("%d", 1186611));
- radio_calibration_value.getDocument().addDocumentListener(this);
+ radio_calibration_value = new JLabel(String.format("%d", 1186611));
pane.add(radio_calibration_value, c);
- set_radio_calibration_tool_tip();
row++;
/* Radio Enable */
@@ -760,10 +751,6 @@ public class TeleGPSConfigUI
}
}
- public int radio_calibration() throws AltosConfigDataException {
- return parse_int("radio calibration", radio_calibration_value.getText(), false);
- }
-
public void set_radio_enable(int new_radio_enable) {
if (new_radio_enable >= 0) {
radio_enable_value.setSelected(new_radio_enable > 0);
diff --git a/telegps/TeleGPSDisplayThread.java b/telegps/TeleGPSDisplayThread.java
index 4d8fdcc9..e44b4fed 100644
--- a/telegps/TeleGPSDisplayThread.java
+++ b/telegps/TeleGPSDisplayThread.java
@@ -21,8 +21,8 @@ import java.awt.*;
import javax.swing.*;
import java.io.*;
import java.text.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class TeleGPSDisplayThread extends Thread {
diff --git a/telegps/TeleGPSGraphUI.java b/telegps/TeleGPSGraphUI.java
index e3902d2f..233c8c1a 100644
--- a/telegps/TeleGPSGraphUI.java
+++ b/telegps/TeleGPSGraphUI.java
@@ -26,8 +26,8 @@ import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
diff --git a/telegps/TeleGPSInfo.java b/telegps/TeleGPSInfo.java
index ae197abe..590f1d1a 100644
--- a/telegps/TeleGPSInfo.java
+++ b/telegps/TeleGPSInfo.java
@@ -21,8 +21,8 @@ import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class TeleGPSInfo extends AltosUIFlightTab {
diff --git a/telegps/TeleGPSPreferences.java b/telegps/TeleGPSPreferences.java
index eab9350a..c03b42d3 100644
--- a/telegps/TeleGPSPreferences.java
+++ b/telegps/TeleGPSPreferences.java
@@ -22,7 +22,7 @@ import java.awt.event.*;
import java.beans.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
public class TeleGPSPreferences
extends AltosUIConfigure
diff --git a/telegps/TeleGPSState.java b/telegps/TeleGPSState.java
index 516eb797..46e48fc4 100644
--- a/telegps/TeleGPSState.java
+++ b/telegps/TeleGPSState.java
@@ -21,8 +21,8 @@ import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class TeleGPSState extends AltosUIFlightTab {
diff --git a/telegps/TeleGPSStatus.java b/telegps/TeleGPSStatus.java
index 3a6b2515..81a1b305 100644
--- a/telegps/TeleGPSStatus.java
+++ b/telegps/TeleGPSStatus.java
@@ -19,8 +19,8 @@ package org.altusmetrum.telegps;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class TeleGPSStatus extends JComponent implements AltosFlightDisplay {
GridBagLayout layout;
diff --git a/telegps/TeleGPSStatusUpdate.java b/telegps/TeleGPSStatusUpdate.java
index 655f42f5..6740ff70 100644
--- a/telegps/TeleGPSStatusUpdate.java
+++ b/telegps/TeleGPSStatusUpdate.java
@@ -18,7 +18,7 @@
package org.altusmetrum.telegps;
import java.awt.event.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class TeleGPSStatusUpdate implements ActionListener {